annotate transform/TransformFactory.cpp @ 35:06787742542a

* Add a bit of resistance to pane dragging so as to make it harder to inadvertently drag in the other axis from the one you intended
author Chris Cannam
date Fri, 22 Sep 2006 16:46:10 +0000
parents 8ad306d8a568
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