Mercurial > hg > svcore
comparison transform/TransformFactory.cpp @ 457:ef14acd6d102
* Add beginnings of capability to search plugins that are not yet
installed -- lots more work to do here, though
| author | Chris Cannam |
|---|---|
| date | Tue, 14 Oct 2008 16:36:35 +0000 |
| parents | 804601e50fd5 |
| children | 93fb1ebff76b |
comparison
equal
deleted
inserted
replaced
| 456:64e64e304a12 | 457:ef14acd6d102 |
|---|---|
| 22 | 22 |
| 23 #include "vamp-sdk/Plugin.h" | 23 #include "vamp-sdk/Plugin.h" |
| 24 #include "vamp-sdk/PluginHostAdapter.h" | 24 #include "vamp-sdk/PluginHostAdapter.h" |
| 25 #include "vamp-sdk/hostext/PluginWrapper.h" | 25 #include "vamp-sdk/hostext/PluginWrapper.h" |
| 26 | 26 |
| 27 #include "rdf/PluginRDFIndexer.h" | |
| 28 #include "rdf/PluginRDFDescription.h" | |
| 29 | |
| 27 #include "base/XmlExportable.h" | 30 #include "base/XmlExportable.h" |
| 28 | 31 |
| 29 #include <iostream> | 32 #include <iostream> |
| 30 #include <set> | 33 #include <set> |
| 31 | 34 |
| 42 TransformFactory::getInstance() | 45 TransformFactory::getInstance() |
| 43 { | 46 { |
| 44 return m_instance; | 47 return m_instance; |
| 45 } | 48 } |
| 46 | 49 |
| 50 TransformFactory::TransformFactory() : | |
| 51 m_transformsPopulated(false), | |
| 52 m_uninstalledTransformsPopulated(false) | |
| 53 { | |
| 54 } | |
| 55 | |
| 47 TransformFactory::~TransformFactory() | 56 TransformFactory::~TransformFactory() |
| 48 { | 57 { |
| 49 } | 58 } |
| 50 | 59 |
| 51 TransformList | 60 TransformList |
| 52 TransformFactory::getAllTransformDescriptions() | 61 TransformFactory::getAllTransformDescriptions() |
| 53 { | 62 { |
| 54 if (m_transforms.empty()) populateTransforms(); | 63 if (!m_transformsPopulated) populateTransforms(); |
| 55 | 64 |
| 56 std::set<TransformDescription> dset; | 65 std::set<TransformDescription> dset; |
| 57 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); | 66 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); |
| 58 i != m_transforms.end(); ++i) { | 67 i != m_transforms.end(); ++i) { |
| 59 // cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << endl; | 68 // cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << endl; |
| 71 } | 80 } |
| 72 | 81 |
| 73 TransformDescription | 82 TransformDescription |
| 74 TransformFactory::getTransformDescription(TransformId id) | 83 TransformFactory::getTransformDescription(TransformId id) |
| 75 { | 84 { |
| 76 if (m_transforms.empty()) populateTransforms(); | 85 if (!m_transformsPopulated) populateTransforms(); |
| 77 | 86 |
| 78 if (m_transforms.find(id) == m_transforms.end()) { | 87 if (m_transforms.find(id) == m_transforms.end()) { |
| 79 return TransformDescription(); | 88 return TransformDescription(); |
| 80 } | 89 } |
| 81 | 90 |
| 82 return m_transforms[id]; | 91 return m_transforms[id]; |
| 83 } | 92 } |
| 84 | 93 |
| 94 TransformList | |
| 95 TransformFactory::getUninstalledTransformDescriptions() | |
| 96 { | |
| 97 if (!m_uninstalledTransformsPopulated) populateUninstalledTransforms(); | |
| 98 | |
| 99 std::set<TransformDescription> dset; | |
| 100 for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin(); | |
| 101 i != m_uninstalledTransforms.end(); ++i) { | |
| 102 // cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << endl; | |
| 103 dset.insert(i->second); | |
| 104 } | |
| 105 | |
| 106 TransformList list; | |
| 107 for (std::set<TransformDescription>::const_iterator i = dset.begin(); | |
| 108 i != dset.end(); ++i) { | |
| 109 // cerr << "inserting transform into list: id = " << i->identifier.toStdString() << endl; | |
| 110 list.push_back(*i); | |
| 111 } | |
| 112 | |
| 113 return list; | |
| 114 } | |
| 115 | |
| 116 TransformDescription | |
| 117 TransformFactory::getUninstalledTransformDescription(TransformId id) | |
| 118 { | |
| 119 if (!m_uninstalledTransformsPopulated) populateUninstalledTransforms(); | |
| 120 | |
| 121 if (m_uninstalledTransforms.find(id) == m_uninstalledTransforms.end()) { | |
| 122 return TransformDescription(); | |
| 123 } | |
| 124 | |
| 125 return m_uninstalledTransforms[id]; | |
| 126 } | |
| 127 | |
| 128 TransformFactory::TransformInstallStatus | |
| 129 TransformFactory::getTransformInstallStatus(TransformId id) | |
| 130 { | |
| 131 if (!m_transformsPopulated) populateTransforms(); | |
| 132 if (!m_uninstalledTransformsPopulated) populateUninstalledTransforms(); | |
| 133 | |
| 134 if (m_transforms.find(id) != m_transforms.end()) { | |
| 135 return TransformInstalled; | |
| 136 } | |
| 137 if (m_uninstalledTransforms.find(id) != m_uninstalledTransforms.end()) { | |
| 138 return TransformNotInstalled; | |
| 139 } | |
| 140 return TransformUnknown; | |
| 141 } | |
| 142 | |
| 143 | |
| 85 std::vector<QString> | 144 std::vector<QString> |
| 86 TransformFactory::getAllTransformTypes() | 145 TransformFactory::getAllTransformTypes() |
| 87 { | 146 { |
| 88 if (m_transforms.empty()) populateTransforms(); | 147 if (!m_transformsPopulated) populateTransforms(); |
| 89 | 148 |
| 90 std::set<QString> types; | 149 std::set<QString> types; |
| 91 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); | 150 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); |
| 92 i != m_transforms.end(); ++i) { | 151 i != m_transforms.end(); ++i) { |
| 93 types.insert(i->second.type); | 152 types.insert(i->second.type); |
| 102 } | 161 } |
| 103 | 162 |
| 104 std::vector<QString> | 163 std::vector<QString> |
| 105 TransformFactory::getTransformCategories(QString transformType) | 164 TransformFactory::getTransformCategories(QString transformType) |
| 106 { | 165 { |
| 107 if (m_transforms.empty()) populateTransforms(); | 166 if (!m_transformsPopulated) populateTransforms(); |
| 108 | 167 |
| 109 std::set<QString> categories; | 168 std::set<QString> categories; |
| 110 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); | 169 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); |
| 111 i != m_transforms.end(); ++i) { | 170 i != m_transforms.end(); ++i) { |
| 112 if (i->second.type == transformType) { | 171 if (i->second.type == transformType) { |
| 129 } | 188 } |
| 130 | 189 |
| 131 std::vector<QString> | 190 std::vector<QString> |
| 132 TransformFactory::getTransformMakers(QString transformType) | 191 TransformFactory::getTransformMakers(QString transformType) |
| 133 { | 192 { |
| 134 if (m_transforms.empty()) populateTransforms(); | 193 if (!m_transformsPopulated) populateTransforms(); |
| 135 | 194 |
| 136 std::set<QString> makers; | 195 std::set<QString> makers; |
| 137 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); | 196 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); |
| 138 i != m_transforms.end(); ++i) { | 197 i != m_transforms.end(); ++i) { |
| 139 if (i->second.type == transformType) { | 198 if (i->second.type == transformType) { |
| 214 desc.name = tn; | 273 desc.name = tn; |
| 215 } | 274 } |
| 216 | 275 |
| 217 m_transforms[identifier] = desc; | 276 m_transforms[identifier] = desc; |
| 218 } | 277 } |
| 278 | |
| 279 m_transformsPopulated = true; | |
| 219 } | 280 } |
| 220 | 281 |
| 221 void | 282 void |
| 222 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms) | 283 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms) |
| 223 { | 284 { |
| 446 } | 507 } |
| 447 } | 508 } |
| 448 } | 509 } |
| 449 } | 510 } |
| 450 | 511 |
| 512 void | |
| 513 TransformFactory::populateUninstalledTransforms() | |
| 514 { | |
| 515 if (!m_uninstalledTransforms.empty()) return; | |
| 516 if (m_transforms.empty()) populateTransforms(); | |
| 517 | |
| 518 //!!! This will be amazingly slow | |
| 519 | |
| 520 QStringList ids = PluginRDFIndexer::getInstance()->getIndexedPluginIds(); | |
| 521 | |
| 522 for (QStringList::const_iterator i = ids.begin(); i != ids.end(); ++i) { | |
| 523 | |
| 524 PluginRDFDescription desc(*i); | |
| 525 | |
| 526 QString name = desc.getPluginName(); | |
| 527 // if (name == "") { | |
| 528 // std::cerr << "TransformFactory::populateUninstalledTransforms: " | |
| 529 // << "No name available for plugin " << i->toStdString() | |
| 530 // << ", skipping" << std::endl; | |
| 531 // continue; | |
| 532 // } | |
| 533 | |
| 534 QString description = desc.getPluginDescription(); | |
| 535 QString maker = desc.getPluginMaker(); | |
| 536 | |
| 537 QStringList oids = desc.getOutputIds(); | |
| 538 | |
| 539 for (QStringList::const_iterator j = oids.begin(); j != oids.end(); ++j) { | |
| 540 | |
| 541 TransformId tid = Transform::getIdentifierForPluginOutput(*i, *j); | |
| 542 | |
| 543 if (m_transforms.find(tid) != m_transforms.end()) { | |
| 544 std::cerr << "TransformFactory::populateUninstalledTransforms: " | |
| 545 << tid.toStdString() << " is installed, skipping" << std::endl; | |
| 546 continue; | |
| 547 } | |
| 548 | |
| 549 std::cerr << "TransformFactory::populateUninstalledTransforms: " | |
| 550 << "adding " << tid.toStdString() << std::endl; | |
| 551 | |
| 552 QString oname = desc.getOutputName(*j); | |
| 553 if (oname == "") oname = *j; | |
| 554 | |
| 555 TransformDescription td; | |
| 556 td.type = tr("Analysis"); //!!! should be enum or something | |
| 557 td.category = ""; | |
| 558 td.identifier = tid; | |
| 559 | |
| 560 if (oids.size() == 1) { | |
| 561 td.name = name; | |
| 562 } else if (name != "") { | |
| 563 td.name = tr("%1: %2").arg(name).arg(oname); | |
| 564 } | |
| 565 | |
| 566 td.friendlyName = name; //!!!??? | |
| 567 td.description = description; | |
| 568 td.longDescription = ""; //!!! | |
| 569 td.maker = maker; | |
| 570 td.units = ""; | |
| 571 td.configurable = false; | |
| 572 | |
| 573 m_uninstalledTransforms[tid] = td; | |
| 574 } | |
| 575 } | |
| 576 | |
| 577 m_uninstalledTransformsPopulated = true; | |
| 578 } | |
| 451 | 579 |
| 452 Transform | 580 Transform |
| 453 TransformFactory::getDefaultTransformFor(TransformId id, size_t rate) | 581 TransformFactory::getDefaultTransformFor(TransformId id, size_t rate) |
| 454 { | 582 { |
| 455 Transform t; | 583 Transform t; |
| 785 | 913 |
| 786 PluginXml(plugin).setParametersFromXml(xml); | 914 PluginXml(plugin).setParametersFromXml(xml); |
| 787 setParametersFromPlugin(t, plugin); | 915 setParametersFromPlugin(t, plugin); |
| 788 delete plugin; | 916 delete plugin; |
| 789 } | 917 } |
| 790 /* | |
| 791 TransformFactory::SearchResults | |
| 792 TransformFactory::search(QStringList keywords) | |
| 793 { | |
| 794 SearchResults results; | |
| 795 SearchResults partial; | |
| 796 for (int i = 0; i < keywords.size(); ++i) { | |
| 797 partial = search(keywords[i]); | |
| 798 for (SearchResults::const_iterator j = partial.begin(); | |
| 799 j != partial.end(); ++j) { | |
| 800 if (results.find(j->first) == results.end()) { | |
| 801 results[j->first] = j->second; | |
| 802 } else { | |
| 803 results[j->first].score += j->second.score; | |
| 804 results[j->first].fragments << j->second.fragments; | |
| 805 } | |
| 806 } | |
| 807 } | |
| 808 return results; | |
| 809 } | |
| 810 */ | |
| 811 | 918 |
| 812 TransformFactory::SearchResults | 919 TransformFactory::SearchResults |
| 813 TransformFactory::search(QString keyword) | 920 TransformFactory::search(QString keyword) |
| 814 { | 921 { |
| 815 QStringList keywords; | 922 QStringList keywords; |
| 826 // Additional score for all keywords in a row | 933 // Additional score for all keywords in a row |
| 827 keywords.push_back(keywords.join(" ")); | 934 keywords.push_back(keywords.join(" ")); |
| 828 } | 935 } |
| 829 | 936 |
| 830 SearchResults results; | 937 SearchResults results; |
| 938 TextMatcher matcher; | |
| 831 | 939 |
| 832 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); | 940 for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); |
| 833 i != m_transforms.end(); ++i) { | 941 i != m_transforms.end(); ++i) { |
| 834 | 942 |
| 835 Match match; | 943 TextMatcher::Match match; |
| 836 | 944 |
| 837 match.transform = i->first; | 945 match.key = i->first; |
| 838 | 946 |
| 839 searchTest(match, keywords, i->second.type, tr("Plugin type"), 10); | 947 matcher.test(match, keywords, i->second.type, tr("Plugin type"), 5); |
| 840 searchTest(match, keywords, i->second.category, tr("Category"), 20); | 948 matcher.test(match, keywords, i->second.category, tr("Category"), 20); |
| 841 searchTest(match, keywords, i->second.identifier, tr("System Identifier"), 5); | 949 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 6); |
| 842 searchTest(match, keywords, i->second.name, tr("Name"), 30); | 950 matcher.test(match, keywords, i->second.name, tr("Name"), 30); |
| 843 searchTest(match, keywords, i->second.description, tr("Description"), 20); | 951 matcher.test(match, keywords, i->second.description, tr("Description"), 20); |
| 844 searchTest(match, keywords, i->second.maker, tr("Maker"), 10); | 952 matcher.test(match, keywords, i->second.maker, tr("Maker"), 10); |
| 845 searchTest(match, keywords, i->second.units, tr("Units"), 10); | 953 matcher.test(match, keywords, i->second.units, tr("Units"), 10); |
| 846 | 954 |
| 847 if (match.score > 0) results[i->first] = match; | 955 if (match.score > 0) results[i->first] = match; |
| 848 } | 956 } |
| 849 | 957 |
| 958 if (m_uninstalledTransforms.empty()) populateUninstalledTransforms(); | |
| 959 | |
| 960 for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin(); | |
| 961 i != m_uninstalledTransforms.end(); ++i) { | |
| 962 | |
| 963 TextMatcher::Match match; | |
| 964 | |
| 965 match.key = i->first; | |
| 966 | |
| 967 matcher.test(match, keywords, i->second.type, tr("Plugin type"), 2); | |
| 968 matcher.test(match, keywords, i->second.category, tr("Category"), 10); | |
| 969 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 3); | |
| 970 matcher.test(match, keywords, i->second.name, tr("Name"), 15); | |
| 971 matcher.test(match, keywords, i->second.description, tr("Description"), 10); | |
| 972 matcher.test(match, keywords, i->second.maker, tr("Maker"), 5); | |
| 973 matcher.test(match, keywords, i->second.units, tr("Units"), 5); | |
| 974 | |
| 975 if (match.score > 0) results[i->first] = match; | |
| 976 } | |
| 977 | |
| 850 return results; | 978 return results; |
| 851 } | 979 } |
| 852 | 980 |
| 853 void | |
| 854 TransformFactory::searchTest(Match &match, QStringList keywords, QString text, | |
| 855 QString textType, int score) | |
| 856 { | |
| 857 /* | |
| 858 if (text.toLower() == keyword.toLower()) { | |
| 859 match.score += score * 1.5; | |
| 860 match.fragments << tr("%1: <b>%2</b>").arg(textType).arg(text); | |
| 861 return; | |
| 862 } | |
| 863 */ | |
| 864 int len = text.length(); | |
| 865 int prevEnd = 0; | |
| 866 QString fragment; | |
| 867 | |
| 868 while (1) { | |
| 869 | |
| 870 bool first = (prevEnd == 0); | |
| 871 | |
| 872 int idx = -1; | |
| 873 QString keyword; | |
| 874 | |
| 875 for (int ki = 0; ki < keywords.size(); ++ki) { | |
| 876 int midx = text.indexOf(keywords[ki], prevEnd, Qt::CaseInsensitive); | |
| 877 if (midx >= 0 && midx < len) { | |
| 878 if (midx < idx || idx == -1) { | |
| 879 idx = midx; | |
| 880 keyword = keywords[ki]; | |
| 881 } | |
| 882 } | |
| 883 } | |
| 884 | |
| 885 if (idx < 0 || idx >= len) break; | |
| 886 | |
| 887 int klen = keyword.length(); | |
| 888 | |
| 889 if (first) { | |
| 890 match.score += score; | |
| 891 } else { | |
| 892 match.score += score / 4; | |
| 893 } | |
| 894 | |
| 895 int start = idx; | |
| 896 int end = start + klen; | |
| 897 | |
| 898 if (start == 0) match.score += 1; | |
| 899 if (end == len) match.score += 1; | |
| 900 | |
| 901 if (start > prevEnd + 14) { | |
| 902 QString s = text.right((len - start) + 10); | |
| 903 s = XmlExportable::encodeEntities(s.left(10)) + "<b>" + | |
| 904 XmlExportable::encodeEntities(s.left(klen + 10).right(klen)) | |
| 905 + "</b>"; | |
| 906 fragment += tr("...%1").arg(s); | |
| 907 } else { | |
| 908 QString s = text.right(len - prevEnd); | |
| 909 s = XmlExportable::encodeEntities(s.left(start - prevEnd)) + "<b>" + | |
| 910 XmlExportable::encodeEntities(s.left(end - prevEnd).right(klen)) | |
| 911 + "</b>"; | |
| 912 fragment += s; | |
| 913 } | |
| 914 | |
| 915 prevEnd = end; | |
| 916 } | |
| 917 | |
| 918 if (prevEnd > 0 && prevEnd < len) { | |
| 919 int n = len - prevEnd; | |
| 920 fragment += | |
| 921 XmlExportable::encodeEntities(text.right(n).left(n < 8 ? n : 8)); | |
| 922 } | |
| 923 | |
| 924 if (fragment != "") { | |
| 925 match.fragments[textType] = fragment; | |
| 926 } | |
| 927 } | |
| 928 | |
| 929 bool | |
| 930 TransformFactory::Match::operator<(const Match &m) const | |
| 931 { | |
| 932 if (score != m.score) { | |
| 933 return score < m.score; | |
| 934 } | |
| 935 if (transform != m.transform) { | |
| 936 return transform < m.transform; | |
| 937 } | |
| 938 if (fragments.size() != m.fragments.size()) { | |
| 939 return fragments.size() < m.fragments.size(); | |
| 940 } | |
| 941 | |
| 942 for (FragmentMap::const_iterator | |
| 943 i = fragments.begin(), | |
| 944 j = m.fragments.begin(); | |
| 945 i != fragments.end(); ++i, ++j) { | |
| 946 if (i->first != j->first) return i->first < j->first; | |
| 947 if (i->second != j->second) return i->second < j->second; | |
| 948 } | |
| 949 | |
| 950 return false; | |
| 951 } | |
| 952 |
