annotate transform/TransformFactory.cpp @ 489:82ab61fa9223

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