Mercurial > hg > svcore
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 |