annotate plugin/transform/TransformFactory.cpp @ 351:7263e37d8913

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