annotate transform/TransformFactory.cpp @ 97:398889687f3d

* Add separate colour mapping unit; use it in spectrogram (colour 3d plot to follow) * Add another colour scheme resembling that of a noted commercial application
author Chris Cannam
date Wed, 31 Jan 2007 12:13:47 +0000
parents f4f52566e451
children dd11619b73ba
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@0 154 std::map<QString, int> descriptions;
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@80 163 QString td = desc.description;
Chris@80 164 QString tn = td.section(": ", 0, 0);
Chris@80 165 QString pn = desc.name.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@80 169 ++descriptions[tn];
Chris@80 170 }
Chris@80 171 } else {
Chris@80 172 ++descriptions[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@0 185 QString name = desc.name;
Chris@0 186 QString maker = desc.maker;
Chris@0 187
Chris@80 188 QString td = desc.description;
Chris@80 189 QString tn = td.section(": ", 0, 0);
Chris@80 190 QString to = td.section(": ", 1);
Chris@80 191
Chris@80 192 if (descriptions[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@80 198 desc.description = QString("%1: %2").arg(tn).arg(to);
Chris@80 199 } else {
Chris@80 200 desc.description = tn;
Chris@80 201 }
Chris@80 202
Chris@0 203 m_transforms[name] = 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@0 233 QString pluginDescription = plugin->getDescription().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@0 241 QString transformName = QString("%1:%2")
Chris@0 242 .arg(pluginId).arg(outputs[j].name.c_str());
Chris@0 243
Chris@0 244 QString userDescription;
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@0 249 userDescription = pluginDescription;
Chris@0 250 friendlyName = pluginDescription;
Chris@0 251 } else {
Chris@0 252 userDescription = QString("%1: %2")
Chris@0 253 .arg(pluginDescription)
Chris@0 254 .arg(outputs[j].description.c_str());
Chris@0 255 friendlyName = outputs[j].description.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@0 261 transforms[transformName] =
Chris@34 262 TransformDesc(tr("Analysis"),
Chris@33 263 category,
Chris@0 264 transformName,
Chris@0 265 userDescription,
Chris@0 266 friendlyName,
Chris@0 267 plugin->getMaker().c_str(),
Chris@0 268 units,
Chris@0 269 configurable);
Chris@0 270 }
Chris@0 271 }
Chris@0 272 }
Chris@0 273
Chris@0 274 void
Chris@0 275 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@0 276 {
Chris@0 277 std::vector<QString> plugs =
Chris@0 278 RealTimePluginFactory::getAllPluginIdentifiers();
Chris@0 279
Chris@34 280 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@0 281
Chris@0 282 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@0 283
Chris@0 284 QString pluginId = plugs[i];
Chris@0 285
Chris@0 286 RealTimePluginFactory *factory =
Chris@0 287 RealTimePluginFactory::instanceFor(pluginId);
Chris@0 288
Chris@0 289 if (!factory) {
Chris@0 290 std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 291 continue;
Chris@0 292 }
Chris@0 293
Chris@0 294 const RealTimePluginDescriptor *descriptor =
Chris@0 295 factory->getPluginDescriptor(pluginId);
Chris@0 296
Chris@0 297 if (!descriptor) {
Chris@0 298 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 299 continue;
Chris@0 300 }
Chris@0 301
Chris@34 302 //!!! if (descriptor->controlOutputPortCount == 0 ||
Chris@34 303 // descriptor->audioInputPortCount == 0) continue;
Chris@0 304
Chris@35 305 // 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 306
Chris@0 307 QString pluginDescription = descriptor->name.c_str();
Chris@33 308 QString category = factory->getPluginCategory(pluginId);
Chris@34 309 bool configurable = (descriptor->parameterCount > 0);
Chris@0 310
Chris@34 311 if (descriptor->audioInputPortCount > 0) {
Chris@0 312
Chris@34 313 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
Chris@0 314
Chris@34 315 QString transformName = QString("%1:%2").arg(pluginId).arg(j);
Chris@34 316 QString userDescription;
Chris@34 317 QString units;
Chris@0 318
Chris@34 319 if (j < descriptor->controlOutputPortNames.size() &&
Chris@34 320 descriptor->controlOutputPortNames[j] != "") {
Chris@0 321
Chris@34 322 QString portName = descriptor->controlOutputPortNames[j].c_str();
Chris@0 323
Chris@34 324 userDescription = tr("%1: %2")
Chris@34 325 .arg(pluginDescription)
Chris@34 326 .arg(portName);
Chris@34 327
Chris@34 328 if (unitRE.indexIn(portName) >= 0) {
Chris@34 329 units = unitRE.cap(1);
Chris@34 330 }
Chris@34 331
Chris@34 332 } else if (descriptor->controlOutputPortCount > 1) {
Chris@34 333
Chris@34 334 userDescription = tr("%1: Output %2")
Chris@34 335 .arg(pluginDescription)
Chris@34 336 .arg(j + 1);
Chris@34 337
Chris@34 338 } else {
Chris@34 339
Chris@34 340 userDescription = pluginDescription;
Chris@0 341 }
Chris@0 342
Chris@0 343
Chris@34 344 transforms[transformName] =
Chris@52 345 TransformDesc(tr("Effects Data"),
Chris@34 346 category,
Chris@34 347 transformName,
Chris@34 348 userDescription,
Chris@34 349 userDescription,
Chris@34 350 descriptor->maker.c_str(),
Chris@34 351 units,
Chris@34 352 configurable);
Chris@34 353 }
Chris@34 354 }
Chris@0 355
Chris@34 356 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@0 357
Chris@34 358 if (descriptor->audioOutputPortCount > 0) {
Chris@34 359
Chris@34 360 QString transformName = QString("%1:A").arg(pluginId);
Chris@34 361 QString type = tr("Effects");
Chris@34 362 if (descriptor->audioInputPortCount == 0) {
Chris@34 363 type = tr("Generators");
Chris@34 364 }
Chris@34 365
Chris@34 366 transforms[transformName] =
Chris@34 367 TransformDesc(type,
Chris@34 368 category,
Chris@34 369 transformName,
Chris@34 370 pluginDescription,
Chris@34 371 pluginDescription,
Chris@34 372 descriptor->maker.c_str(),
Chris@34 373 "",
Chris@34 374 configurable);
Chris@0 375 }
Chris@34 376 }
Chris@0 377 }
Chris@0 378 }
Chris@0 379
Chris@0 380 QString
Chris@0 381 TransformFactory::getTransformDescription(TransformName name)
Chris@0 382 {
Chris@0 383 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 384 return m_transforms[name].description;
Chris@0 385 } else return "";
Chris@0 386 }
Chris@0 387
Chris@0 388 QString
Chris@0 389 TransformFactory::getTransformFriendlyName(TransformName name)
Chris@0 390 {
Chris@0 391 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 392 return m_transforms[name].friendlyName;
Chris@0 393 } else return "";
Chris@0 394 }
Chris@0 395
Chris@0 396 QString
Chris@0 397 TransformFactory::getTransformUnits(TransformName name)
Chris@0 398 {
Chris@0 399 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 400 return m_transforms[name].units;
Chris@0 401 } else return "";
Chris@0 402 }
Chris@0 403
Chris@0 404 bool
Chris@0 405 TransformFactory::isTransformConfigurable(TransformName name)
Chris@0 406 {
Chris@0 407 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 408 return m_transforms[name].configurable;
Chris@0 409 } else return false;
Chris@0 410 }
Chris@0 411
Chris@0 412 bool
Chris@0 413 TransformFactory::getTransformChannelRange(TransformName name,
Chris@0 414 int &min, int &max)
Chris@0 415 {
Chris@0 416 QString id = name.section(':', 0, 2);
Chris@0 417
Chris@0 418 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 419
Chris@0 420 Vamp::Plugin *plugin =
Chris@0 421 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@0 422 instantiatePlugin(id, 48000);
Chris@0 423 if (!plugin) return false;
Chris@0 424
Chris@0 425 min = plugin->getMinChannelCount();
Chris@0 426 max = plugin->getMaxChannelCount();
Chris@0 427 delete plugin;
Chris@0 428
Chris@0 429 return true;
Chris@0 430
Chris@0 431 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 432
Chris@0 433 const RealTimePluginDescriptor *descriptor =
Chris@0 434 RealTimePluginFactory::instanceFor(id)->
Chris@0 435 getPluginDescriptor(id);
Chris@0 436 if (!descriptor) return false;
Chris@0 437
Chris@0 438 min = descriptor->audioInputPortCount;
Chris@0 439 max = descriptor->audioInputPortCount;
Chris@0 440
Chris@0 441 return true;
Chris@0 442 }
Chris@0 443
Chris@0 444 return false;
Chris@0 445 }
Chris@0 446
Chris@0 447 bool
Chris@0 448 TransformFactory::getChannelRange(TransformName name, Vamp::PluginBase *plugin,
Chris@0 449 int &minChannels, int &maxChannels)
Chris@0 450 {
Chris@0 451 Vamp::Plugin *vp = 0;
Chris@28 452 if ((vp = dynamic_cast<Vamp::Plugin *>(plugin)) ||
Chris@28 453 (vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin))) {
Chris@0 454 minChannels = vp->getMinChannelCount();
Chris@0 455 maxChannels = vp->getMaxChannelCount();
Chris@0 456 return true;
Chris@0 457 } else {
Chris@0 458 return getTransformChannelRange(name, minChannels, maxChannels);
Chris@0 459 }
Chris@0 460 }
Chris@0 461
Chris@53 462 Model *
Chris@0 463 TransformFactory::getConfigurationForTransform(TransformName name,
Chris@53 464 const std::vector<Model *> &candidateInputModels,
Chris@27 465 PluginTransform::ExecutionContext &context,
Chris@41 466 QString &configurationXml,
Chris@41 467 AudioCallbackPlaySource *source)
Chris@0 468 {
Chris@53 469 if (candidateInputModels.empty()) return 0;
Chris@53 470
Chris@54 471 //!!! This will need revision -- we'll have to have a callback
Chris@54 472 //from the dialog for when the candidate input model is changed,
Chris@54 473 //as we'll need to reinitialise the channel settings in the dialog
Chris@53 474 Model *inputModel = candidateInputModels[0]; //!!! for now
Chris@54 475 QStringList candidateModelNames;
Chris@54 476 std::map<QString, Model *> modelMap;
Chris@54 477 for (size_t i = 0; i < candidateInputModels.size(); ++i) {
Chris@54 478 QString modelName = candidateInputModels[i]->objectName();
Chris@54 479 QString origModelName = modelName;
Chris@54 480 int dupcount = 1;
Chris@54 481 while (modelMap.find(modelName) != modelMap.end()) {
Chris@54 482 modelName = tr("%1 <%2>").arg(origModelName).arg(++dupcount);
Chris@54 483 }
Chris@54 484 modelMap[modelName] = candidateInputModels[i];
Chris@54 485 candidateModelNames.push_back(modelName);
Chris@54 486 }
Chris@53 487
Chris@0 488 QString id = name.section(':', 0, 2);
Chris@0 489 QString output = name.section(':', 3);
Chris@53 490 QString outputLabel = "";
Chris@0 491
Chris@0 492 bool ok = false;
Chris@0 493 configurationXml = m_lastConfigurations[name];
Chris@0 494
Chris@0 495 // std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl;
Chris@0 496
Chris@0 497 Vamp::PluginBase *plugin = 0;
Chris@0 498
Chris@10 499 bool frequency = false;
Chris@41 500 bool effect = false;
Chris@58 501 bool generator = false;
Chris@10 502
Chris@0 503 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 504
Chris@10 505 Vamp::Plugin *vp =
Chris@10 506 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
Chris@0 507 (id, inputModel->getSampleRate());
Chris@53 508
Chris@10 509 if (vp) {
Chris@53 510
Chris@10 511 plugin = vp;
Chris@10 512 frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
Chris@53 513
Chris@53 514 std::vector<Vamp::Plugin::OutputDescriptor> od =
Chris@53 515 vp->getOutputDescriptors();
Chris@53 516 if (od.size() > 1) {
Chris@53 517 for (size_t i = 0; i < od.size(); ++i) {
Chris@53 518 if (od[i].name == output.toStdString()) {
Chris@53 519 outputLabel = od[i].description.c_str();
Chris@53 520 break;
Chris@53 521 }
Chris@53 522 }
Chris@53 523 }
Chris@10 524 }
Chris@0 525
Chris@0 526 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 527
Chris@41 528 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
Chris@41 529 const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id);
Chris@41 530
Chris@41 531 if (desc->audioInputPortCount > 0 &&
Chris@41 532 desc->audioOutputPortCount > 0 &&
Chris@41 533 !desc->isSynth) {
Chris@41 534 effect = true;
Chris@41 535 }
Chris@41 536
Chris@58 537 if (desc->audioInputPortCount == 0) {
Chris@58 538 generator = true;
Chris@58 539 }
Chris@58 540
Chris@53 541 if (output != "A") {
Chris@53 542 int outputNo = output.toInt();
Chris@53 543 if (outputNo >= 0 && outputNo < desc->controlOutputPortCount) {
Chris@53 544 outputLabel = desc->controlOutputPortNames[outputNo].c_str();
Chris@53 545 }
Chris@53 546 }
Chris@53 547
Chris@41 548 size_t sampleRate = inputModel->getSampleRate();
Chris@41 549 size_t blockSize = 1024;
Chris@41 550 size_t channels = 1;
Chris@41 551 if (effect && source) {
Chris@41 552 sampleRate = source->getTargetSampleRate();
Chris@41 553 blockSize = source->getTargetBlockSize();
Chris@41 554 channels = source->getTargetChannelCount();
Chris@41 555 }
Chris@41 556
Chris@41 557 RealTimePluginInstance *rtp = factory->instantiatePlugin
Chris@41 558 (id, 0, 0, sampleRate, blockSize, channels);
Chris@41 559
Chris@41 560 plugin = rtp;
Chris@41 561
Chris@41 562 if (effect && source && rtp) {
Chris@41 563 source->setAuditioningPlugin(rtp);
Chris@41 564 }
Chris@0 565 }
Chris@0 566
Chris@0 567 if (plugin) {
Chris@27 568
Chris@27 569 context = PluginTransform::ExecutionContext(context.channel, plugin);
Chris@27 570
Chris@0 571 if (configurationXml != "") {
Chris@0 572 PluginXml(plugin).setParametersFromXml(configurationXml);
Chris@0 573 }
Chris@0 574
Chris@0 575 int sourceChannels = 1;
Chris@0 576 if (dynamic_cast<DenseTimeValueModel *>(inputModel)) {
Chris@0 577 sourceChannels = dynamic_cast<DenseTimeValueModel *>(inputModel)
Chris@0 578 ->getChannelCount();
Chris@0 579 }
Chris@0 580
Chris@0 581 int minChannels = 1, maxChannels = sourceChannels;
Chris@0 582 getChannelRange(name, plugin, minChannels, maxChannels);
Chris@0 583
Chris@0 584 int targetChannels = sourceChannels;
Chris@44 585 if (!effect) {
Chris@44 586 if (sourceChannels < minChannels) targetChannels = minChannels;
Chris@44 587 if (sourceChannels > maxChannels) targetChannels = maxChannels;
Chris@44 588 }
Chris@0 589
Chris@27 590 int defaultChannel = context.channel;
Chris@0 591
Chris@53 592 PluginParameterDialog *dialog = new PluginParameterDialog(plugin);
Chris@53 593
Chris@58 594 if (candidateModelNames.size() > 1 && !generator) {
Chris@54 595 dialog->setCandidateInputModels(candidateModelNames);
Chris@54 596 }
Chris@54 597
Chris@58 598 if (targetChannels > 0) {
Chris@58 599 dialog->setChannelArrangement(sourceChannels, targetChannels,
Chris@58 600 defaultChannel);
Chris@58 601 }
Chris@53 602
Chris@53 603 dialog->setOutputLabel(outputLabel);
Chris@53 604
Chris@53 605 dialog->setShowProcessingOptions(true, frequency);
Chris@53 606
Chris@0 607 if (dialog->exec() == QDialog::Accepted) {
Chris@0 608 ok = true;
Chris@0 609 }
Chris@42 610
Chris@54 611 QString selectedInput = dialog->getInputModel();
Chris@54 612 if (selectedInput != "") {
Chris@54 613 if (modelMap.find(selectedInput) != modelMap.end()) {
Chris@54 614 inputModel = modelMap[selectedInput];
Chris@54 615 std::cerr << "Found selected input \"" << selectedInput.toStdString() << "\" in model map, result is " << inputModel << std::endl;
Chris@54 616 } else {
Chris@54 617 std::cerr << "Failed to find selected input \"" << selectedInput.toStdString() << "\" in model map" << std::endl;
Chris@54 618 }
Chris@54 619 }
Chris@54 620
Chris@0 621 configurationXml = PluginXml(plugin).toXmlString();
Chris@27 622 context.channel = dialog->getChannel();
Chris@26 623
Chris@27 624 dialog->getProcessingParameters(context.stepSize,
Chris@27 625 context.blockSize,
Chris@27 626 context.windowType);
Chris@27 627
Chris@27 628 context.makeConsistentWithPlugin(plugin);
Chris@26 629
Chris@0 630 delete dialog;
Chris@41 631
Chris@41 632 if (effect && source) {
Chris@41 633 source->setAuditioningPlugin(0); // will delete our plugin
Chris@41 634 } else {
Chris@41 635 delete plugin;
Chris@41 636 }
Chris@0 637 }
Chris@0 638
Chris@0 639 if (ok) m_lastConfigurations[name] = configurationXml;
Chris@0 640
Chris@53 641 return ok ? inputModel : 0;
Chris@0 642 }
Chris@0 643
Chris@73 644 PluginTransform::ExecutionContext
Chris@73 645 TransformFactory::getDefaultContextForTransform(TransformName name,
Chris@73 646 Model *inputModel)
Chris@73 647 {
Chris@73 648 PluginTransform::ExecutionContext context(-1);
Chris@73 649
Chris@73 650 QString id = name.section(':', 0, 2);
Chris@73 651
Chris@73 652 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@73 653
Chris@73 654 Vamp::Plugin *vp =
Chris@73 655 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
Chris@73 656 (id, inputModel ? inputModel->getSampleRate() : 48000);
Chris@73 657
Chris@73 658 if (vp) context = PluginTransform::ExecutionContext(-1, vp);
Chris@73 659
Chris@73 660 }
Chris@73 661
Chris@73 662 return context;
Chris@73 663 }
Chris@73 664
Chris@0 665 Transform *
Chris@0 666 TransformFactory::createTransform(TransformName name, Model *inputModel,
Chris@27 667 const PluginTransform::ExecutionContext &context,
Chris@27 668 QString configurationXml, bool start)
Chris@0 669 {
Chris@0 670 Transform *transform = 0;
Chris@0 671
Chris@0 672 QString id = name.section(':', 0, 2);
Chris@0 673 QString output = name.section(':', 3);
Chris@0 674
Chris@0 675 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 676 transform = new FeatureExtractionPluginTransform(inputModel,
Chris@0 677 id,
Chris@27 678 context,
Chris@0 679 configurationXml,
Chris@0 680 output);
Chris@0 681 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 682 transform = new RealTimePluginTransform(inputModel,
Chris@0 683 id,
Chris@27 684 context,
Chris@0 685 configurationXml,
Chris@0 686 getTransformUnits(name),
Chris@34 687 output == "A" ? -1 :
Chris@0 688 output.toInt());
Chris@0 689 } else {
Chris@0 690 std::cerr << "TransformFactory::createTransform: Unknown transform \""
Chris@0 691 << name.toStdString() << "\"" << std::endl;
Chris@0 692 return transform;
Chris@0 693 }
Chris@0 694
Chris@0 695 if (start && transform) transform->start();
Chris@0 696 transform->setObjectName(name);
Chris@0 697 return transform;
Chris@0 698 }
Chris@0 699
Chris@0 700 Model *
Chris@0 701 TransformFactory::transform(TransformName name, Model *inputModel,
Chris@27 702 const PluginTransform::ExecutionContext &context,
Chris@27 703 QString configurationXml)
Chris@0 704 {
Chris@27 705 Transform *t = createTransform(name, inputModel, context,
Chris@0 706 configurationXml, false);
Chris@0 707
Chris@0 708 if (!t) return 0;
Chris@0 709
Chris@0 710 connect(t, SIGNAL(finished()), this, SLOT(transformFinished()));
Chris@0 711
Chris@0 712 t->start();
Chris@55 713 Model *model = t->detachOutputModel();
Chris@55 714
Chris@55 715 if (model) {
Chris@55 716 QString imn = inputModel->objectName();
Chris@55 717 QString trn = getTransformFriendlyName(name);
Chris@55 718 if (imn != "") {
Chris@55 719 if (trn != "") {
Chris@55 720 model->setObjectName(tr("%1: %2").arg(imn).arg(trn));
Chris@55 721 } else {
Chris@55 722 model->setObjectName(imn);
Chris@55 723 }
Chris@55 724 } else if (trn != "") {
Chris@55 725 model->setObjectName(trn);
Chris@55 726 }
Chris@55 727 }
Chris@55 728
Chris@55 729 return model;
Chris@0 730 }
Chris@0 731
Chris@0 732 void
Chris@0 733 TransformFactory::transformFinished()
Chris@0 734 {
Chris@0 735 QObject *s = sender();
Chris@0 736 Transform *transform = dynamic_cast<Transform *>(s);
Chris@0 737
Chris@0 738 if (!transform) {
Chris@0 739 std::cerr << "WARNING: TransformFactory::transformFinished: sender is not a transform" << std::endl;
Chris@0 740 return;
Chris@0 741 }
Chris@0 742
Chris@0 743 transform->wait(); // unnecessary but reassuring
Chris@0 744 delete transform;
Chris@0 745 }
Chris@0 746