annotate installer.cpp @ 43:4aea515b404f

Query plugin info from RDF
author Chris Cannam
date Tue, 21 Jan 2020 14:26:13 +0000
parents 37d79024d966
children 6dc29a50b89a
rev   line source
Chris@33 1
Chris@33 2 #include <QApplication>
Chris@33 3 #include <QString>
Chris@33 4 #include <QFile>
Chris@33 5 #include <QDir>
Chris@33 6
Chris@42 7 #include <QDialog>
Chris@42 8 #include <QFrame>
Chris@42 9 #include <QVBoxLayout>
Chris@42 10 #include <QCheckBox>
Chris@42 11 #include <QDialogButtonBox>
Chris@42 12
Chris@41 13 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@41 14
Chris@43 15 #include <dataquay/BasicStore.h>
Chris@43 16 #include <dataquay/RDFException.h>
Chris@43 17
Chris@33 18 #include <iostream>
Chris@43 19 #include <set>
Chris@43 20
Chris@33 21 using namespace std;
Chris@43 22 using namespace Dataquay;
Chris@32 23
Chris@42 24 QString
Chris@42 25 getDefaultInstallDirectory()
Chris@32 26 {
Chris@41 27 auto pathList = Vamp::PluginHostAdapter::getPluginPath();
Chris@41 28 if (pathList.empty()) {
Chris@41 29 cerr << "Failed to look up Vamp plugin path" << endl;
Chris@42 30 return QString();
Chris@41 31 }
Chris@41 32
Chris@42 33 auto firstPath = *pathList.begin();
Chris@42 34 QString target = QString::fromUtf8(firstPath.c_str(), firstPath.size());
Chris@42 35 return target;
Chris@42 36 }
Chris@42 37
Chris@42 38 QStringList
Chris@42 39 getPluginLibraryList()
Chris@42 40 {
Chris@33 41 QDir dir(":out/");
Chris@33 42 auto entries = dir.entryList({ "*.so", "*.dll", "*.dylib" });
Chris@33 43
Chris@33 44 for (auto e: entries) {
Chris@33 45 cerr << e.toStdString() << endl;
Chris@33 46 }
Chris@33 47
Chris@42 48 return entries;
Chris@42 49 }
Chris@33 50
Chris@43 51 unique_ptr<BasicStore>
Chris@43 52 loadLibrariesRdf()
Chris@43 53 {
Chris@43 54 QDir dir(":out/");
Chris@43 55 auto entries = dir.entryList({ "*.ttl", "*.n3" });
Chris@43 56
Chris@43 57 unique_ptr<BasicStore> store(new BasicStore);
Chris@43 58
Chris@43 59 for (auto e: entries) {
Chris@43 60
Chris@43 61 QFile f(":out/" + e);
Chris@43 62 if (!f.open(QFile::ReadOnly | QFile::Text)) {
Chris@43 63 cerr << "Failed to open RDF resource file "
Chris@43 64 << e.toStdString() << endl;
Chris@43 65 continue;
Chris@43 66 }
Chris@43 67
Chris@43 68 QByteArray content = f.readAll();
Chris@43 69 f.close();
Chris@43 70
Chris@43 71 try {
Chris@43 72 store->importString(QString::fromUtf8(content),
Chris@43 73 Uri("file:" + e),
Chris@43 74 BasicStore::ImportIgnoreDuplicates);
Chris@43 75 } catch (const RDFException &ex) {
Chris@43 76 cerr << "Failed to import RDF resource file "
Chris@43 77 << e.toStdString() << ": " << ex.what() << endl;
Chris@43 78 }
Chris@43 79 }
Chris@43 80
Chris@43 81 return store;
Chris@43 82 }
Chris@43 83
Chris@43 84 struct LibraryInfo {
Chris@43 85 QString id;
Chris@43 86 QString fileName;
Chris@43 87 QString title;
Chris@43 88 QString maker;
Chris@43 89 QString description;
Chris@43 90 };
Chris@43 91
Chris@43 92 vector<LibraryInfo>
Chris@43 93 getLibraryInfo(const Store &store, QStringList libraries)
Chris@43 94 {
Chris@43 95 /* e.g.
Chris@43 96
Chris@43 97 plugbase:library a vamp:PluginLibrary ;
Chris@43 98 vamp:identifier "qm-vamp-plugins" ;
Chris@43 99 dc:title "Queen Mary plugin set"
Chris@43 100 */
Chris@43 101
Chris@43 102 Triples tt = store.match(Triple(Node(),
Chris@43 103 Uri("a"),
Chris@43 104 store.expand("vamp:PluginLibrary")));
Chris@43 105
Chris@43 106 std::map<QString, QString> wanted; // basename -> full lib name
Chris@43 107 for (auto lib: libraries) {
Chris@43 108 wanted[QFileInfo(lib).baseName()] = lib;
Chris@43 109 }
Chris@43 110
Chris@43 111 vector<LibraryInfo> results;
Chris@43 112
Chris@43 113 for (auto t: tt) {
Chris@43 114
Chris@43 115 Node libId = store.complete(Triple(t.subject(),
Chris@43 116 store.expand("vamp:identifier"),
Chris@43 117 Node()));
Chris@43 118 if (libId.type != Node::Literal) {
Chris@43 119 continue;
Chris@43 120 }
Chris@43 121 auto wi = wanted.find(libId.value);
Chris@43 122 if (wi == wanted.end()) {
Chris@43 123 continue;
Chris@43 124 }
Chris@43 125
Chris@43 126 LibraryInfo info;
Chris@43 127 info.id = wi->first;
Chris@43 128 info.fileName = wi->second;
Chris@43 129
Chris@43 130 Node title = store.complete(Triple(t.subject(),
Chris@43 131 store.expand("dc:title"),
Chris@43 132 Node()));
Chris@43 133 if (title.type == Node::Literal) {
Chris@43 134 info.title = title.value;
Chris@43 135 } else {
Chris@43 136 info.title = info.id;
Chris@43 137 }
Chris@43 138
Chris@43 139 Node maker = store.complete(Triple(t.subject(),
Chris@43 140 store.expand("foaf:maker"),
Chris@43 141 Node()));
Chris@43 142 if (maker.type == Node::Literal) {
Chris@43 143 info.maker = maker.value;
Chris@43 144 }
Chris@43 145
Chris@43 146 Node desc = store.complete(Triple(t.subject(),
Chris@43 147 store.expand("dc:description"),
Chris@43 148 Node()));
Chris@43 149 if (desc.type == Node::Literal) {
Chris@43 150 info.description = desc.value;
Chris@43 151 }
Chris@43 152
Chris@43 153 results.push_back(info);
Chris@43 154 }
Chris@43 155
Chris@43 156 return results;
Chris@43 157 }
Chris@43 158
Chris@42 159 void
Chris@42 160 installLibrary(QString library, QString target)
Chris@42 161 {
Chris@42 162 QFile f(":out/" + library);
Chris@42 163 QString destination = target + "/" + library;
Chris@42 164 cerr << "Copying " << library.toStdString() << " to "
Chris@42 165 << destination.toStdString() << "..." << endl;
Chris@42 166 if (!f.copy(destination)) {
Chris@42 167 cerr << "Failed to copy " << library.toStdString()
Chris@42 168 << " to target " << destination.toStdString() << endl;
Chris@42 169 return;
Chris@42 170 }
Chris@42 171 if (!QFile::setPermissions
Chris@42 172 (destination,
Chris@42 173 QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner |
Chris@42 174 QFile::ReadGroup | QFile::ExeGroup |
Chris@42 175 QFile::ReadOther | QFile::ExeOther)) {
Chris@42 176 cerr << "Failed to set permissions on "
Chris@42 177 << library.toStdString() << endl;
Chris@42 178 return;
Chris@42 179 }
Chris@42 180 }
Chris@42 181
Chris@42 182 QStringList
Chris@43 183 getUserApprovedPluginLibraries(vector<LibraryInfo> libraries)
Chris@42 184 {
Chris@42 185 QDialog dialog;
Chris@42 186 auto layout = new QVBoxLayout;
Chris@42 187
Chris@43 188 map<QString, QCheckBox *> checkBoxMap;
Chris@43 189
Chris@43 190 map<QString, LibraryInfo> orderedInfo;
Chris@43 191 for (auto info: libraries) {
Chris@43 192 orderedInfo[info.title] = info;
Chris@43 193 }
Chris@42 194
Chris@43 195 for (auto ip: orderedInfo) {
Chris@43 196 LibraryInfo info = ip.second;
Chris@43 197 auto cb = new QCheckBox(info.title);
Chris@42 198 layout->addWidget(cb);
Chris@43 199 checkBoxMap[info.fileName] = cb;
Chris@42 200 }
Chris@42 201
Chris@42 202 auto bb = new QDialogButtonBox(QDialogButtonBox::Ok |
Chris@42 203 QDialogButtonBox::Cancel);
Chris@42 204 layout->addWidget(bb);
Chris@42 205 QObject::connect(bb, SIGNAL(accepted()), &dialog, SLOT(accept()));
Chris@42 206 QObject::connect(bb, SIGNAL(rejected()), &dialog, SLOT(reject()));
Chris@42 207
Chris@42 208 dialog.setLayout(layout);
Chris@42 209
Chris@42 210 if (dialog.exec() == QDialog::Accepted) {
Chris@42 211 cerr << "accepted" << endl;
Chris@42 212 } else {
Chris@42 213 cerr << "rejected" << endl;
Chris@42 214 }
Chris@42 215
Chris@42 216 QStringList approved;
Chris@42 217 for (const auto &p: checkBoxMap) {
Chris@42 218 if (p.second->isChecked()) {
Chris@42 219 approved.push_back(p.first);
Chris@33 220 }
Chris@42 221 }
Chris@42 222
Chris@42 223 return approved;
Chris@42 224 }
Chris@42 225
Chris@42 226 int main(int argc, char **argv)
Chris@42 227 {
Chris@42 228 QApplication app(argc, argv);
Chris@42 229
Chris@42 230 QString target = getDefaultInstallDirectory();
Chris@42 231 if (target == "") {
Chris@42 232 return 1;
Chris@42 233 }
Chris@42 234
Chris@42 235 QStringList libraries = getPluginLibraryList();
Chris@42 236
Chris@43 237 auto rdfStore = loadLibrariesRdf();
Chris@43 238
Chris@43 239 auto info = getLibraryInfo(*rdfStore, libraries);
Chris@43 240
Chris@43 241 QStringList toInstall = getUserApprovedPluginLibraries(info);
Chris@42 242
Chris@42 243 for (auto lib: toInstall) {
Chris@42 244 installLibrary(lib, target);
Chris@33 245 }
Chris@33 246
Chris@32 247 return 0;
Chris@32 248 }