annotate transform/TransformFactory.cpp @ 53:94f1c2747de4

* Tidy up plugin parameter dialog by switching it to a simple constructor with separate methods for passing in the additional options if necessary * Fix sizing problem on advanced pane toggle in plugin parameter dialog * Make a start on passing in list of candidate input models for transform
author Chris Cannam
date Wed, 11 Oct 2006 16:18:51 +0000
parents 527598e2fa10
children ec77936c268e
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@0 7 This file copyright 2006 Chris Cannam.
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@0 152 // disambiguate plugins with similar descriptions
Chris@0 153
Chris@0 154 std::map<QString, int> descriptions;
Chris@0 155
Chris@0 156 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@0 157 i != transforms.end(); ++i) {
Chris@0 158
Chris@0 159 TransformDesc desc = i->second;
Chris@0 160
Chris@0 161 ++descriptions[desc.description];
Chris@0 162 ++descriptions[QString("%1 [%2]").arg(desc.description).arg(desc.maker)];
Chris@0 163 }
Chris@0 164
Chris@0 165 std::map<QString, int> counts;
Chris@0 166 m_transforms.clear();
Chris@0 167
Chris@0 168 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@0 169 i != transforms.end(); ++i) {
Chris@0 170
Chris@0 171 TransformDesc desc = i->second;
Chris@0 172 QString name = desc.name;
Chris@0 173 QString description = desc.description;
Chris@0 174 QString maker = desc.maker;
Chris@0 175
Chris@0 176 if (descriptions[description] > 1) {
Chris@0 177 description = QString("%1 [%2]").arg(description).arg(maker);
Chris@0 178 if (descriptions[description] > 1) {
Chris@0 179 description = QString("%1 <%2>")
Chris@0 180 .arg(description).arg(++counts[description]);
Chris@0 181 }
Chris@0 182 }
Chris@0 183
Chris@0 184 desc.description = description;
Chris@0 185 m_transforms[name] = desc;
Chris@0 186 }
Chris@0 187 }
Chris@0 188
Chris@0 189 void
Chris@0 190 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
Chris@0 191 {
Chris@0 192 std::vector<QString> plugs =
Chris@0 193 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
Chris@0 194
Chris@0 195 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@0 196
Chris@0 197 QString pluginId = plugs[i];
Chris@0 198
Chris@0 199 FeatureExtractionPluginFactory *factory =
Chris@0 200 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@0 201
Chris@0 202 if (!factory) {
Chris@0 203 std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 204 continue;
Chris@0 205 }
Chris@0 206
Chris@0 207 Vamp::Plugin *plugin =
Chris@0 208 factory->instantiatePlugin(pluginId, 48000);
Chris@0 209
Chris@0 210 if (!plugin) {
Chris@0 211 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 212 continue;
Chris@0 213 }
Chris@0 214
Chris@0 215 QString pluginDescription = plugin->getDescription().c_str();
Chris@33 216 QString category = factory->getPluginCategory(pluginId);
Chris@33 217
Chris@0 218 Vamp::Plugin::OutputList outputs =
Chris@0 219 plugin->getOutputDescriptors();
Chris@0 220
Chris@0 221 for (size_t j = 0; j < outputs.size(); ++j) {
Chris@0 222
Chris@0 223 QString transformName = QString("%1:%2")
Chris@0 224 .arg(pluginId).arg(outputs[j].name.c_str());
Chris@0 225
Chris@0 226 QString userDescription;
Chris@0 227 QString friendlyName;
Chris@0 228 QString units = outputs[j].unit.c_str();
Chris@0 229
Chris@0 230 if (outputs.size() == 1) {
Chris@0 231 userDescription = pluginDescription;
Chris@0 232 friendlyName = pluginDescription;
Chris@0 233 } else {
Chris@0 234 userDescription = QString("%1: %2")
Chris@0 235 .arg(pluginDescription)
Chris@0 236 .arg(outputs[j].description.c_str());
Chris@0 237 friendlyName = outputs[j].description.c_str();
Chris@0 238 }
Chris@0 239
Chris@0 240 bool configurable = (!plugin->getPrograms().empty() ||
Chris@0 241 !plugin->getParameterDescriptors().empty());
Chris@0 242
Chris@0 243 transforms[transformName] =
Chris@34 244 TransformDesc(tr("Analysis"),
Chris@33 245 category,
Chris@0 246 transformName,
Chris@0 247 userDescription,
Chris@0 248 friendlyName,
Chris@0 249 plugin->getMaker().c_str(),
Chris@0 250 units,
Chris@0 251 configurable);
Chris@0 252 }
Chris@0 253 }
Chris@0 254 }
Chris@0 255
Chris@0 256 void
Chris@0 257 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@0 258 {
Chris@0 259 std::vector<QString> plugs =
Chris@0 260 RealTimePluginFactory::getAllPluginIdentifiers();
Chris@0 261
Chris@34 262 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@0 263
Chris@0 264 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@0 265
Chris@0 266 QString pluginId = plugs[i];
Chris@0 267
Chris@0 268 RealTimePluginFactory *factory =
Chris@0 269 RealTimePluginFactory::instanceFor(pluginId);
Chris@0 270
Chris@0 271 if (!factory) {
Chris@0 272 std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 273 continue;
Chris@0 274 }
Chris@0 275
Chris@0 276 const RealTimePluginDescriptor *descriptor =
Chris@0 277 factory->getPluginDescriptor(pluginId);
Chris@0 278
Chris@0 279 if (!descriptor) {
Chris@0 280 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 281 continue;
Chris@0 282 }
Chris@0 283
Chris@34 284 //!!! if (descriptor->controlOutputPortCount == 0 ||
Chris@34 285 // descriptor->audioInputPortCount == 0) continue;
Chris@0 286
Chris@35 287 // 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 288
Chris@0 289 QString pluginDescription = descriptor->name.c_str();
Chris@33 290 QString category = factory->getPluginCategory(pluginId);
Chris@34 291 bool configurable = (descriptor->parameterCount > 0);
Chris@0 292
Chris@34 293 if (descriptor->audioInputPortCount > 0) {
Chris@0 294
Chris@34 295 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
Chris@0 296
Chris@34 297 QString transformName = QString("%1:%2").arg(pluginId).arg(j);
Chris@34 298 QString userDescription;
Chris@34 299 QString units;
Chris@0 300
Chris@34 301 if (j < descriptor->controlOutputPortNames.size() &&
Chris@34 302 descriptor->controlOutputPortNames[j] != "") {
Chris@0 303
Chris@34 304 QString portName = descriptor->controlOutputPortNames[j].c_str();
Chris@0 305
Chris@34 306 userDescription = tr("%1: %2")
Chris@34 307 .arg(pluginDescription)
Chris@34 308 .arg(portName);
Chris@34 309
Chris@34 310 if (unitRE.indexIn(portName) >= 0) {
Chris@34 311 units = unitRE.cap(1);
Chris@34 312 }
Chris@34 313
Chris@34 314 } else if (descriptor->controlOutputPortCount > 1) {
Chris@34 315
Chris@34 316 userDescription = tr("%1: Output %2")
Chris@34 317 .arg(pluginDescription)
Chris@34 318 .arg(j + 1);
Chris@34 319
Chris@34 320 } else {
Chris@34 321
Chris@34 322 userDescription = pluginDescription;
Chris@0 323 }
Chris@0 324
Chris@0 325
Chris@34 326 transforms[transformName] =
Chris@52 327 TransformDesc(tr("Effects Data"),
Chris@34 328 category,
Chris@34 329 transformName,
Chris@34 330 userDescription,
Chris@34 331 userDescription,
Chris@34 332 descriptor->maker.c_str(),
Chris@34 333 units,
Chris@34 334 configurable);
Chris@34 335 }
Chris@34 336 }
Chris@0 337
Chris@34 338 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@0 339
Chris@34 340 if (descriptor->audioOutputPortCount > 0) {
Chris@34 341
Chris@34 342 QString transformName = QString("%1:A").arg(pluginId);
Chris@34 343 QString type = tr("Effects");
Chris@34 344 if (descriptor->audioInputPortCount == 0) {
Chris@34 345 type = tr("Generators");
Chris@34 346 }
Chris@34 347
Chris@34 348 transforms[transformName] =
Chris@34 349 TransformDesc(type,
Chris@34 350 category,
Chris@34 351 transformName,
Chris@34 352 pluginDescription,
Chris@34 353 pluginDescription,
Chris@34 354 descriptor->maker.c_str(),
Chris@34 355 "",
Chris@34 356 configurable);
Chris@0 357 }
Chris@34 358 }
Chris@0 359 }
Chris@0 360 }
Chris@0 361
Chris@0 362 QString
Chris@0 363 TransformFactory::getTransformDescription(TransformName name)
Chris@0 364 {
Chris@0 365 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 366 return m_transforms[name].description;
Chris@0 367 } else return "";
Chris@0 368 }
Chris@0 369
Chris@0 370 QString
Chris@0 371 TransformFactory::getTransformFriendlyName(TransformName name)
Chris@0 372 {
Chris@0 373 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 374 return m_transforms[name].friendlyName;
Chris@0 375 } else return "";
Chris@0 376 }
Chris@0 377
Chris@0 378 QString
Chris@0 379 TransformFactory::getTransformUnits(TransformName name)
Chris@0 380 {
Chris@0 381 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 382 return m_transforms[name].units;
Chris@0 383 } else return "";
Chris@0 384 }
Chris@0 385
Chris@0 386 bool
Chris@0 387 TransformFactory::isTransformConfigurable(TransformName name)
Chris@0 388 {
Chris@0 389 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 390 return m_transforms[name].configurable;
Chris@0 391 } else return false;
Chris@0 392 }
Chris@0 393
Chris@0 394 bool
Chris@0 395 TransformFactory::getTransformChannelRange(TransformName name,
Chris@0 396 int &min, int &max)
Chris@0 397 {
Chris@0 398 QString id = name.section(':', 0, 2);
Chris@0 399
Chris@0 400 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 401
Chris@0 402 Vamp::Plugin *plugin =
Chris@0 403 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@0 404 instantiatePlugin(id, 48000);
Chris@0 405 if (!plugin) return false;
Chris@0 406
Chris@0 407 min = plugin->getMinChannelCount();
Chris@0 408 max = plugin->getMaxChannelCount();
Chris@0 409 delete plugin;
Chris@0 410
Chris@0 411 return true;
Chris@0 412
Chris@0 413 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 414
Chris@0 415 const RealTimePluginDescriptor *descriptor =
Chris@0 416 RealTimePluginFactory::instanceFor(id)->
Chris@0 417 getPluginDescriptor(id);
Chris@0 418 if (!descriptor) return false;
Chris@0 419
Chris@0 420 min = descriptor->audioInputPortCount;
Chris@0 421 max = descriptor->audioInputPortCount;
Chris@0 422
Chris@0 423 return true;
Chris@0 424 }
Chris@0 425
Chris@0 426 return false;
Chris@0 427 }
Chris@0 428
Chris@0 429 bool
Chris@0 430 TransformFactory::getChannelRange(TransformName name, Vamp::PluginBase *plugin,
Chris@0 431 int &minChannels, int &maxChannels)
Chris@0 432 {
Chris@0 433 Vamp::Plugin *vp = 0;
Chris@28 434 if ((vp = dynamic_cast<Vamp::Plugin *>(plugin)) ||
Chris@28 435 (vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin))) {
Chris@0 436 minChannels = vp->getMinChannelCount();
Chris@0 437 maxChannels = vp->getMaxChannelCount();
Chris@0 438 return true;
Chris@0 439 } else {
Chris@0 440 return getTransformChannelRange(name, minChannels, maxChannels);
Chris@0 441 }
Chris@0 442 }
Chris@0 443
Chris@53 444 Model *
Chris@0 445 TransformFactory::getConfigurationForTransform(TransformName name,
Chris@53 446 const std::vector<Model *> &candidateInputModels,
Chris@27 447 PluginTransform::ExecutionContext &context,
Chris@41 448 QString &configurationXml,
Chris@41 449 AudioCallbackPlaySource *source)
Chris@0 450 {
Chris@53 451 if (candidateInputModels.empty()) return 0;
Chris@53 452
Chris@53 453 Model *inputModel = candidateInputModels[0]; //!!! for now
Chris@53 454
Chris@0 455 QString id = name.section(':', 0, 2);
Chris@0 456 QString output = name.section(':', 3);
Chris@53 457 QString outputLabel = "";
Chris@0 458
Chris@0 459 bool ok = false;
Chris@0 460 configurationXml = m_lastConfigurations[name];
Chris@0 461
Chris@0 462 // std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl;
Chris@0 463
Chris@0 464 Vamp::PluginBase *plugin = 0;
Chris@0 465
Chris@10 466 bool frequency = false;
Chris@41 467 bool effect = false;
Chris@10 468
Chris@0 469 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 470
Chris@10 471 Vamp::Plugin *vp =
Chris@10 472 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
Chris@0 473 (id, inputModel->getSampleRate());
Chris@53 474
Chris@10 475 if (vp) {
Chris@53 476
Chris@10 477 plugin = vp;
Chris@10 478 frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
Chris@53 479
Chris@53 480 std::vector<Vamp::Plugin::OutputDescriptor> od =
Chris@53 481 vp->getOutputDescriptors();
Chris@53 482 if (od.size() > 1) {
Chris@53 483 for (size_t i = 0; i < od.size(); ++i) {
Chris@53 484 if (od[i].name == output.toStdString()) {
Chris@53 485 outputLabel = od[i].description.c_str();
Chris@53 486 break;
Chris@53 487 }
Chris@53 488 }
Chris@53 489 }
Chris@10 490 }
Chris@0 491
Chris@0 492 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 493
Chris@41 494 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
Chris@41 495 const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id);
Chris@41 496
Chris@41 497 if (desc->audioInputPortCount > 0 &&
Chris@41 498 desc->audioOutputPortCount > 0 &&
Chris@41 499 !desc->isSynth) {
Chris@41 500 effect = true;
Chris@41 501 }
Chris@41 502
Chris@53 503 if (output != "A") {
Chris@53 504 int outputNo = output.toInt();
Chris@53 505 if (outputNo >= 0 && outputNo < desc->controlOutputPortCount) {
Chris@53 506 outputLabel = desc->controlOutputPortNames[outputNo].c_str();
Chris@53 507 }
Chris@53 508 }
Chris@53 509
Chris@41 510 size_t sampleRate = inputModel->getSampleRate();
Chris@41 511 size_t blockSize = 1024;
Chris@41 512 size_t channels = 1;
Chris@41 513 if (effect && source) {
Chris@41 514 sampleRate = source->getTargetSampleRate();
Chris@41 515 blockSize = source->getTargetBlockSize();
Chris@41 516 channels = source->getTargetChannelCount();
Chris@41 517 }
Chris@41 518
Chris@41 519 RealTimePluginInstance *rtp = factory->instantiatePlugin
Chris@41 520 (id, 0, 0, sampleRate, blockSize, channels);
Chris@41 521
Chris@41 522 plugin = rtp;
Chris@41 523
Chris@41 524 if (effect && source && rtp) {
Chris@41 525 source->setAuditioningPlugin(rtp);
Chris@41 526 }
Chris@0 527 }
Chris@0 528
Chris@0 529 if (plugin) {
Chris@27 530
Chris@27 531 context = PluginTransform::ExecutionContext(context.channel, plugin);
Chris@27 532
Chris@0 533 if (configurationXml != "") {
Chris@0 534 PluginXml(plugin).setParametersFromXml(configurationXml);
Chris@0 535 }
Chris@0 536
Chris@0 537 int sourceChannels = 1;
Chris@0 538 if (dynamic_cast<DenseTimeValueModel *>(inputModel)) {
Chris@0 539 sourceChannels = dynamic_cast<DenseTimeValueModel *>(inputModel)
Chris@0 540 ->getChannelCount();
Chris@0 541 }
Chris@0 542
Chris@0 543 int minChannels = 1, maxChannels = sourceChannels;
Chris@0 544 getChannelRange(name, plugin, minChannels, maxChannels);
Chris@0 545
Chris@0 546 int targetChannels = sourceChannels;
Chris@44 547 if (!effect) {
Chris@44 548 if (sourceChannels < minChannels) targetChannels = minChannels;
Chris@44 549 if (sourceChannels > maxChannels) targetChannels = maxChannels;
Chris@44 550 }
Chris@0 551
Chris@27 552 int defaultChannel = context.channel;
Chris@0 553
Chris@53 554 PluginParameterDialog *dialog = new PluginParameterDialog(plugin);
Chris@53 555
Chris@53 556 dialog->setChannelArrangement(sourceChannels, targetChannels,
Chris@53 557 defaultChannel);
Chris@53 558
Chris@53 559 dialog->setOutputLabel(outputLabel);
Chris@53 560
Chris@53 561 dialog->setShowProcessingOptions(true, frequency);
Chris@53 562
Chris@0 563 if (dialog->exec() == QDialog::Accepted) {
Chris@0 564 ok = true;
Chris@0 565 }
Chris@42 566
Chris@0 567 configurationXml = PluginXml(plugin).toXmlString();
Chris@27 568 context.channel = dialog->getChannel();
Chris@26 569
Chris@27 570 dialog->getProcessingParameters(context.stepSize,
Chris@27 571 context.blockSize,
Chris@27 572 context.windowType);
Chris@27 573
Chris@27 574 context.makeConsistentWithPlugin(plugin);
Chris@26 575
Chris@0 576 delete dialog;
Chris@41 577
Chris@41 578 if (effect && source) {
Chris@41 579 source->setAuditioningPlugin(0); // will delete our plugin
Chris@41 580 } else {
Chris@41 581 delete plugin;
Chris@41 582 }
Chris@0 583 }
Chris@0 584
Chris@0 585 if (ok) m_lastConfigurations[name] = configurationXml;
Chris@0 586
Chris@53 587 return ok ? inputModel : 0;
Chris@0 588 }
Chris@0 589
Chris@0 590 Transform *
Chris@0 591 TransformFactory::createTransform(TransformName name, Model *inputModel,
Chris@27 592 const PluginTransform::ExecutionContext &context,
Chris@27 593 QString configurationXml, bool start)
Chris@0 594 {
Chris@0 595 Transform *transform = 0;
Chris@0 596
Chris@0 597 QString id = name.section(':', 0, 2);
Chris@0 598 QString output = name.section(':', 3);
Chris@0 599
Chris@0 600 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 601 transform = new FeatureExtractionPluginTransform(inputModel,
Chris@0 602 id,
Chris@27 603 context,
Chris@0 604 configurationXml,
Chris@0 605 output);
Chris@0 606 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 607 transform = new RealTimePluginTransform(inputModel,
Chris@0 608 id,
Chris@27 609 context,
Chris@0 610 configurationXml,
Chris@0 611 getTransformUnits(name),
Chris@34 612 output == "A" ? -1 :
Chris@0 613 output.toInt());
Chris@0 614 } else {
Chris@0 615 std::cerr << "TransformFactory::createTransform: Unknown transform \""
Chris@0 616 << name.toStdString() << "\"" << std::endl;
Chris@0 617 return transform;
Chris@0 618 }
Chris@0 619
Chris@0 620 if (start && transform) transform->start();
Chris@0 621 transform->setObjectName(name);
Chris@0 622 return transform;
Chris@0 623 }
Chris@0 624
Chris@0 625 Model *
Chris@0 626 TransformFactory::transform(TransformName name, Model *inputModel,
Chris@27 627 const PluginTransform::ExecutionContext &context,
Chris@27 628 QString configurationXml)
Chris@0 629 {
Chris@27 630 Transform *t = createTransform(name, inputModel, context,
Chris@0 631 configurationXml, false);
Chris@0 632
Chris@0 633 if (!t) return 0;
Chris@0 634
Chris@0 635 connect(t, SIGNAL(finished()), this, SLOT(transformFinished()));
Chris@0 636
Chris@0 637 t->start();
Chris@0 638 return t->detachOutputModel();
Chris@0 639 }
Chris@0 640
Chris@0 641 void
Chris@0 642 TransformFactory::transformFinished()
Chris@0 643 {
Chris@0 644 QObject *s = sender();
Chris@0 645 Transform *transform = dynamic_cast<Transform *>(s);
Chris@0 646
Chris@0 647 if (!transform) {
Chris@0 648 std::cerr << "WARNING: TransformFactory::transformFinished: sender is not a transform" << std::endl;
Chris@0 649 return;
Chris@0 650 }
Chris@0 651
Chris@0 652 transform->wait(); // unnecessary but reassuring
Chris@0 653 delete transform;
Chris@0 654 }
Chris@0 655