annotate transform/TransformFactory.cpp @ 39:f18093617b78

* Introduce WritableWaveFileModel, and use it as an output model for audio real-time plugin transforms. Updates aren't working correctly yet.
author Chris Cannam
date Tue, 03 Oct 2006 14:17:37 +0000
parents 06787742542a
children fbd7a497fd89
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@0 31 #include <iostream>
Chris@0 32 #include <set>
Chris@0 33
Chris@0 34 #include <QRegExp>
Chris@0 35
Chris@0 36 TransformFactory *
Chris@0 37 TransformFactory::m_instance = new TransformFactory;
Chris@0 38
Chris@0 39 TransformFactory *
Chris@0 40 TransformFactory::getInstance()
Chris@0 41 {
Chris@0 42 return m_instance;
Chris@0 43 }
Chris@0 44
Chris@0 45 TransformFactory::~TransformFactory()
Chris@0 46 {
Chris@0 47 }
Chris@0 48
Chris@0 49 TransformFactory::TransformList
Chris@0 50 TransformFactory::getAllTransforms()
Chris@0 51 {
Chris@0 52 if (m_transforms.empty()) populateTransforms();
Chris@0 53
Chris@34 54 std::set<TransformDesc> dset;
Chris@0 55 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@0 56 i != m_transforms.end(); ++i) {
Chris@34 57 dset.insert(i->second);
Chris@34 58 }
Chris@34 59
Chris@34 60 TransformList list;
Chris@34 61 for (std::set<TransformDesc>::const_iterator i = dset.begin();
Chris@34 62 i != dset.end(); ++i) {
Chris@34 63 list.push_back(*i);
Chris@0 64 }
Chris@0 65
Chris@0 66 return list;
Chris@0 67 }
Chris@0 68
Chris@0 69 std::vector<QString>
Chris@0 70 TransformFactory::getAllTransformTypes()
Chris@0 71 {
Chris@0 72 if (m_transforms.empty()) populateTransforms();
Chris@0 73
Chris@0 74 std::set<QString> types;
Chris@0 75 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@0 76 i != m_transforms.end(); ++i) {
Chris@0 77 types.insert(i->second.type);
Chris@0 78 }
Chris@0 79
Chris@0 80 std::vector<QString> rv;
Chris@0 81 for (std::set<QString>::iterator i = types.begin(); i != types.end(); ++i) {
Chris@0 82 rv.push_back(*i);
Chris@0 83 }
Chris@0 84
Chris@0 85 return rv;
Chris@0 86 }
Chris@0 87
Chris@33 88 std::vector<QString>
Chris@33 89 TransformFactory::getTransformCategories(QString transformType)
Chris@33 90 {
Chris@33 91 if (m_transforms.empty()) populateTransforms();
Chris@33 92
Chris@33 93 std::set<QString> categories;
Chris@33 94 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@33 95 i != m_transforms.end(); ++i) {
Chris@33 96 if (i->second.type == transformType) {
Chris@33 97 categories.insert(i->second.category);
Chris@33 98 }
Chris@33 99 }
Chris@33 100
Chris@33 101 bool haveEmpty = false;
Chris@33 102
Chris@33 103 std::vector<QString> rv;
Chris@33 104 for (std::set<QString>::iterator i = categories.begin();
Chris@33 105 i != categories.end(); ++i) {
Chris@33 106 if (*i != "") rv.push_back(*i);
Chris@33 107 else haveEmpty = true;
Chris@33 108 }
Chris@33 109
Chris@33 110 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@33 111
Chris@33 112 return rv;
Chris@33 113 }
Chris@33 114
Chris@33 115 std::vector<QString>
Chris@33 116 TransformFactory::getTransformMakers(QString transformType)
Chris@33 117 {
Chris@33 118 if (m_transforms.empty()) populateTransforms();
Chris@33 119
Chris@33 120 std::set<QString> makers;
Chris@33 121 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@33 122 i != m_transforms.end(); ++i) {
Chris@33 123 if (i->second.type == transformType) {
Chris@33 124 makers.insert(i->second.maker);
Chris@33 125 }
Chris@33 126 }
Chris@33 127
Chris@33 128 bool haveEmpty = false;
Chris@33 129
Chris@33 130 std::vector<QString> rv;
Chris@33 131 for (std::set<QString>::iterator i = makers.begin();
Chris@33 132 i != makers.end(); ++i) {
Chris@33 133 if (*i != "") rv.push_back(*i);
Chris@33 134 else haveEmpty = true;
Chris@33 135 }
Chris@33 136
Chris@33 137 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@33 138
Chris@33 139 return rv;
Chris@33 140 }
Chris@33 141
Chris@0 142 void
Chris@0 143 TransformFactory::populateTransforms()
Chris@0 144 {
Chris@0 145 TransformDescriptionMap transforms;
Chris@0 146
Chris@0 147 populateFeatureExtractionPlugins(transforms);
Chris@0 148 populateRealTimePlugins(transforms);
Chris@0 149
Chris@0 150 // disambiguate plugins with similar descriptions
Chris@0 151
Chris@0 152 std::map<QString, int> descriptions;
Chris@0 153
Chris@0 154 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@0 155 i != transforms.end(); ++i) {
Chris@0 156
Chris@0 157 TransformDesc desc = i->second;
Chris@0 158
Chris@0 159 ++descriptions[desc.description];
Chris@0 160 ++descriptions[QString("%1 [%2]").arg(desc.description).arg(desc.maker)];
Chris@0 161 }
Chris@0 162
Chris@0 163 std::map<QString, int> counts;
Chris@0 164 m_transforms.clear();
Chris@0 165
Chris@0 166 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@0 167 i != transforms.end(); ++i) {
Chris@0 168
Chris@0 169 TransformDesc desc = i->second;
Chris@0 170 QString name = desc.name;
Chris@0 171 QString description = desc.description;
Chris@0 172 QString maker = desc.maker;
Chris@0 173
Chris@0 174 if (descriptions[description] > 1) {
Chris@0 175 description = QString("%1 [%2]").arg(description).arg(maker);
Chris@0 176 if (descriptions[description] > 1) {
Chris@0 177 description = QString("%1 <%2>")
Chris@0 178 .arg(description).arg(++counts[description]);
Chris@0 179 }
Chris@0 180 }
Chris@0 181
Chris@0 182 desc.description = description;
Chris@0 183 m_transforms[name] = desc;
Chris@0 184 }
Chris@0 185 }
Chris@0 186
Chris@0 187 void
Chris@0 188 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
Chris@0 189 {
Chris@0 190 std::vector<QString> plugs =
Chris@0 191 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
Chris@0 192
Chris@0 193 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@0 194
Chris@0 195 QString pluginId = plugs[i];
Chris@0 196
Chris@0 197 FeatureExtractionPluginFactory *factory =
Chris@0 198 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@0 199
Chris@0 200 if (!factory) {
Chris@0 201 std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 202 continue;
Chris@0 203 }
Chris@0 204
Chris@0 205 Vamp::Plugin *plugin =
Chris@0 206 factory->instantiatePlugin(pluginId, 48000);
Chris@0 207
Chris@0 208 if (!plugin) {
Chris@0 209 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 210 continue;
Chris@0 211 }
Chris@0 212
Chris@0 213 QString pluginDescription = plugin->getDescription().c_str();
Chris@33 214 QString category = factory->getPluginCategory(pluginId);
Chris@33 215
Chris@0 216 Vamp::Plugin::OutputList outputs =
Chris@0 217 plugin->getOutputDescriptors();
Chris@0 218
Chris@0 219 for (size_t j = 0; j < outputs.size(); ++j) {
Chris@0 220
Chris@0 221 QString transformName = QString("%1:%2")
Chris@0 222 .arg(pluginId).arg(outputs[j].name.c_str());
Chris@0 223
Chris@0 224 QString userDescription;
Chris@0 225 QString friendlyName;
Chris@0 226 QString units = outputs[j].unit.c_str();
Chris@0 227
Chris@0 228 if (outputs.size() == 1) {
Chris@0 229 userDescription = pluginDescription;
Chris@0 230 friendlyName = pluginDescription;
Chris@0 231 } else {
Chris@0 232 userDescription = QString("%1: %2")
Chris@0 233 .arg(pluginDescription)
Chris@0 234 .arg(outputs[j].description.c_str());
Chris@0 235 friendlyName = outputs[j].description.c_str();
Chris@0 236 }
Chris@0 237
Chris@0 238 bool configurable = (!plugin->getPrograms().empty() ||
Chris@0 239 !plugin->getParameterDescriptors().empty());
Chris@0 240
Chris@0 241 transforms[transformName] =
Chris@34 242 TransformDesc(tr("Analysis"),
Chris@33 243 category,
Chris@0 244 transformName,
Chris@0 245 userDescription,
Chris@0 246 friendlyName,
Chris@0 247 plugin->getMaker().c_str(),
Chris@0 248 units,
Chris@0 249 configurable);
Chris@0 250 }
Chris@0 251 }
Chris@0 252 }
Chris@0 253
Chris@0 254 void
Chris@0 255 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@0 256 {
Chris@0 257 std::vector<QString> plugs =
Chris@0 258 RealTimePluginFactory::getAllPluginIdentifiers();
Chris@0 259
Chris@34 260 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@0 261
Chris@0 262 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@0 263
Chris@0 264 QString pluginId = plugs[i];
Chris@0 265
Chris@0 266 RealTimePluginFactory *factory =
Chris@0 267 RealTimePluginFactory::instanceFor(pluginId);
Chris@0 268
Chris@0 269 if (!factory) {
Chris@0 270 std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 271 continue;
Chris@0 272 }
Chris@0 273
Chris@0 274 const RealTimePluginDescriptor *descriptor =
Chris@0 275 factory->getPluginDescriptor(pluginId);
Chris@0 276
Chris@0 277 if (!descriptor) {
Chris@0 278 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@0 279 continue;
Chris@0 280 }
Chris@0 281
Chris@34 282 //!!! if (descriptor->controlOutputPortCount == 0 ||
Chris@34 283 // descriptor->audioInputPortCount == 0) continue;
Chris@0 284
Chris@35 285 // 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 286
Chris@0 287 QString pluginDescription = descriptor->name.c_str();
Chris@33 288 QString category = factory->getPluginCategory(pluginId);
Chris@34 289 bool configurable = (descriptor->parameterCount > 0);
Chris@0 290
Chris@34 291 if (descriptor->audioInputPortCount > 0) {
Chris@0 292
Chris@34 293 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
Chris@0 294
Chris@34 295 QString transformName = QString("%1:%2").arg(pluginId).arg(j);
Chris@34 296 QString userDescription;
Chris@34 297 QString units;
Chris@0 298
Chris@34 299 if (j < descriptor->controlOutputPortNames.size() &&
Chris@34 300 descriptor->controlOutputPortNames[j] != "") {
Chris@0 301
Chris@34 302 QString portName = descriptor->controlOutputPortNames[j].c_str();
Chris@0 303
Chris@34 304 userDescription = tr("%1: %2")
Chris@34 305 .arg(pluginDescription)
Chris@34 306 .arg(portName);
Chris@34 307
Chris@34 308 if (unitRE.indexIn(portName) >= 0) {
Chris@34 309 units = unitRE.cap(1);
Chris@34 310 }
Chris@34 311
Chris@34 312 } else if (descriptor->controlOutputPortCount > 1) {
Chris@34 313
Chris@34 314 userDescription = tr("%1: Output %2")
Chris@34 315 .arg(pluginDescription)
Chris@34 316 .arg(j + 1);
Chris@34 317
Chris@34 318 } else {
Chris@34 319
Chris@34 320 userDescription = pluginDescription;
Chris@0 321 }
Chris@0 322
Chris@0 323
Chris@34 324 transforms[transformName] =
Chris@34 325 TransformDesc(tr("Effects Measurements"),
Chris@34 326 category,
Chris@34 327 transformName,
Chris@34 328 userDescription,
Chris@34 329 userDescription,
Chris@34 330 descriptor->maker.c_str(),
Chris@34 331 units,
Chris@34 332 configurable);
Chris@34 333 }
Chris@34 334 }
Chris@0 335
Chris@34 336 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@0 337
Chris@34 338 if (descriptor->audioOutputPortCount > 0) {
Chris@34 339
Chris@34 340 QString transformName = QString("%1:A").arg(pluginId);
Chris@34 341 QString type = tr("Effects");
Chris@34 342 if (descriptor->audioInputPortCount == 0) {
Chris@34 343 type = tr("Generators");
Chris@34 344 }
Chris@34 345
Chris@34 346 transforms[transformName] =
Chris@34 347 TransformDesc(type,
Chris@34 348 category,
Chris@34 349 transformName,
Chris@34 350 pluginDescription,
Chris@34 351 pluginDescription,
Chris@34 352 descriptor->maker.c_str(),
Chris@34 353 "",
Chris@34 354 configurable);
Chris@0 355 }
Chris@34 356 }
Chris@0 357 }
Chris@0 358 }
Chris@0 359
Chris@0 360 QString
Chris@0 361 TransformFactory::getTransformDescription(TransformName name)
Chris@0 362 {
Chris@0 363 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 364 return m_transforms[name].description;
Chris@0 365 } else return "";
Chris@0 366 }
Chris@0 367
Chris@0 368 QString
Chris@0 369 TransformFactory::getTransformFriendlyName(TransformName name)
Chris@0 370 {
Chris@0 371 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 372 return m_transforms[name].friendlyName;
Chris@0 373 } else return "";
Chris@0 374 }
Chris@0 375
Chris@0 376 QString
Chris@0 377 TransformFactory::getTransformUnits(TransformName name)
Chris@0 378 {
Chris@0 379 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 380 return m_transforms[name].units;
Chris@0 381 } else return "";
Chris@0 382 }
Chris@0 383
Chris@0 384 bool
Chris@0 385 TransformFactory::isTransformConfigurable(TransformName name)
Chris@0 386 {
Chris@0 387 if (m_transforms.find(name) != m_transforms.end()) {
Chris@0 388 return m_transforms[name].configurable;
Chris@0 389 } else return false;
Chris@0 390 }
Chris@0 391
Chris@0 392 bool
Chris@0 393 TransformFactory::getTransformChannelRange(TransformName name,
Chris@0 394 int &min, int &max)
Chris@0 395 {
Chris@0 396 QString id = name.section(':', 0, 2);
Chris@0 397
Chris@0 398 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 399
Chris@0 400 Vamp::Plugin *plugin =
Chris@0 401 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@0 402 instantiatePlugin(id, 48000);
Chris@0 403 if (!plugin) return false;
Chris@0 404
Chris@0 405 min = plugin->getMinChannelCount();
Chris@0 406 max = plugin->getMaxChannelCount();
Chris@0 407 delete plugin;
Chris@0 408
Chris@0 409 return true;
Chris@0 410
Chris@0 411 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 412
Chris@0 413 const RealTimePluginDescriptor *descriptor =
Chris@0 414 RealTimePluginFactory::instanceFor(id)->
Chris@0 415 getPluginDescriptor(id);
Chris@0 416 if (!descriptor) return false;
Chris@0 417
Chris@0 418 min = descriptor->audioInputPortCount;
Chris@0 419 max = descriptor->audioInputPortCount;
Chris@0 420
Chris@0 421 return true;
Chris@0 422 }
Chris@0 423
Chris@0 424 return false;
Chris@0 425 }
Chris@0 426
Chris@0 427 bool
Chris@0 428 TransformFactory::getChannelRange(TransformName name, Vamp::PluginBase *plugin,
Chris@0 429 int &minChannels, int &maxChannels)
Chris@0 430 {
Chris@0 431 Vamp::Plugin *vp = 0;
Chris@28 432 if ((vp = dynamic_cast<Vamp::Plugin *>(plugin)) ||
Chris@28 433 (vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin))) {
Chris@0 434 minChannels = vp->getMinChannelCount();
Chris@0 435 maxChannels = vp->getMaxChannelCount();
Chris@0 436 return true;
Chris@0 437 } else {
Chris@0 438 return getTransformChannelRange(name, minChannels, maxChannels);
Chris@0 439 }
Chris@0 440 }
Chris@0 441
Chris@0 442 bool
Chris@0 443 TransformFactory::getConfigurationForTransform(TransformName name,
Chris@0 444 Model *inputModel,
Chris@27 445 PluginTransform::ExecutionContext &context,
Chris@0 446 QString &configurationXml)
Chris@0 447 {
Chris@0 448 QString id = name.section(':', 0, 2);
Chris@0 449 QString output = name.section(':', 3);
Chris@0 450
Chris@0 451 bool ok = false;
Chris@0 452 configurationXml = m_lastConfigurations[name];
Chris@0 453
Chris@0 454 // std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl;
Chris@0 455
Chris@0 456 Vamp::PluginBase *plugin = 0;
Chris@0 457
Chris@10 458 bool frequency = false;
Chris@10 459
Chris@0 460 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 461
Chris@10 462 Vamp::Plugin *vp =
Chris@10 463 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
Chris@0 464 (id, inputModel->getSampleRate());
Chris@10 465 if (vp) {
Chris@10 466 plugin = vp;
Chris@10 467 frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
Chris@10 468 }
Chris@0 469
Chris@0 470 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 471
Chris@0 472 plugin = RealTimePluginFactory::instanceFor(id)->instantiatePlugin
Chris@0 473 (id, 0, 0, inputModel->getSampleRate(), 1024, 1);
Chris@0 474 }
Chris@0 475
Chris@0 476 if (plugin) {
Chris@27 477
Chris@27 478 context = PluginTransform::ExecutionContext(context.channel, plugin);
Chris@27 479
Chris@0 480 if (configurationXml != "") {
Chris@0 481 PluginXml(plugin).setParametersFromXml(configurationXml);
Chris@0 482 }
Chris@0 483
Chris@0 484 int sourceChannels = 1;
Chris@0 485 if (dynamic_cast<DenseTimeValueModel *>(inputModel)) {
Chris@0 486 sourceChannels = dynamic_cast<DenseTimeValueModel *>(inputModel)
Chris@0 487 ->getChannelCount();
Chris@0 488 }
Chris@0 489
Chris@0 490 int minChannels = 1, maxChannels = sourceChannels;
Chris@0 491 getChannelRange(name, plugin, minChannels, maxChannels);
Chris@0 492
Chris@0 493 int targetChannels = sourceChannels;
Chris@0 494 if (sourceChannels < minChannels) targetChannels = minChannels;
Chris@0 495 if (sourceChannels > maxChannels) targetChannels = maxChannels;
Chris@0 496
Chris@27 497 int defaultChannel = context.channel;
Chris@0 498
Chris@0 499 PluginParameterDialog *dialog = new PluginParameterDialog(plugin,
Chris@0 500 sourceChannels,
Chris@0 501 targetChannels,
Chris@0 502 defaultChannel,
Chris@10 503 output,
Chris@10 504 true,
Chris@10 505 frequency);
Chris@0 506 if (dialog->exec() == QDialog::Accepted) {
Chris@0 507 ok = true;
Chris@0 508 }
Chris@0 509 configurationXml = PluginXml(plugin).toXmlString();
Chris@27 510 context.channel = dialog->getChannel();
Chris@26 511
Chris@27 512 dialog->getProcessingParameters(context.stepSize,
Chris@27 513 context.blockSize,
Chris@27 514 context.windowType);
Chris@27 515
Chris@27 516 context.makeConsistentWithPlugin(plugin);
Chris@26 517
Chris@0 518 delete dialog;
Chris@0 519 delete plugin;
Chris@0 520 }
Chris@0 521
Chris@0 522 if (ok) m_lastConfigurations[name] = configurationXml;
Chris@0 523
Chris@0 524 return ok;
Chris@0 525 }
Chris@0 526
Chris@0 527 Transform *
Chris@0 528 TransformFactory::createTransform(TransformName name, Model *inputModel,
Chris@27 529 const PluginTransform::ExecutionContext &context,
Chris@27 530 QString configurationXml, bool start)
Chris@0 531 {
Chris@0 532 Transform *transform = 0;
Chris@0 533
Chris@0 534 QString id = name.section(':', 0, 2);
Chris@0 535 QString output = name.section(':', 3);
Chris@0 536
Chris@0 537 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@0 538 transform = new FeatureExtractionPluginTransform(inputModel,
Chris@0 539 id,
Chris@27 540 context,
Chris@0 541 configurationXml,
Chris@0 542 output);
Chris@0 543 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@0 544 transform = new RealTimePluginTransform(inputModel,
Chris@0 545 id,
Chris@27 546 context,
Chris@0 547 configurationXml,
Chris@0 548 getTransformUnits(name),
Chris@34 549 output == "A" ? -1 :
Chris@0 550 output.toInt());
Chris@0 551 } else {
Chris@0 552 std::cerr << "TransformFactory::createTransform: Unknown transform \""
Chris@0 553 << name.toStdString() << "\"" << std::endl;
Chris@0 554 return transform;
Chris@0 555 }
Chris@0 556
Chris@0 557 if (start && transform) transform->start();
Chris@0 558 transform->setObjectName(name);
Chris@0 559 return transform;
Chris@0 560 }
Chris@0 561
Chris@0 562 Model *
Chris@0 563 TransformFactory::transform(TransformName name, Model *inputModel,
Chris@27 564 const PluginTransform::ExecutionContext &context,
Chris@27 565 QString configurationXml)
Chris@0 566 {
Chris@27 567 Transform *t = createTransform(name, inputModel, context,
Chris@0 568 configurationXml, false);
Chris@0 569
Chris@0 570 if (!t) return 0;
Chris@0 571
Chris@0 572 connect(t, SIGNAL(finished()), this, SLOT(transformFinished()));
Chris@0 573
Chris@0 574 t->start();
Chris@0 575 return t->detachOutputModel();
Chris@0 576 }
Chris@0 577
Chris@0 578 void
Chris@0 579 TransformFactory::transformFinished()
Chris@0 580 {
Chris@0 581 QObject *s = sender();
Chris@0 582 Transform *transform = dynamic_cast<Transform *>(s);
Chris@0 583
Chris@0 584 if (!transform) {
Chris@0 585 std::cerr << "WARNING: TransformFactory::transformFinished: sender is not a transform" << std::endl;
Chris@0 586 return;
Chris@0 587 }
Chris@0 588
Chris@0 589 transform->wait(); // unnecessary but reassuring
Chris@0 590 delete transform;
Chris@0 591 }
Chris@0 592