annotate plugin/transform/TransformFactory.cpp @ 384:6f6ab834449d spectrogram-cache-rejig

* Merge from trunk
author Chris Cannam
date Wed, 27 Feb 2008 11:59:42 +0000
parents 1afaf98dbf11
children
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@384 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@384 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@384 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@384 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@384 68 TransformDescription
Chris@384 69 TransformFactory::getTransformDescription(TransformId id)
Chris@384 70 {
Chris@384 71 if (m_transforms.empty()) populateTransforms();
Chris@384 72
Chris@384 73 if (m_transforms.find(id) == m_transforms.end()) {
Chris@384 74 return TransformDescription();
Chris@384 75 }
Chris@384 76
Chris@384 77 return m_transforms[id];
Chris@384 78 }
Chris@384 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@384 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@384 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@384 441
Chris@384 442 Transform
Chris@384 443 TransformFactory::getDefaultTransformFor(TransformId id, size_t rate)
Chris@384 444 {
Chris@384 445 Transform t;
Chris@384 446 t.setIdentifier(id);
Chris@384 447 if (rate != 0) t.setSampleRate(rate);
Chris@384 448
Chris@384 449 Vamp::PluginBase *plugin = instantiateDefaultPluginFor(id, rate);
Chris@384 450
Chris@384 451 if (plugin) {
Chris@384 452 t.setPluginVersion(QString("%1").arg(plugin->getPluginVersion()));
Chris@384 453 setParametersFromPlugin(t, plugin);
Chris@384 454 makeContextConsistentWithPlugin(t, plugin);
Chris@384 455 delete plugin;
Chris@384 456 }
Chris@384 457
Chris@384 458 return t;
Chris@384 459 }
Chris@384 460
Chris@384 461 Vamp::PluginBase *
Chris@384 462 TransformFactory::instantiatePluginFor(const Transform &transform)
Chris@384 463 {
Chris@384 464 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@384 465 (transform.getIdentifier(), transform.getSampleRate());
Chris@384 466 if (plugin) {
Chris@384 467 setPluginParameters(transform, plugin);
Chris@384 468 }
Chris@384 469 return plugin;
Chris@384 470 }
Chris@384 471
Chris@384 472 Vamp::PluginBase *
Chris@384 473 TransformFactory::instantiateDefaultPluginFor(TransformId identifier, size_t rate)
Chris@384 474 {
Chris@384 475 Transform t;
Chris@384 476 t.setIdentifier(identifier);
Chris@384 477 if (rate == 0) rate = 44100;
Chris@384 478 QString pluginId = t.getPluginIdentifier();
Chris@384 479
Chris@384 480 Vamp::PluginBase *plugin = 0;
Chris@384 481
Chris@384 482 if (t.getType() == Transform::FeatureExtraction) {
Chris@384 483
Chris@384 484 FeatureExtractionPluginFactory *factory =
Chris@384 485 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@384 486
Chris@384 487 plugin = factory->instantiatePlugin(pluginId, rate);
Chris@384 488
Chris@384 489 } else {
Chris@384 490
Chris@384 491 RealTimePluginFactory *factory =
Chris@384 492 RealTimePluginFactory::instanceFor(pluginId);
Chris@384 493
Chris@384 494 plugin = factory->instantiatePlugin(pluginId, 0, 0, rate, 1024, 1);
Chris@384 495 }
Chris@384 496
Chris@384 497 return plugin;
Chris@384 498 }
Chris@384 499
Chris@384 500 Vamp::Plugin *
Chris@384 501 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin)
Chris@384 502 {
Chris@384 503 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin);
Chris@384 504 if (!vp) {
Chris@384 505 // std::cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << std::endl;
Chris@384 506 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why?
Chris@384 507 }
Chris@384 508 if (!vp) {
Chris@384 509 // std::cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << std::endl;
Chris@384 510 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
Chris@384 511 }
Chris@384 512 if (!vp) {
Chris@384 513 // std::cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << std::endl;
Chris@384 514 }
Chris@384 515 return vp;
Chris@384 516 }
Chris@384 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@384 549 Vamp::Plugin::InputDomain
Chris@384 550 TransformFactory::getTransformInputDomain(TransformId identifier)
Chris@384 551 {
Chris@384 552 Transform transform;
Chris@384 553 transform.setIdentifier(identifier);
Chris@384 554
Chris@384 555 if (transform.getType() != Transform::FeatureExtraction) {
Chris@384 556 return Vamp::Plugin::TimeDomain;
Chris@384 557 }
Chris@384 558
Chris@384 559 Vamp::Plugin *plugin =
Chris@384 560 downcastVampPlugin(instantiateDefaultPluginFor(identifier, 0));
Chris@384 561
Chris@384 562 if (plugin) {
Chris@384 563 Vamp::Plugin::InputDomain d = plugin->getInputDomain();
Chris@384 564 delete plugin;
Chris@384 565 return d;
Chris@384 566 }
Chris@384 567
Chris@384 568 return Vamp::Plugin::TimeDomain;
Chris@384 569 }
Chris@384 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@384 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@384 600 // don't need to instantiate
Chris@384 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@384 622 //!!! record plugin & API version
Chris@384 623
Chris@384 624 //!!! check that this is the right plugin!
Chris@384 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@384 662 TransformFactory::setPluginParameters(const Transform &transform,
Chris@384 663 Vamp::PluginBase *plugin)
Chris@384 664 {
Chris@384 665 //!!! check plugin & API version (see e.g. PluginXml::setParameters)
Chris@384 666
Chris@384 667 //!!! check that this is the right plugin!
Chris@384 668
Chris@384 669 RealTimePluginInstance *rtpi =
Chris@384 670 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@384 671
Chris@384 672 if (rtpi) {
Chris@384 673 const Transform::ConfigurationMap &cmap = transform.getConfiguration();
Chris@384 674 for (Transform::ConfigurationMap::const_iterator i = cmap.begin();
Chris@384 675 i != cmap.end(); ++i) {
Chris@384 676 rtpi->configure(i->first.toStdString(), i->second.toStdString());
Chris@384 677 }
Chris@384 678 }
Chris@384 679
Chris@384 680 if (transform.getProgram() != "") {
Chris@384 681 plugin->selectProgram(transform.getProgram().toStdString());
Chris@384 682 }
Chris@384 683
Chris@384 684 const Transform::ParameterMap &pmap = transform.getParameters();
Chris@384 685
Chris@384 686 Vamp::PluginBase::ParameterList parameters =
Chris@384 687 plugin->getParameterDescriptors();
Chris@384 688
Chris@384 689 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@384 690 i != parameters.end(); ++i) {
Chris@384 691 QString key = i->identifier.c_str();
Chris@384 692 Transform::ParameterMap::const_iterator pmi = pmap.find(key);
Chris@384 693 if (pmi != pmap.end()) {
Chris@384 694 plugin->setParameter(i->identifier, pmi->second);
Chris@384 695 }
Chris@384 696 }
Chris@384 697 }
Chris@384 698
Chris@384 699 void
Chris@332 700 TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
Chris@332 701 Vamp::PluginBase *plugin)
Chris@332 702 {
Chris@384 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@384 736 QString
Chris@384 737 TransformFactory::getPluginConfigurationXml(const Transform &t)
Chris@332 738 {
Chris@384 739 QString xml;
Chris@384 740
Chris@384 741 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@384 742 (t.getIdentifier(), 0);
Chris@384 743 if (!plugin) {
Chris@384 744 std::cerr << "TransformFactory::getPluginConfigurationXml: "
Chris@384 745 << "Unable to instantiate plugin for transform \""
Chris@384 746 << t.getIdentifier().toStdString() << "\"" << std::endl;
Chris@384 747 return xml;
Chris@332 748 }
Chris@332 749
Chris@384 750 setPluginParameters(t, plugin);
Chris@332 751
Chris@384 752 QTextStream out(&xml);
Chris@384 753 PluginXml(plugin).toXml(out);
Chris@384 754 delete plugin;
Chris@332 755
Chris@384 756 return xml;
Chris@384 757 }
Chris@332 758
Chris@384 759 void
Chris@384 760 TransformFactory::setParametersFromPluginConfigurationXml(Transform &t,
Chris@384 761 QString xml)
Chris@384 762 {
Chris@384 763 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@384 764 (t.getIdentifier(), 0);
Chris@384 765 if (!plugin) {
Chris@384 766 std::cerr << "TransformFactory::setParametersFromPluginConfigurationXml: "
Chris@384 767 << "Unable to instantiate plugin for transform \""
Chris@384 768 << t.getIdentifier().toStdString() << "\"" << std::endl;
Chris@384 769 return;
Chris@332 770 }
Chris@332 771
Chris@384 772 PluginXml(plugin).setParametersFromXml(xml);
Chris@384 773 setParametersFromPlugin(t, plugin);
Chris@384 774 delete plugin;
Chris@332 775 }
Chris@332 776