annotate rdf/PluginRDFDescription.cpp @ 458:f60360209e5c

* Fix race condition in FFTFileCache when reading from the same FFT model from multiple threads (e.g. when applying more than one plugin at once)
author Chris Cannam
date Wed, 15 Oct 2008 12:08:02 +0000
parents ef14acd6d102
children 2019d89ebcf9
rev   line source
Chris@439 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@439 2
Chris@439 3 /*
Chris@439 4 Sonic Visualiser
Chris@439 5 An audio file viewer and annotation editor.
Chris@439 6 Centre for Digital Music, Queen Mary, University of London.
Chris@439 7 This file copyright 2008 QMUL.
Chris@439 8
Chris@439 9 This program is free software; you can redistribute it and/or
Chris@439 10 modify it under the terms of the GNU General Public License as
Chris@439 11 published by the Free Software Foundation; either version 2 of the
Chris@439 12 License, or (at your option) any later version. See the file
Chris@439 13 COPYING included with this distribution for more information.
Chris@439 14 */
Chris@439 15
Chris@439 16 #include "PluginRDFDescription.h"
Chris@439 17
Chris@439 18 #include "PluginRDFIndexer.h"
Chris@439 19 #include "SimpleSPARQLQuery.h"
Chris@439 20
Chris@457 21 #include "data/fileio/FileSource.h"
Chris@457 22
Chris@457 23 #include "base/Profiler.h"
Chris@457 24
Chris@439 25 #include "plugin/PluginIdentifier.h"
Chris@439 26
Chris@439 27 #include <iostream>
Chris@439 28 using std::cerr;
Chris@439 29 using std::endl;
Chris@439 30
Chris@439 31 PluginRDFDescription::PluginRDFDescription(QString pluginId) :
Chris@457 32 m_source(0),
Chris@439 33 m_pluginId(pluginId),
Chris@439 34 m_haveDescription(false)
Chris@439 35 {
Chris@439 36 PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
Chris@439 37 QString url = indexer->getDescriptionURLForPluginId(pluginId);
Chris@439 38 if (url == "") {
Chris@439 39 cerr << "PluginRDFDescription: WARNING: No RDF description available for plugin ID \""
Chris@439 40 << pluginId.toStdString() << "\"" << endl;
Chris@439 41 } else {
Chris@439 42 if (!indexURL(url)) {
Chris@439 43 cerr << "PluginRDFDescription: ERROR: Failed to query RDF description for plugin ID \""
Chris@439 44 << pluginId.toStdString() << "\"" << endl;
Chris@439 45 } else {
Chris@439 46 m_haveDescription = true;
Chris@439 47 }
Chris@439 48 }
Chris@439 49 }
Chris@439 50
Chris@439 51 PluginRDFDescription::~PluginRDFDescription()
Chris@439 52 {
Chris@457 53 delete m_source;
Chris@439 54 }
Chris@439 55
Chris@439 56 bool
Chris@439 57 PluginRDFDescription::haveDescription() const
Chris@439 58 {
Chris@439 59 return m_haveDescription;
Chris@439 60 }
Chris@439 61
Chris@457 62 QString
Chris@457 63 PluginRDFDescription::getPluginName() const
Chris@457 64 {
Chris@457 65 return m_pluginName;
Chris@457 66 }
Chris@457 67
Chris@457 68 QString
Chris@457 69 PluginRDFDescription::getPluginDescription() const
Chris@457 70 {
Chris@457 71 return m_pluginDescription;
Chris@457 72 }
Chris@457 73
Chris@457 74 QString
Chris@457 75 PluginRDFDescription::getPluginMaker() const
Chris@457 76 {
Chris@457 77 return m_pluginMaker;
Chris@457 78 }
Chris@457 79
Chris@457 80 QStringList
Chris@457 81 PluginRDFDescription::getOutputIds() const
Chris@457 82 {
Chris@457 83 QStringList ids;
Chris@457 84 for (OutputDispositionMap::const_iterator i = m_outputDispositions.begin();
Chris@457 85 i != m_outputDispositions.end(); ++i) {
Chris@457 86 ids.push_back(i->first);
Chris@457 87 }
Chris@457 88 return ids;
Chris@457 89 }
Chris@457 90
Chris@457 91 QString
Chris@457 92 PluginRDFDescription::getOutputName(QString outputId) const
Chris@457 93 {
Chris@457 94 if (m_outputNames.find(outputId) == m_outputNames.end()) {
Chris@457 95 return "";
Chris@457 96 }
Chris@457 97 return m_outputNames.find(outputId)->second;
Chris@457 98 }
Chris@457 99
Chris@439 100 PluginRDFDescription::OutputDisposition
Chris@439 101 PluginRDFDescription::getOutputDisposition(QString outputId) const
Chris@439 102 {
Chris@439 103 if (m_outputDispositions.find(outputId) == m_outputDispositions.end()) {
Chris@439 104 return OutputDispositionUnknown;
Chris@439 105 }
Chris@439 106 return m_outputDispositions.find(outputId)->second;
Chris@439 107 }
Chris@439 108
Chris@439 109 QString
Chris@439 110 PluginRDFDescription::getOutputEventTypeURI(QString outputId) const
Chris@439 111 {
Chris@439 112 if (m_outputEventTypeURIMap.find(outputId) ==
Chris@439 113 m_outputEventTypeURIMap.end()) {
Chris@439 114 return "";
Chris@439 115 }
Chris@439 116 return m_outputEventTypeURIMap.find(outputId)->second;
Chris@439 117 }
Chris@439 118
Chris@439 119 QString
Chris@440 120 PluginRDFDescription::getOutputFeatureAttributeURI(QString outputId) const
Chris@440 121 {
Chris@440 122 if (m_outputFeatureAttributeURIMap.find(outputId) ==
Chris@440 123 m_outputFeatureAttributeURIMap.end()) {
Chris@440 124 return "";
Chris@440 125 }
Chris@440 126 return m_outputFeatureAttributeURIMap.find(outputId)->second;
Chris@440 127 }
Chris@440 128
Chris@440 129 QString
Chris@440 130 PluginRDFDescription::getOutputSignalTypeURI(QString outputId) const
Chris@440 131 {
Chris@440 132 if (m_outputSignalTypeURIMap.find(outputId) ==
Chris@440 133 m_outputSignalTypeURIMap.end()) {
Chris@440 134 return "";
Chris@440 135 }
Chris@440 136 return m_outputSignalTypeURIMap.find(outputId)->second;
Chris@440 137 }
Chris@440 138
Chris@440 139 QString
Chris@439 140 PluginRDFDescription::getOutputUnit(QString outputId) const
Chris@439 141 {
Chris@439 142 if (m_outputUnitMap.find(outputId) == m_outputUnitMap.end()) {
Chris@439 143 return "";
Chris@439 144 }
Chris@439 145 return m_outputUnitMap.find(outputId)->second;
Chris@439 146 }
Chris@439 147
Chris@439 148 bool
Chris@439 149 PluginRDFDescription::indexURL(QString url)
Chris@439 150 {
Chris@457 151 Profiler profiler("PluginRDFDescription::indexURL");
Chris@457 152
Chris@439 153 QString type, soname, label;
Chris@439 154 PluginIdentifier::parseIdentifier(m_pluginId, type, soname, label);
Chris@439 155
Chris@457 156 bool success = true;
Chris@457 157
Chris@457 158 QString local = url;
Chris@457 159
Chris@457 160 if (FileSource::isRemote(url) &&
Chris@457 161 FileSource::canHandleScheme(url)) {
Chris@457 162
Chris@457 163 m_source = new FileSource(url);
Chris@457 164 if (!m_source->isAvailable()) {
Chris@457 165 delete m_source;
Chris@457 166 m_source = 0;
Chris@457 167 return false;
Chris@457 168 }
Chris@457 169 m_source->waitForData();
Chris@457 170 local = QUrl::fromLocalFile(m_source->getLocalFilename()).toString();
Chris@457 171 }
Chris@457 172
Chris@457 173 if (!indexMetadata(local, label)) success = false;
Chris@457 174 if (!indexOutputs(local, label)) success = false;
Chris@457 175
Chris@457 176 return success;
Chris@457 177 }
Chris@457 178
Chris@457 179 bool
Chris@457 180 PluginRDFDescription::indexMetadata(QString url, QString label)
Chris@457 181 {
Chris@457 182 Profiler profiler("PluginRDFDescription::indexMetadata");
Chris@457 183
Chris@457 184 QString queryTemplate =
Chris@457 185 QString(
Chris@457 186 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 187 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 188 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 189 " SELECT ?%4 FROM <%1> "
Chris@457 190 " WHERE { "
Chris@457 191 " ?plugin a vamp:Plugin ; "
Chris@457 192 " vamp:identifier \"%2\" ; "
Chris@457 193 " %3 ?%4 . "
Chris@457 194 " }")
Chris@457 195 .arg(url)
Chris@457 196 .arg(label);
Chris@457 197
Chris@457 198 SimpleSPARQLQuery::Value v;
Chris@457 199
Chris@457 200 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 201 (queryTemplate.arg("vamp:name").arg("name"), "name");
Chris@457 202
Chris@457 203 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 204 m_pluginName = v.value;
Chris@457 205 }
Chris@457 206
Chris@457 207 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 208 (queryTemplate.arg("dc:description").arg("description"), "description");
Chris@457 209
Chris@457 210 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 211 m_pluginDescription = v.value;
Chris@457 212 }
Chris@457 213
Chris@457 214 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 215 (QString(
Chris@457 216 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 217 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 218 " SELECT ?name FROM <%1> "
Chris@457 219 " WHERE { "
Chris@457 220 " ?plugin a vamp:Plugin ; "
Chris@457 221 " vamp:identifier \"%2\" ; "
Chris@457 222 " foaf:maker ?maker . "
Chris@457 223 " ?maker foaf:name ?name . "
Chris@457 224 " }")
Chris@457 225 .arg(url)
Chris@457 226 .arg(label), "name");
Chris@457 227
Chris@457 228 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 229 m_pluginMaker = v.value;
Chris@457 230 }
Chris@457 231
Chris@457 232 return true;
Chris@457 233 }
Chris@457 234
Chris@457 235 bool
Chris@457 236 PluginRDFDescription::indexOutputs(QString url, QString label)
Chris@457 237 {
Chris@457 238 Profiler profiler("PluginRDFDescription::indexOutputs");
Chris@457 239
Chris@439 240 SimpleSPARQLQuery query
Chris@439 241 (QString
Chris@439 242 (
Chris@439 243 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@439 244
Chris@440 245 " SELECT ?output ?output_id ?output_type ?unit "
Chris@439 246 " FROM <%1> "
Chris@439 247
Chris@439 248 " WHERE { "
Chris@439 249
Chris@439 250 " ?plugin a vamp:Plugin ; "
Chris@439 251 " vamp:identifier \"%2\" ; "
Chris@440 252 " vamp:output ?output . "
Chris@439 253
Chris@439 254 " ?output vamp:identifier ?output_id ; "
Chris@439 255 " a ?output_type . "
Chris@439 256
Chris@439 257 " OPTIONAL { "
Chris@439 258 " ?output vamp:unit ?unit "
Chris@439 259 " } . "
Chris@439 260
Chris@439 261 " } "
Chris@439 262 )
Chris@439 263 .arg(url)
Chris@439 264 .arg(label));
Chris@439 265
Chris@439 266 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@439 267
Chris@439 268 if (!query.isOK()) {
Chris@439 269 cerr << "ERROR: PluginRDFDescription::indexURL: ERROR: Failed to query document at <"
Chris@439 270 << url.toStdString() << ">: "
Chris@439 271 << query.getErrorString().toStdString() << endl;
Chris@439 272 return false;
Chris@439 273 }
Chris@439 274
Chris@439 275 if (results.empty()) {
Chris@439 276 cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: Document at <"
Chris@439 277 << url.toStdString()
Chris@440 278 << "> does not appear to describe any outputs for plugin with id \""
Chris@440 279 << label.toStdString() << "\"" << endl;
Chris@439 280 return false;
Chris@439 281 }
Chris@439 282
Chris@439 283 // Note that an output may appear more than once, if it inherits
Chris@439 284 // more than one type (e.g. DenseOutput and QuantizedOutput). So
Chris@439 285 // these results must accumulate
Chris@439 286
Chris@439 287 for (int i = 0; i < results.size(); ++i) {
Chris@439 288
Chris@440 289 QString outputUri = results[i]["output"].value;
Chris@439 290 QString outputId = results[i]["output_id"].value;
Chris@439 291 QString outputType = results[i]["output_type"].value;
Chris@439 292
Chris@439 293 if (outputType.contains("DenseOutput")) {
Chris@439 294 m_outputDispositions[outputId] = OutputDense;
Chris@439 295 } else if (outputType.contains("SparseOutput")) {
Chris@439 296 m_outputDispositions[outputId] = OutputSparse;
Chris@439 297 } else if (outputType.contains("TrackLevelOutput")) {
Chris@439 298 m_outputDispositions[outputId] = OutputTrackLevel;
Chris@457 299 } else {
Chris@457 300 m_outputDispositions[outputId] = OutputDispositionUnknown;
Chris@439 301 }
Chris@439 302
Chris@439 303 if (results[i]["unit"].type == SimpleSPARQLQuery::LiteralValue) {
Chris@439 304
Chris@439 305 QString unit = results[i]["unit"].value;
Chris@439 306
Chris@439 307 if (unit != "") {
Chris@439 308 m_outputUnitMap[outputId] = unit;
Chris@439 309 }
Chris@439 310 }
Chris@440 311
Chris@457 312 SimpleSPARQLQuery::Value v;
Chris@457 313
Chris@457 314 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 315 (QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 316 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 317 " SELECT ?title FROM <%1> "
Chris@457 318 " WHERE { <%2> dc:title ?title } ")
Chris@457 319 .arg(url).arg(outputUri), "title");
Chris@457 320
Chris@457 321 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 322 m_outputNames[outputId] = v.value;
Chris@457 323 }
Chris@457 324
Chris@440 325 QString queryTemplate =
Chris@440 326 QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@440 327 " SELECT ?%3 FROM <%1> "
Chris@440 328 " WHERE { <%2> vamp:computes_%3 ?%3 } ")
Chris@440 329 .arg(url).arg(outputUri);
Chris@440 330
Chris@440 331 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 332 (queryTemplate.arg("event_type"), "event_type");
Chris@440 333
Chris@440 334 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 335 m_outputEventTypeURIMap[outputId] = v.value;
Chris@440 336 }
Chris@440 337
Chris@440 338 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 339 (queryTemplate.arg("feature_attribute"), "feature_attribute");
Chris@440 340
Chris@440 341 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 342 m_outputFeatureAttributeURIMap[outputId] = v.value;
Chris@440 343 }
Chris@440 344
Chris@440 345 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 346 (queryTemplate.arg("signal_type"), "signal_type");
Chris@440 347
Chris@440 348 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 349 m_outputSignalTypeURIMap[outputId] = v.value;
Chris@440 350 }
Chris@439 351 }
Chris@439 352
Chris@439 353 return true;
Chris@439 354 }
Chris@439 355