annotate transform/TransformFactory.cpp @ 107:dd11619b73ba

* Update along with latest Vamp API change. This has not yet been tested.
author Chris Cannam
date Mon, 26 Feb 2007 18:13:07 +0000
parents f4f52566e451
children 58f21cf235c7
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 Sonic Visualiser
Chris@0 5 An audio file viewer and annotation editor.
Chris@0 6 Centre for Digital Music, Queen Mary, University of London.
Chris@77 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@0 9 This program is free software; you can redistribute it and/or
Chris@0 10 modify it under the terms of the GNU General Public License as
Chris@0 11 published by the Free Software Foundation; either version 2 of the
Chris@0 12 License, or (at your option) any later version. See the file
Chris@0 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "TransformFactory.h"
Chris@0 17
Chris@0 18 #include "FeatureExtractionPluginTransform.h"
Chris@0 19 #include "RealTimePluginTransform.h"
Chris@0 20
Chris@0 21 #include "plugin/FeatureExtractionPluginFactory.h"
Chris@0 22 #include "plugin/RealTimePluginFactory.h"
Chris@0 23 #include "plugin/PluginXml.h"
Chris@0 24
Chris@0 25 #include "widgets/PluginParameterDialog.h"
Chris@0 26
Chris@1 27 #include "data/model/DenseTimeValueModel.h"
Chris@0 28
Chris@28 29 #include "vamp-sdk/PluginHostAdapter.h"
Chris@28 30
Chris@41 31 #include "sv/audioio/AudioCallbackPlaySource.h" //!!! shouldn't include here
Chris@41 32
Chris@0 33 #include <iostream>
Chris@0 34 #include <set>
Chris@0 35
Chris@0 36 #include <QRegExp>
Chris@0 37
Chris@0 38 TransformFactory *
Chris@0 39 TransformFactory::m_instance = new TransformFactory;
Chris@0 40
Chris@0 41 TransformFactory *
Chris@0 42 TransformFactory::getInstance()
Chris@0 43 {
Chris@0 44 return m_instance;
Chris@0 45 }
Chris@0 46
Chris@0 47 TransformFactory::~TransformFactory()
Chris@0 48 {
Chris@0 49 }
Chris@0 50
Chris@0 51 TransformFactory::TransformList
Chris@0 52 TransformFactory::getAllTransforms()
Chris@0 53 {
Chris@0 54 if (m_transforms.empty()) populateTransforms();
Chris@0 55
Chris@34 56 std::set<TransformDesc> dset;
Chris@0 57 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@0 58 i != m_transforms.end(); ++i) {
Chris@34 59 dset.insert(i->second);
Chris@34 60 }
Chris@34 61
Chris@34 62 TransformList list;
Chris@34 63 for (std::set<TransformDesc>::const_iterator i = dset.begin();
Chris@34 64 i != dset.end(); ++i) {
Chris@34 65 list.push_back(*i);
Chris@0 66 }
Chris@0 67
Chris@0 68 return list;
Chris@0 69 }
Chris@0 70
Chris@0 71 std::vector<QString>
Chris@0 72 TransformFactory::getAllTransformTypes()
Chris@0 73 {
Chris@0 74 if (m_transforms.empty()) populateTransforms();
Chris@0 75
Chris@0 76 std::set<QString> types;
Chris@0 77 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@0 78 i != m_transforms.end(); ++i) {
Chris@0 79 types.insert(i->second.type);
Chris@0 80 }
Chris@0 81
Chris@0 82 std::vector<QString> rv;
Chris@0 83 for (std::set<QString>::iterator i = types.begin(); i != types.end(); ++i) {
Chris@0 84 rv.push_back(*i);
Chris@0 85 }
Chris@0 86
Chris@0 87 return rv;
Chris@0 88 }
Chris@0 89
Chris@33 90 std::vector<QString>
Chris@33 91 TransformFactory::getTransformCategories(QString transformType)
Chris@33 92 {
Chris@33 93 if (m_transforms.empty()) populateTransforms();
Chris@33 94
Chris@33 95 std::set<QString> categories;
Chris@33 96 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@33 97 i != m_transforms.end(); ++i) {
Chris@33 98 if (i->second.type == transformType) {
Chris@33 99 categories.insert(i->second.category);
Chris@33 100 }
Chris@33 101 }
Chris@33 102
Chris@33 103 bool haveEmpty = false;
Chris@33 104
Chris@33 105 std::vector<QString> rv;
Chris@33 106 for (std::set<QString>::iterator i = categories.begin();
Chris@33 107 i != categories.end(); ++i) {
Chris@33 108 if (*i != "") rv.push_back(*i);
Chris@33 109 else haveEmpty = true;
Chris@33 110 }
Chris@33 111
Chris@33 112 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@33 113
Chris@33 114 return rv;
Chris@33 115 }
Chris@33 116
Chris@33 117 std::vector<QString>
Chris@33 118 TransformFactory::getTransformMakers(QString transformType)
Chris@33 119 {
Chris@33 120 if (m_transforms.empty()) populateTransforms();
Chris@33 121
Chris@33 122 std::set<QString> makers;
Chris@33 123 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@33 124 i != m_transforms.end(); ++i) {
Chris@33 125 if (i->second.type == transformType) {
Chris@33 126 makers.insert(i->second.maker);
Chris@33 127 }
Chris@33 128 }
Chris@33 129
Chris@33 130 bool haveEmpty = false;
Chris@33 131
Chris@33 132 std::vector<QString> rv;
Chris@33 133 for (std::set<QString>::iterator i = makers.begin();
Chris@33 134 i != makers.end(); ++i) {
Chris@33 135 if (*i != "") rv.push_back(*i);
Chris@33 136 else haveEmpty = true;
Chris@33 137 }
Chris@33 138
Chris@33 139 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@33 140
Chris@33 141 return rv;
Chris@33 142 }
Chris@33 143
Chris@0 144 void
Chris@0 145 TransformFactory::populateTransforms()
Chris@0 146 {
Chris@0 147 TransformDescriptionMap transforms;
Chris@0 148
Chris@0 149 populateFeatureExtractionPlugins(transforms);
Chris@0 150 populateRealTimePlugins(transforms);
Chris@0 151
Chris@80 152 // disambiguate plugins with similar names
Chris@0 153
Chris@107 154 std::map<QString, int> names;
Chris@80 155 std::map<QString, QString> pluginSources;
Chris@80 156 std::map<QString, QString> pluginMakers;
Chris@0 157
Chris@0 158 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@0 159 i != transforms.end(); ++i) {
Chris@0 160
Chris@0 161 TransformDesc desc = i->second;
Chris@0 162
Chris@107 163 QString td = desc.name;
Chris@80 164 QString tn = td.section(": ", 0, 0);
Chris@107 165 QString pn = desc.identifier.section(":", 1, 1);
Chris@80 166
Chris@80 167 if (pluginSources.find(tn) != pluginSources.end()) {
Chris@80 168 if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) {
Chris@107 169 ++names[tn];
Chris@80 170 }
Chris@80 171 } else {
Chris@107 172 ++names[tn];
Chris@80 173 pluginSources[tn] = pn;
Chris@80 174 pluginMakers[tn] = desc.maker;
Chris@80 175 }
Chris@0 176 }
Chris@0 177
Chris@0 178 std::map<QString, int> counts;
Chris@0 179 m_transforms.clear();
Chris@0 180
Chris@0 181 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@0 182 i != transforms.end(); ++i) {
Chris@0 183
Chris@0 184 TransformDesc desc = i->second;
Chris@107 185 QString identifier = desc.identifier;
Chris@0 186 QString maker = desc.maker;
Chris@0 187
Chris@107 188 QString td = desc.name;
Chris@80 189 QString tn = td.section(": ", 0, 0);
Chris@80 190 QString to = td.section(": ", 1);
Chris@80 191
Chris@107 192 if (names[tn] > 1) {
Chris@80 193 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
Chris@80 194 tn = QString("%1 [%2]").arg(tn).arg(maker);
Chris@0 195 }
Chris@0 196
Chris@80 197 if (to != "") {
Chris@107 198 desc.name = QString("%1: %2").arg(tn).arg(to);
Chris@80 199 } else {
Chris@107 200 desc.name = tn;
Chris@80 201 }
Chris@80 202
Chris@107 203 m_transforms[identifier] = desc;
Chris@0 204 }
Chris@0 205 }
Chris@0 206
Chris@0 207 void
Chris@0 208 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
Chris@0 209 {
Chris@0 210 std::vector<QString> plugs =
Chris@0 211 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
Chris@0 212
Chris@0 213 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@0 214
Chris@0 215 QString pluginId = plugs[i];
Chris@0 216
Chris@0 217 FeatureExtractionPluginFactory *factory =
Chris@0 218 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@0 219
Chris@0 220 if (!factory) {
Chris@0 221 std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 222 continue;
Chris@0 223 }
Chris@0 224
Chris@0 225 Vamp::Plugin *plugin =
Chris@0 226 factory->instantiatePlugin(pluginId, 48000);
Chris@0 227
Chris@0 228 if (!plugin) {
Chris@0 229 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 230 continue;
Chris@0 231 }
Chris@0 232
Chris@107 233 QString pluginName = plugin->getName().c_str();
Chris@33 234 QString category = factory->getPluginCategory(pluginId);
Chris@33 235
Chris@0 236 Vamp::Plugin::OutputList outputs =
Chris@0 237 plugin->getOutputDescriptors();
Chris@0 238
Chris@0 239 for (size_t j = 0; j < outputs.size(); ++j) {
Chris@0 240
Chris@107 241 QString transformId = QString("%1:%2")
Chris@107 242 .arg(pluginId).arg(outputs[j].identifier.c_str());
Chris@0 243
Chris@107 244 QString userName;
Chris@0 245 QString friendlyName;
Chris@0 246 QString units = outputs[j].unit.c_str();
Chris@0 247
Chris@0 248 if (outputs.size() == 1) {
Chris@107 249 userName = pluginName;
Chris@107 250 friendlyName = pluginName;
Chris@0 251 } else {
Chris@107 252 userName = QString("%1: %2")
Chris@107 253 .arg(pluginName)
Chris@107 254 .arg(outputs[j].name.c_str());
Chris@107 255 friendlyName = outputs[j].name.c_str();
Chris@0 256 }
Chris@0 257
Chris@0 258 bool configurable = (!plugin->getPrograms().empty() ||
Chris@0 259 !plugin->getParameterDescriptors().empty());
Chris@0 260
Chris@107 261 std::cerr << "Adding feature extraction plugin transform: id = " << transformId.toStdString() << std::endl;
Chris@107 262
Chris@107 263 transforms[transformId] =
Chris@34 264 TransformDesc(tr("Analysis"),
Chris@33 265 category,
Chris@107 266 transformId,
Chris@107 267 userName,
Chris@0 268 friendlyName,
Chris@0 269 plugin->getMaker().c_str(),
Chris@0 270 units,
Chris@0 271 configurable);
Chris@0 272 }
Chris@0 273 }
Chris@0 274 }
Chris@0 275
Chris@0 276 void
Chris@0 277 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@0 278 {
Chris@0 279 std::vector<QString> plugs =
Chris@0 280 RealTimePluginFactory::getAllPluginIdentifiers();
Chris@0 281
Chris@34 282 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@0 283
Chris@0 284 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@0 285
Chris@0 286 QString pluginId = plugs[i];
Chris@0 287
Chris@0 288 RealTimePluginFactory *factory =
Chris@0 289 RealTimePluginFactory::instanceFor(pluginId);
Chris@0 290
Chris@0 291 if (!factory) {
Chris@0 292 std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 293 continue;
Chris@0 294 }
Chris@0 295
Chris@0 296 const RealTimePluginDescriptor *descriptor =
Chris@0 297 factory->getPluginDescriptor(pluginId);
Chris@0 298
Chris@0 299 if (!descriptor) {
Chris@0 300 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 301 continue;
Chris@0 302 }
Chris@0 303
Chris@34 304 //!!! if (descriptor->controlOutputPortCount == 0 ||
Chris@34 305 // descriptor->audioInputPortCount == 0) continue;
Chris@0 306
Chris@35 307 // std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << std::endl;
Chris@0 308
Chris@107 309 QString pluginName = descriptor->name.c_str();
Chris@33 310 QString category = factory->getPluginCategory(pluginId);
Chris@34 311 bool configurable = (descriptor->parameterCount > 0);
Chris@0 312
Chris@34 313 if (descriptor->audioInputPortCount > 0) {
Chris@0 314
Chris@34 315 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
Chris@0 316
Chris@107 317 QString transformId = QString("%1:%2").arg(pluginId).arg(j);
Chris@107 318 QString userName;
Chris@34 319 QString units;
Chris@0 320
Chris@34 321 if (j < descriptor->controlOutputPortNames.size() &&
Chris@34 322 descriptor->controlOutputPortNames[j] != "") {
Chris@0 323
Chris@34 324 QString portName = descriptor->controlOutputPortNames[j].c_str();
Chris@0 325
Chris@107 326 userName = tr("%1: %2")
Chris@107 327 .arg(pluginName)
Chris@34 328 .arg(portName);
Chris@34 329
Chris@34 330 if (unitRE.indexIn(portName) >= 0) {
Chris@34 331 units = unitRE.cap(1);
Chris@34 332 }
Chris@34 333
Chris@34 334 } else if (descriptor->controlOutputPortCount > 1) {
Chris@34 335
Chris@107 336 userName = tr("%1: Output %2")
Chris@107 337 .arg(pluginName)
Chris@34 338 .arg(j + 1);
Chris@34 339
Chris@34 340 } else {
Chris@34 341
Chris@107 342 userName = pluginName;
Chris@0 343 }
Chris@0 344
Chris@0 345
Chris@107 346 transforms[transformId] =
Chris@52 347 TransformDesc(tr("Effects Data"),
Chris@34 348 category,
Chris@107 349 transformId,
Chris@107 350 userName,
Chris@107 351 userName,
Chris@34 352 descriptor->maker.c_str(),
Chris@34 353 units,
Chris@34 354 configurable);
Chris@34 355 }
Chris@34 356 }
Chris@0 357
Chris@34 358 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@0 359
Chris@34 360 if (descriptor->audioOutputPortCount > 0) {
Chris@34 361
Chris@107 362 QString transformId = QString("%1:A").arg(pluginId);
Chris@34 363 QString type = tr("Effects");
Chris@34 364 if (descriptor->audioInputPortCount == 0) {
Chris@34 365 type = tr("Generators");
Chris@34 366 }
Chris@34 367
Chris@107 368 transforms[transformId] =
Chris@34 369 TransformDesc(type,
Chris@34 370 category,
Chris@107 371 transformId,
Chris@107 372 pluginName,
Chris@107 373 pluginName,
Chris@34 374 descriptor->maker.c_str(),
Chris@34 375 "",
Chris@34 376 configurable);
Chris@0 377 }
Chris@34 378 }
Chris@0 379 }
Chris@0 380 }
Chris@0 381
Chris@0 382 QString
Chris@107 383 TransformFactory::getTransformName(TransformId identifier)
Chris@0 384 {
Chris@107 385 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@107 386 return m_transforms[identifier].name;
Chris@0 387 } else return "";
Chris@0 388 }
Chris@0 389
Chris@0 390 QString
Chris@107 391 TransformFactory::getTransformFriendlyName(TransformId identifier)
Chris@0 392 {
Chris@107 393 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@107 394 return m_transforms[identifier].friendlyName;
Chris@0 395 } else return "";
Chris@0 396 }
Chris@0 397
Chris@0 398 QString
Chris@107 399 TransformFactory::getTransformUnits(TransformId identifier)
Chris@0 400 {
Chris@107 401 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@107 402 return m_transforms[identifier].units;
Chris@0 403 } else return "";
Chris@0 404 }
Chris@0 405
Chris@0 406 bool
Chris@107 407 TransformFactory::isTransformConfigurable(TransformId identifier)
Chris@0 408 {
Chris@107 409 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@107 410 return m_transforms[identifier].configurable;
Chris@0 411 } else return false;
Chris@0 412 }
Chris@0 413
Chris@0 414 bool
Chris@107 415 TransformFactory::getTransformChannelRange(TransformId identifier,
Chris@0 416 int &min, int &max)
Chris@0 417 {
Chris@107 418 QString id = identifier.section(':', 0, 2);
Chris@0 419
Chris@0 420 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 421
Chris@0 422 Vamp::Plugin *plugin =
Chris@0 423 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@0 424 instantiatePlugin(id, 48000);
Chris@0 425 if (!plugin) return false;
Chris@0 426
Chris@0 427 min = plugin->getMinChannelCount();
Chris@0 428 max = plugin->getMaxChannelCount();
Chris@0 429 delete plugin;
Chris@0 430
Chris@0 431 return true;
Chris@0 432
Chris@0 433 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 434
Chris@0 435 const RealTimePluginDescriptor *descriptor =
Chris@0 436 RealTimePluginFactory::instanceFor(id)->
Chris@0 437 getPluginDescriptor(id);
Chris@0 438 if (!descriptor) return false;
Chris@0 439
Chris@0 440 min = descriptor->audioInputPortCount;
Chris@0 441 max = descriptor->audioInputPortCount;
Chris@0 442
Chris@0 443 return true;
Chris@0 444 }
Chris@0 445
Chris@0 446 return false;
Chris@0 447 }
Chris@0 448
Chris@0 449 bool
Chris@107 450 TransformFactory::getChannelRange(TransformId identifier, Vamp::PluginBase *plugin,
Chris@0 451 int &minChannels, int &maxChannels)
Chris@0 452 {
Chris@0 453 Vamp::Plugin *vp = 0;
Chris@28 454 if ((vp = dynamic_cast<Vamp::Plugin *>(plugin)) ||
Chris@28 455 (vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin))) {
Chris@0 456 minChannels = vp->getMinChannelCount();
Chris@0 457 maxChannels = vp->getMaxChannelCount();
Chris@0 458 return true;
Chris@0 459 } else {
Chris@107 460 return getTransformChannelRange(identifier, minChannels, maxChannels);
Chris@0 461 }
Chris@0 462 }
Chris@0 463
Chris@53 464 Model *
Chris@107 465 TransformFactory::getConfigurationForTransform(TransformId identifier,
Chris@53 466 const std::vector<Model *> &candidateInputModels,
Chris@27 467 PluginTransform::ExecutionContext &context,
Chris@41 468 QString &configurationXml,
Chris@41 469 AudioCallbackPlaySource *source)
Chris@0 470 {
Chris@53 471 if (candidateInputModels.empty()) return 0;
Chris@53 472
Chris@54 473 //!!! This will need revision -- we'll have to have a callback
Chris@54 474 //from the dialog for when the candidate input model is changed,
Chris@54 475 //as we'll need to reinitialise the channel settings in the dialog
Chris@53 476 Model *inputModel = candidateInputModels[0]; //!!! for now
Chris@54 477 QStringList candidateModelNames;
Chris@54 478 std::map<QString, Model *> modelMap;
Chris@54 479 for (size_t i = 0; i < candidateInputModels.size(); ++i) {
Chris@54 480 QString modelName = candidateInputModels[i]->objectName();
Chris@54 481 QString origModelName = modelName;
Chris@54 482 int dupcount = 1;
Chris@54 483 while (modelMap.find(modelName) != modelMap.end()) {
Chris@54 484 modelName = tr("%1 <%2>").arg(origModelName).arg(++dupcount);
Chris@54 485 }
Chris@54 486 modelMap[modelName] = candidateInputModels[i];
Chris@54 487 candidateModelNames.push_back(modelName);
Chris@54 488 }
Chris@53 489
Chris@107 490 QString id = identifier.section(':', 0, 2);
Chris@107 491 QString output = identifier.section(':', 3);
Chris@53 492 QString outputLabel = "";
Chris@0 493
Chris@0 494 bool ok = false;
Chris@107 495 configurationXml = m_lastConfigurations[identifier];
Chris@0 496
Chris@0 497 // std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl;
Chris@0 498
Chris@0 499 Vamp::PluginBase *plugin = 0;
Chris@0 500
Chris@10 501 bool frequency = false;
Chris@41 502 bool effect = false;
Chris@58 503 bool generator = false;
Chris@10 504
Chris@0 505 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 506
Chris@10 507 Vamp::Plugin *vp =
Chris@10 508 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
Chris@0 509 (id, inputModel->getSampleRate());
Chris@53 510
Chris@10 511 if (vp) {
Chris@53 512
Chris@10 513 plugin = vp;
Chris@10 514 frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
Chris@53 515
Chris@53 516 std::vector<Vamp::Plugin::OutputDescriptor> od =
Chris@53 517 vp->getOutputDescriptors();
Chris@53 518 if (od.size() > 1) {
Chris@53 519 for (size_t i = 0; i < od.size(); ++i) {
Chris@107 520 if (od[i].identifier == output.toStdString()) {
Chris@107 521 outputLabel = od[i].name.c_str();
Chris@53 522 break;
Chris@53 523 }
Chris@53 524 }
Chris@53 525 }
Chris@10 526 }
Chris@0 527
Chris@0 528 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 529
Chris@41 530 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
Chris@41 531 const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id);
Chris@41 532
Chris@41 533 if (desc->audioInputPortCount > 0 &&
Chris@41 534 desc->audioOutputPortCount > 0 &&
Chris@41 535 !desc->isSynth) {
Chris@41 536 effect = true;
Chris@41 537 }
Chris@41 538
Chris@58 539 if (desc->audioInputPortCount == 0) {
Chris@58 540 generator = true;
Chris@58 541 }
Chris@58 542
Chris@53 543 if (output != "A") {
Chris@53 544 int outputNo = output.toInt();
Chris@53 545 if (outputNo >= 0 && outputNo < desc->controlOutputPortCount) {
Chris@53 546 outputLabel = desc->controlOutputPortNames[outputNo].c_str();
Chris@53 547 }
Chris@53 548 }
Chris@53 549
Chris@41 550 size_t sampleRate = inputModel->getSampleRate();
Chris@41 551 size_t blockSize = 1024;
Chris@41 552 size_t channels = 1;
Chris@41 553 if (effect && source) {
Chris@41 554 sampleRate = source->getTargetSampleRate();
Chris@41 555 blockSize = source->getTargetBlockSize();
Chris@41 556 channels = source->getTargetChannelCount();
Chris@41 557 }
Chris@41 558
Chris@41 559 RealTimePluginInstance *rtp = factory->instantiatePlugin
Chris@41 560 (id, 0, 0, sampleRate, blockSize, channels);
Chris@41 561
Chris@41 562 plugin = rtp;
Chris@41 563
Chris@41 564 if (effect && source && rtp) {
Chris@41 565 source->setAuditioningPlugin(rtp);
Chris@41 566 }
Chris@0 567 }
Chris@0 568
Chris@0 569 if (plugin) {
Chris@27 570
Chris@27 571 context = PluginTransform::ExecutionContext(context.channel, plugin);
Chris@27 572
Chris@0 573 if (configurationXml != "") {
Chris@0 574 PluginXml(plugin).setParametersFromXml(configurationXml);
Chris@0 575 }
Chris@0 576
Chris@0 577 int sourceChannels = 1;
Chris@0 578 if (dynamic_cast<DenseTimeValueModel *>(inputModel)) {
Chris@0 579 sourceChannels = dynamic_cast<DenseTimeValueModel *>(inputModel)
Chris@0 580 ->getChannelCount();
Chris@0 581 }
Chris@0 582
Chris@0 583 int minChannels = 1, maxChannels = sourceChannels;
Chris@107 584 getChannelRange(identifier, plugin, minChannels, maxChannels);
Chris@0 585
Chris@0 586 int targetChannels = sourceChannels;
Chris@44 587 if (!effect) {
Chris@44 588 if (sourceChannels < minChannels) targetChannels = minChannels;
Chris@44 589 if (sourceChannels > maxChannels) targetChannels = maxChannels;
Chris@44 590 }
Chris@0 591
Chris@27 592 int defaultChannel = context.channel;
Chris@0 593
Chris@53 594 PluginParameterDialog *dialog = new PluginParameterDialog(plugin);
Chris@53 595
Chris@58 596 if (candidateModelNames.size() > 1 && !generator) {
Chris@54 597 dialog->setCandidateInputModels(candidateModelNames);
Chris@54 598 }
Chris@54 599
Chris@58 600 if (targetChannels > 0) {
Chris@58 601 dialog->setChannelArrangement(sourceChannels, targetChannels,
Chris@58 602 defaultChannel);
Chris@58 603 }
Chris@53 604
Chris@53 605 dialog->setOutputLabel(outputLabel);
Chris@53 606
Chris@53 607 dialog->setShowProcessingOptions(true, frequency);
Chris@53 608
Chris@0 609 if (dialog->exec() == QDialog::Accepted) {
Chris@0 610 ok = true;
Chris@0 611 }
Chris@42 612
Chris@54 613 QString selectedInput = dialog->getInputModel();
Chris@54 614 if (selectedInput != "") {
Chris@54 615 if (modelMap.find(selectedInput) != modelMap.end()) {
Chris@54 616 inputModel = modelMap[selectedInput];
Chris@54 617 std::cerr << "Found selected input \"" << selectedInput.toStdString() << "\" in model map, result is " << inputModel << std::endl;
Chris@54 618 } else {
Chris@54 619 std::cerr << "Failed to find selected input \"" << selectedInput.toStdString() << "\" in model map" << std::endl;
Chris@54 620 }
Chris@54 621 }
Chris@54 622
Chris@0 623 configurationXml = PluginXml(plugin).toXmlString();
Chris@27 624 context.channel = dialog->getChannel();
Chris@26 625
Chris@27 626 dialog->getProcessingParameters(context.stepSize,
Chris@27 627 context.blockSize,
Chris@27 628 context.windowType);
Chris@27 629
Chris@27 630 context.makeConsistentWithPlugin(plugin);
Chris@26 631
Chris@0 632 delete dialog;
Chris@41 633
Chris@41 634 if (effect && source) {
Chris@41 635 source->setAuditioningPlugin(0); // will delete our plugin
Chris@41 636 } else {
Chris@41 637 delete plugin;
Chris@41 638 }
Chris@0 639 }
Chris@0 640
Chris@107 641 if (ok) m_lastConfigurations[identifier] = configurationXml;
Chris@0 642
Chris@53 643 return ok ? inputModel : 0;
Chris@0 644 }
Chris@0 645
Chris@73 646 PluginTransform::ExecutionContext
Chris@107 647 TransformFactory::getDefaultContextForTransform(TransformId identifier,
Chris@73 648 Model *inputModel)
Chris@73 649 {
Chris@73 650 PluginTransform::ExecutionContext context(-1);
Chris@73 651
Chris@107 652 QString id = identifier.section(':', 0, 2);
Chris@73 653
Chris@73 654 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@73 655
Chris@73 656 Vamp::Plugin *vp =
Chris@73 657 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
Chris@73 658 (id, inputModel ? inputModel->getSampleRate() : 48000);
Chris@73 659
Chris@73 660 if (vp) context = PluginTransform::ExecutionContext(-1, vp);
Chris@73 661
Chris@73 662 }
Chris@73 663
Chris@73 664 return context;
Chris@73 665 }
Chris@73 666
Chris@0 667 Transform *
Chris@107 668 TransformFactory::createTransform(TransformId identifier, Model *inputModel,
Chris@27 669 const PluginTransform::ExecutionContext &context,
Chris@27 670 QString configurationXml, bool start)
Chris@0 671 {
Chris@0 672 Transform *transform = 0;
Chris@0 673
Chris@107 674 QString id = identifier.section(':', 0, 2);
Chris@107 675 QString output = identifier.section(':', 3);
Chris@0 676
Chris@0 677 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 678 transform = new FeatureExtractionPluginTransform(inputModel,
Chris@0 679 id,
Chris@27 680 context,
Chris@0 681 configurationXml,
Chris@0 682 output);
Chris@0 683 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 684 transform = new RealTimePluginTransform(inputModel,
Chris@0 685 id,
Chris@27 686 context,
Chris@0 687 configurationXml,
Chris@107 688 getTransformUnits(identifier),
Chris@34 689 output == "A" ? -1 :
Chris@0 690 output.toInt());
Chris@0 691 } else {
Chris@0 692 std::cerr << "TransformFactory::createTransform: Unknown transform \""
Chris@107 693 << identifier.toStdString() << "\"" << std::endl;
Chris@0 694 return transform;
Chris@0 695 }
Chris@0 696
Chris@0 697 if (start && transform) transform->start();
Chris@107 698 transform->setObjectName(identifier);
Chris@0 699 return transform;
Chris@0 700 }
Chris@0 701
Chris@0 702 Model *
Chris@107 703 TransformFactory::transform(TransformId identifier, Model *inputModel,
Chris@27 704 const PluginTransform::ExecutionContext &context,
Chris@27 705 QString configurationXml)
Chris@0 706 {
Chris@107 707 Transform *t = createTransform(identifier, inputModel, context,
Chris@0 708 configurationXml, false);
Chris@0 709
Chris@0 710 if (!t) return 0;
Chris@0 711
Chris@0 712 connect(t, SIGNAL(finished()), this, SLOT(transformFinished()));
Chris@0 713
Chris@0 714 t->start();
Chris@55 715 Model *model = t->detachOutputModel();
Chris@55 716
Chris@55 717 if (model) {
Chris@55 718 QString imn = inputModel->objectName();
Chris@107 719 QString trn = getTransformFriendlyName(identifier);
Chris@55 720 if (imn != "") {
Chris@55 721 if (trn != "") {
Chris@55 722 model->setObjectName(tr("%1: %2").arg(imn).arg(trn));
Chris@55 723 } else {
Chris@55 724 model->setObjectName(imn);
Chris@55 725 }
Chris@55 726 } else if (trn != "") {
Chris@55 727 model->setObjectName(trn);
Chris@55 728 }
Chris@55 729 }
Chris@55 730
Chris@55 731 return model;
Chris@0 732 }
Chris@0 733
Chris@0 734 void
Chris@0 735 TransformFactory::transformFinished()
Chris@0 736 {
Chris@0 737 QObject *s = sender();
Chris@0 738 Transform *transform = dynamic_cast<Transform *>(s);
Chris@0 739
Chris@0 740 if (!transform) {
Chris@0 741 std::cerr << "WARNING: TransformFactory::transformFinished: sender is not a transform" << std::endl;
Chris@0 742 return;
Chris@0 743 }
Chris@0 744
Chris@0 745 transform->wait(); // unnecessary but reassuring
Chris@0 746 delete transform;
Chris@0 747 }
Chris@0 748