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