annotate transform/TransformFactory.cpp @ 392:183ee2a55fc7

* More work to abstract out interactive components used in the data library, so that it does not need to depend on QtGui.
author Chris Cannam
date Fri, 14 Mar 2008 17:14:21 +0000
parents 370aa9714ef5
children beb2948baa77
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@332 23 #include "vamp-sdk/Plugin.h"
Chris@330 24 #include "vamp-sdk/PluginHostAdapter.h"
Chris@332 25 #include "vamp-sdk/hostext/PluginWrapper.h"
Chris@330 26
Chris@330 27 #include <iostream>
Chris@330 28 #include <set>
Chris@330 29
Chris@330 30 #include <QRegExp>
Chris@350 31 #include <QTextStream>
Chris@330 32
Chris@330 33 TransformFactory *
Chris@330 34 TransformFactory::m_instance = new TransformFactory;
Chris@330 35
Chris@330 36 TransformFactory *
Chris@330 37 TransformFactory::getInstance()
Chris@330 38 {
Chris@330 39 return m_instance;
Chris@330 40 }
Chris@330 41
Chris@330 42 TransformFactory::~TransformFactory()
Chris@330 43 {
Chris@330 44 }
Chris@330 45
Chris@330 46 TransformList
Chris@350 47 TransformFactory::getAllTransformDescriptions()
Chris@330 48 {
Chris@330 49 if (m_transforms.empty()) populateTransforms();
Chris@330 50
Chris@330 51 std::set<TransformDescription> dset;
Chris@330 52 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 53 i != m_transforms.end(); ++i) {
Chris@358 54 // std::cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << std::endl;
Chris@330 55 dset.insert(i->second);
Chris@330 56 }
Chris@330 57
Chris@330 58 TransformList list;
Chris@330 59 for (std::set<TransformDescription>::const_iterator i = dset.begin();
Chris@330 60 i != dset.end(); ++i) {
Chris@358 61 // std::cerr << "inserting transform into list: id = " << i->identifier.toStdString() << std::endl;
Chris@330 62 list.push_back(*i);
Chris@330 63 }
Chris@330 64
Chris@330 65 return list;
Chris@330 66 }
Chris@330 67
Chris@350 68 TransformDescription
Chris@350 69 TransformFactory::getTransformDescription(TransformId id)
Chris@350 70 {
Chris@350 71 if (m_transforms.empty()) populateTransforms();
Chris@350 72
Chris@350 73 if (m_transforms.find(id) == m_transforms.end()) {
Chris@350 74 return TransformDescription();
Chris@350 75 }
Chris@350 76
Chris@350 77 return m_transforms[id];
Chris@350 78 }
Chris@350 79
Chris@330 80 std::vector<QString>
Chris@330 81 TransformFactory::getAllTransformTypes()
Chris@330 82 {
Chris@330 83 if (m_transforms.empty()) populateTransforms();
Chris@330 84
Chris@330 85 std::set<QString> types;
Chris@330 86 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 87 i != m_transforms.end(); ++i) {
Chris@330 88 types.insert(i->second.type);
Chris@330 89 }
Chris@330 90
Chris@330 91 std::vector<QString> rv;
Chris@330 92 for (std::set<QString>::iterator i = types.begin(); i != types.end(); ++i) {
Chris@330 93 rv.push_back(*i);
Chris@330 94 }
Chris@330 95
Chris@330 96 return rv;
Chris@330 97 }
Chris@330 98
Chris@330 99 std::vector<QString>
Chris@330 100 TransformFactory::getTransformCategories(QString transformType)
Chris@330 101 {
Chris@330 102 if (m_transforms.empty()) populateTransforms();
Chris@330 103
Chris@330 104 std::set<QString> categories;
Chris@330 105 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 106 i != m_transforms.end(); ++i) {
Chris@330 107 if (i->second.type == transformType) {
Chris@330 108 categories.insert(i->second.category);
Chris@330 109 }
Chris@330 110 }
Chris@330 111
Chris@330 112 bool haveEmpty = false;
Chris@330 113
Chris@330 114 std::vector<QString> rv;
Chris@330 115 for (std::set<QString>::iterator i = categories.begin();
Chris@330 116 i != categories.end(); ++i) {
Chris@330 117 if (*i != "") rv.push_back(*i);
Chris@330 118 else haveEmpty = true;
Chris@330 119 }
Chris@330 120
Chris@330 121 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330 122
Chris@330 123 return rv;
Chris@330 124 }
Chris@330 125
Chris@330 126 std::vector<QString>
Chris@330 127 TransformFactory::getTransformMakers(QString transformType)
Chris@330 128 {
Chris@330 129 if (m_transforms.empty()) populateTransforms();
Chris@330 130
Chris@330 131 std::set<QString> makers;
Chris@330 132 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 133 i != m_transforms.end(); ++i) {
Chris@330 134 if (i->second.type == transformType) {
Chris@330 135 makers.insert(i->second.maker);
Chris@330 136 }
Chris@330 137 }
Chris@330 138
Chris@330 139 bool haveEmpty = false;
Chris@330 140
Chris@330 141 std::vector<QString> rv;
Chris@330 142 for (std::set<QString>::iterator i = makers.begin();
Chris@330 143 i != makers.end(); ++i) {
Chris@330 144 if (*i != "") rv.push_back(*i);
Chris@330 145 else haveEmpty = true;
Chris@330 146 }
Chris@330 147
Chris@330 148 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330 149
Chris@330 150 return rv;
Chris@330 151 }
Chris@330 152
Chris@330 153 void
Chris@330 154 TransformFactory::populateTransforms()
Chris@330 155 {
Chris@330 156 TransformDescriptionMap transforms;
Chris@330 157
Chris@330 158 populateFeatureExtractionPlugins(transforms);
Chris@330 159 populateRealTimePlugins(transforms);
Chris@330 160
Chris@330 161 // disambiguate plugins with similar names
Chris@330 162
Chris@330 163 std::map<QString, int> names;
Chris@330 164 std::map<QString, QString> pluginSources;
Chris@330 165 std::map<QString, QString> pluginMakers;
Chris@330 166
Chris@330 167 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 168 i != transforms.end(); ++i) {
Chris@330 169
Chris@330 170 TransformDescription desc = i->second;
Chris@330 171
Chris@330 172 QString td = desc.name;
Chris@330 173 QString tn = td.section(": ", 0, 0);
Chris@330 174 QString pn = desc.identifier.section(":", 1, 1);
Chris@330 175
Chris@330 176 if (pluginSources.find(tn) != pluginSources.end()) {
Chris@330 177 if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) {
Chris@330 178 ++names[tn];
Chris@330 179 }
Chris@330 180 } else {
Chris@330 181 ++names[tn];
Chris@330 182 pluginSources[tn] = pn;
Chris@330 183 pluginMakers[tn] = desc.maker;
Chris@330 184 }
Chris@330 185 }
Chris@330 186
Chris@330 187 std::map<QString, int> counts;
Chris@330 188 m_transforms.clear();
Chris@330 189
Chris@330 190 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 191 i != transforms.end(); ++i) {
Chris@330 192
Chris@330 193 TransformDescription desc = i->second;
Chris@330 194 QString identifier = desc.identifier;
Chris@330 195 QString maker = desc.maker;
Chris@330 196
Chris@330 197 QString td = desc.name;
Chris@330 198 QString tn = td.section(": ", 0, 0);
Chris@330 199 QString to = td.section(": ", 1);
Chris@330 200
Chris@330 201 if (names[tn] > 1) {
Chris@330 202 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
Chris@330 203 tn = QString("%1 [%2]").arg(tn).arg(maker);
Chris@330 204 }
Chris@330 205
Chris@330 206 if (to != "") {
Chris@330 207 desc.name = QString("%1: %2").arg(tn).arg(to);
Chris@330 208 } else {
Chris@330 209 desc.name = tn;
Chris@330 210 }
Chris@330 211
Chris@330 212 m_transforms[identifier] = desc;
Chris@330 213 }
Chris@330 214 }
Chris@330 215
Chris@330 216 void
Chris@330 217 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
Chris@330 218 {
Chris@330 219 std::vector<QString> plugs =
Chris@330 220 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
Chris@330 221
Chris@330 222 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@330 223
Chris@330 224 QString pluginId = plugs[i];
Chris@330 225
Chris@330 226 FeatureExtractionPluginFactory *factory =
Chris@330 227 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@330 228
Chris@330 229 if (!factory) {
Chris@330 230 std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@330 231 continue;
Chris@330 232 }
Chris@330 233
Chris@330 234 Vamp::Plugin *plugin =
Chris@350 235 factory->instantiatePlugin(pluginId, 44100);
Chris@330 236
Chris@330 237 if (!plugin) {
Chris@330 238 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@330 239 continue;
Chris@330 240 }
Chris@330 241
Chris@330 242 QString pluginName = plugin->getName().c_str();
Chris@330 243 QString category = factory->getPluginCategory(pluginId);
Chris@330 244
Chris@330 245 Vamp::Plugin::OutputList outputs =
Chris@330 246 plugin->getOutputDescriptors();
Chris@330 247
Chris@330 248 for (size_t j = 0; j < outputs.size(); ++j) {
Chris@330 249
Chris@330 250 QString transformId = QString("%1:%2")
Chris@330 251 .arg(pluginId).arg(outputs[j].identifier.c_str());
Chris@330 252
Chris@330 253 QString userName;
Chris@330 254 QString friendlyName;
Chris@330 255 QString units = outputs[j].unit.c_str();
Chris@330 256 QString description = plugin->getDescription().c_str();
Chris@330 257 QString maker = plugin->getMaker().c_str();
Chris@330 258 if (maker == "") maker = tr("<unknown maker>");
Chris@330 259
Chris@330 260 if (description == "") {
Chris@330 261 if (outputs.size() == 1) {
Chris@330 262 description = tr("Extract features using \"%1\" plugin (from %2)")
Chris@330 263 .arg(pluginName).arg(maker);
Chris@330 264 } else {
Chris@330 265 description = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
Chris@330 266 .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330 267 }
Chris@330 268 } else {
Chris@330 269 if (outputs.size() == 1) {
Chris@330 270 description = tr("%1 using \"%2\" plugin (from %3)")
Chris@330 271 .arg(description).arg(pluginName).arg(maker);
Chris@330 272 } else {
Chris@330 273 description = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
Chris@330 274 .arg(description).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330 275 }
Chris@330 276 }
Chris@330 277
Chris@330 278 if (outputs.size() == 1) {
Chris@330 279 userName = pluginName;
Chris@330 280 friendlyName = pluginName;
Chris@330 281 } else {
Chris@330 282 userName = QString("%1: %2")
Chris@330 283 .arg(pluginName)
Chris@330 284 .arg(outputs[j].name.c_str());
Chris@330 285 friendlyName = outputs[j].name.c_str();
Chris@330 286 }
Chris@330 287
Chris@330 288 bool configurable = (!plugin->getPrograms().empty() ||
Chris@330 289 !plugin->getParameterDescriptors().empty());
Chris@330 290
Chris@358 291 // std::cerr << "Feature extraction plugin transform: " << transformId.toStdString() << " friendly name: " << friendlyName.toStdString() << std::endl;
Chris@330 292
Chris@330 293 transforms[transformId] =
Chris@330 294 TransformDescription(tr("Analysis"),
Chris@332 295 category,
Chris@332 296 transformId,
Chris@332 297 userName,
Chris@332 298 friendlyName,
Chris@332 299 description,
Chris@332 300 maker,
Chris@332 301 units,
Chris@332 302 configurable);
Chris@330 303 }
Chris@330 304
Chris@330 305 delete plugin;
Chris@330 306 }
Chris@330 307 }
Chris@330 308
Chris@330 309 void
Chris@330 310 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@330 311 {
Chris@330 312 std::vector<QString> plugs =
Chris@330 313 RealTimePluginFactory::getAllPluginIdentifiers();
Chris@330 314
Chris@330 315 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@330 316
Chris@330 317 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@330 318
Chris@330 319 QString pluginId = plugs[i];
Chris@330 320
Chris@330 321 RealTimePluginFactory *factory =
Chris@330 322 RealTimePluginFactory::instanceFor(pluginId);
Chris@330 323
Chris@330 324 if (!factory) {
Chris@330 325 std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@330 326 continue;
Chris@330 327 }
Chris@330 328
Chris@330 329 const RealTimePluginDescriptor *descriptor =
Chris@330 330 factory->getPluginDescriptor(pluginId);
Chris@330 331
Chris@330 332 if (!descriptor) {
Chris@330 333 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@330 334 continue;
Chris@330 335 }
Chris@330 336
Chris@330 337 //!!! if (descriptor->controlOutputPortCount == 0 ||
Chris@330 338 // descriptor->audioInputPortCount == 0) continue;
Chris@330 339
Chris@330 340 // std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << std::endl;
Chris@330 341
Chris@330 342 QString pluginName = descriptor->name.c_str();
Chris@330 343 QString category = factory->getPluginCategory(pluginId);
Chris@330 344 bool configurable = (descriptor->parameterCount > 0);
Chris@330 345 QString maker = descriptor->maker.c_str();
Chris@330 346 if (maker == "") maker = tr("<unknown maker>");
Chris@330 347
Chris@330 348 if (descriptor->audioInputPortCount > 0) {
Chris@330 349
Chris@330 350 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
Chris@330 351
Chris@330 352 QString transformId = QString("%1:%2").arg(pluginId).arg(j);
Chris@330 353 QString userName;
Chris@330 354 QString units;
Chris@330 355 QString portName;
Chris@330 356
Chris@330 357 if (j < descriptor->controlOutputPortNames.size() &&
Chris@330 358 descriptor->controlOutputPortNames[j] != "") {
Chris@330 359
Chris@330 360 portName = descriptor->controlOutputPortNames[j].c_str();
Chris@330 361
Chris@330 362 userName = tr("%1: %2")
Chris@330 363 .arg(pluginName)
Chris@330 364 .arg(portName);
Chris@330 365
Chris@330 366 if (unitRE.indexIn(portName) >= 0) {
Chris@330 367 units = unitRE.cap(1);
Chris@330 368 }
Chris@330 369
Chris@330 370 } else if (descriptor->controlOutputPortCount > 1) {
Chris@330 371
Chris@330 372 userName = tr("%1: Output %2")
Chris@330 373 .arg(pluginName)
Chris@330 374 .arg(j + 1);
Chris@330 375
Chris@330 376 } else {
Chris@330 377
Chris@330 378 userName = pluginName;
Chris@330 379 }
Chris@330 380
Chris@330 381 QString description;
Chris@330 382
Chris@330 383 if (portName != "") {
Chris@330 384 description = tr("Extract \"%1\" data output from \"%2\" effect plugin (from %3)")
Chris@330 385 .arg(portName)
Chris@330 386 .arg(pluginName)
Chris@330 387 .arg(maker);
Chris@330 388 } else {
Chris@330 389 description = tr("Extract data output %1 from \"%2\" effect plugin (from %3)")
Chris@330 390 .arg(j + 1)
Chris@330 391 .arg(pluginName)
Chris@330 392 .arg(maker);
Chris@330 393 }
Chris@330 394
Chris@330 395 transforms[transformId] =
Chris@330 396 TransformDescription(tr("Effects Data"),
Chris@332 397 category,
Chris@332 398 transformId,
Chris@332 399 userName,
Chris@332 400 userName,
Chris@332 401 description,
Chris@332 402 maker,
Chris@332 403 units,
Chris@332 404 configurable);
Chris@330 405 }
Chris@330 406 }
Chris@330 407
Chris@330 408 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@330 409
Chris@330 410 if (descriptor->audioOutputPortCount > 0) {
Chris@330 411
Chris@330 412 QString transformId = QString("%1:A").arg(pluginId);
Chris@330 413 QString type = tr("Effects");
Chris@330 414
Chris@330 415 QString description = tr("Transform audio signal with \"%1\" effect plugin (from %2)")
Chris@330 416 .arg(pluginName)
Chris@330 417 .arg(maker);
Chris@330 418
Chris@330 419 if (descriptor->audioInputPortCount == 0) {
Chris@330 420 type = tr("Generators");
Chris@330 421 QString description = tr("Generate audio signal using \"%1\" plugin (from %2)")
Chris@330 422 .arg(pluginName)
Chris@330 423 .arg(maker);
Chris@330 424 }
Chris@330 425
Chris@330 426 transforms[transformId] =
Chris@330 427 TransformDescription(type,
Chris@332 428 category,
Chris@332 429 transformId,
Chris@332 430 pluginName,
Chris@332 431 pluginName,
Chris@332 432 description,
Chris@332 433 maker,
Chris@332 434 "",
Chris@332 435 configurable);
Chris@330 436 }
Chris@330 437 }
Chris@330 438 }
Chris@330 439 }
Chris@330 440
Chris@350 441
Chris@350 442 Transform
Chris@350 443 TransformFactory::getDefaultTransformFor(TransformId id, size_t rate)
Chris@350 444 {
Chris@350 445 Transform t;
Chris@350 446 t.setIdentifier(id);
Chris@350 447 if (rate != 0) t.setSampleRate(rate);
Chris@350 448
Chris@351 449 Vamp::PluginBase *plugin = instantiateDefaultPluginFor(id, rate);
Chris@350 450
Chris@350 451 if (plugin) {
Chris@366 452 t.setPluginVersion(QString("%1").arg(plugin->getPluginVersion()));
Chris@350 453 setParametersFromPlugin(t, plugin);
Chris@350 454 makeContextConsistentWithPlugin(t, plugin);
Chris@350 455 delete plugin;
Chris@350 456 }
Chris@350 457
Chris@350 458 return t;
Chris@350 459 }
Chris@350 460
Chris@350 461 Vamp::PluginBase *
Chris@351 462 TransformFactory::instantiatePluginFor(const Transform &transform)
Chris@351 463 {
Chris@351 464 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 465 (transform.getIdentifier(), transform.getSampleRate());
Chris@351 466 if (plugin) {
Chris@351 467 setPluginParameters(transform, plugin);
Chris@351 468 }
Chris@351 469 return plugin;
Chris@351 470 }
Chris@351 471
Chris@351 472 Vamp::PluginBase *
Chris@351 473 TransformFactory::instantiateDefaultPluginFor(TransformId identifier, size_t rate)
Chris@350 474 {
Chris@350 475 Transform t;
Chris@350 476 t.setIdentifier(identifier);
Chris@350 477 if (rate == 0) rate = 44100;
Chris@350 478 QString pluginId = t.getPluginIdentifier();
Chris@350 479
Chris@350 480 Vamp::PluginBase *plugin = 0;
Chris@350 481
Chris@350 482 if (t.getType() == Transform::FeatureExtraction) {
Chris@350 483
Chris@350 484 FeatureExtractionPluginFactory *factory =
Chris@350 485 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@350 486
Chris@350 487 plugin = factory->instantiatePlugin(pluginId, rate);
Chris@350 488
Chris@350 489 } else {
Chris@350 490
Chris@350 491 RealTimePluginFactory *factory =
Chris@350 492 RealTimePluginFactory::instanceFor(pluginId);
Chris@350 493
Chris@350 494 plugin = factory->instantiatePlugin(pluginId, 0, 0, rate, 1024, 1);
Chris@350 495 }
Chris@350 496
Chris@350 497 return plugin;
Chris@350 498 }
Chris@350 499
Chris@350 500 Vamp::Plugin *
Chris@350 501 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin)
Chris@350 502 {
Chris@350 503 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin);
Chris@350 504 if (!vp) {
Chris@350 505 // std::cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << std::endl;
Chris@350 506 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why?
Chris@350 507 }
Chris@350 508 if (!vp) {
Chris@350 509 // std::cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << std::endl;
Chris@350 510 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
Chris@350 511 }
Chris@350 512 if (!vp) {
Chris@350 513 // std::cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << std::endl;
Chris@350 514 }
Chris@350 515 return vp;
Chris@350 516 }
Chris@350 517
Chris@330 518 bool
Chris@330 519 TransformFactory::haveTransform(TransformId identifier)
Chris@330 520 {
Chris@333 521 if (m_transforms.empty()) populateTransforms();
Chris@330 522 return (m_transforms.find(identifier) != m_transforms.end());
Chris@330 523 }
Chris@330 524
Chris@330 525 QString
Chris@330 526 TransformFactory::getTransformName(TransformId identifier)
Chris@330 527 {
Chris@330 528 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 529 return m_transforms[identifier].name;
Chris@330 530 } else return "";
Chris@330 531 }
Chris@330 532
Chris@330 533 QString
Chris@330 534 TransformFactory::getTransformFriendlyName(TransformId identifier)
Chris@330 535 {
Chris@330 536 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 537 return m_transforms[identifier].friendlyName;
Chris@330 538 } else return "";
Chris@330 539 }
Chris@330 540
Chris@330 541 QString
Chris@330 542 TransformFactory::getTransformUnits(TransformId identifier)
Chris@330 543 {
Chris@330 544 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 545 return m_transforms[identifier].units;
Chris@330 546 } else return "";
Chris@330 547 }
Chris@330 548
Chris@350 549 Vamp::Plugin::InputDomain
Chris@350 550 TransformFactory::getTransformInputDomain(TransformId identifier)
Chris@350 551 {
Chris@350 552 Transform transform;
Chris@350 553 transform.setIdentifier(identifier);
Chris@350 554
Chris@350 555 if (transform.getType() != Transform::FeatureExtraction) {
Chris@350 556 return Vamp::Plugin::TimeDomain;
Chris@350 557 }
Chris@350 558
Chris@350 559 Vamp::Plugin *plugin =
Chris@351 560 downcastVampPlugin(instantiateDefaultPluginFor(identifier, 0));
Chris@350 561
Chris@350 562 if (plugin) {
Chris@350 563 Vamp::Plugin::InputDomain d = plugin->getInputDomain();
Chris@350 564 delete plugin;
Chris@350 565 return d;
Chris@350 566 }
Chris@350 567
Chris@350 568 return Vamp::Plugin::TimeDomain;
Chris@350 569 }
Chris@350 570
Chris@330 571 bool
Chris@330 572 TransformFactory::isTransformConfigurable(TransformId identifier)
Chris@330 573 {
Chris@330 574 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 575 return m_transforms[identifier].configurable;
Chris@330 576 } else return false;
Chris@330 577 }
Chris@330 578
Chris@330 579 bool
Chris@330 580 TransformFactory::getTransformChannelRange(TransformId identifier,
Chris@330 581 int &min, int &max)
Chris@330 582 {
Chris@330 583 QString id = identifier.section(':', 0, 2);
Chris@330 584
Chris@330 585 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@330 586
Chris@330 587 Vamp::Plugin *plugin =
Chris@330 588 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@350 589 instantiatePlugin(id, 44100);
Chris@330 590 if (!plugin) return false;
Chris@330 591
Chris@330 592 min = plugin->getMinChannelCount();
Chris@330 593 max = plugin->getMaxChannelCount();
Chris@330 594 delete plugin;
Chris@330 595
Chris@330 596 return true;
Chris@330 597
Chris@330 598 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@330 599
Chris@350 600 // don't need to instantiate
Chris@350 601
Chris@330 602 const RealTimePluginDescriptor *descriptor =
Chris@330 603 RealTimePluginFactory::instanceFor(id)->
Chris@330 604 getPluginDescriptor(id);
Chris@330 605 if (!descriptor) return false;
Chris@330 606
Chris@330 607 min = descriptor->audioInputPortCount;
Chris@330 608 max = descriptor->audioInputPortCount;
Chris@330 609
Chris@330 610 return true;
Chris@330 611 }
Chris@330 612
Chris@330 613 return false;
Chris@330 614 }
Chris@332 615
Chris@332 616 void
Chris@332 617 TransformFactory::setParametersFromPlugin(Transform &transform,
Chris@332 618 Vamp::PluginBase *plugin)
Chris@332 619 {
Chris@332 620 Transform::ParameterMap pmap;
Chris@332 621
Chris@350 622 //!!! record plugin & API version
Chris@350 623
Chris@350 624 //!!! check that this is the right plugin!
Chris@350 625
Chris@332 626 Vamp::PluginBase::ParameterList parameters =
Chris@332 627 plugin->getParameterDescriptors();
Chris@332 628
Chris@332 629 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@332 630 i != parameters.end(); ++i) {
Chris@332 631 pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier);
Chris@332 632 }
Chris@332 633
Chris@332 634 transform.setParameters(pmap);
Chris@332 635
Chris@332 636 if (plugin->getPrograms().empty()) {
Chris@332 637 transform.setProgram("");
Chris@332 638 } else {
Chris@332 639 transform.setProgram(plugin->getCurrentProgram().c_str());
Chris@332 640 }
Chris@332 641
Chris@332 642 RealTimePluginInstance *rtpi =
Chris@332 643 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@332 644
Chris@332 645 Transform::ConfigurationMap cmap;
Chris@332 646
Chris@332 647 if (rtpi) {
Chris@332 648
Chris@332 649 RealTimePluginInstance::ConfigurationPairMap configurePairs =
Chris@332 650 rtpi->getConfigurePairs();
Chris@332 651
Chris@332 652 for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i
Chris@332 653 = configurePairs.begin(); i != configurePairs.end(); ++i) {
Chris@332 654 cmap[i->first.c_str()] = i->second.c_str();
Chris@332 655 }
Chris@332 656 }
Chris@332 657
Chris@332 658 transform.setConfiguration(cmap);
Chris@332 659 }
Chris@332 660
Chris@332 661 void
Chris@350 662 TransformFactory::setPluginParameters(const Transform &transform,
Chris@350 663 Vamp::PluginBase *plugin)
Chris@350 664 {
Chris@350 665 //!!! check plugin & API version (see e.g. PluginXml::setParameters)
Chris@350 666
Chris@350 667 //!!! check that this is the right plugin!
Chris@350 668
Chris@350 669 RealTimePluginInstance *rtpi =
Chris@350 670 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@350 671
Chris@350 672 if (rtpi) {
Chris@350 673 const Transform::ConfigurationMap &cmap = transform.getConfiguration();
Chris@350 674 for (Transform::ConfigurationMap::const_iterator i = cmap.begin();
Chris@350 675 i != cmap.end(); ++i) {
Chris@350 676 rtpi->configure(i->first.toStdString(), i->second.toStdString());
Chris@350 677 }
Chris@350 678 }
Chris@350 679
Chris@350 680 if (transform.getProgram() != "") {
Chris@350 681 plugin->selectProgram(transform.getProgram().toStdString());
Chris@350 682 }
Chris@350 683
Chris@350 684 const Transform::ParameterMap &pmap = transform.getParameters();
Chris@350 685
Chris@350 686 Vamp::PluginBase::ParameterList parameters =
Chris@350 687 plugin->getParameterDescriptors();
Chris@350 688
Chris@350 689 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@350 690 i != parameters.end(); ++i) {
Chris@350 691 QString key = i->identifier.c_str();
Chris@350 692 Transform::ParameterMap::const_iterator pmi = pmap.find(key);
Chris@350 693 if (pmi != pmap.end()) {
Chris@350 694 plugin->setParameter(i->identifier, pmi->second);
Chris@350 695 }
Chris@350 696 }
Chris@350 697 }
Chris@350 698
Chris@350 699 void
Chris@332 700 TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
Chris@332 701 Vamp::PluginBase *plugin)
Chris@332 702 {
Chris@350 703 const Vamp::Plugin *vp = downcastVampPlugin(plugin);
Chris@332 704
Chris@332 705 if (!vp) {
Chris@332 706 // time domain input for real-time effects plugin
Chris@332 707 if (!transform.getBlockSize()) {
Chris@332 708 if (!transform.getStepSize()) transform.setStepSize(1024);
Chris@332 709 transform.setBlockSize(transform.getStepSize());
Chris@332 710 } else {
Chris@332 711 transform.setStepSize(transform.getBlockSize());
Chris@332 712 }
Chris@332 713 } else {
Chris@332 714 Vamp::Plugin::InputDomain domain = vp->getInputDomain();
Chris@332 715 if (!transform.getStepSize()) {
Chris@332 716 transform.setStepSize(vp->getPreferredStepSize());
Chris@332 717 }
Chris@332 718 if (!transform.getBlockSize()) {
Chris@332 719 transform.setBlockSize(vp->getPreferredBlockSize());
Chris@332 720 }
Chris@332 721 if (!transform.getBlockSize()) {
Chris@332 722 transform.setBlockSize(1024);
Chris@332 723 }
Chris@332 724 if (!transform.getStepSize()) {
Chris@332 725 if (domain == Vamp::Plugin::FrequencyDomain) {
Chris@332 726 // std::cerr << "frequency domain, step = " << blockSize/2 << std::endl;
Chris@332 727 transform.setStepSize(transform.getBlockSize()/2);
Chris@332 728 } else {
Chris@332 729 // std::cerr << "time domain, step = " << blockSize/2 << std::endl;
Chris@332 730 transform.setStepSize(transform.getBlockSize());
Chris@332 731 }
Chris@332 732 }
Chris@332 733 }
Chris@332 734 }
Chris@332 735
Chris@350 736 QString
Chris@350 737 TransformFactory::getPluginConfigurationXml(const Transform &t)
Chris@332 738 {
Chris@350 739 QString xml;
Chris@350 740
Chris@351 741 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 742 (t.getIdentifier(), 0);
Chris@350 743 if (!plugin) {
Chris@350 744 std::cerr << "TransformFactory::getPluginConfigurationXml: "
Chris@350 745 << "Unable to instantiate plugin for transform \""
Chris@350 746 << t.getIdentifier().toStdString() << "\"" << std::endl;
Chris@350 747 return xml;
Chris@332 748 }
Chris@332 749
Chris@351 750 setPluginParameters(t, plugin);
Chris@351 751
Chris@350 752 QTextStream out(&xml);
Chris@350 753 PluginXml(plugin).toXml(out);
Chris@350 754 delete plugin;
Chris@332 755
Chris@350 756 return xml;
Chris@350 757 }
Chris@332 758
Chris@350 759 void
Chris@350 760 TransformFactory::setParametersFromPluginConfigurationXml(Transform &t,
Chris@350 761 QString xml)
Chris@350 762 {
Chris@351 763 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 764 (t.getIdentifier(), 0);
Chris@350 765 if (!plugin) {
Chris@350 766 std::cerr << "TransformFactory::setParametersFromPluginConfigurationXml: "
Chris@350 767 << "Unable to instantiate plugin for transform \""
Chris@350 768 << t.getIdentifier().toStdString() << "\"" << std::endl;
Chris@350 769 return;
Chris@332 770 }
Chris@332 771
Chris@350 772 PluginXml(plugin).setParametersFromXml(xml);
Chris@350 773 setParametersFromPlugin(t, plugin);
Chris@350 774 delete plugin;
Chris@332 775 }
Chris@332 776