Chris@33: Chris@33: #include Chris@33: #include Chris@33: #include Chris@33: #include Chris@33: Chris@42: #include Chris@42: #include Chris@42: #include Chris@42: #include Chris@42: #include Chris@42: Chris@41: #include Chris@41: Chris@43: #include Chris@43: #include Chris@43: Chris@33: #include Chris@43: #include Chris@43: Chris@33: using namespace std; Chris@43: using namespace Dataquay; Chris@32: Chris@42: QString Chris@42: getDefaultInstallDirectory() Chris@32: { Chris@41: auto pathList = Vamp::PluginHostAdapter::getPluginPath(); Chris@41: if (pathList.empty()) { Chris@41: cerr << "Failed to look up Vamp plugin path" << endl; Chris@42: return QString(); Chris@41: } Chris@41: Chris@42: auto firstPath = *pathList.begin(); Chris@42: QString target = QString::fromUtf8(firstPath.c_str(), firstPath.size()); Chris@42: return target; Chris@42: } Chris@42: Chris@42: QStringList Chris@42: getPluginLibraryList() Chris@42: { Chris@33: QDir dir(":out/"); Chris@33: auto entries = dir.entryList({ "*.so", "*.dll", "*.dylib" }); Chris@33: Chris@33: for (auto e: entries) { Chris@33: cerr << e.toStdString() << endl; Chris@33: } Chris@33: Chris@42: return entries; Chris@42: } Chris@33: Chris@43: unique_ptr Chris@43: loadLibrariesRdf() Chris@43: { Chris@43: QDir dir(":out/"); Chris@43: auto entries = dir.entryList({ "*.ttl", "*.n3" }); Chris@43: Chris@43: unique_ptr store(new BasicStore); Chris@43: Chris@43: for (auto e: entries) { Chris@43: Chris@43: QFile f(":out/" + e); Chris@43: if (!f.open(QFile::ReadOnly | QFile::Text)) { Chris@43: cerr << "Failed to open RDF resource file " Chris@43: << e.toStdString() << endl; Chris@43: continue; Chris@43: } Chris@43: Chris@43: QByteArray content = f.readAll(); Chris@43: f.close(); Chris@43: Chris@43: try { Chris@43: store->importString(QString::fromUtf8(content), Chris@43: Uri("file:" + e), Chris@43: BasicStore::ImportIgnoreDuplicates); Chris@43: } catch (const RDFException &ex) { Chris@43: cerr << "Failed to import RDF resource file " Chris@43: << e.toStdString() << ": " << ex.what() << endl; Chris@43: } Chris@43: } Chris@43: Chris@43: return store; Chris@43: } Chris@43: Chris@43: struct LibraryInfo { Chris@43: QString id; Chris@43: QString fileName; Chris@43: QString title; Chris@43: QString maker; Chris@43: QString description; Chris@43: }; Chris@43: Chris@43: vector Chris@43: getLibraryInfo(const Store &store, QStringList libraries) Chris@43: { Chris@43: /* e.g. Chris@43: Chris@43: plugbase:library a vamp:PluginLibrary ; Chris@43: vamp:identifier "qm-vamp-plugins" ; Chris@43: dc:title "Queen Mary plugin set" Chris@43: */ Chris@43: Chris@43: Triples tt = store.match(Triple(Node(), Chris@43: Uri("a"), Chris@43: store.expand("vamp:PluginLibrary"))); Chris@43: Chris@43: std::map wanted; // basename -> full lib name Chris@43: for (auto lib: libraries) { Chris@43: wanted[QFileInfo(lib).baseName()] = lib; Chris@43: } Chris@43: Chris@43: vector results; Chris@43: Chris@43: for (auto t: tt) { Chris@43: Chris@43: Node libId = store.complete(Triple(t.subject(), Chris@43: store.expand("vamp:identifier"), Chris@43: Node())); Chris@43: if (libId.type != Node::Literal) { Chris@43: continue; Chris@43: } Chris@43: auto wi = wanted.find(libId.value); Chris@43: if (wi == wanted.end()) { Chris@43: continue; Chris@43: } Chris@43: Chris@43: LibraryInfo info; Chris@43: info.id = wi->first; Chris@43: info.fileName = wi->second; Chris@43: Chris@43: Node title = store.complete(Triple(t.subject(), Chris@43: store.expand("dc:title"), Chris@43: Node())); Chris@43: if (title.type == Node::Literal) { Chris@43: info.title = title.value; Chris@43: } else { Chris@43: info.title = info.id; Chris@43: } Chris@43: Chris@43: Node maker = store.complete(Triple(t.subject(), Chris@43: store.expand("foaf:maker"), Chris@43: Node())); Chris@43: if (maker.type == Node::Literal) { Chris@43: info.maker = maker.value; Chris@43: } Chris@43: Chris@43: Node desc = store.complete(Triple(t.subject(), Chris@43: store.expand("dc:description"), Chris@43: Node())); Chris@43: if (desc.type == Node::Literal) { Chris@43: info.description = desc.value; Chris@43: } Chris@43: Chris@43: results.push_back(info); Chris@43: } Chris@43: Chris@43: return results; Chris@43: } Chris@43: Chris@42: void Chris@42: installLibrary(QString library, QString target) Chris@42: { Chris@42: QFile f(":out/" + library); Chris@42: QString destination = target + "/" + library; Chris@42: cerr << "Copying " << library.toStdString() << " to " Chris@42: << destination.toStdString() << "..." << endl; Chris@42: if (!f.copy(destination)) { Chris@42: cerr << "Failed to copy " << library.toStdString() Chris@42: << " to target " << destination.toStdString() << endl; Chris@42: return; Chris@42: } Chris@42: if (!QFile::setPermissions Chris@42: (destination, Chris@42: QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | Chris@42: QFile::ReadGroup | QFile::ExeGroup | Chris@42: QFile::ReadOther | QFile::ExeOther)) { Chris@42: cerr << "Failed to set permissions on " Chris@42: << library.toStdString() << endl; Chris@42: return; Chris@42: } Chris@42: } Chris@42: Chris@42: QStringList Chris@43: getUserApprovedPluginLibraries(vector libraries) Chris@42: { Chris@42: QDialog dialog; Chris@42: auto layout = new QVBoxLayout; Chris@42: Chris@43: map checkBoxMap; Chris@43: Chris@43: map orderedInfo; Chris@43: for (auto info: libraries) { Chris@43: orderedInfo[info.title] = info; Chris@43: } Chris@42: Chris@43: for (auto ip: orderedInfo) { Chris@43: LibraryInfo info = ip.second; Chris@43: auto cb = new QCheckBox(info.title); Chris@42: layout->addWidget(cb); Chris@43: checkBoxMap[info.fileName] = cb; Chris@42: } Chris@42: Chris@42: auto bb = new QDialogButtonBox(QDialogButtonBox::Ok | Chris@42: QDialogButtonBox::Cancel); Chris@42: layout->addWidget(bb); Chris@42: QObject::connect(bb, SIGNAL(accepted()), &dialog, SLOT(accept())); Chris@42: QObject::connect(bb, SIGNAL(rejected()), &dialog, SLOT(reject())); Chris@42: Chris@42: dialog.setLayout(layout); Chris@42: Chris@42: if (dialog.exec() == QDialog::Accepted) { Chris@42: cerr << "accepted" << endl; Chris@42: } else { Chris@42: cerr << "rejected" << endl; Chris@42: } Chris@42: Chris@42: QStringList approved; Chris@42: for (const auto &p: checkBoxMap) { Chris@42: if (p.second->isChecked()) { Chris@42: approved.push_back(p.first); Chris@33: } Chris@42: } Chris@42: Chris@42: return approved; Chris@42: } Chris@42: Chris@42: int main(int argc, char **argv) Chris@42: { Chris@42: QApplication app(argc, argv); Chris@42: Chris@42: QString target = getDefaultInstallDirectory(); Chris@42: if (target == "") { Chris@42: return 1; Chris@42: } Chris@42: Chris@42: QStringList libraries = getPluginLibraryList(); Chris@42: Chris@43: auto rdfStore = loadLibrariesRdf(); Chris@43: Chris@43: auto info = getLibraryInfo(*rdfStore, libraries); Chris@43: Chris@43: QStringList toInstall = getUserApprovedPluginLibraries(info); Chris@42: Chris@42: for (auto lib: toInstall) { Chris@42: installLibrary(lib, target); Chris@33: } Chris@33: Chris@32: return 0; Chris@32: }