Chris@439: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@439: 
Chris@439: /*
Chris@439:     Sonic Visualiser
Chris@439:     An audio file viewer and annotation editor.
Chris@439:     Centre for Digital Music, Queen Mary, University of London.
Chris@727:     This file copyright 2008-2012 QMUL.
Chris@439:    
Chris@439:     This program is free software; you can redistribute it and/or
Chris@439:     modify it under the terms of the GNU General Public License as
Chris@439:     published by the Free Software Foundation; either version 2 of the
Chris@439:     License, or (at your option) any later version.  See the file
Chris@439:     COPYING included with this distribution for more information.
Chris@439: */
Chris@439: 
Chris@439: #include "PluginRDFDescription.h"
Chris@439: 
Chris@439: #include "PluginRDFIndexer.h"
Chris@439: 
Chris@457: #include "base/Profiler.h"
Chris@457: 
Chris@439: #include "plugin/PluginIdentifier.h"
Chris@439: 
Chris@725: #include <dataquay/BasicStore.h>
Chris@725: 
Chris@439: #include <iostream>
Chris@439: 
Chris@725: using Dataquay::Uri;
Chris@725: using Dataquay::Node;
Chris@725: using Dataquay::Nodes;
Chris@725: using Dataquay::Triple;
Chris@725: using Dataquay::Triples;
Chris@725: using Dataquay::BasicStore;
Chris@725: 
Chris@439: PluginRDFDescription::PluginRDFDescription(QString pluginId) :
Chris@439:     m_pluginId(pluginId),
Chris@439:     m_haveDescription(false)
Chris@439: {
Chris@439:     PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
Chris@489:     m_pluginUri = indexer->getURIForPluginId(pluginId);
Chris@489:     if (m_pluginUri == "") {
Chris@439:         cerr << "PluginRDFDescription: WARNING: No RDF description available for plugin ID \""
Chris@686:              << pluginId << "\"" << endl;
Chris@439:     } else {
Chris@489:         // All the data we need should be in our RDF model already:
Chris@489:         // if it's not there, we don't know where to find it anyway
Chris@489:         if (index()) {
Chris@439:             m_haveDescription = true;
Chris@439:         }
Chris@439:     }
Chris@439: }
Chris@439: 
Chris@439: PluginRDFDescription::~PluginRDFDescription()
Chris@439: {
Chris@439: }
Chris@439: 
Chris@439: bool
Chris@439: PluginRDFDescription::haveDescription() const
Chris@439: {
Chris@439:     return m_haveDescription;
Chris@439: }
Chris@439: 
Chris@457: QString
Chris@457: PluginRDFDescription::getPluginName() const
Chris@457: {
Chris@457:     return m_pluginName;
Chris@457: }
Chris@457: 
Chris@457: QString
Chris@457: PluginRDFDescription::getPluginDescription() const
Chris@457: {
Chris@457:     return m_pluginDescription;
Chris@457: }
Chris@457: 
Chris@457: QString
Chris@457: PluginRDFDescription::getPluginMaker() const
Chris@457: {
Chris@457:     return m_pluginMaker;
Chris@457: }
Chris@457: 
Chris@462: QString
Chris@462: PluginRDFDescription::getPluginInfoURL() const
Chris@462: {
Chris@462:     return m_pluginInfoURL;
Chris@462: }
Chris@462: 
Chris@457: QStringList
Chris@457: PluginRDFDescription::getOutputIds() const
Chris@457: {
Chris@457:     QStringList ids;
Chris@457:     for (OutputDispositionMap::const_iterator i = m_outputDispositions.begin();
Chris@457:          i != m_outputDispositions.end(); ++i) {
Chris@457:         ids.push_back(i->first);
Chris@457:     }
Chris@457:     return ids;
Chris@457: }
Chris@457: 
Chris@457: QString
Chris@457: PluginRDFDescription::getOutputName(QString outputId) const
Chris@457: {
Chris@457:     if (m_outputNames.find(outputId) == m_outputNames.end()) {
Chris@457:         return "";
Chris@457:     } 
Chris@457:     return m_outputNames.find(outputId)->second;
Chris@457: }
Chris@457: 
Chris@439: PluginRDFDescription::OutputDisposition
Chris@439: PluginRDFDescription::getOutputDisposition(QString outputId) const
Chris@439: {
Chris@439:     if (m_outputDispositions.find(outputId) == m_outputDispositions.end()) {
Chris@439:         return OutputDispositionUnknown;
Chris@439:     }
Chris@439:     return m_outputDispositions.find(outputId)->second;
Chris@439: }
Chris@439: 
Chris@439: QString
Chris@439: PluginRDFDescription::getOutputEventTypeURI(QString outputId) const
Chris@439: {
Chris@439:     if (m_outputEventTypeURIMap.find(outputId) ==
Chris@439:         m_outputEventTypeURIMap.end()) {
Chris@439:         return "";
Chris@439:     }
Chris@439:     return m_outputEventTypeURIMap.find(outputId)->second;
Chris@439: }
Chris@439: 
Chris@439: QString
Chris@440: PluginRDFDescription::getOutputFeatureAttributeURI(QString outputId) const
Chris@440: {
Chris@440:     if (m_outputFeatureAttributeURIMap.find(outputId) ==
Chris@440:         m_outputFeatureAttributeURIMap.end()) {
Chris@440:         return "";
Chris@440:     }
Chris@440:     return m_outputFeatureAttributeURIMap.find(outputId)->second;
Chris@440: }
Chris@440: 
Chris@440: QString
Chris@440: PluginRDFDescription::getOutputSignalTypeURI(QString outputId) const
Chris@440: {
Chris@440:     if (m_outputSignalTypeURIMap.find(outputId) ==
Chris@440:         m_outputSignalTypeURIMap.end()) {
Chris@440:         return "";
Chris@440:     }
Chris@440:     return m_outputSignalTypeURIMap.find(outputId)->second;
Chris@440: }
Chris@440: 
Chris@440: QString
Chris@439: PluginRDFDescription::getOutputUnit(QString outputId) const
Chris@439: {
Chris@439:     if (m_outputUnitMap.find(outputId) == m_outputUnitMap.end()) {
Chris@439:         return "";
Chris@439:     }
Chris@439:     return m_outputUnitMap.find(outputId)->second;
Chris@439: }
Chris@439: 
Chris@494: QString
Chris@494: PluginRDFDescription::getOutputUri(QString outputId) const
Chris@494: {
Chris@494:     if (m_outputUriMap.find(outputId) == m_outputUriMap.end()) {
Chris@494:         return "";
Chris@494:     }
Chris@494:     return m_outputUriMap.find(outputId)->second;
Chris@494: }
Chris@494: 
Chris@439: bool
Chris@489: PluginRDFDescription::index() 
Chris@439: {
Chris@489:     Profiler profiler("PluginRDFDescription::index");
Chris@439: 
Chris@457:     bool success = true;
Chris@489:     if (!indexMetadata()) success = false;
Chris@489:     if (!indexOutputs()) success = false;
Chris@457: 
Chris@457:     return success;
Chris@457: }
Chris@457: 
Chris@457: bool
Chris@489: PluginRDFDescription::indexMetadata()
Chris@457: {
Chris@489:     Profiler profiler("PluginRDFDescription::index");
Chris@489: 
Chris@725:     PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
Chris@725:     const BasicStore *index = indexer->getIndex();
Chris@725:     Uri plugin(m_pluginUri);
Chris@457: 
Chris@730:     Node n = index->complete
Chris@730:         (Triple(plugin, index->expand("vamp:name"), Node()));
Chris@730: 
Chris@725:     if (n.type == Node::Literal && n.value != "") {
Chris@725:         m_pluginName = n.value;
Chris@457:     }
Chris@457: 
Chris@730:     n = index->complete
Chris@730:         (Triple(plugin, index->expand("dc:description"), Node()));
Chris@730: 
Chris@725:     if (n.type == Node::Literal && n.value != "") {
Chris@725:         m_pluginDescription = n.value;
Chris@457:     }
Chris@457: 
Chris@730:     n = index->complete
Chris@730:         (Triple(plugin, index->expand("foaf:maker"), Node()));
Chris@730: 
Chris@725:     if (n.type == Node::URI || n.type == Node::Blank) {
Chris@730:         n = index->complete(Triple(n, index->expand("foaf:name"), Node()));
Chris@725:         if (n.type == Node::Literal && n.value != "") {
Chris@725:             m_pluginMaker = n.value;
Chris@725:         }
Chris@457:     }
Chris@457: 
Chris@462:     // If we have a more-information URL for this plugin, then we take
Chris@725:     // that.  Otherwise, a more-information URL for the plugin library
Chris@725:     // would do nicely.
Chris@462: 
Chris@730:     n = index->complete
Chris@730:         (Triple(plugin, index->expand("foaf:page"), Node()));
Chris@730: 
Chris@725:     if (n.type == Node::URI && n.value != "") {
Chris@725:         m_pluginInfoURL = n.value;
Chris@725:     }
Chris@462: 
Chris@730:     n = index->complete
Chris@730:         (Triple(Node(), index->expand("vamp:available_plugin"), plugin));
Chris@730: 
Chris@725:     if (n.value != "") {
Chris@730:         n = index->complete(Triple(n, index->expand("foaf:page"), Node()));
Chris@725:         if (n.type == Node::URI && n.value != "") {
Chris@725:             m_pluginInfoURL = n.value;
Chris@462:         }
Chris@462:     }
Chris@462: 
Chris@457:     return true;
Chris@457: }
Chris@457: 
Chris@457: bool
Chris@489: PluginRDFDescription::indexOutputs()
Chris@457: {
Chris@457:     Profiler profiler("PluginRDFDescription::indexOutputs");
Chris@489:     
Chris@725:     PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
Chris@725:     const BasicStore *index = indexer->getIndex();
Chris@725:     Uri plugin(m_pluginUri);
Chris@457: 
Chris@730:     Nodes outputs = index->match
Chris@730:         (Triple(plugin, index->expand("vamp:output"), Node())).objects();
Chris@439: 
Chris@725:     if (outputs.empty()) {
Chris@718:         cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: No outputs defined for <"
Chris@686:              << m_pluginUri << ">" << endl;
Chris@439:         return false;
Chris@439:     }
Chris@439: 
Chris@725:     foreach (Node output, outputs) {
Chris@439: 
Chris@725:         if ((output.type != Node::URI && output.type != Node::Blank) ||
Chris@725:             output.value == "") {
Chris@725:             cerr << "ERROR: PluginRDFDescription::indexURL: No valid URI for output " << output << " of plugin <" << m_pluginUri << ">" << endl;
Chris@718:             return false;
Chris@718:         }
Chris@725:         
Chris@730:         Node n = index->complete(Triple(output, index->expand("vamp:identifier"), Node()));
Chris@725:         if (n.type != Node::Literal || n.value == "") {
Chris@725:             cerr << "ERROR: PluginRDFDescription::indexURL: No vamp:identifier for output <" << output << ">" << endl;
Chris@718:             return false;
Chris@718:         }
Chris@725:         QString outputId = n.value;
Chris@718: 
Chris@730:         m_outputUriMap[outputId] = output.value;
Chris@730: 
Chris@730:         n = index->complete(Triple(output, Uri("a"), Node()));
Chris@725:         QString outputType;
Chris@725:         if (n.type == Node::URI) outputType = n.value;
Chris@718: 
Chris@730:         n = index->complete(Triple(output, index->expand("vamp:unit"), Node()));
Chris@725:         QString outputUnit;
Chris@725:         if (n.type == Node::Literal) outputUnit = n.value;
Chris@718: 
Chris@439:         if (outputType.contains("DenseOutput")) {
Chris@439:             m_outputDispositions[outputId] = OutputDense;
Chris@439:         } else if (outputType.contains("SparseOutput")) {
Chris@439:             m_outputDispositions[outputId] = OutputSparse;
Chris@439:         } else if (outputType.contains("TrackLevelOutput")) {
Chris@439:             m_outputDispositions[outputId] = OutputTrackLevel;
Chris@457:         } else {
Chris@457:             m_outputDispositions[outputId] = OutputDispositionUnknown;
Chris@439:         }
Chris@732: //        cerr << "output " << output << " -> id " << outputId << ", type " << outputType << ", unit " 
Chris@732: //             << outputUnit << ", disposition " << m_outputDispositions[outputId] << endl;
Chris@439:             
Chris@718:         if (outputUnit != "") {
Chris@718:             m_outputUnitMap[outputId] = outputUnit;
Chris@439:         }
Chris@440: 
Chris@730:         n = index->complete(Triple(output, index->expand("dc:title"), Node()));
Chris@725:         if (n.type == Node::Literal && n.value != "") {
Chris@725:             m_outputNames[outputId] = n.value;
Chris@457:         }
Chris@457: 
Chris@730:         n = index->complete(Triple(output, index->expand("vamp:computes_event_type"), Node()));
Chris@732: //        cerr << output << " -> computes_event_type " << n << endl;
Chris@725:         if (n.type == Node::URI && n.value != "") {
Chris@725:             m_outputEventTypeURIMap[outputId] = n.value;
Chris@440:         }
Chris@440: 
Chris@730:         n = index->complete(Triple(output, index->expand("vamp:computes_feature"), Node()));
Chris@725:         if (n.type == Node::URI && n.value != "") {
Chris@725:             m_outputFeatureAttributeURIMap[outputId] = n.value;
Chris@725:         }
Chris@440: 
Chris@730:         n = index->complete(Triple(output, index->expand("vamp:computes_signal_type"), Node()));
Chris@725:         if (n.type == Node::URI && n.value != "") {
Chris@725:             m_outputSignalTypeURIMap[outputId] = n.value;
Chris@440:         }
Chris@439:     }
Chris@439: 
Chris@439:     return true;
Chris@439: }
Chris@439: