annotate transform/TransformFactory.cpp @ 1455:ec9e65fcf749

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