annotate transform/TransformFactory.cpp @ 588:d04b8674b710

* Try to identify the properly conformant audio file structure written out by Sonic Annotator (but we still don't actually import it yet)
author Chris Cannam
date Wed, 13 May 2009 13:30:08 +0000
parents ecbd99d5d2c4
children 3f6d9930bc28
rev   line source
Chris@330 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@330 2
Chris@330 3 /*
Chris@330 4 Sonic Visualiser
Chris@330 5 An audio file viewer and annotation editor.
Chris@330 6 Centre for Digital Music, Queen Mary, University of London.
Chris@330 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@330 8
Chris@330 9 This program is free software; you can redistribute it and/or
Chris@330 10 modify it under the terms of the GNU General Public License as
Chris@330 11 published by the Free Software Foundation; either version 2 of the
Chris@330 12 License, or (at your option) any later version. See the file
Chris@330 13 COPYING included with this distribution for more information.
Chris@330 14 */
Chris@330 15
Chris@330 16 #include "TransformFactory.h"
Chris@330 17
Chris@330 18 #include "plugin/FeatureExtractionPluginFactory.h"
Chris@330 19 #include "plugin/RealTimePluginFactory.h"
Chris@332 20 #include "plugin/RealTimePluginInstance.h"
Chris@330 21 #include "plugin/PluginXml.h"
Chris@330 22
Chris@475 23 #include <vamp-hostsdk/Plugin.h>
Chris@475 24 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@475 25 #include <vamp-hostsdk/PluginWrapper.h>
Chris@330 26
Chris@457 27 #include "rdf/PluginRDFIndexer.h"
Chris@457 28 #include "rdf/PluginRDFDescription.h"
Chris@457 29
Chris@446 30 #include "base/XmlExportable.h"
Chris@446 31
Chris@330 32 #include <iostream>
Chris@330 33 #include <set>
Chris@330 34
Chris@330 35 #include <QRegExp>
Chris@350 36 #include <QTextStream>
Chris@330 37
Chris@460 38 #include "base/Thread.h"
Chris@460 39
Chris@443 40 using std::cerr;
Chris@443 41 using std::endl;
Chris@443 42
Chris@330 43 TransformFactory *
Chris@330 44 TransformFactory::m_instance = new TransformFactory;
Chris@330 45
Chris@330 46 TransformFactory *
Chris@330 47 TransformFactory::getInstance()
Chris@330 48 {
Chris@330 49 return m_instance;
Chris@330 50 }
Chris@330 51
Chris@574 52 void
Chris@574 53 TransformFactory::deleteInstance()
Chris@574 54 {
Chris@574 55 std::cerr << "TransformFactory::deleteInstance called" << std::endl;
Chris@574 56 delete m_instance;
Chris@574 57 m_instance = 0;
Chris@574 58 }
Chris@574 59
Chris@457 60 TransformFactory::TransformFactory() :
Chris@457 61 m_transformsPopulated(false),
Chris@477 62 m_uninstalledTransformsPopulated(false),
Chris@574 63 m_thread(0),
Chris@574 64 m_exiting(false)
Chris@457 65 {
Chris@457 66 }
Chris@457 67
Chris@330 68 TransformFactory::~TransformFactory()
Chris@330 69 {
Chris@574 70 m_exiting = true;
Chris@574 71 if (m_thread) {
Chris@574 72 std::cerr << "TransformFactory::~TransformFactory: waiting on thread" << std::endl;
Chris@574 73 m_thread->wait();
Chris@574 74 delete m_thread;
Chris@574 75 }
Chris@330 76 }
Chris@330 77
Chris@477 78 void
Chris@477 79 TransformFactory::startPopulationThread()
Chris@477 80 {
Chris@482 81 m_uninstalledTransformsMutex.lock();
Chris@477 82
Chris@482 83 if (m_thread) {
Chris@482 84 m_uninstalledTransformsMutex.unlock();
Chris@482 85 return;
Chris@482 86 }
Chris@482 87 m_thread = new UninstalledTransformsPopulateThread(this);
Chris@477 88
Chris@482 89 m_uninstalledTransformsMutex.unlock();
Chris@482 90
Chris@477 91 m_thread->start();
Chris@477 92 }
Chris@477 93
Chris@481 94 void
Chris@481 95 TransformFactory::UninstalledTransformsPopulateThread::run()
Chris@481 96 {
Chris@481 97 m_factory->m_populatingSlowly = true;
Chris@481 98 sleep(1);
Chris@481 99 m_factory->populateUninstalledTransforms();
Chris@481 100 }
Chris@481 101
Chris@330 102 TransformList
Chris@350 103 TransformFactory::getAllTransformDescriptions()
Chris@330 104 {
Chris@460 105 populateTransforms();
Chris@330 106
Chris@330 107 std::set<TransformDescription> dset;
Chris@330 108 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 109 i != m_transforms.end(); ++i) {
Chris@443 110 // cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << endl;
Chris@330 111 dset.insert(i->second);
Chris@330 112 }
Chris@330 113
Chris@330 114 TransformList list;
Chris@330 115 for (std::set<TransformDescription>::const_iterator i = dset.begin();
Chris@330 116 i != dset.end(); ++i) {
Chris@443 117 // cerr << "inserting transform into list: id = " << i->identifier.toStdString() << endl;
Chris@330 118 list.push_back(*i);
Chris@330 119 }
Chris@330 120
Chris@330 121 return list;
Chris@330 122 }
Chris@330 123
Chris@350 124 TransformDescription
Chris@350 125 TransformFactory::getTransformDescription(TransformId id)
Chris@350 126 {
Chris@460 127 populateTransforms();
Chris@350 128
Chris@350 129 if (m_transforms.find(id) == m_transforms.end()) {
Chris@350 130 return TransformDescription();
Chris@350 131 }
Chris@350 132
Chris@350 133 return m_transforms[id];
Chris@350 134 }
Chris@350 135
Chris@485 136 bool
Chris@485 137 TransformFactory::haveInstalledTransforms()
Chris@485 138 {
Chris@485 139 populateTransforms();
Chris@485 140 return !m_transforms.empty();
Chris@485 141 }
Chris@485 142
Chris@457 143 TransformList
Chris@457 144 TransformFactory::getUninstalledTransformDescriptions()
Chris@457 145 {
Chris@479 146 m_populatingSlowly = false;
Chris@460 147 populateUninstalledTransforms();
Chris@457 148
Chris@457 149 std::set<TransformDescription> dset;
Chris@457 150 for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin();
Chris@457 151 i != m_uninstalledTransforms.end(); ++i) {
Chris@457 152 // cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << endl;
Chris@457 153 dset.insert(i->second);
Chris@457 154 }
Chris@457 155
Chris@457 156 TransformList list;
Chris@457 157 for (std::set<TransformDescription>::const_iterator i = dset.begin();
Chris@457 158 i != dset.end(); ++i) {
Chris@460 159 // cerr << "inserting transform into uninstalled list: id = " << i->identifier.toStdString() << endl;
Chris@457 160 list.push_back(*i);
Chris@457 161 }
Chris@457 162
Chris@457 163 return list;
Chris@457 164 }
Chris@457 165
Chris@457 166 TransformDescription
Chris@457 167 TransformFactory::getUninstalledTransformDescription(TransformId id)
Chris@457 168 {
Chris@479 169 m_populatingSlowly = false;
Chris@460 170 populateUninstalledTransforms();
Chris@457 171
Chris@457 172 if (m_uninstalledTransforms.find(id) == m_uninstalledTransforms.end()) {
Chris@457 173 return TransformDescription();
Chris@457 174 }
Chris@457 175
Chris@457 176 return m_uninstalledTransforms[id];
Chris@457 177 }
Chris@457 178
Chris@485 179 bool
Chris@485 180 TransformFactory::haveUninstalledTransforms(bool waitForCheckToComplete)
Chris@485 181 {
Chris@485 182 if (waitForCheckToComplete) {
Chris@485 183 populateUninstalledTransforms();
Chris@485 184 } else {
Chris@485 185 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@485 186 return false;
Chris@485 187 }
Chris@485 188 if (!m_uninstalledTransformsPopulated) {
Chris@485 189 m_uninstalledTransformsMutex.unlock();
Chris@485 190 return false;
Chris@485 191 }
Chris@485 192 m_uninstalledTransformsMutex.unlock();
Chris@485 193 }
Chris@485 194
Chris@485 195 return !m_uninstalledTransforms.empty();
Chris@485 196 }
Chris@485 197
Chris@457 198 TransformFactory::TransformInstallStatus
Chris@457 199 TransformFactory::getTransformInstallStatus(TransformId id)
Chris@457 200 {
Chris@460 201 populateTransforms();
Chris@457 202
Chris@457 203 if (m_transforms.find(id) != m_transforms.end()) {
Chris@457 204 return TransformInstalled;
Chris@457 205 }
Chris@473 206
Chris@473 207 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@473 208 // uninstalled transforms are being populated; this may take some time,
Chris@473 209 // and they aren't critical
Chris@473 210 return TransformUnknown;
Chris@473 211 }
Chris@473 212
Chris@473 213 if (!m_uninstalledTransformsPopulated) {
Chris@473 214 m_uninstalledTransformsMutex.unlock();
Chris@479 215 m_populatingSlowly = false;
Chris@473 216 populateUninstalledTransforms();
Chris@473 217 m_uninstalledTransformsMutex.lock();
Chris@473 218 }
Chris@473 219
Chris@457 220 if (m_uninstalledTransforms.find(id) != m_uninstalledTransforms.end()) {
Chris@482 221 m_uninstalledTransformsMutex.unlock();
Chris@457 222 return TransformNotInstalled;
Chris@457 223 }
Chris@473 224
Chris@473 225 m_uninstalledTransformsMutex.unlock();
Chris@457 226 return TransformUnknown;
Chris@457 227 }
Chris@457 228
Chris@457 229
Chris@487 230 std::vector<TransformDescription::Type>
Chris@330 231 TransformFactory::getAllTransformTypes()
Chris@330 232 {
Chris@460 233 populateTransforms();
Chris@330 234
Chris@487 235 std::set<TransformDescription::Type> types;
Chris@330 236 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 237 i != m_transforms.end(); ++i) {
Chris@330 238 types.insert(i->second.type);
Chris@330 239 }
Chris@330 240
Chris@487 241 std::vector<TransformDescription::Type> rv;
Chris@487 242 for (std::set<TransformDescription::Type>::iterator i = types.begin(); i != types.end(); ++i) {
Chris@330 243 rv.push_back(*i);
Chris@330 244 }
Chris@330 245
Chris@330 246 return rv;
Chris@330 247 }
Chris@330 248
Chris@330 249 std::vector<QString>
Chris@487 250 TransformFactory::getTransformCategories(TransformDescription::Type transformType)
Chris@330 251 {
Chris@460 252 populateTransforms();
Chris@330 253
Chris@330 254 std::set<QString> categories;
Chris@330 255 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 256 i != m_transforms.end(); ++i) {
Chris@330 257 if (i->second.type == transformType) {
Chris@330 258 categories.insert(i->second.category);
Chris@330 259 }
Chris@330 260 }
Chris@330 261
Chris@330 262 bool haveEmpty = false;
Chris@330 263
Chris@330 264 std::vector<QString> rv;
Chris@330 265 for (std::set<QString>::iterator i = categories.begin();
Chris@330 266 i != categories.end(); ++i) {
Chris@330 267 if (*i != "") rv.push_back(*i);
Chris@330 268 else haveEmpty = true;
Chris@330 269 }
Chris@330 270
Chris@330 271 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330 272
Chris@330 273 return rv;
Chris@330 274 }
Chris@330 275
Chris@330 276 std::vector<QString>
Chris@487 277 TransformFactory::getTransformMakers(TransformDescription::Type transformType)
Chris@330 278 {
Chris@460 279 populateTransforms();
Chris@330 280
Chris@330 281 std::set<QString> makers;
Chris@330 282 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 283 i != m_transforms.end(); ++i) {
Chris@330 284 if (i->second.type == transformType) {
Chris@330 285 makers.insert(i->second.maker);
Chris@330 286 }
Chris@330 287 }
Chris@330 288
Chris@330 289 bool haveEmpty = false;
Chris@330 290
Chris@330 291 std::vector<QString> rv;
Chris@330 292 for (std::set<QString>::iterator i = makers.begin();
Chris@330 293 i != makers.end(); ++i) {
Chris@330 294 if (*i != "") rv.push_back(*i);
Chris@330 295 else haveEmpty = true;
Chris@330 296 }
Chris@330 297
Chris@330 298 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330 299
Chris@330 300 return rv;
Chris@330 301 }
Chris@330 302
Chris@487 303 QString
Chris@487 304 TransformFactory::getTransformTypeName(TransformDescription::Type type) const
Chris@487 305 {
Chris@487 306 switch (type) {
Chris@487 307 case TransformDescription::Analysis: return tr("Analysis");
Chris@487 308 case TransformDescription::Effects: return tr("Effects");
Chris@487 309 case TransformDescription::EffectsData: return tr("Effects Data");
Chris@487 310 case TransformDescription::Generator: return tr("Generator");
Chris@487 311 case TransformDescription::UnknownType: return tr("Other");
Chris@487 312 }
Chris@489 313 return tr("Other");
Chris@487 314 }
Chris@487 315
Chris@330 316 void
Chris@330 317 TransformFactory::populateTransforms()
Chris@330 318 {
Chris@460 319 MutexLocker locker(&m_transformsMutex,
Chris@460 320 "TransformFactory::populateTransforms");
Chris@460 321 if (m_transformsPopulated) {
Chris@460 322 return;
Chris@460 323 }
Chris@460 324
Chris@330 325 TransformDescriptionMap transforms;
Chris@330 326
Chris@330 327 populateFeatureExtractionPlugins(transforms);
Chris@576 328 if (m_exiting) return;
Chris@330 329 populateRealTimePlugins(transforms);
Chris@576 330 if (m_exiting) return;
Chris@330 331
Chris@330 332 // disambiguate plugins with similar names
Chris@330 333
Chris@330 334 std::map<QString, int> names;
Chris@330 335 std::map<QString, QString> pluginSources;
Chris@330 336 std::map<QString, QString> pluginMakers;
Chris@330 337
Chris@330 338 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 339 i != transforms.end(); ++i) {
Chris@330 340
Chris@330 341 TransformDescription desc = i->second;
Chris@330 342
Chris@330 343 QString td = desc.name;
Chris@330 344 QString tn = td.section(": ", 0, 0);
Chris@330 345 QString pn = desc.identifier.section(":", 1, 1);
Chris@330 346
Chris@330 347 if (pluginSources.find(tn) != pluginSources.end()) {
Chris@330 348 if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) {
Chris@330 349 ++names[tn];
Chris@330 350 }
Chris@330 351 } else {
Chris@330 352 ++names[tn];
Chris@330 353 pluginSources[tn] = pn;
Chris@330 354 pluginMakers[tn] = desc.maker;
Chris@330 355 }
Chris@330 356 }
Chris@330 357
Chris@330 358 std::map<QString, int> counts;
Chris@330 359 m_transforms.clear();
Chris@330 360
Chris@330 361 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 362 i != transforms.end(); ++i) {
Chris@330 363
Chris@330 364 TransformDescription desc = i->second;
Chris@330 365 QString identifier = desc.identifier;
Chris@330 366 QString maker = desc.maker;
Chris@330 367
Chris@330 368 QString td = desc.name;
Chris@330 369 QString tn = td.section(": ", 0, 0);
Chris@330 370 QString to = td.section(": ", 1);
Chris@330 371
Chris@330 372 if (names[tn] > 1) {
Chris@330 373 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
Chris@330 374 tn = QString("%1 [%2]").arg(tn).arg(maker);
Chris@330 375 }
Chris@330 376
Chris@330 377 if (to != "") {
Chris@330 378 desc.name = QString("%1: %2").arg(tn).arg(to);
Chris@330 379 } else {
Chris@330 380 desc.name = tn;
Chris@330 381 }
Chris@330 382
Chris@330 383 m_transforms[identifier] = desc;
Chris@330 384 }
Chris@457 385
Chris@457 386 m_transformsPopulated = true;
Chris@330 387 }
Chris@330 388
Chris@330 389 void
Chris@330 390 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
Chris@330 391 {
Chris@330 392 std::vector<QString> plugs =
Chris@330 393 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
Chris@576 394 if (m_exiting) return;
Chris@330 395
Chris@330 396 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@330 397
Chris@330 398 QString pluginId = plugs[i];
Chris@330 399
Chris@330 400 FeatureExtractionPluginFactory *factory =
Chris@330 401 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@330 402
Chris@330 403 if (!factory) {
Chris@443 404 cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << endl;
Chris@330 405 continue;
Chris@330 406 }
Chris@330 407
Chris@330 408 Vamp::Plugin *plugin =
Chris@350 409 factory->instantiatePlugin(pluginId, 44100);
Chris@330 410
Chris@330 411 if (!plugin) {
Chris@443 412 cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << endl;
Chris@330 413 continue;
Chris@330 414 }
Chris@330 415
Chris@330 416 QString pluginName = plugin->getName().c_str();
Chris@330 417 QString category = factory->getPluginCategory(pluginId);
Chris@330 418
Chris@330 419 Vamp::Plugin::OutputList outputs =
Chris@330 420 plugin->getOutputDescriptors();
Chris@330 421
Chris@330 422 for (size_t j = 0; j < outputs.size(); ++j) {
Chris@330 423
Chris@330 424 QString transformId = QString("%1:%2")
Chris@330 425 .arg(pluginId).arg(outputs[j].identifier.c_str());
Chris@330 426
Chris@330 427 QString userName;
Chris@330 428 QString friendlyName;
Chris@330 429 QString units = outputs[j].unit.c_str();
Chris@330 430 QString description = plugin->getDescription().c_str();
Chris@330 431 QString maker = plugin->getMaker().c_str();
Chris@330 432 if (maker == "") maker = tr("<unknown maker>");
Chris@330 433
Chris@443 434 QString longDescription = description;
Chris@443 435
Chris@443 436 if (longDescription == "") {
Chris@330 437 if (outputs.size() == 1) {
Chris@443 438 longDescription = tr("Extract features using \"%1\" plugin (from %2)")
Chris@330 439 .arg(pluginName).arg(maker);
Chris@330 440 } else {
Chris@443 441 longDescription = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
Chris@330 442 .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330 443 }
Chris@330 444 } else {
Chris@330 445 if (outputs.size() == 1) {
Chris@443 446 longDescription = tr("%1 using \"%2\" plugin (from %3)")
Chris@443 447 .arg(longDescription).arg(pluginName).arg(maker);
Chris@330 448 } else {
Chris@443 449 longDescription = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
Chris@443 450 .arg(longDescription).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330 451 }
Chris@330 452 }
Chris@330 453
Chris@330 454 if (outputs.size() == 1) {
Chris@330 455 userName = pluginName;
Chris@330 456 friendlyName = pluginName;
Chris@330 457 } else {
Chris@330 458 userName = QString("%1: %2")
Chris@330 459 .arg(pluginName)
Chris@330 460 .arg(outputs[j].name.c_str());
Chris@330 461 friendlyName = outputs[j].name.c_str();
Chris@330 462 }
Chris@330 463
Chris@330 464 bool configurable = (!plugin->getPrograms().empty() ||
Chris@330 465 !plugin->getParameterDescriptors().empty());
Chris@330 466
Chris@443 467 // cerr << "Feature extraction plugin transform: " << transformId.toStdString() << " friendly name: " << friendlyName.toStdString() << endl;
Chris@330 468
Chris@330 469 transforms[transformId] =
Chris@487 470 TransformDescription(TransformDescription::Analysis,
Chris@332 471 category,
Chris@332 472 transformId,
Chris@332 473 userName,
Chris@332 474 friendlyName,
Chris@332 475 description,
Chris@443 476 longDescription,
Chris@332 477 maker,
Chris@332 478 units,
Chris@332 479 configurable);
Chris@330 480 }
Chris@330 481
Chris@330 482 delete plugin;
Chris@330 483 }
Chris@330 484 }
Chris@330 485
Chris@330 486 void
Chris@330 487 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@330 488 {
Chris@330 489 std::vector<QString> plugs =
Chris@330 490 RealTimePluginFactory::getAllPluginIdentifiers();
Chris@576 491 if (m_exiting) return;
Chris@330 492
Chris@330 493 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@330 494
Chris@330 495 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@330 496
Chris@330 497 QString pluginId = plugs[i];
Chris@330 498
Chris@330 499 RealTimePluginFactory *factory =
Chris@330 500 RealTimePluginFactory::instanceFor(pluginId);
Chris@330 501
Chris@330 502 if (!factory) {
Chris@443 503 cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << endl;
Chris@330 504 continue;
Chris@330 505 }
Chris@330 506
Chris@330 507 const RealTimePluginDescriptor *descriptor =
Chris@330 508 factory->getPluginDescriptor(pluginId);
Chris@330 509
Chris@330 510 if (!descriptor) {
Chris@443 511 cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << endl;
Chris@330 512 continue;
Chris@330 513 }
Chris@330 514
Chris@330 515 //!!! if (descriptor->controlOutputPortCount == 0 ||
Chris@330 516 // descriptor->audioInputPortCount == 0) continue;
Chris@330 517
Chris@443 518 // std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << endl;
Chris@330 519
Chris@330 520 QString pluginName = descriptor->name.c_str();
Chris@330 521 QString category = factory->getPluginCategory(pluginId);
Chris@330 522 bool configurable = (descriptor->parameterCount > 0);
Chris@330 523 QString maker = descriptor->maker.c_str();
Chris@330 524 if (maker == "") maker = tr("<unknown maker>");
Chris@330 525
Chris@330 526 if (descriptor->audioInputPortCount > 0) {
Chris@330 527
Chris@330 528 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
Chris@330 529
Chris@330 530 QString transformId = QString("%1:%2").arg(pluginId).arg(j);
Chris@330 531 QString userName;
Chris@330 532 QString units;
Chris@330 533 QString portName;
Chris@330 534
Chris@330 535 if (j < descriptor->controlOutputPortNames.size() &&
Chris@330 536 descriptor->controlOutputPortNames[j] != "") {
Chris@330 537
Chris@330 538 portName = descriptor->controlOutputPortNames[j].c_str();
Chris@330 539
Chris@330 540 userName = tr("%1: %2")
Chris@330 541 .arg(pluginName)
Chris@330 542 .arg(portName);
Chris@330 543
Chris@330 544 if (unitRE.indexIn(portName) >= 0) {
Chris@330 545 units = unitRE.cap(1);
Chris@330 546 }
Chris@330 547
Chris@330 548 } else if (descriptor->controlOutputPortCount > 1) {
Chris@330 549
Chris@330 550 userName = tr("%1: Output %2")
Chris@330 551 .arg(pluginName)
Chris@330 552 .arg(j + 1);
Chris@330 553
Chris@330 554 } else {
Chris@330 555
Chris@330 556 userName = pluginName;
Chris@330 557 }
Chris@330 558
Chris@330 559 QString description;
Chris@330 560
Chris@330 561 if (portName != "") {
Chris@330 562 description = tr("Extract \"%1\" data output from \"%2\" effect plugin (from %3)")
Chris@330 563 .arg(portName)
Chris@330 564 .arg(pluginName)
Chris@330 565 .arg(maker);
Chris@330 566 } else {
Chris@330 567 description = tr("Extract data output %1 from \"%2\" effect plugin (from %3)")
Chris@330 568 .arg(j + 1)
Chris@330 569 .arg(pluginName)
Chris@330 570 .arg(maker);
Chris@330 571 }
Chris@330 572
Chris@330 573 transforms[transformId] =
Chris@487 574 TransformDescription(TransformDescription::EffectsData,
Chris@332 575 category,
Chris@332 576 transformId,
Chris@332 577 userName,
Chris@332 578 userName,
Chris@443 579 "",
Chris@332 580 description,
Chris@332 581 maker,
Chris@332 582 units,
Chris@332 583 configurable);
Chris@330 584 }
Chris@330 585 }
Chris@330 586
Chris@330 587 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@330 588
Chris@330 589 if (descriptor->audioOutputPortCount > 0) {
Chris@330 590
Chris@330 591 QString transformId = QString("%1:A").arg(pluginId);
Chris@487 592 TransformDescription::Type type = TransformDescription::Effects;
Chris@330 593
Chris@330 594 QString description = tr("Transform audio signal with \"%1\" effect plugin (from %2)")
Chris@330 595 .arg(pluginName)
Chris@330 596 .arg(maker);
Chris@330 597
Chris@330 598 if (descriptor->audioInputPortCount == 0) {
Chris@487 599 type = TransformDescription::Generator;
Chris@330 600 QString description = tr("Generate audio signal using \"%1\" plugin (from %2)")
Chris@330 601 .arg(pluginName)
Chris@330 602 .arg(maker);
Chris@330 603 }
Chris@330 604
Chris@330 605 transforms[transformId] =
Chris@330 606 TransformDescription(type,
Chris@332 607 category,
Chris@332 608 transformId,
Chris@332 609 pluginName,
Chris@332 610 pluginName,
Chris@443 611 "",
Chris@332 612 description,
Chris@332 613 maker,
Chris@332 614 "",
Chris@332 615 configurable);
Chris@330 616 }
Chris@330 617 }
Chris@330 618 }
Chris@330 619 }
Chris@330 620
Chris@457 621 void
Chris@457 622 TransformFactory::populateUninstalledTransforms()
Chris@457 623 {
Chris@576 624 if (m_exiting) return;
Chris@576 625
Chris@460 626 populateTransforms();
Chris@576 627 if (m_exiting) return;
Chris@460 628
Chris@460 629 MutexLocker locker(&m_uninstalledTransformsMutex,
Chris@460 630 "TransformFactory::populateUninstalledTransforms");
Chris@460 631 if (m_uninstalledTransformsPopulated) return;
Chris@460 632
Chris@461 633 PluginRDFIndexer::getInstance()->indexConfiguredURLs();
Chris@576 634 if (m_exiting) return;
Chris@457 635
Chris@457 636 //!!! This will be amazingly slow
Chris@457 637
Chris@457 638 QStringList ids = PluginRDFIndexer::getInstance()->getIndexedPluginIds();
Chris@457 639
Chris@457 640 for (QStringList::const_iterator i = ids.begin(); i != ids.end(); ++i) {
Chris@457 641
Chris@457 642 PluginRDFDescription desc(*i);
Chris@457 643
Chris@457 644 QString name = desc.getPluginName();
Chris@457 645 // if (name == "") {
Chris@457 646 // std::cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@457 647 // << "No name available for plugin " << i->toStdString()
Chris@457 648 // << ", skipping" << std::endl;
Chris@457 649 // continue;
Chris@457 650 // }
Chris@457 651
Chris@457 652 QString description = desc.getPluginDescription();
Chris@457 653 QString maker = desc.getPluginMaker();
Chris@462 654 QString infoUrl = desc.getPluginInfoURL();
Chris@457 655
Chris@457 656 QStringList oids = desc.getOutputIds();
Chris@457 657
Chris@457 658 for (QStringList::const_iterator j = oids.begin(); j != oids.end(); ++j) {
Chris@457 659
Chris@457 660 TransformId tid = Transform::getIdentifierForPluginOutput(*i, *j);
Chris@457 661
Chris@457 662 if (m_transforms.find(tid) != m_transforms.end()) {
Chris@494 663 // std::cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@494 664 // << tid.toStdString() << " is installed; adding info url if appropriate, skipping rest" << std::endl;
Chris@468 665 if (infoUrl != "") {
Chris@468 666 if (m_transforms[tid].infoUrl == "") {
Chris@468 667 m_transforms[tid].infoUrl = infoUrl;
Chris@468 668 }
Chris@468 669 }
Chris@457 670 continue;
Chris@457 671 }
Chris@457 672
Chris@494 673 // std::cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@494 674 // << "adding " << tid.toStdString() << std::endl;
Chris@457 675
Chris@457 676 QString oname = desc.getOutputName(*j);
Chris@457 677 if (oname == "") oname = *j;
Chris@457 678
Chris@457 679 TransformDescription td;
Chris@487 680 td.type = TransformDescription::Analysis;
Chris@457 681 td.category = "";
Chris@457 682 td.identifier = tid;
Chris@457 683
Chris@457 684 if (oids.size() == 1) {
Chris@457 685 td.name = name;
Chris@457 686 } else if (name != "") {
Chris@457 687 td.name = tr("%1: %2").arg(name).arg(oname);
Chris@457 688 }
Chris@457 689
Chris@462 690 QString longDescription = description;
Chris@462 691 //!!! basically duplicated from above
Chris@462 692 if (longDescription == "") {
Chris@462 693 if (oids.size() == 1) {
Chris@462 694 longDescription = tr("Extract features using \"%1\" plugin (from %2)")
Chris@462 695 .arg(name).arg(maker);
Chris@462 696 } else {
Chris@462 697 longDescription = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
Chris@462 698 .arg(oname).arg(name).arg(maker);
Chris@462 699 }
Chris@462 700 } else {
Chris@462 701 if (oids.size() == 1) {
Chris@462 702 longDescription = tr("%1 using \"%2\" plugin (from %3)")
Chris@462 703 .arg(longDescription).arg(name).arg(maker);
Chris@462 704 } else {
Chris@462 705 longDescription = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
Chris@462 706 .arg(longDescription).arg(oname).arg(name).arg(maker);
Chris@462 707 }
Chris@462 708 }
Chris@462 709
Chris@457 710 td.friendlyName = name; //!!!???
Chris@457 711 td.description = description;
Chris@462 712 td.longDescription = longDescription;
Chris@457 713 td.maker = maker;
Chris@462 714 td.infoUrl = infoUrl;
Chris@457 715 td.units = "";
Chris@457 716 td.configurable = false;
Chris@457 717
Chris@457 718 m_uninstalledTransforms[tid] = td;
Chris@457 719 }
Chris@574 720
Chris@576 721 if (m_exiting) return;
Chris@457 722 }
Chris@457 723
Chris@457 724 m_uninstalledTransformsPopulated = true;
Chris@460 725
Chris@460 726 std::cerr << "populateUninstalledTransforms exiting" << std::endl;
Chris@457 727 }
Chris@350 728
Chris@350 729 Transform
Chris@350 730 TransformFactory::getDefaultTransformFor(TransformId id, size_t rate)
Chris@350 731 {
Chris@350 732 Transform t;
Chris@350 733 t.setIdentifier(id);
Chris@350 734 if (rate != 0) t.setSampleRate(rate);
Chris@350 735
Chris@351 736 Vamp::PluginBase *plugin = instantiateDefaultPluginFor(id, rate);
Chris@350 737
Chris@350 738 if (plugin) {
Chris@366 739 t.setPluginVersion(QString("%1").arg(plugin->getPluginVersion()));
Chris@350 740 setParametersFromPlugin(t, plugin);
Chris@350 741 makeContextConsistentWithPlugin(t, plugin);
Chris@350 742 delete plugin;
Chris@350 743 }
Chris@350 744
Chris@350 745 return t;
Chris@350 746 }
Chris@350 747
Chris@350 748 Vamp::PluginBase *
Chris@351 749 TransformFactory::instantiatePluginFor(const Transform &transform)
Chris@351 750 {
Chris@351 751 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 752 (transform.getIdentifier(), transform.getSampleRate());
Chris@508 753
Chris@351 754 if (plugin) {
Chris@351 755 setPluginParameters(transform, plugin);
Chris@351 756 }
Chris@508 757
Chris@351 758 return plugin;
Chris@351 759 }
Chris@351 760
Chris@351 761 Vamp::PluginBase *
Chris@351 762 TransformFactory::instantiateDefaultPluginFor(TransformId identifier, size_t rate)
Chris@350 763 {
Chris@350 764 Transform t;
Chris@350 765 t.setIdentifier(identifier);
Chris@350 766 if (rate == 0) rate = 44100;
Chris@350 767 QString pluginId = t.getPluginIdentifier();
Chris@350 768
Chris@350 769 Vamp::PluginBase *plugin = 0;
Chris@350 770
Chris@350 771 if (t.getType() == Transform::FeatureExtraction) {
Chris@350 772
Chris@350 773 FeatureExtractionPluginFactory *factory =
Chris@350 774 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@350 775
Chris@439 776 if (factory) {
Chris@439 777 plugin = factory->instantiatePlugin(pluginId, rate);
Chris@439 778 }
Chris@350 779
Chris@350 780 } else {
Chris@350 781
Chris@350 782 RealTimePluginFactory *factory =
Chris@350 783 RealTimePluginFactory::instanceFor(pluginId);
Chris@439 784
Chris@439 785 if (factory) {
Chris@439 786 plugin = factory->instantiatePlugin(pluginId, 0, 0, rate, 1024, 1);
Chris@439 787 }
Chris@350 788 }
Chris@350 789
Chris@350 790 return plugin;
Chris@350 791 }
Chris@350 792
Chris@350 793 Vamp::Plugin *
Chris@350 794 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin)
Chris@350 795 {
Chris@350 796 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin);
Chris@350 797 if (!vp) {
Chris@443 798 // cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << endl;
Chris@350 799 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why?
Chris@350 800 }
Chris@350 801 if (!vp) {
Chris@443 802 // cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << endl;
Chris@350 803 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
Chris@350 804 }
Chris@350 805 if (!vp) {
Chris@443 806 // cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << endl;
Chris@350 807 }
Chris@350 808 return vp;
Chris@350 809 }
Chris@350 810
Chris@330 811 bool
Chris@330 812 TransformFactory::haveTransform(TransformId identifier)
Chris@330 813 {
Chris@460 814 populateTransforms();
Chris@330 815 return (m_transforms.find(identifier) != m_transforms.end());
Chris@330 816 }
Chris@330 817
Chris@330 818 QString
Chris@330 819 TransformFactory::getTransformName(TransformId identifier)
Chris@330 820 {
Chris@330 821 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 822 return m_transforms[identifier].name;
Chris@330 823 } else return "";
Chris@330 824 }
Chris@330 825
Chris@330 826 QString
Chris@330 827 TransformFactory::getTransformFriendlyName(TransformId identifier)
Chris@330 828 {
Chris@330 829 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 830 return m_transforms[identifier].friendlyName;
Chris@330 831 } else return "";
Chris@330 832 }
Chris@330 833
Chris@330 834 QString
Chris@330 835 TransformFactory::getTransformUnits(TransformId identifier)
Chris@330 836 {
Chris@330 837 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 838 return m_transforms[identifier].units;
Chris@330 839 } else return "";
Chris@330 840 }
Chris@330 841
Chris@472 842 QString
Chris@472 843 TransformFactory::getTransformInfoUrl(TransformId identifier)
Chris@472 844 {
Chris@472 845 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@472 846 return m_transforms[identifier].infoUrl;
Chris@472 847 } else return "";
Chris@472 848 }
Chris@472 849
Chris@350 850 Vamp::Plugin::InputDomain
Chris@350 851 TransformFactory::getTransformInputDomain(TransformId identifier)
Chris@350 852 {
Chris@350 853 Transform transform;
Chris@350 854 transform.setIdentifier(identifier);
Chris@350 855
Chris@350 856 if (transform.getType() != Transform::FeatureExtraction) {
Chris@350 857 return Vamp::Plugin::TimeDomain;
Chris@350 858 }
Chris@350 859
Chris@350 860 Vamp::Plugin *plugin =
Chris@351 861 downcastVampPlugin(instantiateDefaultPluginFor(identifier, 0));
Chris@350 862
Chris@350 863 if (plugin) {
Chris@350 864 Vamp::Plugin::InputDomain d = plugin->getInputDomain();
Chris@350 865 delete plugin;
Chris@350 866 return d;
Chris@350 867 }
Chris@350 868
Chris@350 869 return Vamp::Plugin::TimeDomain;
Chris@350 870 }
Chris@350 871
Chris@330 872 bool
Chris@330 873 TransformFactory::isTransformConfigurable(TransformId identifier)
Chris@330 874 {
Chris@330 875 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 876 return m_transforms[identifier].configurable;
Chris@330 877 } else return false;
Chris@330 878 }
Chris@330 879
Chris@330 880 bool
Chris@330 881 TransformFactory::getTransformChannelRange(TransformId identifier,
Chris@330 882 int &min, int &max)
Chris@330 883 {
Chris@330 884 QString id = identifier.section(':', 0, 2);
Chris@330 885
Chris@330 886 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@330 887
Chris@330 888 Vamp::Plugin *plugin =
Chris@330 889 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@350 890 instantiatePlugin(id, 44100);
Chris@330 891 if (!plugin) return false;
Chris@330 892
Chris@330 893 min = plugin->getMinChannelCount();
Chris@330 894 max = plugin->getMaxChannelCount();
Chris@330 895 delete plugin;
Chris@330 896
Chris@330 897 return true;
Chris@330 898
Chris@330 899 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@330 900
Chris@350 901 // don't need to instantiate
Chris@350 902
Chris@330 903 const RealTimePluginDescriptor *descriptor =
Chris@330 904 RealTimePluginFactory::instanceFor(id)->
Chris@330 905 getPluginDescriptor(id);
Chris@330 906 if (!descriptor) return false;
Chris@330 907
Chris@330 908 min = descriptor->audioInputPortCount;
Chris@330 909 max = descriptor->audioInputPortCount;
Chris@330 910
Chris@330 911 return true;
Chris@330 912 }
Chris@330 913
Chris@330 914 return false;
Chris@330 915 }
Chris@332 916
Chris@332 917 void
Chris@332 918 TransformFactory::setParametersFromPlugin(Transform &transform,
Chris@332 919 Vamp::PluginBase *plugin)
Chris@332 920 {
Chris@332 921 Transform::ParameterMap pmap;
Chris@332 922
Chris@350 923 //!!! record plugin & API version
Chris@350 924
Chris@350 925 //!!! check that this is the right plugin!
Chris@350 926
Chris@332 927 Vamp::PluginBase::ParameterList parameters =
Chris@332 928 plugin->getParameterDescriptors();
Chris@332 929
Chris@332 930 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@332 931 i != parameters.end(); ++i) {
Chris@332 932 pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier);
Chris@583 933 // std::cerr << "TransformFactory::setParametersFromPlugin: parameter "
Chris@583 934 // << i->identifier << " -> value " <<
Chris@583 935 // pmap[i->identifier.c_str()] << std::endl;
Chris@332 936 }
Chris@332 937
Chris@332 938 transform.setParameters(pmap);
Chris@332 939
Chris@332 940 if (plugin->getPrograms().empty()) {
Chris@332 941 transform.setProgram("");
Chris@332 942 } else {
Chris@332 943 transform.setProgram(plugin->getCurrentProgram().c_str());
Chris@332 944 }
Chris@332 945
Chris@332 946 RealTimePluginInstance *rtpi =
Chris@332 947 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@332 948
Chris@332 949 Transform::ConfigurationMap cmap;
Chris@332 950
Chris@332 951 if (rtpi) {
Chris@332 952
Chris@332 953 RealTimePluginInstance::ConfigurationPairMap configurePairs =
Chris@332 954 rtpi->getConfigurePairs();
Chris@332 955
Chris@332 956 for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i
Chris@332 957 = configurePairs.begin(); i != configurePairs.end(); ++i) {
Chris@332 958 cmap[i->first.c_str()] = i->second.c_str();
Chris@332 959 }
Chris@332 960 }
Chris@332 961
Chris@332 962 transform.setConfiguration(cmap);
Chris@332 963 }
Chris@332 964
Chris@332 965 void
Chris@350 966 TransformFactory::setPluginParameters(const Transform &transform,
Chris@350 967 Vamp::PluginBase *plugin)
Chris@350 968 {
Chris@350 969 //!!! check plugin & API version (see e.g. PluginXml::setParameters)
Chris@350 970
Chris@350 971 //!!! check that this is the right plugin!
Chris@350 972
Chris@350 973 RealTimePluginInstance *rtpi =
Chris@350 974 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@350 975
Chris@350 976 if (rtpi) {
Chris@350 977 const Transform::ConfigurationMap &cmap = transform.getConfiguration();
Chris@350 978 for (Transform::ConfigurationMap::const_iterator i = cmap.begin();
Chris@350 979 i != cmap.end(); ++i) {
Chris@350 980 rtpi->configure(i->first.toStdString(), i->second.toStdString());
Chris@350 981 }
Chris@350 982 }
Chris@350 983
Chris@350 984 if (transform.getProgram() != "") {
Chris@350 985 plugin->selectProgram(transform.getProgram().toStdString());
Chris@350 986 }
Chris@350 987
Chris@350 988 const Transform::ParameterMap &pmap = transform.getParameters();
Chris@350 989
Chris@350 990 Vamp::PluginBase::ParameterList parameters =
Chris@350 991 plugin->getParameterDescriptors();
Chris@350 992
Chris@350 993 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@350 994 i != parameters.end(); ++i) {
Chris@350 995 QString key = i->identifier.c_str();
Chris@350 996 Transform::ParameterMap::const_iterator pmi = pmap.find(key);
Chris@350 997 if (pmi != pmap.end()) {
Chris@350 998 plugin->setParameter(i->identifier, pmi->second);
Chris@350 999 }
Chris@350 1000 }
Chris@350 1001 }
Chris@350 1002
Chris@350 1003 void
Chris@332 1004 TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
Chris@332 1005 Vamp::PluginBase *plugin)
Chris@332 1006 {
Chris@350 1007 const Vamp::Plugin *vp = downcastVampPlugin(plugin);
Chris@332 1008
Chris@332 1009 if (!vp) {
Chris@332 1010 // time domain input for real-time effects plugin
Chris@332 1011 if (!transform.getBlockSize()) {
Chris@332 1012 if (!transform.getStepSize()) transform.setStepSize(1024);
Chris@332 1013 transform.setBlockSize(transform.getStepSize());
Chris@332 1014 } else {
Chris@332 1015 transform.setStepSize(transform.getBlockSize());
Chris@332 1016 }
Chris@332 1017 } else {
Chris@332 1018 Vamp::Plugin::InputDomain domain = vp->getInputDomain();
Chris@332 1019 if (!transform.getStepSize()) {
Chris@332 1020 transform.setStepSize(vp->getPreferredStepSize());
Chris@332 1021 }
Chris@332 1022 if (!transform.getBlockSize()) {
Chris@332 1023 transform.setBlockSize(vp->getPreferredBlockSize());
Chris@332 1024 }
Chris@332 1025 if (!transform.getBlockSize()) {
Chris@332 1026 transform.setBlockSize(1024);
Chris@332 1027 }
Chris@332 1028 if (!transform.getStepSize()) {
Chris@332 1029 if (domain == Vamp::Plugin::FrequencyDomain) {
Chris@443 1030 // cerr << "frequency domain, step = " << blockSize/2 << endl;
Chris@332 1031 transform.setStepSize(transform.getBlockSize()/2);
Chris@332 1032 } else {
Chris@443 1033 // cerr << "time domain, step = " << blockSize/2 << endl;
Chris@332 1034 transform.setStepSize(transform.getBlockSize());
Chris@332 1035 }
Chris@332 1036 }
Chris@332 1037 }
Chris@332 1038 }
Chris@332 1039
Chris@350 1040 QString
Chris@350 1041 TransformFactory::getPluginConfigurationXml(const Transform &t)
Chris@332 1042 {
Chris@350 1043 QString xml;
Chris@350 1044
Chris@351 1045 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1046 (t.getIdentifier(), 0);
Chris@350 1047 if (!plugin) {
Chris@443 1048 cerr << "TransformFactory::getPluginConfigurationXml: "
Chris@350 1049 << "Unable to instantiate plugin for transform \""
Chris@443 1050 << t.getIdentifier().toStdString() << "\"" << endl;
Chris@350 1051 return xml;
Chris@332 1052 }
Chris@332 1053
Chris@351 1054 setPluginParameters(t, plugin);
Chris@351 1055
Chris@350 1056 QTextStream out(&xml);
Chris@350 1057 PluginXml(plugin).toXml(out);
Chris@350 1058 delete plugin;
Chris@332 1059
Chris@350 1060 return xml;
Chris@350 1061 }
Chris@332 1062
Chris@350 1063 void
Chris@350 1064 TransformFactory::setParametersFromPluginConfigurationXml(Transform &t,
Chris@350 1065 QString xml)
Chris@350 1066 {
Chris@351 1067 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1068 (t.getIdentifier(), 0);
Chris@350 1069 if (!plugin) {
Chris@443 1070 cerr << "TransformFactory::setParametersFromPluginConfigurationXml: "
Chris@350 1071 << "Unable to instantiate plugin for transform \""
Chris@443 1072 << t.getIdentifier().toStdString() << "\"" << endl;
Chris@350 1073 return;
Chris@332 1074 }
Chris@332 1075
Chris@350 1076 PluginXml(plugin).setParametersFromXml(xml);
Chris@350 1077 setParametersFromPlugin(t, plugin);
Chris@350 1078 delete plugin;
Chris@332 1079 }
Chris@332 1080
Chris@443 1081 TransformFactory::SearchResults
Chris@443 1082 TransformFactory::search(QString keyword)
Chris@443 1083 {
Chris@443 1084 QStringList keywords;
Chris@443 1085 keywords << keyword;
Chris@443 1086 return search(keywords);
Chris@443 1087 }
Chris@443 1088
Chris@443 1089 TransformFactory::SearchResults
Chris@443 1090 TransformFactory::search(QStringList keywords)
Chris@443 1091 {
Chris@460 1092 populateTransforms();
Chris@443 1093
Chris@447 1094 if (keywords.size() > 1) {
Chris@447 1095 // Additional score for all keywords in a row
Chris@447 1096 keywords.push_back(keywords.join(" "));
Chris@447 1097 }
Chris@447 1098
Chris@443 1099 SearchResults results;
Chris@457 1100 TextMatcher matcher;
Chris@443 1101
Chris@443 1102 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@443 1103 i != m_transforms.end(); ++i) {
Chris@443 1104
Chris@457 1105 TextMatcher::Match match;
Chris@443 1106
Chris@457 1107 match.key = i->first;
Chris@443 1108
Chris@487 1109 matcher.test(match, keywords,
Chris@487 1110 getTransformTypeName(i->second.type),
Chris@487 1111 tr("Plugin type"), 5);
Chris@487 1112
Chris@457 1113 matcher.test(match, keywords, i->second.category, tr("Category"), 20);
Chris@457 1114 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 6);
Chris@457 1115 matcher.test(match, keywords, i->second.name, tr("Name"), 30);
Chris@457 1116 matcher.test(match, keywords, i->second.description, tr("Description"), 20);
Chris@457 1117 matcher.test(match, keywords, i->second.maker, tr("Maker"), 10);
Chris@457 1118 matcher.test(match, keywords, i->second.units, tr("Units"), 10);
Chris@457 1119
Chris@457 1120 if (match.score > 0) results[i->first] = match;
Chris@457 1121 }
Chris@457 1122
Chris@460 1123 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@460 1124 // uninstalled transforms are being populated; this may take some time,
Chris@484 1125 // and they aren't critical, but we will speed them up if necessary
Chris@460 1126 std::cerr << "TransformFactory::search: Uninstalled transforms mutex is held, skipping" << std::endl;
Chris@484 1127 m_populatingSlowly = false;
Chris@460 1128 return results;
Chris@460 1129 }
Chris@460 1130
Chris@460 1131 if (!m_uninstalledTransformsPopulated) {
Chris@460 1132 std::cerr << "WARNING: TransformFactory::search: Uninstalled transforms are not populated yet" << endl
Chris@460 1133 << "and are not being populated either -- was the thread not started correctly?" << endl;
Chris@460 1134 m_uninstalledTransformsMutex.unlock();
Chris@460 1135 return results;
Chris@460 1136 }
Chris@460 1137
Chris@460 1138 m_uninstalledTransformsMutex.unlock();
Chris@457 1139
Chris@457 1140 for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin();
Chris@457 1141 i != m_uninstalledTransforms.end(); ++i) {
Chris@457 1142
Chris@457 1143 TextMatcher::Match match;
Chris@457 1144
Chris@457 1145 match.key = i->first;
Chris@457 1146
Chris@487 1147 matcher.test(match, keywords,
Chris@487 1148 getTransformTypeName(i->second.type),
Chris@487 1149 tr("Plugin type"), 2);
Chris@487 1150
Chris@457 1151 matcher.test(match, keywords, i->second.category, tr("Category"), 10);
Chris@457 1152 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 3);
Chris@457 1153 matcher.test(match, keywords, i->second.name, tr("Name"), 15);
Chris@457 1154 matcher.test(match, keywords, i->second.description, tr("Description"), 10);
Chris@457 1155 matcher.test(match, keywords, i->second.maker, tr("Maker"), 5);
Chris@457 1156 matcher.test(match, keywords, i->second.units, tr("Units"), 5);
Chris@443 1157
Chris@443 1158 if (match.score > 0) results[i->first] = match;
Chris@443 1159 }
Chris@443 1160
Chris@443 1161 return results;
Chris@443 1162 }
Chris@443 1163