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