annotate transform/TransformFactory.cpp @ 574:2d551c765d51

* thread tidying fix, etc
author Chris Cannam
date Mon, 16 Mar 2009 13:56:11 +0000
parents 1b8c748fd7ea
children 2ba202c5be8d
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@330 328 populateRealTimePlugins(transforms);
Chris@330 329
Chris@330 330 // disambiguate plugins with similar names
Chris@330 331
Chris@330 332 std::map<QString, int> names;
Chris@330 333 std::map<QString, QString> pluginSources;
Chris@330 334 std::map<QString, QString> pluginMakers;
Chris@330 335
Chris@330 336 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 337 i != transforms.end(); ++i) {
Chris@330 338
Chris@330 339 TransformDescription desc = i->second;
Chris@330 340
Chris@330 341 QString td = desc.name;
Chris@330 342 QString tn = td.section(": ", 0, 0);
Chris@330 343 QString pn = desc.identifier.section(":", 1, 1);
Chris@330 344
Chris@330 345 if (pluginSources.find(tn) != pluginSources.end()) {
Chris@330 346 if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) {
Chris@330 347 ++names[tn];
Chris@330 348 }
Chris@330 349 } else {
Chris@330 350 ++names[tn];
Chris@330 351 pluginSources[tn] = pn;
Chris@330 352 pluginMakers[tn] = desc.maker;
Chris@330 353 }
Chris@330 354 }
Chris@330 355
Chris@330 356 std::map<QString, int> counts;
Chris@330 357 m_transforms.clear();
Chris@330 358
Chris@330 359 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 360 i != transforms.end(); ++i) {
Chris@330 361
Chris@330 362 TransformDescription desc = i->second;
Chris@330 363 QString identifier = desc.identifier;
Chris@330 364 QString maker = desc.maker;
Chris@330 365
Chris@330 366 QString td = desc.name;
Chris@330 367 QString tn = td.section(": ", 0, 0);
Chris@330 368 QString to = td.section(": ", 1);
Chris@330 369
Chris@330 370 if (names[tn] > 1) {
Chris@330 371 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
Chris@330 372 tn = QString("%1 [%2]").arg(tn).arg(maker);
Chris@330 373 }
Chris@330 374
Chris@330 375 if (to != "") {
Chris@330 376 desc.name = QString("%1: %2").arg(tn).arg(to);
Chris@330 377 } else {
Chris@330 378 desc.name = tn;
Chris@330 379 }
Chris@330 380
Chris@330 381 m_transforms[identifier] = desc;
Chris@330 382 }
Chris@457 383
Chris@457 384 m_transformsPopulated = true;
Chris@330 385 }
Chris@330 386
Chris@330 387 void
Chris@330 388 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
Chris@330 389 {
Chris@330 390 std::vector<QString> plugs =
Chris@330 391 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
Chris@330 392
Chris@330 393 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@330 394
Chris@330 395 QString pluginId = plugs[i];
Chris@330 396
Chris@330 397 FeatureExtractionPluginFactory *factory =
Chris@330 398 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@330 399
Chris@330 400 if (!factory) {
Chris@443 401 cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << endl;
Chris@330 402 continue;
Chris@330 403 }
Chris@330 404
Chris@330 405 Vamp::Plugin *plugin =
Chris@350 406 factory->instantiatePlugin(pluginId, 44100);
Chris@330 407
Chris@330 408 if (!plugin) {
Chris@443 409 cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << endl;
Chris@330 410 continue;
Chris@330 411 }
Chris@330 412
Chris@330 413 QString pluginName = plugin->getName().c_str();
Chris@330 414 QString category = factory->getPluginCategory(pluginId);
Chris@330 415
Chris@330 416 Vamp::Plugin::OutputList outputs =
Chris@330 417 plugin->getOutputDescriptors();
Chris@330 418
Chris@330 419 for (size_t j = 0; j < outputs.size(); ++j) {
Chris@330 420
Chris@330 421 QString transformId = QString("%1:%2")
Chris@330 422 .arg(pluginId).arg(outputs[j].identifier.c_str());
Chris@330 423
Chris@330 424 QString userName;
Chris@330 425 QString friendlyName;
Chris@330 426 QString units = outputs[j].unit.c_str();
Chris@330 427 QString description = plugin->getDescription().c_str();
Chris@330 428 QString maker = plugin->getMaker().c_str();
Chris@330 429 if (maker == "") maker = tr("<unknown maker>");
Chris@330 430
Chris@443 431 QString longDescription = description;
Chris@443 432
Chris@443 433 if (longDescription == "") {
Chris@330 434 if (outputs.size() == 1) {
Chris@443 435 longDescription = tr("Extract features using \"%1\" plugin (from %2)")
Chris@330 436 .arg(pluginName).arg(maker);
Chris@330 437 } else {
Chris@443 438 longDescription = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
Chris@330 439 .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330 440 }
Chris@330 441 } else {
Chris@330 442 if (outputs.size() == 1) {
Chris@443 443 longDescription = tr("%1 using \"%2\" plugin (from %3)")
Chris@443 444 .arg(longDescription).arg(pluginName).arg(maker);
Chris@330 445 } else {
Chris@443 446 longDescription = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
Chris@443 447 .arg(longDescription).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330 448 }
Chris@330 449 }
Chris@330 450
Chris@330 451 if (outputs.size() == 1) {
Chris@330 452 userName = pluginName;
Chris@330 453 friendlyName = pluginName;
Chris@330 454 } else {
Chris@330 455 userName = QString("%1: %2")
Chris@330 456 .arg(pluginName)
Chris@330 457 .arg(outputs[j].name.c_str());
Chris@330 458 friendlyName = outputs[j].name.c_str();
Chris@330 459 }
Chris@330 460
Chris@330 461 bool configurable = (!plugin->getPrograms().empty() ||
Chris@330 462 !plugin->getParameterDescriptors().empty());
Chris@330 463
Chris@443 464 // cerr << "Feature extraction plugin transform: " << transformId.toStdString() << " friendly name: " << friendlyName.toStdString() << endl;
Chris@330 465
Chris@330 466 transforms[transformId] =
Chris@487 467 TransformDescription(TransformDescription::Analysis,
Chris@332 468 category,
Chris@332 469 transformId,
Chris@332 470 userName,
Chris@332 471 friendlyName,
Chris@332 472 description,
Chris@443 473 longDescription,
Chris@332 474 maker,
Chris@332 475 units,
Chris@332 476 configurable);
Chris@330 477 }
Chris@330 478
Chris@330 479 delete plugin;
Chris@330 480 }
Chris@330 481 }
Chris@330 482
Chris@330 483 void
Chris@330 484 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@330 485 {
Chris@330 486 std::vector<QString> plugs =
Chris@330 487 RealTimePluginFactory::getAllPluginIdentifiers();
Chris@330 488
Chris@330 489 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@330 490
Chris@330 491 for (size_t i = 0; i < plugs.size(); ++i) {
Chris@330 492
Chris@330 493 QString pluginId = plugs[i];
Chris@330 494
Chris@330 495 RealTimePluginFactory *factory =
Chris@330 496 RealTimePluginFactory::instanceFor(pluginId);
Chris@330 497
Chris@330 498 if (!factory) {
Chris@443 499 cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << endl;
Chris@330 500 continue;
Chris@330 501 }
Chris@330 502
Chris@330 503 const RealTimePluginDescriptor *descriptor =
Chris@330 504 factory->getPluginDescriptor(pluginId);
Chris@330 505
Chris@330 506 if (!descriptor) {
Chris@443 507 cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << endl;
Chris@330 508 continue;
Chris@330 509 }
Chris@330 510
Chris@330 511 //!!! if (descriptor->controlOutputPortCount == 0 ||
Chris@330 512 // descriptor->audioInputPortCount == 0) continue;
Chris@330 513
Chris@443 514 // std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << endl;
Chris@330 515
Chris@330 516 QString pluginName = descriptor->name.c_str();
Chris@330 517 QString category = factory->getPluginCategory(pluginId);
Chris@330 518 bool configurable = (descriptor->parameterCount > 0);
Chris@330 519 QString maker = descriptor->maker.c_str();
Chris@330 520 if (maker == "") maker = tr("<unknown maker>");
Chris@330 521
Chris@330 522 if (descriptor->audioInputPortCount > 0) {
Chris@330 523
Chris@330 524 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
Chris@330 525
Chris@330 526 QString transformId = QString("%1:%2").arg(pluginId).arg(j);
Chris@330 527 QString userName;
Chris@330 528 QString units;
Chris@330 529 QString portName;
Chris@330 530
Chris@330 531 if (j < descriptor->controlOutputPortNames.size() &&
Chris@330 532 descriptor->controlOutputPortNames[j] != "") {
Chris@330 533
Chris@330 534 portName = descriptor->controlOutputPortNames[j].c_str();
Chris@330 535
Chris@330 536 userName = tr("%1: %2")
Chris@330 537 .arg(pluginName)
Chris@330 538 .arg(portName);
Chris@330 539
Chris@330 540 if (unitRE.indexIn(portName) >= 0) {
Chris@330 541 units = unitRE.cap(1);
Chris@330 542 }
Chris@330 543
Chris@330 544 } else if (descriptor->controlOutputPortCount > 1) {
Chris@330 545
Chris@330 546 userName = tr("%1: Output %2")
Chris@330 547 .arg(pluginName)
Chris@330 548 .arg(j + 1);
Chris@330 549
Chris@330 550 } else {
Chris@330 551
Chris@330 552 userName = pluginName;
Chris@330 553 }
Chris@330 554
Chris@330 555 QString description;
Chris@330 556
Chris@330 557 if (portName != "") {
Chris@330 558 description = tr("Extract \"%1\" data output from \"%2\" effect plugin (from %3)")
Chris@330 559 .arg(portName)
Chris@330 560 .arg(pluginName)
Chris@330 561 .arg(maker);
Chris@330 562 } else {
Chris@330 563 description = tr("Extract data output %1 from \"%2\" effect plugin (from %3)")
Chris@330 564 .arg(j + 1)
Chris@330 565 .arg(pluginName)
Chris@330 566 .arg(maker);
Chris@330 567 }
Chris@330 568
Chris@330 569 transforms[transformId] =
Chris@487 570 TransformDescription(TransformDescription::EffectsData,
Chris@332 571 category,
Chris@332 572 transformId,
Chris@332 573 userName,
Chris@332 574 userName,
Chris@443 575 "",
Chris@332 576 description,
Chris@332 577 maker,
Chris@332 578 units,
Chris@332 579 configurable);
Chris@330 580 }
Chris@330 581 }
Chris@330 582
Chris@330 583 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@330 584
Chris@330 585 if (descriptor->audioOutputPortCount > 0) {
Chris@330 586
Chris@330 587 QString transformId = QString("%1:A").arg(pluginId);
Chris@487 588 TransformDescription::Type type = TransformDescription::Effects;
Chris@330 589
Chris@330 590 QString description = tr("Transform audio signal with \"%1\" effect plugin (from %2)")
Chris@330 591 .arg(pluginName)
Chris@330 592 .arg(maker);
Chris@330 593
Chris@330 594 if (descriptor->audioInputPortCount == 0) {
Chris@487 595 type = TransformDescription::Generator;
Chris@330 596 QString description = tr("Generate audio signal using \"%1\" plugin (from %2)")
Chris@330 597 .arg(pluginName)
Chris@330 598 .arg(maker);
Chris@330 599 }
Chris@330 600
Chris@330 601 transforms[transformId] =
Chris@330 602 TransformDescription(type,
Chris@332 603 category,
Chris@332 604 transformId,
Chris@332 605 pluginName,
Chris@332 606 pluginName,
Chris@443 607 "",
Chris@332 608 description,
Chris@332 609 maker,
Chris@332 610 "",
Chris@332 611 configurable);
Chris@330 612 }
Chris@330 613 }
Chris@330 614 }
Chris@330 615 }
Chris@330 616
Chris@457 617 void
Chris@457 618 TransformFactory::populateUninstalledTransforms()
Chris@457 619 {
Chris@460 620 populateTransforms();
Chris@460 621
Chris@460 622 MutexLocker locker(&m_uninstalledTransformsMutex,
Chris@460 623 "TransformFactory::populateUninstalledTransforms");
Chris@460 624 if (m_uninstalledTransformsPopulated) return;
Chris@460 625
Chris@461 626 PluginRDFIndexer::getInstance()->indexConfiguredURLs();
Chris@457 627
Chris@457 628 //!!! This will be amazingly slow
Chris@457 629
Chris@457 630 QStringList ids = PluginRDFIndexer::getInstance()->getIndexedPluginIds();
Chris@457 631
Chris@457 632 for (QStringList::const_iterator i = ids.begin(); i != ids.end(); ++i) {
Chris@457 633
Chris@457 634 PluginRDFDescription desc(*i);
Chris@457 635
Chris@457 636 QString name = desc.getPluginName();
Chris@457 637 // if (name == "") {
Chris@457 638 // std::cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@457 639 // << "No name available for plugin " << i->toStdString()
Chris@457 640 // << ", skipping" << std::endl;
Chris@457 641 // continue;
Chris@457 642 // }
Chris@457 643
Chris@457 644 QString description = desc.getPluginDescription();
Chris@457 645 QString maker = desc.getPluginMaker();
Chris@462 646 QString infoUrl = desc.getPluginInfoURL();
Chris@457 647
Chris@457 648 QStringList oids = desc.getOutputIds();
Chris@457 649
Chris@457 650 for (QStringList::const_iterator j = oids.begin(); j != oids.end(); ++j) {
Chris@457 651
Chris@457 652 TransformId tid = Transform::getIdentifierForPluginOutput(*i, *j);
Chris@457 653
Chris@457 654 if (m_transforms.find(tid) != m_transforms.end()) {
Chris@494 655 // std::cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@494 656 // << tid.toStdString() << " is installed; adding info url if appropriate, skipping rest" << std::endl;
Chris@468 657 if (infoUrl != "") {
Chris@468 658 if (m_transforms[tid].infoUrl == "") {
Chris@468 659 m_transforms[tid].infoUrl = infoUrl;
Chris@468 660 }
Chris@468 661 }
Chris@457 662 continue;
Chris@457 663 }
Chris@457 664
Chris@494 665 // std::cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@494 666 // << "adding " << tid.toStdString() << std::endl;
Chris@457 667
Chris@457 668 QString oname = desc.getOutputName(*j);
Chris@457 669 if (oname == "") oname = *j;
Chris@457 670
Chris@457 671 TransformDescription td;
Chris@487 672 td.type = TransformDescription::Analysis;
Chris@457 673 td.category = "";
Chris@457 674 td.identifier = tid;
Chris@457 675
Chris@457 676 if (oids.size() == 1) {
Chris@457 677 td.name = name;
Chris@457 678 } else if (name != "") {
Chris@457 679 td.name = tr("%1: %2").arg(name).arg(oname);
Chris@457 680 }
Chris@457 681
Chris@462 682 QString longDescription = description;
Chris@462 683 //!!! basically duplicated from above
Chris@462 684 if (longDescription == "") {
Chris@462 685 if (oids.size() == 1) {
Chris@462 686 longDescription = tr("Extract features using \"%1\" plugin (from %2)")
Chris@462 687 .arg(name).arg(maker);
Chris@462 688 } else {
Chris@462 689 longDescription = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
Chris@462 690 .arg(oname).arg(name).arg(maker);
Chris@462 691 }
Chris@462 692 } else {
Chris@462 693 if (oids.size() == 1) {
Chris@462 694 longDescription = tr("%1 using \"%2\" plugin (from %3)")
Chris@462 695 .arg(longDescription).arg(name).arg(maker);
Chris@462 696 } else {
Chris@462 697 longDescription = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
Chris@462 698 .arg(longDescription).arg(oname).arg(name).arg(maker);
Chris@462 699 }
Chris@462 700 }
Chris@462 701
Chris@457 702 td.friendlyName = name; //!!!???
Chris@457 703 td.description = description;
Chris@462 704 td.longDescription = longDescription;
Chris@457 705 td.maker = maker;
Chris@462 706 td.infoUrl = infoUrl;
Chris@457 707 td.units = "";
Chris@457 708 td.configurable = false;
Chris@457 709
Chris@457 710 m_uninstalledTransforms[tid] = td;
Chris@457 711 }
Chris@574 712
Chris@574 713 if (m_exiting) break;
Chris@457 714 }
Chris@457 715
Chris@457 716 m_uninstalledTransformsPopulated = true;
Chris@460 717
Chris@460 718 std::cerr << "populateUninstalledTransforms exiting" << std::endl;
Chris@457 719 }
Chris@350 720
Chris@350 721 Transform
Chris@350 722 TransformFactory::getDefaultTransformFor(TransformId id, size_t rate)
Chris@350 723 {
Chris@350 724 Transform t;
Chris@350 725 t.setIdentifier(id);
Chris@350 726 if (rate != 0) t.setSampleRate(rate);
Chris@350 727
Chris@351 728 Vamp::PluginBase *plugin = instantiateDefaultPluginFor(id, rate);
Chris@350 729
Chris@350 730 if (plugin) {
Chris@366 731 t.setPluginVersion(QString("%1").arg(plugin->getPluginVersion()));
Chris@350 732 setParametersFromPlugin(t, plugin);
Chris@350 733 makeContextConsistentWithPlugin(t, plugin);
Chris@350 734 delete plugin;
Chris@350 735 }
Chris@350 736
Chris@350 737 return t;
Chris@350 738 }
Chris@350 739
Chris@350 740 Vamp::PluginBase *
Chris@351 741 TransformFactory::instantiatePluginFor(const Transform &transform)
Chris@351 742 {
Chris@351 743 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 744 (transform.getIdentifier(), transform.getSampleRate());
Chris@508 745
Chris@351 746 if (plugin) {
Chris@351 747 setPluginParameters(transform, plugin);
Chris@351 748 }
Chris@508 749
Chris@351 750 return plugin;
Chris@351 751 }
Chris@351 752
Chris@351 753 Vamp::PluginBase *
Chris@351 754 TransformFactory::instantiateDefaultPluginFor(TransformId identifier, size_t rate)
Chris@350 755 {
Chris@350 756 Transform t;
Chris@350 757 t.setIdentifier(identifier);
Chris@350 758 if (rate == 0) rate = 44100;
Chris@350 759 QString pluginId = t.getPluginIdentifier();
Chris@350 760
Chris@350 761 Vamp::PluginBase *plugin = 0;
Chris@350 762
Chris@350 763 if (t.getType() == Transform::FeatureExtraction) {
Chris@350 764
Chris@350 765 FeatureExtractionPluginFactory *factory =
Chris@350 766 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@350 767
Chris@439 768 if (factory) {
Chris@439 769 plugin = factory->instantiatePlugin(pluginId, rate);
Chris@439 770 }
Chris@350 771
Chris@350 772 } else {
Chris@350 773
Chris@350 774 RealTimePluginFactory *factory =
Chris@350 775 RealTimePluginFactory::instanceFor(pluginId);
Chris@439 776
Chris@439 777 if (factory) {
Chris@439 778 plugin = factory->instantiatePlugin(pluginId, 0, 0, rate, 1024, 1);
Chris@439 779 }
Chris@350 780 }
Chris@350 781
Chris@350 782 return plugin;
Chris@350 783 }
Chris@350 784
Chris@350 785 Vamp::Plugin *
Chris@350 786 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin)
Chris@350 787 {
Chris@350 788 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin);
Chris@350 789 if (!vp) {
Chris@443 790 // cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << endl;
Chris@350 791 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why?
Chris@350 792 }
Chris@350 793 if (!vp) {
Chris@443 794 // cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << endl;
Chris@350 795 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
Chris@350 796 }
Chris@350 797 if (!vp) {
Chris@443 798 // cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << endl;
Chris@350 799 }
Chris@350 800 return vp;
Chris@350 801 }
Chris@350 802
Chris@330 803 bool
Chris@330 804 TransformFactory::haveTransform(TransformId identifier)
Chris@330 805 {
Chris@460 806 populateTransforms();
Chris@330 807 return (m_transforms.find(identifier) != m_transforms.end());
Chris@330 808 }
Chris@330 809
Chris@330 810 QString
Chris@330 811 TransformFactory::getTransformName(TransformId identifier)
Chris@330 812 {
Chris@330 813 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 814 return m_transforms[identifier].name;
Chris@330 815 } else return "";
Chris@330 816 }
Chris@330 817
Chris@330 818 QString
Chris@330 819 TransformFactory::getTransformFriendlyName(TransformId identifier)
Chris@330 820 {
Chris@330 821 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 822 return m_transforms[identifier].friendlyName;
Chris@330 823 } else return "";
Chris@330 824 }
Chris@330 825
Chris@330 826 QString
Chris@330 827 TransformFactory::getTransformUnits(TransformId identifier)
Chris@330 828 {
Chris@330 829 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 830 return m_transforms[identifier].units;
Chris@330 831 } else return "";
Chris@330 832 }
Chris@330 833
Chris@472 834 QString
Chris@472 835 TransformFactory::getTransformInfoUrl(TransformId identifier)
Chris@472 836 {
Chris@472 837 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@472 838 return m_transforms[identifier].infoUrl;
Chris@472 839 } else return "";
Chris@472 840 }
Chris@472 841
Chris@350 842 Vamp::Plugin::InputDomain
Chris@350 843 TransformFactory::getTransformInputDomain(TransformId identifier)
Chris@350 844 {
Chris@350 845 Transform transform;
Chris@350 846 transform.setIdentifier(identifier);
Chris@350 847
Chris@350 848 if (transform.getType() != Transform::FeatureExtraction) {
Chris@350 849 return Vamp::Plugin::TimeDomain;
Chris@350 850 }
Chris@350 851
Chris@350 852 Vamp::Plugin *plugin =
Chris@351 853 downcastVampPlugin(instantiateDefaultPluginFor(identifier, 0));
Chris@350 854
Chris@350 855 if (plugin) {
Chris@350 856 Vamp::Plugin::InputDomain d = plugin->getInputDomain();
Chris@350 857 delete plugin;
Chris@350 858 return d;
Chris@350 859 }
Chris@350 860
Chris@350 861 return Vamp::Plugin::TimeDomain;
Chris@350 862 }
Chris@350 863
Chris@330 864 bool
Chris@330 865 TransformFactory::isTransformConfigurable(TransformId identifier)
Chris@330 866 {
Chris@330 867 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330 868 return m_transforms[identifier].configurable;
Chris@330 869 } else return false;
Chris@330 870 }
Chris@330 871
Chris@330 872 bool
Chris@330 873 TransformFactory::getTransformChannelRange(TransformId identifier,
Chris@330 874 int &min, int &max)
Chris@330 875 {
Chris@330 876 QString id = identifier.section(':', 0, 2);
Chris@330 877
Chris@330 878 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@330 879
Chris@330 880 Vamp::Plugin *plugin =
Chris@330 881 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@350 882 instantiatePlugin(id, 44100);
Chris@330 883 if (!plugin) return false;
Chris@330 884
Chris@330 885 min = plugin->getMinChannelCount();
Chris@330 886 max = plugin->getMaxChannelCount();
Chris@330 887 delete plugin;
Chris@330 888
Chris@330 889 return true;
Chris@330 890
Chris@330 891 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@330 892
Chris@350 893 // don't need to instantiate
Chris@350 894
Chris@330 895 const RealTimePluginDescriptor *descriptor =
Chris@330 896 RealTimePluginFactory::instanceFor(id)->
Chris@330 897 getPluginDescriptor(id);
Chris@330 898 if (!descriptor) return false;
Chris@330 899
Chris@330 900 min = descriptor->audioInputPortCount;
Chris@330 901 max = descriptor->audioInputPortCount;
Chris@330 902
Chris@330 903 return true;
Chris@330 904 }
Chris@330 905
Chris@330 906 return false;
Chris@330 907 }
Chris@332 908
Chris@332 909 void
Chris@332 910 TransformFactory::setParametersFromPlugin(Transform &transform,
Chris@332 911 Vamp::PluginBase *plugin)
Chris@332 912 {
Chris@332 913 Transform::ParameterMap pmap;
Chris@332 914
Chris@350 915 //!!! record plugin & API version
Chris@350 916
Chris@350 917 //!!! check that this is the right plugin!
Chris@350 918
Chris@332 919 Vamp::PluginBase::ParameterList parameters =
Chris@332 920 plugin->getParameterDescriptors();
Chris@332 921
Chris@332 922 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@332 923 i != parameters.end(); ++i) {
Chris@332 924 pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier);
Chris@332 925 }
Chris@332 926
Chris@332 927 transform.setParameters(pmap);
Chris@332 928
Chris@332 929 if (plugin->getPrograms().empty()) {
Chris@332 930 transform.setProgram("");
Chris@332 931 } else {
Chris@332 932 transform.setProgram(plugin->getCurrentProgram().c_str());
Chris@332 933 }
Chris@332 934
Chris@332 935 RealTimePluginInstance *rtpi =
Chris@332 936 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@332 937
Chris@332 938 Transform::ConfigurationMap cmap;
Chris@332 939
Chris@332 940 if (rtpi) {
Chris@332 941
Chris@332 942 RealTimePluginInstance::ConfigurationPairMap configurePairs =
Chris@332 943 rtpi->getConfigurePairs();
Chris@332 944
Chris@332 945 for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i
Chris@332 946 = configurePairs.begin(); i != configurePairs.end(); ++i) {
Chris@332 947 cmap[i->first.c_str()] = i->second.c_str();
Chris@332 948 }
Chris@332 949 }
Chris@332 950
Chris@332 951 transform.setConfiguration(cmap);
Chris@332 952 }
Chris@332 953
Chris@332 954 void
Chris@350 955 TransformFactory::setPluginParameters(const Transform &transform,
Chris@350 956 Vamp::PluginBase *plugin)
Chris@350 957 {
Chris@350 958 //!!! check plugin & API version (see e.g. PluginXml::setParameters)
Chris@350 959
Chris@350 960 //!!! check that this is the right plugin!
Chris@350 961
Chris@350 962 RealTimePluginInstance *rtpi =
Chris@350 963 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@350 964
Chris@350 965 if (rtpi) {
Chris@350 966 const Transform::ConfigurationMap &cmap = transform.getConfiguration();
Chris@350 967 for (Transform::ConfigurationMap::const_iterator i = cmap.begin();
Chris@350 968 i != cmap.end(); ++i) {
Chris@350 969 rtpi->configure(i->first.toStdString(), i->second.toStdString());
Chris@350 970 }
Chris@350 971 }
Chris@350 972
Chris@350 973 if (transform.getProgram() != "") {
Chris@350 974 plugin->selectProgram(transform.getProgram().toStdString());
Chris@350 975 }
Chris@350 976
Chris@350 977 const Transform::ParameterMap &pmap = transform.getParameters();
Chris@350 978
Chris@350 979 Vamp::PluginBase::ParameterList parameters =
Chris@350 980 plugin->getParameterDescriptors();
Chris@350 981
Chris@350 982 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@350 983 i != parameters.end(); ++i) {
Chris@350 984 QString key = i->identifier.c_str();
Chris@350 985 Transform::ParameterMap::const_iterator pmi = pmap.find(key);
Chris@350 986 if (pmi != pmap.end()) {
Chris@350 987 plugin->setParameter(i->identifier, pmi->second);
Chris@350 988 }
Chris@350 989 }
Chris@350 990 }
Chris@350 991
Chris@350 992 void
Chris@332 993 TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
Chris@332 994 Vamp::PluginBase *plugin)
Chris@332 995 {
Chris@350 996 const Vamp::Plugin *vp = downcastVampPlugin(plugin);
Chris@332 997
Chris@332 998 if (!vp) {
Chris@332 999 // time domain input for real-time effects plugin
Chris@332 1000 if (!transform.getBlockSize()) {
Chris@332 1001 if (!transform.getStepSize()) transform.setStepSize(1024);
Chris@332 1002 transform.setBlockSize(transform.getStepSize());
Chris@332 1003 } else {
Chris@332 1004 transform.setStepSize(transform.getBlockSize());
Chris@332 1005 }
Chris@332 1006 } else {
Chris@332 1007 Vamp::Plugin::InputDomain domain = vp->getInputDomain();
Chris@332 1008 if (!transform.getStepSize()) {
Chris@332 1009 transform.setStepSize(vp->getPreferredStepSize());
Chris@332 1010 }
Chris@332 1011 if (!transform.getBlockSize()) {
Chris@332 1012 transform.setBlockSize(vp->getPreferredBlockSize());
Chris@332 1013 }
Chris@332 1014 if (!transform.getBlockSize()) {
Chris@332 1015 transform.setBlockSize(1024);
Chris@332 1016 }
Chris@332 1017 if (!transform.getStepSize()) {
Chris@332 1018 if (domain == Vamp::Plugin::FrequencyDomain) {
Chris@443 1019 // cerr << "frequency domain, step = " << blockSize/2 << endl;
Chris@332 1020 transform.setStepSize(transform.getBlockSize()/2);
Chris@332 1021 } else {
Chris@443 1022 // cerr << "time domain, step = " << blockSize/2 << endl;
Chris@332 1023 transform.setStepSize(transform.getBlockSize());
Chris@332 1024 }
Chris@332 1025 }
Chris@332 1026 }
Chris@332 1027 }
Chris@332 1028
Chris@350 1029 QString
Chris@350 1030 TransformFactory::getPluginConfigurationXml(const Transform &t)
Chris@332 1031 {
Chris@350 1032 QString xml;
Chris@350 1033
Chris@351 1034 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1035 (t.getIdentifier(), 0);
Chris@350 1036 if (!plugin) {
Chris@443 1037 cerr << "TransformFactory::getPluginConfigurationXml: "
Chris@350 1038 << "Unable to instantiate plugin for transform \""
Chris@443 1039 << t.getIdentifier().toStdString() << "\"" << endl;
Chris@350 1040 return xml;
Chris@332 1041 }
Chris@332 1042
Chris@351 1043 setPluginParameters(t, plugin);
Chris@351 1044
Chris@350 1045 QTextStream out(&xml);
Chris@350 1046 PluginXml(plugin).toXml(out);
Chris@350 1047 delete plugin;
Chris@332 1048
Chris@350 1049 return xml;
Chris@350 1050 }
Chris@332 1051
Chris@350 1052 void
Chris@350 1053 TransformFactory::setParametersFromPluginConfigurationXml(Transform &t,
Chris@350 1054 QString xml)
Chris@350 1055 {
Chris@351 1056 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1057 (t.getIdentifier(), 0);
Chris@350 1058 if (!plugin) {
Chris@443 1059 cerr << "TransformFactory::setParametersFromPluginConfigurationXml: "
Chris@350 1060 << "Unable to instantiate plugin for transform \""
Chris@443 1061 << t.getIdentifier().toStdString() << "\"" << endl;
Chris@350 1062 return;
Chris@332 1063 }
Chris@332 1064
Chris@350 1065 PluginXml(plugin).setParametersFromXml(xml);
Chris@350 1066 setParametersFromPlugin(t, plugin);
Chris@350 1067 delete plugin;
Chris@332 1068 }
Chris@332 1069
Chris@443 1070 TransformFactory::SearchResults
Chris@443 1071 TransformFactory::search(QString keyword)
Chris@443 1072 {
Chris@443 1073 QStringList keywords;
Chris@443 1074 keywords << keyword;
Chris@443 1075 return search(keywords);
Chris@443 1076 }
Chris@443 1077
Chris@443 1078 TransformFactory::SearchResults
Chris@443 1079 TransformFactory::search(QStringList keywords)
Chris@443 1080 {
Chris@460 1081 populateTransforms();
Chris@443 1082
Chris@447 1083 if (keywords.size() > 1) {
Chris@447 1084 // Additional score for all keywords in a row
Chris@447 1085 keywords.push_back(keywords.join(" "));
Chris@447 1086 }
Chris@447 1087
Chris@443 1088 SearchResults results;
Chris@457 1089 TextMatcher matcher;
Chris@443 1090
Chris@443 1091 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@443 1092 i != m_transforms.end(); ++i) {
Chris@443 1093
Chris@457 1094 TextMatcher::Match match;
Chris@443 1095
Chris@457 1096 match.key = i->first;
Chris@443 1097
Chris@487 1098 matcher.test(match, keywords,
Chris@487 1099 getTransformTypeName(i->second.type),
Chris@487 1100 tr("Plugin type"), 5);
Chris@487 1101
Chris@457 1102 matcher.test(match, keywords, i->second.category, tr("Category"), 20);
Chris@457 1103 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 6);
Chris@457 1104 matcher.test(match, keywords, i->second.name, tr("Name"), 30);
Chris@457 1105 matcher.test(match, keywords, i->second.description, tr("Description"), 20);
Chris@457 1106 matcher.test(match, keywords, i->second.maker, tr("Maker"), 10);
Chris@457 1107 matcher.test(match, keywords, i->second.units, tr("Units"), 10);
Chris@457 1108
Chris@457 1109 if (match.score > 0) results[i->first] = match;
Chris@457 1110 }
Chris@457 1111
Chris@460 1112 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@460 1113 // uninstalled transforms are being populated; this may take some time,
Chris@484 1114 // and they aren't critical, but we will speed them up if necessary
Chris@460 1115 std::cerr << "TransformFactory::search: Uninstalled transforms mutex is held, skipping" << std::endl;
Chris@484 1116 m_populatingSlowly = false;
Chris@460 1117 return results;
Chris@460 1118 }
Chris@460 1119
Chris@460 1120 if (!m_uninstalledTransformsPopulated) {
Chris@460 1121 std::cerr << "WARNING: TransformFactory::search: Uninstalled transforms are not populated yet" << endl
Chris@460 1122 << "and are not being populated either -- was the thread not started correctly?" << endl;
Chris@460 1123 m_uninstalledTransformsMutex.unlock();
Chris@460 1124 return results;
Chris@460 1125 }
Chris@460 1126
Chris@460 1127 m_uninstalledTransformsMutex.unlock();
Chris@457 1128
Chris@457 1129 for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin();
Chris@457 1130 i != m_uninstalledTransforms.end(); ++i) {
Chris@457 1131
Chris@457 1132 TextMatcher::Match match;
Chris@457 1133
Chris@457 1134 match.key = i->first;
Chris@457 1135
Chris@487 1136 matcher.test(match, keywords,
Chris@487 1137 getTransformTypeName(i->second.type),
Chris@487 1138 tr("Plugin type"), 2);
Chris@487 1139
Chris@457 1140 matcher.test(match, keywords, i->second.category, tr("Category"), 10);
Chris@457 1141 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 3);
Chris@457 1142 matcher.test(match, keywords, i->second.name, tr("Name"), 15);
Chris@457 1143 matcher.test(match, keywords, i->second.description, tr("Description"), 10);
Chris@457 1144 matcher.test(match, keywords, i->second.maker, tr("Maker"), 5);
Chris@457 1145 matcher.test(match, keywords, i->second.units, tr("Units"), 5);
Chris@443 1146
Chris@443 1147 if (match.score > 0) results[i->first] = match;
Chris@443 1148 }
Chris@443 1149
Chris@443 1150 return results;
Chris@443 1151 }
Chris@443 1152