annotate transform/TransformFactory.cpp @ 1196:c7b9c902642f spectrogram-minor-refactor

Fix threshold in spectrogram -- it wasn't working in the last release. There is a new protocol for this. Formerly the threshold parameter had a range from -50dB to 0 with the default at -50, and -50 treated internally as "no threshold". However, there was a hardcoded, hidden internal threshold for spectrogram colour mapping at -80dB with anything below this being rounded to zero. Now the threshold parameter has range -81 to -1 with the default at -80, -81 is treated internally as "no threshold", and there is no hidden internal threshold. So the default behaviour is the same as before, an effective -80dB threshold, but it is now possible to change this in both directions. Sessions reloaded from prior versions may look slightly different because, if the session says there should be no threshold, there will now actually be no threshold instead of having the hidden internal one. Still need to do something in the UI to make it apparent that the -81dB setting removes the threshold entirely. This is at least no worse than the previous, also obscured, magic -50dB setting.
author Chris Cannam
date Mon, 01 Aug 2016 16:21:01 +0100
parents 6b1af0f05f06
children c2207877689d
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@330 421 Vamp::Plugin *plugin =
Chris@350 422 factory->instantiatePlugin(pluginId, 44100);
Chris@330 423
Chris@330 424 if (!plugin) {
Chris@845 425 cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId << endl;
Chris@330 426 continue;
Chris@330 427 }
Chris@330 428
Chris@330 429 QString pluginName = plugin->getName().c_str();
Chris@330 430 QString category = factory->getPluginCategory(pluginId);
Chris@330 431
Chris@330 432 Vamp::Plugin::OutputList outputs =
Chris@330 433 plugin->getOutputDescriptors();
Chris@330 434
Chris@930 435 for (int j = 0; j < (int)outputs.size(); ++j) {
Chris@330 436
Chris@330 437 QString transformId = QString("%1:%2")
Chris@330 438 .arg(pluginId).arg(outputs[j].identifier.c_str());
Chris@330 439
Chris@330 440 QString userName;
Chris@330 441 QString friendlyName;
Chris@330 442 QString units = outputs[j].unit.c_str();
Chris@330 443 QString description = plugin->getDescription().c_str();
Chris@330 444 QString maker = plugin->getMaker().c_str();
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@330 450 if (outputs.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@330 455 .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330 456 }
Chris@330 457 } else {
Chris@330 458 if (outputs.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@443 463 .arg(longDescription).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330 464 }
Chris@330 465 }
Chris@330 466
Chris@330 467 if (outputs.size() == 1) {
Chris@330 468 userName = pluginName;
Chris@330 469 friendlyName = pluginName;
Chris@330 470 } else {
Chris@330 471 userName = QString("%1: %2")
Chris@330 472 .arg(pluginName)
Chris@330 473 .arg(outputs[j].name.c_str());
Chris@330 474 friendlyName = outputs[j].name.c_str();
Chris@330 475 }
Chris@330 476
Chris@330 477 bool configurable = (!plugin->getPrograms().empty() ||
Chris@330 478 !plugin->getParameterDescriptors().empty());
Chris@330 479
Chris@600 480 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@686 481 cerr << "Feature extraction plugin transform: " << transformId << " friendly name: " << friendlyName << endl;
Chris@600 482 #endif
Chris@330 483
Chris@330 484 transforms[transformId] =
Chris@487 485 TransformDescription(TransformDescription::Analysis,
Chris@332 486 category,
Chris@332 487 transformId,
Chris@332 488 userName,
Chris@332 489 friendlyName,
Chris@332 490 description,
Chris@443 491 longDescription,
Chris@332 492 maker,
Chris@332 493 units,
Chris@332 494 configurable);
Chris@330 495 }
Chris@330 496
Chris@330 497 delete plugin;
Chris@330 498 }
Chris@330 499 }
Chris@330 500
Chris@330 501 void
Chris@330 502 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@330 503 {
Chris@330 504 std::vector<QString> plugs =
Chris@330 505 RealTimePluginFactory::getAllPluginIdentifiers();
Chris@576 506 if (m_exiting) return;
Chris@330 507
Chris@330 508 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@330 509
Chris@930 510 for (int i = 0; i < (int)plugs.size(); ++i) {
Chris@330 511
Chris@330 512 QString pluginId = plugs[i];
Chris@330 513
Chris@330 514 RealTimePluginFactory *factory =
Chris@330 515 RealTimePluginFactory::instanceFor(pluginId);
Chris@330 516
Chris@330 517 if (!factory) {
Chris@845 518 cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId << endl;
Chris@330 519 continue;
Chris@330 520 }
Chris@330 521
Chris@330 522 const RealTimePluginDescriptor *descriptor =
Chris@330 523 factory->getPluginDescriptor(pluginId);
Chris@330 524
Chris@330 525 if (!descriptor) {
Chris@845 526 cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId << endl;
Chris@330 527 continue;
Chris@330 528 }
Chris@330 529
Chris@330 530 //!!! if (descriptor->controlOutputPortCount == 0 ||
Chris@330 531 // descriptor->audioInputPortCount == 0) continue;
Chris@330 532
Chris@843 533 // cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << endl;
Chris@330 534
Chris@330 535 QString pluginName = descriptor->name.c_str();
Chris@330 536 QString category = factory->getPluginCategory(pluginId);
Chris@330 537 bool configurable = (descriptor->parameterCount > 0);
Chris@330 538 QString maker = descriptor->maker.c_str();
Chris@330 539 if (maker == "") maker = tr("<unknown maker>");
Chris@330 540
Chris@330 541 if (descriptor->audioInputPortCount > 0) {
Chris@330 542
Chris@930 543 for (int j = 0; j < (int)descriptor->controlOutputPortCount; ++j) {
Chris@330 544
Chris@330 545 QString transformId = QString("%1:%2").arg(pluginId).arg(j);
Chris@330 546 QString userName;
Chris@330 547 QString units;
Chris@330 548 QString portName;
Chris@330 549
Chris@930 550 if (j < (int)descriptor->controlOutputPortNames.size() &&
Chris@330 551 descriptor->controlOutputPortNames[j] != "") {
Chris@330 552
Chris@330 553 portName = descriptor->controlOutputPortNames[j].c_str();
Chris@330 554
Chris@330 555 userName = tr("%1: %2")
Chris@330 556 .arg(pluginName)
Chris@330 557 .arg(portName);
Chris@330 558
Chris@330 559 if (unitRE.indexIn(portName) >= 0) {
Chris@330 560 units = unitRE.cap(1);
Chris@330 561 }
Chris@330 562
Chris@330 563 } else if (descriptor->controlOutputPortCount > 1) {
Chris@330 564
Chris@330 565 userName = tr("%1: Output %2")
Chris@330 566 .arg(pluginName)
Chris@330 567 .arg(j + 1);
Chris@330 568
Chris@330 569 } else {
Chris@330 570
Chris@330 571 userName = pluginName;
Chris@330 572 }
Chris@330 573
Chris@330 574 QString description;
Chris@330 575
Chris@330 576 if (portName != "") {
Chris@330 577 description = tr("Extract \"%1\" data output from \"%2\" effect plugin (from %3)")
Chris@330 578 .arg(portName)
Chris@330 579 .arg(pluginName)
Chris@330 580 .arg(maker);
Chris@330 581 } else {
Chris@330 582 description = tr("Extract data output %1 from \"%2\" effect plugin (from %3)")
Chris@330 583 .arg(j + 1)
Chris@330 584 .arg(pluginName)
Chris@330 585 .arg(maker);
Chris@330 586 }
Chris@330 587
Chris@330 588 transforms[transformId] =
Chris@487 589 TransformDescription(TransformDescription::EffectsData,
Chris@332 590 category,
Chris@332 591 transformId,
Chris@332 592 userName,
Chris@332 593 userName,
Chris@443 594 "",
Chris@332 595 description,
Chris@332 596 maker,
Chris@332 597 units,
Chris@332 598 configurable);
Chris@330 599 }
Chris@330 600 }
Chris@330 601
Chris@330 602 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@330 603
Chris@330 604 if (descriptor->audioOutputPortCount > 0) {
Chris@330 605
Chris@330 606 QString transformId = QString("%1:A").arg(pluginId);
Chris@487 607 TransformDescription::Type type = TransformDescription::Effects;
Chris@330 608
Chris@330 609 QString description = tr("Transform audio signal with \"%1\" effect plugin (from %2)")
Chris@330 610 .arg(pluginName)
Chris@330 611 .arg(maker);
Chris@330 612
Chris@330 613 if (descriptor->audioInputPortCount == 0) {
Chris@487 614 type = TransformDescription::Generator;
Chris@330 615 QString description = tr("Generate audio signal using \"%1\" plugin (from %2)")
Chris@330 616 .arg(pluginName)
Chris@330 617 .arg(maker);
Chris@330 618 }
Chris@330 619
Chris@330 620 transforms[transformId] =
Chris@330 621 TransformDescription(type,
Chris@332 622 category,
Chris@332 623 transformId,
Chris@332 624 pluginName,
Chris@332 625 pluginName,
Chris@443 626 "",
Chris@332 627 description,
Chris@332 628 maker,
Chris@332 629 "",
Chris@332 630 configurable);
Chris@330 631 }
Chris@330 632 }
Chris@330 633 }
Chris@330 634 }
Chris@330 635
Chris@457 636 void
Chris@457 637 TransformFactory::populateUninstalledTransforms()
Chris@457 638 {
Chris@576 639 if (m_exiting) return;
Chris@576 640
Chris@460 641 populateTransforms();
Chris@576 642 if (m_exiting) return;
Chris@460 643
Chris@460 644 MutexLocker locker(&m_uninstalledTransformsMutex,
Chris@460 645 "TransformFactory::populateUninstalledTransforms");
Chris@460 646 if (m_uninstalledTransformsPopulated) return;
Chris@460 647
Chris@461 648 PluginRDFIndexer::getInstance()->indexConfiguredURLs();
Chris@576 649 if (m_exiting) return;
Chris@457 650
Chris@457 651 //!!! This will be amazingly slow
Chris@457 652
Chris@457 653 QStringList ids = PluginRDFIndexer::getInstance()->getIndexedPluginIds();
Chris@457 654
Chris@457 655 for (QStringList::const_iterator i = ids.begin(); i != ids.end(); ++i) {
Chris@457 656
Chris@457 657 PluginRDFDescription desc(*i);
Chris@457 658
Chris@457 659 QString name = desc.getPluginName();
Chris@600 660 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@600 661 if (name == "") {
Chris@810 662 cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@810 663 << "No name available for plugin " << *i
Chris@810 664 << ", skipping" << endl;
Chris@600 665 continue;
Chris@600 666 }
Chris@600 667 #endif
Chris@457 668
Chris@457 669 QString description = desc.getPluginDescription();
Chris@457 670 QString maker = desc.getPluginMaker();
Chris@462 671 QString infoUrl = desc.getPluginInfoURL();
Chris@457 672
Chris@457 673 QStringList oids = desc.getOutputIds();
Chris@457 674
Chris@457 675 for (QStringList::const_iterator j = oids.begin(); j != oids.end(); ++j) {
Chris@457 676
Chris@457 677 TransformId tid = Transform::getIdentifierForPluginOutput(*i, *j);
Chris@457 678
Chris@457 679 if (m_transforms.find(tid) != m_transforms.end()) {
Chris@600 680 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@810 681 cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@687 682 << tid << " is installed; adding info url if appropriate, skipping rest" << endl;
Chris@600 683 #endif
Chris@468 684 if (infoUrl != "") {
Chris@468 685 if (m_transforms[tid].infoUrl == "") {
Chris@468 686 m_transforms[tid].infoUrl = infoUrl;
Chris@468 687 }
Chris@468 688 }
Chris@457 689 continue;
Chris@457 690 }
Chris@457 691
Chris@600 692 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@810 693 cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@687 694 << "adding " << tid << endl;
Chris@600 695 #endif
Chris@457 696
Chris@457 697 QString oname = desc.getOutputName(*j);
Chris@457 698 if (oname == "") oname = *j;
Chris@457 699
Chris@457 700 TransformDescription td;
Chris@487 701 td.type = TransformDescription::Analysis;
Chris@457 702 td.category = "";
Chris@457 703 td.identifier = tid;
Chris@457 704
Chris@457 705 if (oids.size() == 1) {
Chris@457 706 td.name = name;
Chris@457 707 } else if (name != "") {
Chris@457 708 td.name = tr("%1: %2").arg(name).arg(oname);
Chris@457 709 }
Chris@457 710
Chris@462 711 QString longDescription = description;
Chris@462 712 //!!! basically duplicated from above
Chris@462 713 if (longDescription == "") {
Chris@462 714 if (oids.size() == 1) {
Chris@462 715 longDescription = tr("Extract features using \"%1\" plugin (from %2)")
Chris@462 716 .arg(name).arg(maker);
Chris@462 717 } else {
Chris@462 718 longDescription = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
Chris@462 719 .arg(oname).arg(name).arg(maker);
Chris@462 720 }
Chris@462 721 } else {
Chris@462 722 if (oids.size() == 1) {
Chris@462 723 longDescription = tr("%1 using \"%2\" plugin (from %3)")
Chris@462 724 .arg(longDescription).arg(name).arg(maker);
Chris@462 725 } else {
Chris@462 726 longDescription = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
Chris@462 727 .arg(longDescription).arg(oname).arg(name).arg(maker);
Chris@462 728 }
Chris@462 729 }
Chris@462 730
Chris@457 731 td.friendlyName = name; //!!!???
Chris@457 732 td.description = description;
Chris@462 733 td.longDescription = longDescription;
Chris@457 734 td.maker = maker;
Chris@462 735 td.infoUrl = infoUrl;
Chris@457 736 td.units = "";
Chris@457 737 td.configurable = false;
Chris@457 738
Chris@457 739 m_uninstalledTransforms[tid] = td;
Chris@457 740 }
Chris@574 741
Chris@576 742 if (m_exiting) return;
Chris@457 743 }
Chris@457 744
Chris@457 745 m_uninstalledTransformsPopulated = true;
Chris@460 746
Chris@600 747 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@843 748 cerr << "populateUninstalledTransforms exiting" << endl;
Chris@600 749 #endif
Chris@457 750 }
Chris@350 751
Chris@350 752 Transform
Chris@1047 753 TransformFactory::getDefaultTransformFor(TransformId id, sv_samplerate_t rate)
Chris@350 754 {
Chris@350 755 Transform t;
Chris@350 756 t.setIdentifier(id);
Chris@1047 757 if (rate != 0) t.setSampleRate(rate);
Chris@350 758
Chris@351 759 Vamp::PluginBase *plugin = instantiateDefaultPluginFor(id, rate);
Chris@350 760
Chris@350 761 if (plugin) {
Chris@366 762 t.setPluginVersion(QString("%1").arg(plugin->getPluginVersion()));
Chris@350 763 setParametersFromPlugin(t, plugin);
Chris@350 764 makeContextConsistentWithPlugin(t, plugin);
Chris@350 765 delete plugin;
Chris@350 766 }
Chris@350 767
Chris@350 768 return t;
Chris@350 769 }
Chris@350 770
Chris@350 771 Vamp::PluginBase *
Chris@351 772 TransformFactory::instantiatePluginFor(const Transform &transform)
Chris@351 773 {
Chris@351 774 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@1047 775 (transform.getIdentifier(), transform.getSampleRate());
Chris@508 776
Chris@351 777 if (plugin) {
Chris@351 778 setPluginParameters(transform, plugin);
Chris@351 779 }
Chris@508 780
Chris@351 781 return plugin;
Chris@351 782 }
Chris@351 783
Chris@351 784 Vamp::PluginBase *
Chris@1047 785 TransformFactory::instantiateDefaultPluginFor(TransformId identifier,
Chris@1047 786 sv_samplerate_t rate)
Chris@350 787 {
Chris@350 788 Transform t;
Chris@350 789 t.setIdentifier(identifier);
Chris@1047 790 if (rate == 0) rate = 44100.0;
Chris@350 791 QString pluginId = t.getPluginIdentifier();
Chris@350 792
Chris@350 793 Vamp::PluginBase *plugin = 0;
Chris@350 794
Chris@350 795 if (t.getType() == Transform::FeatureExtraction) {
Chris@350 796
Chris@1139 797 // cerr << "TransformFactory::instantiateDefaultPluginFor: identifier \""
Chris@1139 798 // << identifier << "\" is a feature extraction transform" << endl;
Chris@1139 799
Chris@350 800 FeatureExtractionPluginFactory *factory =
Chris@350 801 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@350 802
Chris@439 803 if (factory) {
Chris@1047 804 plugin = factory->instantiatePlugin(pluginId, rate);
Chris@439 805 }
Chris@350 806
Chris@1139 807 } else if (t.getType() == Transform::RealTimeEffect) {
Chris@1139 808
Chris@1139 809 // cerr << "TransformFactory::instantiateDefaultPluginFor: identifier \""
Chris@1139 810 // << identifier << "\" is a real-time transform" << endl;
Chris@350 811
Chris@350 812 RealTimePluginFactory *factory =
Chris@350 813 RealTimePluginFactory::instanceFor(pluginId);
Chris@439 814
Chris@439 815 if (factory) {
Chris@439 816 plugin = factory->instantiatePlugin(pluginId, 0, 0, rate, 1024, 1);
Chris@439 817 }
Chris@1139 818
Chris@1139 819 } else {
Chris@1139 820 cerr << "TransformFactory: ERROR: transform id \""
Chris@1139 821 << identifier << "\" is of unknown type" << endl;
Chris@350 822 }
Chris@350 823
Chris@350 824 return plugin;
Chris@350 825 }
Chris@350 826
Chris@350 827 Vamp::Plugin *
Chris@350 828 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin)
Chris@350 829 {
Chris@350 830 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin);
Chris@350 831 if (!vp) {
Chris@443 832 // cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << endl;
Chris@350 833 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why?
Chris@350 834 }
Chris@350 835 if (!vp) {
Chris@443 836 // cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << endl;
Chris@350 837 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
Chris@350 838 }
Chris@350 839 if (!vp) {
Chris@443 840 // cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << endl;
Chris@350 841 }
Chris@350 842 return vp;
Chris@350 843 }
Chris@350 844
Chris@330 845 bool
Chris@330 846 TransformFactory::haveTransform(TransformId identifier)
Chris@330 847 {
Chris@460 848 populateTransforms();
Chris@330 849 return (m_transforms.find(identifier) != m_transforms.end());
Chris@330 850 }
Chris@330 851
Chris@330 852 QString
Chris@330 853 TransformFactory::getTransformName(TransformId identifier)
Chris@330 854 {
Chris@330 855 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 856 return m_transforms[identifier].name;
Chris@330 857 } else return "";
Chris@330 858 }
Chris@330 859
Chris@330 860 QString
Chris@330 861 TransformFactory::getTransformFriendlyName(TransformId identifier)
Chris@330 862 {
Chris@330 863 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 864 return m_transforms[identifier].friendlyName;
Chris@330 865 } else return "";
Chris@330 866 }
Chris@330 867
Chris@330 868 QString
Chris@330 869 TransformFactory::getTransformUnits(TransformId identifier)
Chris@330 870 {
Chris@330 871 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 872 return m_transforms[identifier].units;
Chris@330 873 } else return "";
Chris@330 874 }
Chris@330 875
Chris@472 876 QString
Chris@472 877 TransformFactory::getTransformInfoUrl(TransformId identifier)
Chris@472 878 {
Chris@472 879 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@472 880 return m_transforms[identifier].infoUrl;
Chris@472 881 } else return "";
Chris@472 882 }
Chris@472 883
Chris@350 884 Vamp::Plugin::InputDomain
Chris@350 885 TransformFactory::getTransformInputDomain(TransformId identifier)
Chris@350 886 {
Chris@350 887 Transform transform;
Chris@350 888 transform.setIdentifier(identifier);
Chris@350 889
Chris@350 890 if (transform.getType() != Transform::FeatureExtraction) {
Chris@350 891 return Vamp::Plugin::TimeDomain;
Chris@350 892 }
Chris@350 893
Chris@350 894 Vamp::Plugin *plugin =
Chris@351 895 downcastVampPlugin(instantiateDefaultPluginFor(identifier, 0));
Chris@350 896
Chris@350 897 if (plugin) {
Chris@350 898 Vamp::Plugin::InputDomain d = plugin->getInputDomain();
Chris@350 899 delete plugin;
Chris@350 900 return d;
Chris@350 901 }
Chris@350 902
Chris@350 903 return Vamp::Plugin::TimeDomain;
Chris@350 904 }
Chris@350 905
Chris@330 906 bool
Chris@330 907 TransformFactory::isTransformConfigurable(TransformId identifier)
Chris@330 908 {
Chris@330 909 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 910 return m_transforms[identifier].configurable;
Chris@330 911 } else return false;
Chris@330 912 }
Chris@330 913
Chris@330 914 bool
Chris@330 915 TransformFactory::getTransformChannelRange(TransformId identifier,
Chris@330 916 int &min, int &max)
Chris@330 917 {
Chris@330 918 QString id = identifier.section(':', 0, 2);
Chris@330 919
Chris@330 920 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@330 921
Chris@330 922 Vamp::Plugin *plugin =
Chris@330 923 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@350 924 instantiatePlugin(id, 44100);
Chris@330 925 if (!plugin) return false;
Chris@330 926
Chris@1039 927 min = (int)plugin->getMinChannelCount();
Chris@1039 928 max = (int)plugin->getMaxChannelCount();
Chris@330 929 delete plugin;
Chris@330 930
Chris@330 931 return true;
Chris@330 932
Chris@330 933 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@330 934
Chris@350 935 // don't need to instantiate
Chris@350 936
Chris@330 937 const RealTimePluginDescriptor *descriptor =
Chris@330 938 RealTimePluginFactory::instanceFor(id)->
Chris@330 939 getPluginDescriptor(id);
Chris@330 940 if (!descriptor) return false;
Chris@330 941
Chris@330 942 min = descriptor->audioInputPortCount;
Chris@330 943 max = descriptor->audioInputPortCount;
Chris@330 944
Chris@330 945 return true;
Chris@330 946 }
Chris@330 947
Chris@330 948 return false;
Chris@330 949 }
Chris@332 950
Chris@332 951 void
Chris@332 952 TransformFactory::setParametersFromPlugin(Transform &transform,
Chris@332 953 Vamp::PluginBase *plugin)
Chris@332 954 {
Chris@332 955 Transform::ParameterMap pmap;
Chris@332 956
Chris@350 957 //!!! record plugin & API version
Chris@350 958
Chris@350 959 //!!! check that this is the right plugin!
Chris@350 960
Chris@332 961 Vamp::PluginBase::ParameterList parameters =
Chris@332 962 plugin->getParameterDescriptors();
Chris@332 963
Chris@332 964 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@332 965 i != parameters.end(); ++i) {
Chris@332 966 pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier);
Chris@810 967 // cerr << "TransformFactory::setParametersFromPlugin: parameter "
Chris@583 968 // << i->identifier << " -> value " <<
Chris@687 969 // pmap[i->identifier.c_str()] << endl;
Chris@332 970 }
Chris@332 971
Chris@332 972 transform.setParameters(pmap);
Chris@332 973
Chris@332 974 if (plugin->getPrograms().empty()) {
Chris@332 975 transform.setProgram("");
Chris@332 976 } else {
Chris@332 977 transform.setProgram(plugin->getCurrentProgram().c_str());
Chris@332 978 }
Chris@332 979
Chris@332 980 RealTimePluginInstance *rtpi =
Chris@332 981 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@332 982
Chris@332 983 Transform::ConfigurationMap cmap;
Chris@332 984
Chris@332 985 if (rtpi) {
Chris@332 986
Chris@332 987 RealTimePluginInstance::ConfigurationPairMap configurePairs =
Chris@332 988 rtpi->getConfigurePairs();
Chris@332 989
Chris@332 990 for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i
Chris@332 991 = configurePairs.begin(); i != configurePairs.end(); ++i) {
Chris@332 992 cmap[i->first.c_str()] = i->second.c_str();
Chris@332 993 }
Chris@332 994 }
Chris@332 995
Chris@332 996 transform.setConfiguration(cmap);
Chris@332 997 }
Chris@332 998
Chris@332 999 void
Chris@350 1000 TransformFactory::setPluginParameters(const Transform &transform,
Chris@350 1001 Vamp::PluginBase *plugin)
Chris@350 1002 {
Chris@350 1003 //!!! check plugin & API version (see e.g. PluginXml::setParameters)
Chris@350 1004
Chris@350 1005 //!!! check that this is the right plugin!
Chris@350 1006
Chris@350 1007 RealTimePluginInstance *rtpi =
Chris@350 1008 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@350 1009
Chris@350 1010 if (rtpi) {
Chris@350 1011 const Transform::ConfigurationMap &cmap = transform.getConfiguration();
Chris@350 1012 for (Transform::ConfigurationMap::const_iterator i = cmap.begin();
Chris@350 1013 i != cmap.end(); ++i) {
Chris@350 1014 rtpi->configure(i->first.toStdString(), i->second.toStdString());
Chris@350 1015 }
Chris@350 1016 }
Chris@350 1017
Chris@350 1018 if (transform.getProgram() != "") {
Chris@350 1019 plugin->selectProgram(transform.getProgram().toStdString());
Chris@350 1020 }
Chris@350 1021
Chris@350 1022 const Transform::ParameterMap &pmap = transform.getParameters();
Chris@350 1023
Chris@350 1024 Vamp::PluginBase::ParameterList parameters =
Chris@350 1025 plugin->getParameterDescriptors();
Chris@350 1026
Chris@350 1027 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@350 1028 i != parameters.end(); ++i) {
Chris@350 1029 QString key = i->identifier.c_str();
Chris@350 1030 Transform::ParameterMap::const_iterator pmi = pmap.find(key);
Chris@350 1031 if (pmi != pmap.end()) {
Chris@350 1032 plugin->setParameter(i->identifier, pmi->second);
Chris@350 1033 }
Chris@350 1034 }
Chris@350 1035 }
Chris@350 1036
Chris@350 1037 void
Chris@332 1038 TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
Chris@332 1039 Vamp::PluginBase *plugin)
Chris@332 1040 {
Chris@350 1041 const Vamp::Plugin *vp = downcastVampPlugin(plugin);
Chris@332 1042
Chris@332 1043 if (!vp) {
Chris@332 1044 // time domain input for real-time effects plugin
Chris@332 1045 if (!transform.getBlockSize()) {
Chris@332 1046 if (!transform.getStepSize()) transform.setStepSize(1024);
Chris@332 1047 transform.setBlockSize(transform.getStepSize());
Chris@332 1048 } else {
Chris@332 1049 transform.setStepSize(transform.getBlockSize());
Chris@332 1050 }
Chris@332 1051 } else {
Chris@332 1052 Vamp::Plugin::InputDomain domain = vp->getInputDomain();
Chris@332 1053 if (!transform.getStepSize()) {
Chris@1039 1054 transform.setStepSize((int)vp->getPreferredStepSize());
Chris@332 1055 }
Chris@332 1056 if (!transform.getBlockSize()) {
Chris@1039 1057 transform.setBlockSize((int)vp->getPreferredBlockSize());
Chris@332 1058 }
Chris@332 1059 if (!transform.getBlockSize()) {
Chris@332 1060 transform.setBlockSize(1024);
Chris@332 1061 }
Chris@332 1062 if (!transform.getStepSize()) {
Chris@332 1063 if (domain == Vamp::Plugin::FrequencyDomain) {
Chris@443 1064 // cerr << "frequency domain, step = " << blockSize/2 << endl;
Chris@332 1065 transform.setStepSize(transform.getBlockSize()/2);
Chris@332 1066 } else {
Chris@443 1067 // cerr << "time domain, step = " << blockSize/2 << endl;
Chris@332 1068 transform.setStepSize(transform.getBlockSize());
Chris@332 1069 }
Chris@332 1070 }
Chris@332 1071 }
Chris@332 1072 }
Chris@332 1073
Chris@350 1074 QString
Chris@350 1075 TransformFactory::getPluginConfigurationXml(const Transform &t)
Chris@332 1076 {
Chris@350 1077 QString xml;
Chris@350 1078
Chris@351 1079 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1080 (t.getIdentifier(), 0);
Chris@350 1081 if (!plugin) {
Chris@810 1082 cerr << "TransformFactory::getPluginConfigurationXml: "
Chris@350 1083 << "Unable to instantiate plugin for transform \""
Chris@686 1084 << t.getIdentifier() << "\"" << endl;
Chris@350 1085 return xml;
Chris@332 1086 }
Chris@332 1087
Chris@351 1088 setPluginParameters(t, plugin);
Chris@351 1089
Chris@350 1090 QTextStream out(&xml);
Chris@350 1091 PluginXml(plugin).toXml(out);
Chris@350 1092 delete plugin;
Chris@332 1093
Chris@350 1094 return xml;
Chris@350 1095 }
Chris@332 1096
Chris@350 1097 void
Chris@350 1098 TransformFactory::setParametersFromPluginConfigurationXml(Transform &t,
Chris@350 1099 QString xml)
Chris@350 1100 {
Chris@351 1101 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1102 (t.getIdentifier(), 0);
Chris@350 1103 if (!plugin) {
Chris@810 1104 cerr << "TransformFactory::setParametersFromPluginConfigurationXml: "
Chris@350 1105 << "Unable to instantiate plugin for transform \""
Chris@686 1106 << t.getIdentifier() << "\"" << endl;
Chris@350 1107 return;
Chris@332 1108 }
Chris@332 1109
Chris@350 1110 PluginXml(plugin).setParametersFromXml(xml);
Chris@350 1111 setParametersFromPlugin(t, plugin);
Chris@350 1112 delete plugin;
Chris@332 1113 }
Chris@332 1114
Chris@443 1115 TransformFactory::SearchResults
Chris@443 1116 TransformFactory::search(QString keyword)
Chris@443 1117 {
Chris@443 1118 QStringList keywords;
Chris@443 1119 keywords << keyword;
Chris@443 1120 return search(keywords);
Chris@443 1121 }
Chris@443 1122
Chris@443 1123 TransformFactory::SearchResults
Chris@443 1124 TransformFactory::search(QStringList keywords)
Chris@443 1125 {
Chris@460 1126 populateTransforms();
Chris@443 1127
Chris@447 1128 if (keywords.size() > 1) {
Chris@447 1129 // Additional score for all keywords in a row
Chris@447 1130 keywords.push_back(keywords.join(" "));
Chris@447 1131 }
Chris@447 1132
Chris@443 1133 SearchResults results;
Chris@457 1134 TextMatcher matcher;
Chris@443 1135
Chris@443 1136 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@443 1137 i != m_transforms.end(); ++i) {
Chris@443 1138
Chris@457 1139 TextMatcher::Match match;
Chris@443 1140
Chris@457 1141 match.key = i->first;
Chris@443 1142
Chris@487 1143 matcher.test(match, keywords,
Chris@487 1144 getTransformTypeName(i->second.type),
Chris@487 1145 tr("Plugin type"), 5);
Chris@487 1146
Chris@457 1147 matcher.test(match, keywords, i->second.category, tr("Category"), 20);
Chris@457 1148 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 6);
Chris@457 1149 matcher.test(match, keywords, i->second.name, tr("Name"), 30);
Chris@457 1150 matcher.test(match, keywords, i->second.description, tr("Description"), 20);
Chris@457 1151 matcher.test(match, keywords, i->second.maker, tr("Maker"), 10);
Chris@457 1152 matcher.test(match, keywords, i->second.units, tr("Units"), 10);
Chris@457 1153
Chris@457 1154 if (match.score > 0) results[i->first] = match;
Chris@457 1155 }
Chris@457 1156
Chris@460 1157 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@460 1158 // uninstalled transforms are being populated; this may take some time,
Chris@484 1159 // and they aren't critical, but we will speed them up if necessary
Chris@810 1160 cerr << "TransformFactory::search: Uninstalled transforms mutex is held, skipping" << endl;
Chris@484 1161 m_populatingSlowly = false;
Chris@460 1162 return results;
Chris@460 1163 }
Chris@460 1164
Chris@460 1165 if (!m_uninstalledTransformsPopulated) {
Chris@843 1166 cerr << "WARNING: TransformFactory::search: Uninstalled transforms are not populated yet" << endl
Chris@460 1167 << "and are not being populated either -- was the thread not started correctly?" << endl;
Chris@460 1168 m_uninstalledTransformsMutex.unlock();
Chris@460 1169 return results;
Chris@460 1170 }
Chris@460 1171
Chris@460 1172 m_uninstalledTransformsMutex.unlock();
Chris@457 1173
Chris@457 1174 for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin();
Chris@457 1175 i != m_uninstalledTransforms.end(); ++i) {
Chris@457 1176
Chris@457 1177 TextMatcher::Match match;
Chris@457 1178
Chris@457 1179 match.key = i->first;
Chris@457 1180
Chris@487 1181 matcher.test(match, keywords,
Chris@487 1182 getTransformTypeName(i->second.type),
Chris@487 1183 tr("Plugin type"), 2);
Chris@487 1184
Chris@457 1185 matcher.test(match, keywords, i->second.category, tr("Category"), 10);
Chris@457 1186 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 3);
Chris@457 1187 matcher.test(match, keywords, i->second.name, tr("Name"), 15);
Chris@457 1188 matcher.test(match, keywords, i->second.description, tr("Description"), 10);
Chris@457 1189 matcher.test(match, keywords, i->second.maker, tr("Maker"), 5);
Chris@457 1190 matcher.test(match, keywords, i->second.units, tr("Units"), 5);
Chris@443 1191
Chris@443 1192 if (match.score > 0) results[i->first] = match;
Chris@443 1193 }
Chris@443 1194
Chris@443 1195 return results;
Chris@443 1196 }
Chris@443 1197