annotate transform/TransformFactory.cpp @ 441:288f45533041

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