annotate plugin/transform/TransformFactory.cpp @ 364:876a79afd376

* Also use multi-channel read when supplying data to real-time effects plugin
author Chris Cannam
date Thu, 24 Jan 2008 14:40:48 +0000
parents 9203b82a8c53
children 4bb19132da23
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@350 452 setParametersFromPlugin(t, plugin);
Chris@350 453 makeContextConsistentWithPlugin(t, plugin);
Chris@350 454 delete plugin;
Chris@350 455 }
Chris@350 456
Chris@350 457 return t;
Chris@350 458 }
Chris@350 459
Chris@350 460 Vamp::PluginBase *
Chris@351 461 TransformFactory::instantiatePluginFor(const Transform &transform)
Chris@351 462 {
Chris@351 463 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 464 (transform.getIdentifier(), transform.getSampleRate());
Chris@351 465 if (plugin) {
Chris@351 466 setPluginParameters(transform, plugin);
Chris@351 467 }
Chris@351 468 return plugin;
Chris@351 469 }
Chris@351 470
Chris@351 471 Vamp::PluginBase *
Chris@351 472 TransformFactory::instantiateDefaultPluginFor(TransformId identifier, size_t rate)
Chris@350 473 {
Chris@350 474 Transform t;
Chris@350 475 t.setIdentifier(identifier);
Chris@350 476 if (rate == 0) rate = 44100;
Chris@350 477 QString pluginId = t.getPluginIdentifier();
Chris@350 478
Chris@350 479 Vamp::PluginBase *plugin = 0;
Chris@350 480
Chris@350 481 if (t.getType() == Transform::FeatureExtraction) {
Chris@350 482
Chris@350 483 FeatureExtractionPluginFactory *factory =
Chris@350 484 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@350 485
Chris@350 486 plugin = factory->instantiatePlugin(pluginId, rate);
Chris@350 487
Chris@350 488 } else {
Chris@350 489
Chris@350 490 RealTimePluginFactory *factory =
Chris@350 491 RealTimePluginFactory::instanceFor(pluginId);
Chris@350 492
Chris@350 493 plugin = factory->instantiatePlugin(pluginId, 0, 0, rate, 1024, 1);
Chris@350 494 }
Chris@350 495
Chris@350 496 return plugin;
Chris@350 497 }
Chris@350 498
Chris@350 499 Vamp::Plugin *
Chris@350 500 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin)
Chris@350 501 {
Chris@350 502 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin);
Chris@350 503 if (!vp) {
Chris@350 504 // std::cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << std::endl;
Chris@350 505 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why?
Chris@350 506 }
Chris@350 507 if (!vp) {
Chris@350 508 // std::cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << std::endl;
Chris@350 509 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
Chris@350 510 }
Chris@350 511 if (!vp) {
Chris@350 512 // std::cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << std::endl;
Chris@350 513 }
Chris@350 514 return vp;
Chris@350 515 }
Chris@350 516
Chris@330 517 bool
Chris@330 518 TransformFactory::haveTransform(TransformId identifier)
Chris@330 519 {
Chris@333 520 if (m_transforms.empty()) populateTransforms();
Chris@330 521 return (m_transforms.find(identifier) != m_transforms.end());
Chris@330 522 }
Chris@330 523
Chris@330 524 QString
Chris@330 525 TransformFactory::getTransformName(TransformId identifier)
Chris@330 526 {
Chris@330 527 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 528 return m_transforms[identifier].name;
Chris@330 529 } else return "";
Chris@330 530 }
Chris@330 531
Chris@330 532 QString
Chris@330 533 TransformFactory::getTransformFriendlyName(TransformId identifier)
Chris@330 534 {
Chris@330 535 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 536 return m_transforms[identifier].friendlyName;
Chris@330 537 } else return "";
Chris@330 538 }
Chris@330 539
Chris@330 540 QString
Chris@330 541 TransformFactory::getTransformUnits(TransformId identifier)
Chris@330 542 {
Chris@330 543 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 544 return m_transforms[identifier].units;
Chris@330 545 } else return "";
Chris@330 546 }
Chris@330 547
Chris@350 548 Vamp::Plugin::InputDomain
Chris@350 549 TransformFactory::getTransformInputDomain(TransformId identifier)
Chris@350 550 {
Chris@350 551 Transform transform;
Chris@350 552 transform.setIdentifier(identifier);
Chris@350 553
Chris@350 554 if (transform.getType() != Transform::FeatureExtraction) {
Chris@350 555 return Vamp::Plugin::TimeDomain;
Chris@350 556 }
Chris@350 557
Chris@350 558 Vamp::Plugin *plugin =
Chris@351 559 downcastVampPlugin(instantiateDefaultPluginFor(identifier, 0));
Chris@350 560
Chris@350 561 if (plugin) {
Chris@350 562 Vamp::Plugin::InputDomain d = plugin->getInputDomain();
Chris@350 563 delete plugin;
Chris@350 564 return d;
Chris@350 565 }
Chris@350 566
Chris@350 567 return Vamp::Plugin::TimeDomain;
Chris@350 568 }
Chris@350 569
Chris@330 570 bool
Chris@330 571 TransformFactory::isTransformConfigurable(TransformId identifier)
Chris@330 572 {
Chris@330 573 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 574 return m_transforms[identifier].configurable;
Chris@330 575 } else return false;
Chris@330 576 }
Chris@330 577
Chris@330 578 bool
Chris@330 579 TransformFactory::getTransformChannelRange(TransformId identifier,
Chris@330 580 int &min, int &max)
Chris@330 581 {
Chris@330 582 QString id = identifier.section(':', 0, 2);
Chris@330 583
Chris@330 584 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@330 585
Chris@330 586 Vamp::Plugin *plugin =
Chris@330 587 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@350 588 instantiatePlugin(id, 44100);
Chris@330 589 if (!plugin) return false;
Chris@330 590
Chris@330 591 min = plugin->getMinChannelCount();
Chris@330 592 max = plugin->getMaxChannelCount();
Chris@330 593 delete plugin;
Chris@330 594
Chris@330 595 return true;
Chris@330 596
Chris@330 597 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@330 598
Chris@350 599 // don't need to instantiate
Chris@350 600
Chris@330 601 const RealTimePluginDescriptor *descriptor =
Chris@330 602 RealTimePluginFactory::instanceFor(id)->
Chris@330 603 getPluginDescriptor(id);
Chris@330 604 if (!descriptor) return false;
Chris@330 605
Chris@330 606 min = descriptor->audioInputPortCount;
Chris@330 607 max = descriptor->audioInputPortCount;
Chris@330 608
Chris@330 609 return true;
Chris@330 610 }
Chris@330 611
Chris@330 612 return false;
Chris@330 613 }
Chris@332 614
Chris@332 615 void
Chris@332 616 TransformFactory::setParametersFromPlugin(Transform &transform,
Chris@332 617 Vamp::PluginBase *plugin)
Chris@332 618 {
Chris@332 619 Transform::ParameterMap pmap;
Chris@332 620
Chris@350 621 //!!! record plugin & API version
Chris@350 622
Chris@350 623 //!!! check that this is the right plugin!
Chris@350 624
Chris@332 625 Vamp::PluginBase::ParameterList parameters =
Chris@332 626 plugin->getParameterDescriptors();
Chris@332 627
Chris@332 628 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@332 629 i != parameters.end(); ++i) {
Chris@332 630 pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier);
Chris@332 631 }
Chris@332 632
Chris@332 633 transform.setParameters(pmap);
Chris@332 634
Chris@332 635 if (plugin->getPrograms().empty()) {
Chris@332 636 transform.setProgram("");
Chris@332 637 } else {
Chris@332 638 transform.setProgram(plugin->getCurrentProgram().c_str());
Chris@332 639 }
Chris@332 640
Chris@332 641 RealTimePluginInstance *rtpi =
Chris@332 642 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@332 643
Chris@332 644 Transform::ConfigurationMap cmap;
Chris@332 645
Chris@332 646 if (rtpi) {
Chris@332 647
Chris@332 648 RealTimePluginInstance::ConfigurationPairMap configurePairs =
Chris@332 649 rtpi->getConfigurePairs();
Chris@332 650
Chris@332 651 for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i
Chris@332 652 = configurePairs.begin(); i != configurePairs.end(); ++i) {
Chris@332 653 cmap[i->first.c_str()] = i->second.c_str();
Chris@332 654 }
Chris@332 655 }
Chris@332 656
Chris@332 657 transform.setConfiguration(cmap);
Chris@332 658 }
Chris@332 659
Chris@332 660 void
Chris@350 661 TransformFactory::setPluginParameters(const Transform &transform,
Chris@350 662 Vamp::PluginBase *plugin)
Chris@350 663 {
Chris@350 664 //!!! check plugin & API version (see e.g. PluginXml::setParameters)
Chris@350 665
Chris@350 666 //!!! check that this is the right plugin!
Chris@350 667
Chris@350 668 RealTimePluginInstance *rtpi =
Chris@350 669 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@350 670
Chris@350 671 if (rtpi) {
Chris@350 672 const Transform::ConfigurationMap &cmap = transform.getConfiguration();
Chris@350 673 for (Transform::ConfigurationMap::const_iterator i = cmap.begin();
Chris@350 674 i != cmap.end(); ++i) {
Chris@350 675 rtpi->configure(i->first.toStdString(), i->second.toStdString());
Chris@350 676 }
Chris@350 677 }
Chris@350 678
Chris@350 679 if (transform.getProgram() != "") {
Chris@350 680 plugin->selectProgram(transform.getProgram().toStdString());
Chris@350 681 }
Chris@350 682
Chris@350 683 const Transform::ParameterMap &pmap = transform.getParameters();
Chris@350 684
Chris@350 685 Vamp::PluginBase::ParameterList parameters =
Chris@350 686 plugin->getParameterDescriptors();
Chris@350 687
Chris@350 688 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@350 689 i != parameters.end(); ++i) {
Chris@350 690 QString key = i->identifier.c_str();
Chris@350 691 Transform::ParameterMap::const_iterator pmi = pmap.find(key);
Chris@350 692 if (pmi != pmap.end()) {
Chris@350 693 plugin->setParameter(i->identifier, pmi->second);
Chris@350 694 }
Chris@350 695 }
Chris@350 696 }
Chris@350 697
Chris@350 698 void
Chris@332 699 TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
Chris@332 700 Vamp::PluginBase *plugin)
Chris@332 701 {
Chris@350 702 const Vamp::Plugin *vp = downcastVampPlugin(plugin);
Chris@332 703
Chris@332 704 if (!vp) {
Chris@332 705 // time domain input for real-time effects plugin
Chris@332 706 if (!transform.getBlockSize()) {
Chris@332 707 if (!transform.getStepSize()) transform.setStepSize(1024);
Chris@332 708 transform.setBlockSize(transform.getStepSize());
Chris@332 709 } else {
Chris@332 710 transform.setStepSize(transform.getBlockSize());
Chris@332 711 }
Chris@332 712 } else {
Chris@332 713 Vamp::Plugin::InputDomain domain = vp->getInputDomain();
Chris@332 714 if (!transform.getStepSize()) {
Chris@332 715 transform.setStepSize(vp->getPreferredStepSize());
Chris@332 716 }
Chris@332 717 if (!transform.getBlockSize()) {
Chris@332 718 transform.setBlockSize(vp->getPreferredBlockSize());
Chris@332 719 }
Chris@332 720 if (!transform.getBlockSize()) {
Chris@332 721 transform.setBlockSize(1024);
Chris@332 722 }
Chris@332 723 if (!transform.getStepSize()) {
Chris@332 724 if (domain == Vamp::Plugin::FrequencyDomain) {
Chris@332 725 // std::cerr << "frequency domain, step = " << blockSize/2 << std::endl;
Chris@332 726 transform.setStepSize(transform.getBlockSize()/2);
Chris@332 727 } else {
Chris@332 728 // std::cerr << "time domain, step = " << blockSize/2 << std::endl;
Chris@332 729 transform.setStepSize(transform.getBlockSize());
Chris@332 730 }
Chris@332 731 }
Chris@332 732 }
Chris@332 733 }
Chris@332 734
Chris@350 735 QString
Chris@350 736 TransformFactory::getPluginConfigurationXml(const Transform &t)
Chris@332 737 {
Chris@350 738 QString xml;
Chris@350 739
Chris@351 740 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 741 (t.getIdentifier(), 0);
Chris@350 742 if (!plugin) {
Chris@350 743 std::cerr << "TransformFactory::getPluginConfigurationXml: "
Chris@350 744 << "Unable to instantiate plugin for transform \""
Chris@350 745 << t.getIdentifier().toStdString() << "\"" << std::endl;
Chris@350 746 return xml;
Chris@332 747 }
Chris@332 748
Chris@351 749 setPluginParameters(t, plugin);
Chris@351 750
Chris@350 751 QTextStream out(&xml);
Chris@350 752 PluginXml(plugin).toXml(out);
Chris@350 753 delete plugin;
Chris@332 754
Chris@350 755 return xml;
Chris@350 756 }
Chris@332 757
Chris@350 758 void
Chris@350 759 TransformFactory::setParametersFromPluginConfigurationXml(Transform &t,
Chris@350 760 QString xml)
Chris@350 761 {
Chris@351 762 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 763 (t.getIdentifier(), 0);
Chris@350 764 if (!plugin) {
Chris@350 765 std::cerr << "TransformFactory::setParametersFromPluginConfigurationXml: "
Chris@350 766 << "Unable to instantiate plugin for transform \""
Chris@350 767 << t.getIdentifier().toStdString() << "\"" << std::endl;
Chris@350 768 return;
Chris@332 769 }
Chris@332 770
Chris@350 771 PluginXml(plugin).setParametersFromXml(xml);
Chris@350 772 setParametersFromPlugin(t, plugin);
Chris@350 773 delete plugin;
Chris@332 774 }
Chris@332 775