comparison transform/TransformFactory.cpp @ 443:381ec750eeee

* Add beginnings of transform-search-by-text function
author Chris Cannam
date Mon, 22 Sep 2008 15:44:03 +0000
parents beb2948baa77
children 14521503f196
comparison
equal deleted inserted replaced
442:04b7fd31e1c6 443:381ec750eeee
28 #include <set> 28 #include <set>
29 29
30 #include <QRegExp> 30 #include <QRegExp>
31 #include <QTextStream> 31 #include <QTextStream>
32 32
33 using std::cerr;
34 using std::endl;
35
33 TransformFactory * 36 TransformFactory *
34 TransformFactory::m_instance = new TransformFactory; 37 TransformFactory::m_instance = new TransformFactory;
35 38
36 TransformFactory * 39 TransformFactory *
37 TransformFactory::getInstance() 40 TransformFactory::getInstance()
49 if (m_transforms.empty()) populateTransforms(); 52 if (m_transforms.empty()) populateTransforms();
50 53
51 std::set<TransformDescription> dset; 54 std::set<TransformDescription> dset;
52 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); 55 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
53 i != m_transforms.end(); ++i) { 56 i != m_transforms.end(); ++i) {
54 // std::cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << std::endl; 57 // cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << endl;
55 dset.insert(i->second); 58 dset.insert(i->second);
56 } 59 }
57 60
58 TransformList list; 61 TransformList list;
59 for (std::set<TransformDescription>::const_iterator i = dset.begin(); 62 for (std::set<TransformDescription>::const_iterator i = dset.begin();
60 i != dset.end(); ++i) { 63 i != dset.end(); ++i) {
61 // std::cerr << "inserting transform into list: id = " << i->identifier.toStdString() << std::endl; 64 // cerr << "inserting transform into list: id = " << i->identifier.toStdString() << endl;
62 list.push_back(*i); 65 list.push_back(*i);
63 } 66 }
64 67
65 return list; 68 return list;
66 } 69 }
225 228
226 FeatureExtractionPluginFactory *factory = 229 FeatureExtractionPluginFactory *factory =
227 FeatureExtractionPluginFactory::instanceFor(pluginId); 230 FeatureExtractionPluginFactory::instanceFor(pluginId);
228 231
229 if (!factory) { 232 if (!factory) {
230 std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl; 233 cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << endl;
231 continue; 234 continue;
232 } 235 }
233 236
234 Vamp::Plugin *plugin = 237 Vamp::Plugin *plugin =
235 factory->instantiatePlugin(pluginId, 44100); 238 factory->instantiatePlugin(pluginId, 44100);
236 239
237 if (!plugin) { 240 if (!plugin) {
238 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl; 241 cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << endl;
239 continue; 242 continue;
240 } 243 }
241 244
242 QString pluginName = plugin->getName().c_str(); 245 QString pluginName = plugin->getName().c_str();
243 QString category = factory->getPluginCategory(pluginId); 246 QString category = factory->getPluginCategory(pluginId);
255 QString units = outputs[j].unit.c_str(); 258 QString units = outputs[j].unit.c_str();
256 QString description = plugin->getDescription().c_str(); 259 QString description = plugin->getDescription().c_str();
257 QString maker = plugin->getMaker().c_str(); 260 QString maker = plugin->getMaker().c_str();
258 if (maker == "") maker = tr("<unknown maker>"); 261 if (maker == "") maker = tr("<unknown maker>");
259 262
260 if (description == "") { 263 QString longDescription = description;
264
265 if (longDescription == "") {
261 if (outputs.size() == 1) { 266 if (outputs.size() == 1) {
262 description = tr("Extract features using \"%1\" plugin (from %2)") 267 longDescription = tr("Extract features using \"%1\" plugin (from %2)")
263 .arg(pluginName).arg(maker); 268 .arg(pluginName).arg(maker);
264 } else { 269 } else {
265 description = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)") 270 longDescription = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
266 .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker); 271 .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
267 } 272 }
268 } else { 273 } else {
269 if (outputs.size() == 1) { 274 if (outputs.size() == 1) {
270 description = tr("%1 using \"%2\" plugin (from %3)") 275 longDescription = tr("%1 using \"%2\" plugin (from %3)")
271 .arg(description).arg(pluginName).arg(maker); 276 .arg(longDescription).arg(pluginName).arg(maker);
272 } else { 277 } else {
273 description = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)") 278 longDescription = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
274 .arg(description).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker); 279 .arg(longDescription).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
275 } 280 }
276 } 281 }
277 282
278 if (outputs.size() == 1) { 283 if (outputs.size() == 1) {
279 userName = pluginName; 284 userName = pluginName;
286 } 291 }
287 292
288 bool configurable = (!plugin->getPrograms().empty() || 293 bool configurable = (!plugin->getPrograms().empty() ||
289 !plugin->getParameterDescriptors().empty()); 294 !plugin->getParameterDescriptors().empty());
290 295
291 // std::cerr << "Feature extraction plugin transform: " << transformId.toStdString() << " friendly name: " << friendlyName.toStdString() << std::endl; 296 // cerr << "Feature extraction plugin transform: " << transformId.toStdString() << " friendly name: " << friendlyName.toStdString() << endl;
292 297
293 transforms[transformId] = 298 transforms[transformId] =
294 TransformDescription(tr("Analysis"), 299 TransformDescription(tr("Analysis"),
295 category, 300 category,
296 transformId, 301 transformId,
297 userName, 302 userName,
298 friendlyName, 303 friendlyName,
299 description, 304 description,
305 longDescription,
300 maker, 306 maker,
301 units, 307 units,
302 configurable); 308 configurable);
303 } 309 }
304 310
320 326
321 RealTimePluginFactory *factory = 327 RealTimePluginFactory *factory =
322 RealTimePluginFactory::instanceFor(pluginId); 328 RealTimePluginFactory::instanceFor(pluginId);
323 329
324 if (!factory) { 330 if (!factory) {
325 std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl; 331 cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << endl;
326 continue; 332 continue;
327 } 333 }
328 334
329 const RealTimePluginDescriptor *descriptor = 335 const RealTimePluginDescriptor *descriptor =
330 factory->getPluginDescriptor(pluginId); 336 factory->getPluginDescriptor(pluginId);
331 337
332 if (!descriptor) { 338 if (!descriptor) {
333 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl; 339 cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << endl;
334 continue; 340 continue;
335 } 341 }
336 342
337 //!!! if (descriptor->controlOutputPortCount == 0 || 343 //!!! if (descriptor->controlOutputPortCount == 0 ||
338 // descriptor->audioInputPortCount == 0) continue; 344 // descriptor->audioInputPortCount == 0) continue;
339 345
340 // std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << std::endl; 346 // std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << endl;
341 347
342 QString pluginName = descriptor->name.c_str(); 348 QString pluginName = descriptor->name.c_str();
343 QString category = factory->getPluginCategory(pluginId); 349 QString category = factory->getPluginCategory(pluginId);
344 bool configurable = (descriptor->parameterCount > 0); 350 bool configurable = (descriptor->parameterCount > 0);
345 QString maker = descriptor->maker.c_str(); 351 QString maker = descriptor->maker.c_str();
396 TransformDescription(tr("Effects Data"), 402 TransformDescription(tr("Effects Data"),
397 category, 403 category,
398 transformId, 404 transformId,
399 userName, 405 userName,
400 userName, 406 userName,
407 "",
401 description, 408 description,
402 maker, 409 maker,
403 units, 410 units,
404 configurable); 411 configurable);
405 } 412 }
427 TransformDescription(type, 434 TransformDescription(type,
428 category, 435 category,
429 transformId, 436 transformId,
430 pluginName, 437 pluginName,
431 pluginName, 438 pluginName,
439 "",
432 description, 440 description,
433 maker, 441 maker,
434 "", 442 "",
435 configurable); 443 configurable);
436 } 444 }
504 Vamp::Plugin * 512 Vamp::Plugin *
505 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin) 513 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin)
506 { 514 {
507 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin); 515 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin);
508 if (!vp) { 516 if (!vp) {
509 // std::cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << std::endl; 517 // cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << endl;
510 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why? 518 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why?
511 } 519 }
512 if (!vp) { 520 if (!vp) {
513 // std::cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << std::endl; 521 // cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << endl;
514 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why? 522 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
515 } 523 }
516 if (!vp) { 524 if (!vp) {
517 // std::cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << std::endl; 525 // cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << endl;
518 } 526 }
519 return vp; 527 return vp;
520 } 528 }
521 529
522 bool 530 bool
725 if (!transform.getBlockSize()) { 733 if (!transform.getBlockSize()) {
726 transform.setBlockSize(1024); 734 transform.setBlockSize(1024);
727 } 735 }
728 if (!transform.getStepSize()) { 736 if (!transform.getStepSize()) {
729 if (domain == Vamp::Plugin::FrequencyDomain) { 737 if (domain == Vamp::Plugin::FrequencyDomain) {
730 // std::cerr << "frequency domain, step = " << blockSize/2 << std::endl; 738 // cerr << "frequency domain, step = " << blockSize/2 << endl;
731 transform.setStepSize(transform.getBlockSize()/2); 739 transform.setStepSize(transform.getBlockSize()/2);
732 } else { 740 } else {
733 // std::cerr << "time domain, step = " << blockSize/2 << std::endl; 741 // cerr << "time domain, step = " << blockSize/2 << endl;
734 transform.setStepSize(transform.getBlockSize()); 742 transform.setStepSize(transform.getBlockSize());
735 } 743 }
736 } 744 }
737 } 745 }
738 } 746 }
743 QString xml; 751 QString xml;
744 752
745 Vamp::PluginBase *plugin = instantiateDefaultPluginFor 753 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
746 (t.getIdentifier(), 0); 754 (t.getIdentifier(), 0);
747 if (!plugin) { 755 if (!plugin) {
748 std::cerr << "TransformFactory::getPluginConfigurationXml: " 756 cerr << "TransformFactory::getPluginConfigurationXml: "
749 << "Unable to instantiate plugin for transform \"" 757 << "Unable to instantiate plugin for transform \""
750 << t.getIdentifier().toStdString() << "\"" << std::endl; 758 << t.getIdentifier().toStdString() << "\"" << endl;
751 return xml; 759 return xml;
752 } 760 }
753 761
754 setPluginParameters(t, plugin); 762 setPluginParameters(t, plugin);
755 763
765 QString xml) 773 QString xml)
766 { 774 {
767 Vamp::PluginBase *plugin = instantiateDefaultPluginFor 775 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
768 (t.getIdentifier(), 0); 776 (t.getIdentifier(), 0);
769 if (!plugin) { 777 if (!plugin) {
770 std::cerr << "TransformFactory::setParametersFromPluginConfigurationXml: " 778 cerr << "TransformFactory::setParametersFromPluginConfigurationXml: "
771 << "Unable to instantiate plugin for transform \"" 779 << "Unable to instantiate plugin for transform \""
772 << t.getIdentifier().toStdString() << "\"" << std::endl; 780 << t.getIdentifier().toStdString() << "\"" << endl;
773 return; 781 return;
774 } 782 }
775 783
776 PluginXml(plugin).setParametersFromXml(xml); 784 PluginXml(plugin).setParametersFromXml(xml);
777 setParametersFromPlugin(t, plugin); 785 setParametersFromPlugin(t, plugin);
778 delete plugin; 786 delete plugin;
779 } 787 }
780 788 /*
789 TransformFactory::SearchResults
790 TransformFactory::search(QStringList keywords)
791 {
792 SearchResults results;
793 SearchResults partial;
794 for (int i = 0; i < keywords.size(); ++i) {
795 partial = search(keywords[i]);
796 for (SearchResults::const_iterator j = partial.begin();
797 j != partial.end(); ++j) {
798 if (results.find(j->first) == results.end()) {
799 results[j->first] = j->second;
800 } else {
801 results[j->first].score += j->second.score;
802 results[j->first].fragments << j->second.fragments;
803 }
804 }
805 }
806 return results;
807 }
808 */
809
810 TransformFactory::SearchResults
811 TransformFactory::search(QString keyword)
812 {
813 QStringList keywords;
814 keywords << keyword;
815 return search(keywords);
816 }
817
818 TransformFactory::SearchResults
819 TransformFactory::search(QStringList keywords)
820 {
821 if (m_transforms.empty()) populateTransforms();
822
823 SearchResults results;
824
825 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
826 i != m_transforms.end(); ++i) {
827
828 Match match;
829
830 match.transform = i->first;
831
832 searchTest(match, keywords, i->second.type, tr("Plugin type"), 10);
833 searchTest(match, keywords, i->second.category, tr("Category"), 20);
834 searchTest(match, keywords, i->second.identifier, tr("System Identifier"), 5);
835 searchTest(match, keywords, i->second.name, tr("Name"), 30);
836 searchTest(match, keywords, i->second.description, tr("Description"), 20);
837 searchTest(match, keywords, i->second.maker, tr("Maker"), 10);
838 searchTest(match, keywords, i->second.units, tr("Units"), 10);
839
840 if (match.score > 0) results[i->first] = match;
841 }
842
843 return results;
844 }
845
846 void
847 TransformFactory::searchTest(Match &match, QStringList keywords, QString text,
848 QString textType, int score)
849 {
850 /*
851 if (text.toLower() == keyword.toLower()) {
852 match.score += score * 1.5;
853 match.fragments << tr("%1: <b>%2</b>").arg(textType).arg(text);
854 return;
855 }
856 */
857 int len = text.length();
858 int prevEnd = 0;
859 QString fragment;
860
861 while (1) {
862
863 bool first = (prevEnd == 0);
864
865 int idx = -1;
866 QString keyword;
867
868 for (int ki = 0; ki < keywords.size(); ++ki) {
869 int midx = text.indexOf(keywords[ki], prevEnd, Qt::CaseInsensitive);
870 if (midx >= 0 && midx < len) {
871 if (midx < idx || idx == -1) {
872 idx = midx;
873 keyword = keywords[ki];
874 }
875 }
876 }
877
878 if (idx < 0 || idx >= len) break;
879
880 int klen = keyword.length();
881
882 if (first) {
883 match.score += score;
884 } else {
885 match.score += score / 4;
886 }
887
888 int start = idx;
889 int end = start + klen;
890
891 if (start == 0) match.score += 1;
892 if (end == len) match.score += 1;
893
894 if (start > prevEnd + 14) {
895 // cerr << "start = " << start << ", prevEnd = " <<prevEnd << ", length = " << len << ", text = " << text.toStdString() << endl;
896 QString s = text.right((len - start) + 10);
897 // cerr << "s = " << s.toStdString() << endl;
898 s = s.left(10) + "<b>" + s.left(klen + 10).right(klen) + "</b>";
899 // cerr << "s = " << s.toStdString() << endl;
900 fragment += tr("...%1").arg(s);
901 // cerr << "fragment = " << fragment.toStdString() << endl;
902 } else {
903 QString s = text.right(len - prevEnd);
904 s = s.left(start - prevEnd) + "<b>" + s.left(end - prevEnd).right(klen) + "</b>";
905 fragment += s;
906 }
907
908 prevEnd = end;
909 }
910
911 if (prevEnd > 0 && prevEnd < len) {
912 int n = len - prevEnd;
913 fragment += text.right(n).left(n < 8 ? n : 8);
914 }
915
916 if (fragment != "") {
917 fragment = tr("%1: %2").arg(textType).arg(fragment);
918 match.fragments << fragment;
919 }
920 }
921