annotate rdf/PluginRDFDescription.cpp @ 1879:652c5360e682

Ensure transforms are populated before instantiateDefaultPluginFor runs - otherwise if we have prior knowledge of a transform id, we can find ourselves trying to instantiate it before the plugin factory has heard of it and e.g. knows which server to use
author Chris Cannam
date Thu, 25 Jun 2020 12:20:06 +0100
parents 9762a7f084a0
children 1adbeb52d761
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@727 7 This file copyright 2008-2012 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
Chris@457 20 #include "base/Profiler.h"
Chris@457 21
Chris@439 22 #include "plugin/PluginIdentifier.h"
Chris@439 23
Chris@725 24 #include <dataquay/BasicStore.h>
Chris@725 25
Chris@439 26 #include <iostream>
Chris@439 27
Chris@725 28 using Dataquay::Uri;
Chris@725 29 using Dataquay::Node;
Chris@725 30 using Dataquay::Nodes;
Chris@725 31 using Dataquay::Triple;
Chris@725 32 using Dataquay::Triples;
Chris@725 33 using Dataquay::BasicStore;
Chris@725 34
Chris@1847 35 //#define DEBUG_PLUGIN_RDF_DESCRIPTION 1
Chris@1844 36
Chris@439 37 PluginRDFDescription::PluginRDFDescription(QString pluginId) :
Chris@439 38 m_pluginId(pluginId),
Chris@439 39 m_haveDescription(false)
Chris@439 40 {
Chris@439 41 PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
Chris@489 42 m_pluginUri = indexer->getURIForPluginId(pluginId);
Chris@489 43 if (m_pluginUri == "") {
Chris@439 44 cerr << "PluginRDFDescription: WARNING: No RDF description available for plugin ID \""
Chris@686 45 << pluginId << "\"" << endl;
Chris@439 46 } else {
Chris@489 47 // All the data we need should be in our RDF model already:
Chris@489 48 // if it's not there, we don't know where to find it anyway
Chris@489 49 if (index()) {
Chris@439 50 m_haveDescription = true;
Chris@439 51 }
Chris@439 52 }
Chris@439 53 }
Chris@439 54
Chris@439 55 PluginRDFDescription::~PluginRDFDescription()
Chris@439 56 {
Chris@439 57 }
Chris@439 58
Chris@439 59 bool
Chris@439 60 PluginRDFDescription::haveDescription() const
Chris@439 61 {
Chris@439 62 return m_haveDescription;
Chris@439 63 }
Chris@439 64
Chris@457 65 QString
Chris@457 66 PluginRDFDescription::getPluginName() const
Chris@457 67 {
Chris@457 68 return m_pluginName;
Chris@457 69 }
Chris@457 70
Chris@457 71 QString
Chris@457 72 PluginRDFDescription::getPluginDescription() const
Chris@457 73 {
Chris@457 74 return m_pluginDescription;
Chris@457 75 }
Chris@457 76
Chris@457 77 QString
Chris@457 78 PluginRDFDescription::getPluginMaker() const
Chris@457 79 {
Chris@457 80 return m_pluginMaker;
Chris@457 81 }
Chris@457 82
Chris@1845 83 Provider
Chris@1845 84 PluginRDFDescription::getPluginProvider() const
Chris@462 85 {
Chris@1845 86 return m_provider;
Chris@1843 87 }
Chris@1843 88
Chris@457 89 QStringList
Chris@457 90 PluginRDFDescription::getOutputIds() const
Chris@457 91 {
Chris@457 92 QStringList ids;
Chris@457 93 for (OutputDispositionMap::const_iterator i = m_outputDispositions.begin();
Chris@457 94 i != m_outputDispositions.end(); ++i) {
Chris@457 95 ids.push_back(i->first);
Chris@457 96 }
Chris@457 97 return ids;
Chris@457 98 }
Chris@457 99
Chris@457 100 QString
Chris@457 101 PluginRDFDescription::getOutputName(QString outputId) const
Chris@457 102 {
Chris@457 103 if (m_outputNames.find(outputId) == m_outputNames.end()) {
Chris@457 104 return "";
Chris@457 105 }
Chris@457 106 return m_outputNames.find(outputId)->second;
Chris@457 107 }
Chris@457 108
Chris@439 109 PluginRDFDescription::OutputDisposition
Chris@439 110 PluginRDFDescription::getOutputDisposition(QString outputId) const
Chris@439 111 {
Chris@439 112 if (m_outputDispositions.find(outputId) == m_outputDispositions.end()) {
Chris@439 113 return OutputDispositionUnknown;
Chris@439 114 }
Chris@439 115 return m_outputDispositions.find(outputId)->second;
Chris@439 116 }
Chris@439 117
Chris@439 118 QString
Chris@439 119 PluginRDFDescription::getOutputEventTypeURI(QString outputId) const
Chris@439 120 {
Chris@439 121 if (m_outputEventTypeURIMap.find(outputId) ==
Chris@439 122 m_outputEventTypeURIMap.end()) {
Chris@439 123 return "";
Chris@439 124 }
Chris@439 125 return m_outputEventTypeURIMap.find(outputId)->second;
Chris@439 126 }
Chris@439 127
Chris@439 128 QString
Chris@440 129 PluginRDFDescription::getOutputFeatureAttributeURI(QString outputId) const
Chris@440 130 {
Chris@440 131 if (m_outputFeatureAttributeURIMap.find(outputId) ==
Chris@440 132 m_outputFeatureAttributeURIMap.end()) {
Chris@440 133 return "";
Chris@440 134 }
Chris@440 135 return m_outputFeatureAttributeURIMap.find(outputId)->second;
Chris@440 136 }
Chris@440 137
Chris@440 138 QString
Chris@440 139 PluginRDFDescription::getOutputSignalTypeURI(QString outputId) const
Chris@440 140 {
Chris@440 141 if (m_outputSignalTypeURIMap.find(outputId) ==
Chris@440 142 m_outputSignalTypeURIMap.end()) {
Chris@440 143 return "";
Chris@440 144 }
Chris@440 145 return m_outputSignalTypeURIMap.find(outputId)->second;
Chris@440 146 }
Chris@440 147
Chris@440 148 QString
Chris@439 149 PluginRDFDescription::getOutputUnit(QString outputId) const
Chris@439 150 {
Chris@439 151 if (m_outputUnitMap.find(outputId) == m_outputUnitMap.end()) {
Chris@439 152 return "";
Chris@439 153 }
Chris@439 154 return m_outputUnitMap.find(outputId)->second;
Chris@439 155 }
Chris@439 156
Chris@494 157 QString
Chris@494 158 PluginRDFDescription::getOutputUri(QString outputId) const
Chris@494 159 {
Chris@494 160 if (m_outputUriMap.find(outputId) == m_outputUriMap.end()) {
Chris@494 161 return "";
Chris@494 162 }
Chris@494 163 return m_outputUriMap.find(outputId)->second;
Chris@494 164 }
Chris@494 165
Chris@439 166 bool
Chris@489 167 PluginRDFDescription::index()
Chris@439 168 {
Chris@489 169 Profiler profiler("PluginRDFDescription::index");
Chris@439 170
Chris@457 171 bool success = true;
Chris@489 172 if (!indexMetadata()) success = false;
Chris@489 173 if (!indexOutputs()) success = false;
Chris@457 174
Chris@457 175 return success;
Chris@457 176 }
Chris@457 177
Chris@457 178 bool
Chris@489 179 PluginRDFDescription::indexMetadata()
Chris@457 180 {
Chris@489 181 Profiler profiler("PluginRDFDescription::index");
Chris@489 182
Chris@725 183 PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
Chris@725 184 const BasicStore *index = indexer->getIndex();
Chris@725 185 Uri plugin(m_pluginUri);
Chris@457 186
Chris@730 187 Node n = index->complete
Chris@730 188 (Triple(plugin, index->expand("vamp:name"), Node()));
Chris@730 189
Chris@725 190 if (n.type == Node::Literal && n.value != "") {
Chris@725 191 m_pluginName = n.value;
Chris@457 192 }
Chris@457 193
Chris@730 194 n = index->complete
Chris@730 195 (Triple(plugin, index->expand("dc:description"), Node()));
Chris@730 196
Chris@725 197 if (n.type == Node::Literal && n.value != "") {
Chris@725 198 m_pluginDescription = n.value;
Chris@457 199 }
Chris@457 200
Chris@730 201 n = index->complete
Chris@730 202 (Triple(plugin, index->expand("foaf:maker"), Node()));
Chris@730 203
Chris@725 204 if (n.type == Node::URI || n.type == Node::Blank) {
Chris@730 205 n = index->complete(Triple(n, index->expand("foaf:name"), Node()));
Chris@725 206 if (n.type == Node::Literal && n.value != "") {
Chris@725 207 m_pluginMaker = n.value;
Chris@725 208 }
Chris@457 209 }
Chris@457 210
Chris@462 211 // If we have a more-information URL for this plugin, then we take
Chris@725 212 // that. Otherwise, a more-information URL for the plugin library
Chris@725 213 // would do nicely.
Chris@462 214
Chris@730 215 n = index->complete
Chris@730 216 (Triple(plugin, index->expand("foaf:page"), Node()));
Chris@730 217
Chris@725 218 if (n.type == Node::URI && n.value != "") {
Chris@1845 219 m_provider.infoUrl = n.value;
Chris@725 220 }
Chris@462 221
Chris@1844 222 // There may be more than one library node claiming this
Chris@1844 223 // plugin. That's because older RDF descriptions tend to use a
Chris@1844 224 // library node URI derived from the description's own URI, so it
Chris@1844 225 // varies depending on where you read the description from. It's
Chris@1844 226 // common therefore to end up with both a file: URI (from an
Chris@1844 227 // installed older version) and an http: one (from an online
Chris@1844 228 // updated version). We have no way to pick an authoritative one,
Chris@1844 229 // but it's also common that only one of them will have the
Chris@1844 230 // resources we need anyway, so let's iterate through them all.
Chris@1844 231
Chris@1844 232 Nodes libnodes = index->match
Chris@1844 233 (Triple(Node(), index->expand("vamp:available_plugin"), plugin))
Chris@1844 234 .subjects();
Chris@730 235
Chris@1844 236 for (Node libn: libnodes) {
Chris@1844 237
Chris@1844 238 if (libn.type != Node::URI || libn.value == "") {
Chris@1844 239 continue;
Chris@1844 240 }
Chris@1843 241
Chris@1843 242 n = index->complete
Chris@1843 243 (Triple(libn, index->expand("foaf:page"), Node()));
Chris@1844 244
Chris@1844 245 if (n.type == Node::URI && n.value != "") {
Chris@1845 246 m_provider.infoUrl = n.value;
Chris@1843 247 }
Chris@1843 248
Chris@1843 249 n = index->complete
Chris@1843 250 (Triple(libn, index->expand("doap:download-page"), Node()));
Chris@1843 251
Chris@725 252 if (n.type == Node::URI && n.value != "") {
Chris@1845 253 m_provider.downloadUrl = n.value;
Chris@1843 254
Chris@1843 255 n = index->complete
Chris@1843 256 (Triple(libn, index->expand("vamp:has_source"), Node()));
Chris@1843 257 if (n.type == Node::Literal && n.value == "true") {
Chris@1845 258 m_provider.downloadTypes.insert(Provider::DownloadSourceCode);
Chris@1843 259 }
Chris@1843 260
Chris@1843 261 Nodes binaries = index->match
Chris@1843 262 (Triple(libn, index->expand("vamp:has_binary"), Node()))
Chris@1843 263 .objects();
Chris@1843 264
Chris@1843 265 for (Node bin: binaries) {
Chris@1843 266 if (bin.type != Node::Literal) continue;
Chris@1843 267 if (bin.value == "linux32") {
Chris@1845 268 m_provider.downloadTypes.insert(Provider::DownloadLinux32);
Chris@1843 269 } else if (bin.value == "linux64") {
Chris@1845 270 m_provider.downloadTypes.insert(Provider::DownloadLinux64);
Chris@1843 271 } else if (bin.value == "win32") {
Chris@1845 272 m_provider.downloadTypes.insert(Provider::DownloadWindows);
Chris@1843 273 } else if (bin.value == "osx") {
Chris@1845 274 m_provider.downloadTypes.insert(Provider::DownloadMac);
Chris@1843 275 }
Chris@1843 276 }
Chris@462 277 }
Chris@1844 278
Chris@1844 279 Nodes packs = index->match
Chris@1844 280 (Triple(Node(), index->expand("vamp:available_library"), libn))
Chris@1844 281 .subjects();
Chris@1844 282
Chris@1847 283 #ifdef DEBUG_PLUGIN_RDF_DESCRIPTION
Chris@1844 284 SVCERR << packs.size() << " matching pack(s) for library node "
Chris@1844 285 << libn << endl;
Chris@1847 286 #endif
Chris@1844 287
Chris@1844 288 for (Node packn: packs) {
Chris@1844 289 if (packn.type != Node::URI) continue;
Chris@1844 290
Chris@1845 291 QString packName;
Chris@1845 292 QString packUrl;
Chris@1844 293 n = index->complete
Chris@1844 294 (Triple(packn, index->expand("dc:title"), Node()));
Chris@1844 295 if (n.type == Node::Literal) {
Chris@1845 296 packName = n.value;
Chris@1844 297 }
Chris@1844 298 n = index->complete
Chris@1844 299 (Triple(packn, index->expand("foaf:page"), Node()));
Chris@1844 300 if (n.type == Node::URI) {
Chris@1845 301 packUrl = n.value;
Chris@1844 302 }
Chris@1844 303
Chris@1845 304 if (packName != "" && packUrl != "") {
Chris@1845 305 m_provider.foundInPacks[packName] = packUrl;
Chris@1844 306 }
Chris@1844 307 }
Chris@462 308 }
Chris@462 309
Chris@1844 310 #ifdef DEBUG_PLUGIN_RDF_DESCRIPTION
Chris@1844 311 SVCERR << "PluginRDFDescription::indexMetadata:" << endl;
Chris@1844 312 SVCERR << " * id: " << m_pluginId << endl;
Chris@1844 313 SVCERR << " * uri: <" << m_pluginUri << ">" << endl;
Chris@1844 314 SVCERR << " * name: " << m_pluginName << endl;
Chris@1844 315 SVCERR << " * description: " << m_pluginDescription << endl;
Chris@1844 316 SVCERR << " * maker: " << m_pluginMaker << endl;
Chris@1845 317 SVCERR << " * info url: <" << m_provider.infoUrl << ">" << endl;
Chris@1845 318 SVCERR << " * download url: <" << m_provider.downloadUrl << ">" << endl;
Chris@1844 319 SVCERR << " * download types:" << endl;
Chris@1845 320 for (auto t: m_provider.downloadTypes) {
Chris@1844 321 SVCERR << " * " << int(t) << endl;
Chris@1844 322 }
Chris@1844 323 SVCERR << " * packs:" << endl;
Chris@1845 324 for (auto t: m_provider.foundInPacks) {
Chris@1845 325 SVCERR << " * " << t.first
Chris@1845 326 << ", download url: <" << t.second << ">" << endl;
Chris@1844 327 }
Chris@1844 328 SVCERR << endl;
Chris@1844 329 #endif
Chris@1843 330
Chris@457 331 return true;
Chris@457 332 }
Chris@457 333
Chris@457 334 bool
Chris@489 335 PluginRDFDescription::indexOutputs()
Chris@457 336 {
Chris@457 337 Profiler profiler("PluginRDFDescription::indexOutputs");
Chris@489 338
Chris@725 339 PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
Chris@725 340 const BasicStore *index = indexer->getIndex();
Chris@725 341 Uri plugin(m_pluginUri);
Chris@457 342
Chris@730 343 Nodes outputs = index->match
Chris@730 344 (Triple(plugin, index->expand("vamp:output"), Node())).objects();
Chris@439 345
Chris@725 346 if (outputs.empty()) {
Chris@718 347 cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: No outputs defined for <"
Chris@686 348 << m_pluginUri << ">" << endl;
Chris@439 349 return false;
Chris@439 350 }
Chris@439 351
Chris@725 352 foreach (Node output, outputs) {
Chris@439 353
Chris@725 354 if ((output.type != Node::URI && output.type != Node::Blank) ||
Chris@725 355 output.value == "") {
Chris@725 356 cerr << "ERROR: PluginRDFDescription::indexURL: No valid URI for output " << output << " of plugin <" << m_pluginUri << ">" << endl;
Chris@718 357 return false;
Chris@718 358 }
Chris@725 359
Chris@730 360 Node n = index->complete(Triple(output, index->expand("vamp:identifier"), Node()));
Chris@725 361 if (n.type != Node::Literal || n.value == "") {
Chris@725 362 cerr << "ERROR: PluginRDFDescription::indexURL: No vamp:identifier for output <" << output << ">" << endl;
Chris@718 363 return false;
Chris@718 364 }
Chris@725 365 QString outputId = n.value;
Chris@718 366
Chris@730 367 m_outputUriMap[outputId] = output.value;
Chris@730 368
Chris@730 369 n = index->complete(Triple(output, Uri("a"), Node()));
Chris@725 370 QString outputType;
Chris@725 371 if (n.type == Node::URI) outputType = n.value;
Chris@718 372
Chris@730 373 n = index->complete(Triple(output, index->expand("vamp:unit"), Node()));
Chris@725 374 QString outputUnit;
Chris@725 375 if (n.type == Node::Literal) outputUnit = n.value;
Chris@718 376
Chris@439 377 if (outputType.contains("DenseOutput")) {
Chris@439 378 m_outputDispositions[outputId] = OutputDense;
Chris@439 379 } else if (outputType.contains("SparseOutput")) {
Chris@439 380 m_outputDispositions[outputId] = OutputSparse;
Chris@439 381 } else if (outputType.contains("TrackLevelOutput")) {
Chris@439 382 m_outputDispositions[outputId] = OutputTrackLevel;
Chris@457 383 } else {
Chris@457 384 m_outputDispositions[outputId] = OutputDispositionUnknown;
Chris@439 385 }
Chris@732 386 // cerr << "output " << output << " -> id " << outputId << ", type " << outputType << ", unit "
Chris@732 387 // << outputUnit << ", disposition " << m_outputDispositions[outputId] << endl;
Chris@439 388
Chris@718 389 if (outputUnit != "") {
Chris@718 390 m_outputUnitMap[outputId] = outputUnit;
Chris@439 391 }
Chris@440 392
Chris@730 393 n = index->complete(Triple(output, index->expand("dc:title"), Node()));
Chris@725 394 if (n.type == Node::Literal && n.value != "") {
Chris@725 395 m_outputNames[outputId] = n.value;
Chris@457 396 }
Chris@457 397
Chris@730 398 n = index->complete(Triple(output, index->expand("vamp:computes_event_type"), Node()));
Chris@732 399 // cerr << output << " -> computes_event_type " << n << endl;
Chris@725 400 if (n.type == Node::URI && n.value != "") {
Chris@725 401 m_outputEventTypeURIMap[outputId] = n.value;
Chris@440 402 }
Chris@440 403
Chris@730 404 n = index->complete(Triple(output, index->expand("vamp:computes_feature"), Node()));
Chris@725 405 if (n.type == Node::URI && n.value != "") {
Chris@725 406 m_outputFeatureAttributeURIMap[outputId] = n.value;
Chris@725 407 }
Chris@440 408
Chris@730 409 n = index->complete(Triple(output, index->expand("vamp:computes_signal_type"), Node()));
Chris@725 410 if (n.type == Node::URI && n.value != "") {
Chris@725 411 m_outputSignalTypeURIMap[outputId] = n.value;
Chris@440 412 }
Chris@439 413 }
Chris@439 414
Chris@439 415 return true;
Chris@439 416 }
Chris@439 417