# HG changeset patch # User Chris Cannam # Date 1497259225 -3600 # Node ID d54dab075247da3321a294e39b9b8ab317803ac5 # Parent 691b0daad1c6ed9ca41ba73ac83248cf07e65aff Implement RDF type lookup diff -r 691b0daad1c6 -r d54dab075247 .travis.yml --- a/.travis.yml Mon Jun 12 10:19:52 2017 +0100 +++ b/.travis.yml Mon Jun 12 10:20:25 2017 +0100 @@ -17,7 +17,7 @@ - qt5-default before_install: - - ( cd ../ ; git clone https://github.com/piper-audio/piper ) + - ( cd ../ ; git clone -b output-type-uri https://github.com/piper-audio/piper ) - ( cd ../ ; hg clone https://code.soundsoftware.ac.uk/hg/vamp-plugin-sdk ) - ( cd ../ ; git clone https://github.com/sandstorm-io/capnproto ) - ( cd ../capnproto/c++ ; ./setup-autotools.sh && autoreconf -i ) diff -r 691b0daad1c6 -r d54dab075247 vamp-server/test.sh --- a/vamp-server/test.sh Mon Jun 12 10:19:52 2017 +0100 +++ b/vamp-server/test.sh Mon Jun 12 10:20:25 2017 +0100 @@ -80,7 +80,7 @@ # Expected output, apart from the plugin list which seems a bit # fragile to check here cat > "$expected" < suffixes { "ttl", "TTL", "n3", "N3" }; + std::vector suffixes { "n3", "N3", "ttl", "TTL" }; std::vector candidates; for (auto suffix : suffixes) { @@ -128,9 +139,12 @@ } void - loadStaticOutputInfoFromModel(SordModel *model, std::string pluginKey, + loadStaticOutputInfoFromModel(SordModel *model, + std::string pluginKey, StaticOutputInfo &info) { + // we want to find a graph like + // // :plugin a vamp:Plugin // :plugin vamp:identifier "pluginId" // :library vamp:available_plugin :plugin @@ -141,18 +155,144 @@ // :output1 vamp:computes_event_type :event // :output2 vamp:computes_feature :feature // :output3 vamp:computes_signal_type :signal - // and where pluginKey == libraryId + ":" + pluginId - - // Although, since we know we just loaded an RDF file - // associated with one particular plugin library, we could in - // theory skip the library bits. We'd still have most of the - // rest though since each library can have multiple plugins - // with output names that could conflict + // + // in which pluginKey == libraryId + ":" + pluginId std::string libraryId, pluginId; decomposePluginKey(pluginKey, libraryId, pluginId); - //!!! + typedef const uint8_t *S; + + SordNode *a = sord_new_uri + (m_world, S("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")); + + SordNode *pluginType = sord_new_uri + (m_world, S("http://purl.org/ontology/vamp/Plugin")); + + SordNode *identProp = sord_new_uri + (m_world, S("http://purl.org/ontology/vamp/identifier")); + SordNode *availProp = sord_new_uri + (m_world, S("http://purl.org/ontology/vamp/available_plugin")); + SordNode *outputProp = sord_new_uri + (m_world, S("http://purl.org/ontology/vamp/output")); + + SordNode *computesEventProp = sord_new_uri + (m_world, S("http://purl.org/ontology/vamp/computes_event_type")); + SordNode *computesFeatureProp = sord_new_uri + (m_world, S("http://purl.org/ontology/vamp/computes_feature")); + SordNode *computesSignalProp = sord_new_uri + (m_world, S("http://purl.org/ontology/vamp/computes_signal_type")); + + SordIter *pluginItr = 0; + + for (pluginItr = sord_search(model, 0, a, pluginType, 0); + !sord_iter_end(pluginItr); + sord_iter_next(pluginItr)) { + + const SordNode *pluginNode = + sord_iter_get_node(pluginItr, SORD_SUBJECT); + + SordNode *pluginIdNode = + sord_get(model, pluginNode, identProp, 0, 0); + + if (!pluginIdNode || + sord_node_get_type(pluginIdNode) != SORD_LITERAL || + (const char *)sord_node_get_string(pluginIdNode) != pluginId) { + // This is a plugin node, but it's not the plugin node + // we're looking for. (We have to check both the type + // property, vamp:Plugin, and the identifier, + // vamp:identifier, because the identifier is just a + // string and it's possible it could be used for an + // output or parameter rather than just a plugin.) + continue; + } + + SordNode *libraryNode = + sord_get(model, 0, availProp, pluginNode, 0); + + if (!libraryNode) { + std::cerr << "Plugin is not listed as being in a library, " + << "skipping library id check" << std::endl; + } else { + SordNode *libIdNode = + sord_get(model, libraryNode, identProp, 0, 0); + if (!libIdNode || + sord_node_get_type(libIdNode) != SORD_LITERAL || + (const char *)sord_node_get_string(libIdNode) != libraryId) { + std::cerr << "Ignoring plugin in wrong library" << std::endl; + continue; + } + } + + SordIter *outputItr = 0; + + for (outputItr = sord_search(model, pluginNode, outputProp, 0, 0); + !sord_iter_end(outputItr); + sord_iter_next(outputItr)) { + + const SordNode *outputNode = + sord_iter_get_node(outputItr, SORD_OBJECT); + + SordNode *outputIdNode = + sord_get(model, outputNode, identProp, 0, 0); + + if (!outputIdNode || + sord_node_get_type(outputIdNode) != SORD_LITERAL || + !sord_node_get_string(outputIdNode)) { + std::cerr << "Ignoring output with no id" << std::endl; + continue; + } + + std::string outputId = + (const char *)sord_node_get_string(outputIdNode); + + SordIter *propItr = 0; + + for (propItr = sord_search(model, outputNode, 0, 0, 0); + !sord_iter_end(propItr); + sord_iter_next(propItr)) { + + const SordNode *propNode = + sord_iter_get_node(propItr, SORD_PREDICATE); + + if (sord_node_equals(propNode, computesEventProp) || + sord_node_equals(propNode, computesFeatureProp) || + sord_node_equals(propNode, computesSignalProp)) { + + const SordNode *computesNode = + sord_iter_get_node(propItr, SORD_OBJECT); + + if (sord_node_get_type(computesNode) != SORD_URI || + !sord_node_get_string(computesNode)) { + std::cerr << "Ignoring non-URI computes node" + << std::endl; + continue; + } + + std::string typeURI = + (const char *)sord_node_get_string(computesNode); + + std::cerr << "Found type <" << typeURI + << "> for output \"" << outputId + << "\" of plugin \"" << pluginId + << "\" in library " << libraryId + << std::endl; + + StaticOutputDescriptor desc; + desc.typeURI = typeURI; + info[outputId] = desc; + + break; // only interested in one "computes" property + } + } + + sord_iter_free(propItr); + } + + sord_iter_free(outputItr); + } + + sord_iter_free(pluginItr); } bool decomposePluginKey(std::string pluginKey,