annotate rdf/generator/template-generator.cpp @ 218:81ffb843c8cc

* add foaf:page &c
author cannam
date Wed, 29 Oct 2008 15:18:23 +0000
parents f9b4f60280db
children 2d713ece8dbf
rev   line source
cannam@138 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@138 2
cannam@138 3 #include "vamp-sdk/PluginHostAdapter.h"
cannam@138 4 #include "vamp-sdk/hostext/PluginChannelAdapter.h"
cannam@138 5 #include "vamp-sdk/hostext/PluginInputDomainAdapter.h"
cannam@138 6 #include "vamp-sdk/hostext/PluginLoader.h"
cannam@138 7 #include "vamp/vamp.h"
cannam@138 8
cannam@138 9 #include <iostream>
cannam@138 10 #include <fstream>
cannam@138 11 #include <sstream>
cannam@138 12 #include <sndfile.h>
cannam@138 13
cannam@138 14 #include <cmath>
cannam@138 15
cannam@138 16 using std::cout;
cannam@138 17 using std::cin;
cannam@138 18 using std::cerr;
cannam@138 19 using std::getline;
cannam@138 20 using std::endl;
cannam@138 21 using std::string;
cannam@138 22 using std::vector;
cannam@138 23 using std::ofstream;
cannam@138 24 using std::ios;
cannam@138 25
cannam@138 26 using Vamp::HostExt::PluginLoader;
cannam@138 27 using Vamp::Plugin;
cannam@138 28
cannam@217 29 //???
cannam@138 30 string programURI = "http://www.vamp-plugins.org/doap.rdf#template-generator";
cannam@138 31
cannam@138 32 void usage()
cannam@138 33 {
cannam@217 34 cerr << endl;
cannam@217 35 cerr << "template-generator: Create a skeleton RDF description file describing a Vamp" << endl;
cannam@217 36 cerr << "plugin library using the Vamp ontology." << endl;
cannam@217 37 cerr << endl;
cannam@217 38 cerr << "Usage:" << endl;
cannam@217 39 cerr << " template-generator -i vamp:soname[:plugin] [vamp:soname[:plugin] ...]" << endl;
cannam@217 40 cerr << " template-generator PLUGIN_BASE_URI [ -m YOUR_URI ] [vamp:]soname[:plugin] [[vamp:]soname[:plugin] ...]" << endl;
cannam@217 41 cerr << endl;
cannam@217 42 cerr << "Example:" << endl;
cannam@217 43 cerr << " template-generator http://vamp-plugins.org/rdf/plugins/ vamp-example-plugins" << endl;
cannam@217 44 cerr << endl;
cannam@138 45 exit(2);
cannam@138 46 }
cannam@138 47
cannam@138 48 template <class T>
cannam@138 49 inline string to_string (const T& t)
cannam@138 50 {
cannam@138 51 std::stringstream ss;
cannam@138 52 ss << t;
cannam@138 53 return ss.str();
cannam@138 54 }
cannam@138 55
cannam@144 56 string describe_namespaces(string pluginBundleBaseURI, string libname)
cannam@138 57 {
cannam@142 58 string res=\
cannam@142 59 "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\
cannam@138 60 @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n\
cannam@147 61 @prefix vamp: <http://purl.org/ontology/vamp/> .\n\
cannam@144 62 @prefix plugbase: <"+pluginBundleBaseURI+libname+"#> .\n\
cannam@138 63 @prefix owl: <http://www.w3.org/2002/07/owl#> .\n\
cannam@138 64 @prefix dc: <http://purl.org/dc/elements/1.1/> .\n\
cannam@138 65 @prefix af: <http://purl.org/ontology/af/> .\n\
cannam@138 66 @prefix foaf: <http://xmlns.com/foaf/0.1/> .\n\
cannam@138 67 @prefix cc: <http://web.resource.org/cc/> .\n\
cannam@138 68 @prefix : <> .\n\n";
cannam@138 69
cannam@142 70 return res;
cannam@138 71 }
cannam@138 72
cannam@144 73 string describe_doc(string describerURI, string pluginBundleBaseURI,
cannam@144 74 string libname)
cannam@138 75 {
cannam@142 76 string res=\
cannam@217 77 "<> a vamp:PluginDescription ;\n";
cannam@217 78 if (describerURI != "") {
cannam@217 79 res += " foaf:maker <"+describerURI+"> ;\n";
cannam@217 80 }
cannam@217 81 res += "\
cannam@144 82 foaf:maker <"+programURI+"> ;\n\
cannam@144 83 foaf:primaryTopic <"+pluginBundleBaseURI+libname+"> .\n\n";
cannam@142 84 return res;
cannam@138 85 }
cannam@138 86
cannam@138 87
cannam@144 88 string describe_library(string libname, vector<Plugin *> plugins)
cannam@144 89 {
cannam@144 90 string res=\
cannam@144 91 ":"+libname+" a vamp:PluginLibrary ;\n\
cannam@144 92 vamp:identifier \""+libname+"\" ";
cannam@144 93
cannam@144 94 for (size_t i = 0; i < plugins.size(); ++i) {
cannam@218 95 res += " ; \n\
cannam@145 96 vamp:available_plugin plugbase:"+plugins[i]->getIdentifier();
cannam@144 97 }
cannam@144 98
cannam@218 99 res += " ; \n\
cannam@218 100 # foaf:page <Place more-information HTML page URL here and uncomment> ;\n\
cannam@218 101 .\n\n";
cannam@144 102 return res;
cannam@144 103 }
cannam@144 104
cannam@138 105 string describe_plugin(Plugin* plugin)
cannam@138 106 {
cannam@142 107 string res=\
cannam@142 108 "plugbase:"+plugin->getIdentifier()+" a vamp:Plugin ;\n\
cannam@138 109 dc:title \""+plugin->getName()+"\" ;\n\
cannam@139 110 vamp:name \""+plugin->getName()+"\" ;\n\
cannam@138 111 dc:description \""+plugin->getDescription()+"\" ;\n\
cannam@154 112 foaf:maker [ foaf:name \""+plugin->getMaker()+"\" ] ; # FIXME could give plugin author's URI here\n\
cannam@154 113 # cc:license <Place plugin license URI here and uncomment> ; \n\
cannam@138 114 vamp:identifier \""+plugin->getIdentifier()+"\" ;\n\
cannam@138 115 vamp:vamp_API_version vamp:api_version_"+to_string(plugin->getVampApiVersion())+" ;\n\
cannam@138 116 owl:versionInfo \""+to_string(plugin->getPluginVersion())+"\" ;\n";
cannam@142 117 if (plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain)
cannam@142 118 res+=" vamp:input_domain vamp:FrequencyDomain ;\n\n";
cannam@142 119 else
cannam@194 120 res+=" vamp:input_domain vamp:TimeDomain ;\n";
cannam@138 121
cannam@138 122
cannam@142 123 Plugin::ParameterList params = plugin->getParameterDescriptors();
cannam@194 124 if (!params.empty()) res+="\n";
cannam@142 125 for (Plugin::ParameterList::const_iterator i = params.begin(); i != params.end(); i++)
dpastor@156 126 res+=" vamp:parameter plugbase:"+plugin->getIdentifier()+"_param_"+(*i).identifier+" ;\n";
cannam@194 127 if (!params.empty()) res+="\n";
cannam@138 128
cannam@142 129 Plugin::OutputList outputs = plugin->getOutputDescriptors();
cannam@142 130 for (Plugin::OutputList::const_iterator i = outputs.begin(); i!= outputs.end(); i++)
cannam@158 131 res+=" vamp:output plugbase:"+plugin->getIdentifier()+"_output_"+(*i).identifier+" ;\n";
cannam@142 132 res+=" .\n";
cannam@138 133
cannam@142 134 return res;
cannam@138 135 }
cannam@138 136
cannam@144 137 string describe_param(Plugin *plugin, Plugin::ParameterDescriptor p)
cannam@138 138 {
cannam@148 139
cannam@148 140 //FIXME: dc:format and vamp:unit are the same???
dpastor@157 141 //Should be a QUantizedParameter also a Parameter??
cannam@148 142 if(p.isQuantized){
cannam@148 143 string res=\
dpastor@156 144 "plugbase:"+plugin->getIdentifier()+"_param_"+p.identifier+" a vamp:QuantizedParameter ;\n\
cannam@148 145 vamp:identifier \""+p.identifier+"\" ;\n\
cannam@148 146 dc:title \""+p.name+"\" ;\n\
cannam@148 147 dc:format \""+p.unit+"\" ;\n\
cannam@148 148 vamp:min_value "+to_string(p.minValue)+" ;\n\
cannam@148 149 vamp:max_value "+to_string(p.maxValue)+" ;\n\
cannam@148 150 vamp:unit \""+p.unit+"\" ;\n\
cannam@152 151 vamp:quantize_step "+to_string(p.quantizeStep)+" ;\n\
cannam@148 152 vamp:default_value "+to_string(p.defaultValue)+" ;\n\
cannam@148 153 vamp:value_names (";
cannam@148 154
cannam@148 155 unsigned int i;
cannam@148 156 for (i=0; i+1 < p.valueNames.size(); i++)
cannam@148 157 res+=" \""+p.valueNames[i]+"\"";
cannam@148 158 if (i < p.valueNames.size())
cannam@148 159 res+=" \""+p.valueNames[i]+"\"";
cannam@148 160 res+=");\n";
cannam@148 161
cannam@148 162 res+=" .\n";
cannam@148 163
cannam@148 164 return res;
cannam@148 165
cannam@148 166 }else{
cannam@142 167 string res=\
dpastor@156 168 "plugbase:"+plugin->getIdentifier()+"_param_"+p.identifier+" a vamp:Parameter ;\n\
cannam@138 169 vamp:identifier \""+p.identifier+"\" ;\n\
cannam@138 170 dc:title \""+p.name+"\" ;\n\
cannam@138 171 dc:format \""+p.unit+"\" ;\n\
cannam@139 172 vamp:min_value "+to_string(p.minValue)+" ;\n\
cannam@139 173 vamp:max_value "+to_string(p.maxValue)+" ;\n\
cannam@148 174 vamp:unit \""+p.unit+"\" ;\n\
cannam@148 175 vamp:default_value "+to_string(p.defaultValue)+" ;\n\
cannam@148 176 vamp:value_names (";
cannam@148 177
cannam@148 178 unsigned int i;
cannam@148 179 for (i=0; i+1 < p.valueNames.size(); i++)
cannam@148 180 res+=" \""+p.valueNames[i]+"\"";
cannam@148 181 if (i < p.valueNames.size())
cannam@148 182 res+=" \""+p.valueNames[i]+"\"";
cannam@148 183 res+=");\n";
cannam@148 184
cannam@148 185 res+=" .\n";
cannam@148 186
cannam@142 187 return res;
cannam@148 188
cannam@148 189 }
cannam@138 190 }
cannam@138 191
cannam@144 192 string describe_output(Plugin *plugin, Plugin::OutputDescriptor o)
cannam@138 193 {
cannam@138 194
cannam@142 195 //we need to distinguish here between different output types:
cannam@148 196
cannam@148 197 //Quantize or not
cannam@148 198 //KnownExtents or not
cannam@148 199 //Data output classification:
cannam@142 200 //DenseOutput
cannam@142 201 //SparseOutput
cannam@142 202 //TrackLevelOutput
cannam@139 203
cannam@139 204
cannam@168 205 // SparseOutput: variable sample rate. Events are not evenly
cannam@168 206 // spaced so we need to record the time associated with the event
cannam@168 207 // as it its not ensured that we have an event after the next one
cannam@168 208 // (but there is not time to set the duration, it has to be
cannam@168 209 // calculated as the different between 2 different events). The
cannam@168 210 // timestamp must be read.
cannam@139 211
cannam@142 212 string res;
cannam@139 213
cannam@168 214 if (o.sampleType == Plugin::OutputDescriptor::VariableSampleRate ||
cannam@168 215 !o.hasFixedBinCount)
cannam@142 216 {
cannam@139 217
cannam@142 218 res=\
cannam@144 219 "plugbase:"+plugin->getIdentifier()+"_output_"+o.identifier+" a vamp:SparseOutput ;\n\
cannam@139 220 vamp:identifier \""+o.identifier+"\" ;\n\
cannam@139 221 dc:title \""+o.name+"\" ;\n\
cannam@139 222 dc:description \""+o.description+"\" ;\n\
cannam@139 223 vamp:fixed_bin_count \""+(o.hasFixedBinCount == 1 ? "true" : "false")+"\" ;\n\
cannam@139 224 vamp:unit \""+(o.unit)+"\" ;\n";
cannam@139 225
cannam@148 226
cannam@148 227 //another type of output
cannam@148 228 if(o.isQuantized){
cannam@148 229
cannam@148 230 res+=" a vamp:QuantizedOutput ;\n";
cannam@148 231 res+=" vamp:quantize_step "+to_string(o.quantizeStep)+" ;\n";
cannam@148 232 }
cannam@148 233
cannam@148 234 //and yet another type
cannam@148 235 if(o.hasKnownExtents){
cannam@148 236
cannam@148 237 res+=" a vamp:KnownExtentsOutput ;\n";
cannam@148 238 res+=" vamp:min_value "+to_string(o.minValue)+" ;\n";
cannam@148 239 res+=" vamp:max_value "+to_string(o.maxValue)+" ;\n";
cannam@148 240 }
cannam@139 241
cannam@142 242 // FIXME ? Bin names may vary based on plugin setup, so including them here might be misleading...
cannam@142 243 if (o.hasFixedBinCount)
cannam@142 244 {
cannam@144 245 res+=" vamp:bin_count "+to_string(o.binCount)+" ;\n";
cannam@144 246 res+=" vamp:bin_names (";
cannam@138 247
cannam@142 248 unsigned int i;
cannam@142 249 for (i=0; i+1 < o.binNames.size(); i++)
cannam@142 250 res+=" \""+o.binNames[i]+"\"";
cannam@142 251 if (i < o.binNames.size())
cannam@142 252 res+=" \""+o.binNames[i]+"\"";
cannam@142 253 res+=");\n";
cannam@142 254 }
cannam@148 255
cannam@144 256 res+=" vamp:sample_type vamp:VariableSampleRate ;\n";
cannam@142 257 if (o.sampleRate > 0.0f)
cannam@144 258 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n";
cannam@142 259
cannam@142 260 }
cannam@139 261
cannam@142 262 //If we do not have SparseOutput, then we have DenseOutput. TrackLevelOutput can not be inferred from the plugin directly without actually
cannam@142 263 //running the plugin.
cannam@142 264 else{
cannam@142 265
cannam@142 266 res=\
cannam@144 267 "plugbase:"+plugin->getIdentifier()+"_output_"+o.identifier+" a vamp:DenseOutput ;\n\
cannam@139 268 vamp:identifier \""+o.identifier+"\" ;\n\
cannam@139 269 dc:title \""+o.name+"\" ;\n\
cannam@139 270 dc:description \""+o.description+"\" ;\n\
cannam@139 271 vamp:fixed_bin_count \""+(o.hasFixedBinCount == 1 ? "true" : "false")+"\" ;\n\
cannam@139 272 vamp:unit \""+(o.unit)+"\" ;\n";
cannam@139 273
cannam@139 274
cannam@148 275 //another type of output
cannam@148 276 if(o.isQuantized){
cannam@148 277
cannam@148 278 res+=" a vamp:QuantizedOutput ;\n";
cannam@148 279 res+=" vamp:quantize_step "+to_string(o.quantizeStep)+" ;\n";
cannam@148 280 }
cannam@148 281
cannam@148 282 //and yet another type
cannam@148 283 if(o.hasKnownExtents){
cannam@148 284
cannam@148 285 res+=" a vamp:KnownExtentsOutput ;\n";
cannam@148 286 res+=" vamp:min_value "+to_string(o.minValue)+" ;\n";
cannam@148 287 res+=" vamp:max_value "+to_string(o.maxValue)+" ;\n";
cannam@148 288 }
cannam@139 289
cannam@142 290 // FIXME ? Bin names may vary based on plugin setup, so including them here might be misleading...
cannam@142 291 if (o.hasFixedBinCount)
cannam@142 292 {
cannam@144 293 res+=" vamp:bin_count "+to_string(o.binCount)+" ;\n";
cannam@144 294 res+=" vamp:bin_names (";
cannam@139 295
cannam@142 296 unsigned int i;
cannam@142 297 for (i=0; i+1 < o.binNames.size(); i++)
cannam@142 298 res+=" \""+o.binNames[i]+"\"";
cannam@142 299 if (i < o.binNames.size())
cannam@142 300 res+=" \""+o.binNames[i]+"\"";
cannam@142 301 res+=");\n";
cannam@139 302 }
cannam@139 303
cannam@142 304 else if (o.sampleType == Plugin::OutputDescriptor::FixedSampleRate)
cannam@142 305 {
cannam@144 306 res+=" vamp:sample_type vamp:FixedSampleRate ;\n";
cannam@144 307 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n";
cannam@142 308 }
cannam@142 309 else if (o.sampleType == Plugin::OutputDescriptor::OneSamplePerStep)
cannam@144 310 res+=" vamp:sample_type vamp:OneSamplePerStep ;\n";
cannam@142 311 else
cannam@142 312 {
cannam@142 313 cerr<<"Incomprehensible sampleType for output descriptor "+o.identifier<<" !"<<endl;
cannam@142 314 exit(1);
cannam@142 315 }
cannam@142 316 }
cannam@142 317
cannam@142 318 //There is no way to know this in advance, but we can use the km a bit for this.
cannam@159 319 res+="# vamp:computes_event_type <Place event type URI here and uncomment> ;\n";
cannam@159 320 res+="# vamp:computes_feature <Place feature attribute URI here and uncomment> ;\n";
cannam@159 321 res+="# vamp:computes_signal_type <Place signal type URI here and uncomment> ;\n";
cannam@142 322 res+=" .\n";
cannam@142 323
cannam@142 324 return res;
cannam@138 325 }
cannam@139 326
cannam@144 327 string describe(vector<Plugin *> plugins, string pluginBundleBaseURI,
cannam@144 328 string describerURI, string libname)
cannam@138 329 {
cannam@144 330 string res = describe_namespaces(pluginBundleBaseURI, libname);
cannam@138 331
cannam@144 332 res += describe_doc(describerURI, pluginBundleBaseURI, libname);
cannam@138 333
cannam@144 334 res += describe_library(libname, plugins);
cannam@144 335
cannam@144 336 for (size_t i = 0; i < plugins.size(); ++i) {
cannam@144 337
cannam@144 338 Plugin *plugin = plugins[i];
cannam@144 339
cannam@144 340 res += describe_plugin(plugin);
cannam@138 341
cannam@144 342 Plugin::ParameterList params = plugin->getParameterDescriptors();
cannam@144 343 for (Plugin::ParameterList::const_iterator i = params.begin(); i != params.end(); i++)
cannam@144 344 res += describe_param(plugin, *i);
cannam@138 345
cannam@144 346 Plugin::OutputList outputs = plugin->getOutputDescriptors();
cannam@144 347 for (Plugin::OutputList::const_iterator i = outputs.begin(); i!= outputs.end(); i++)
cannam@144 348 res += describe_output(plugin, *i);
cannam@144 349 }
cannam@138 350
cannam@142 351 return res;
cannam@138 352 }
cannam@138 353
cannam@138 354 int main(int argc, char **argv)
cannam@138 355 {
cannam@144 356 if (argc < 3) usage();
cannam@138 357
cannam@144 358 bool interactive = false;
cannam@144 359 if (!strcmp(argv[1], "-i")) interactive = true;
cannam@138 360
cannam@217 361 if (!interactive && argc < 3) usage();
cannam@138 362
cannam@138 363 string pluginBundleBaseURI, describerURI;
cannam@144 364
cannam@144 365 int argidx = 2;
cannam@138 366
cannam@144 367 if (!interactive) {
cannam@138 368 pluginBundleBaseURI = argv[1];
cannam@217 369 if (!strcmp(argv[2], "-m")) {
cannam@217 370 if (argc < 5) usage();
cannam@217 371 describerURI = argv[3];
cannam@217 372 argidx = 4;
cannam@217 373 }
cannam@144 374 } else {
cannam@138 375 cerr << "Please enter the base URI for the plugin bundle : ";
cannam@138 376 getline(cin, pluginBundleBaseURI);
cannam@217 377 cerr << "Please enter your URI (empty to omit) : ";
cannam@138 378 getline(cin, describerURI);
cannam@138 379 }
cannam@144 380
cannam@144 381 vector<Plugin *> plugins;
cannam@144 382 string libname;
cannam@144 383
cannam@144 384 PluginLoader *loader = PluginLoader::getInstance();
cannam@144 385
cannam@144 386 while (argidx < argc) {
cannam@144 387
cannam@144 388 string pluginName = argv[argidx];
cannam@144 389
cannam@144 390 if (pluginName.substr(0, 5) == "vamp:") {
cannam@144 391 pluginName = pluginName.substr(5);
cannam@144 392 }
cannam@144 393
cannam@144 394 string mylibname = pluginName.substr(0, pluginName.find(':'));
cannam@144 395
cannam@144 396 if (libname == "") libname = mylibname;
cannam@144 397 else if (libname != mylibname) {
cannam@144 398 cerr << "ERROR: All plugins specified on command line must originate in the same library" << endl;
cannam@144 399 exit(1);
cannam@144 400 }
cannam@144 401
cannam@144 402 if (mylibname == pluginName) { // pluginName is a library, not a plugin
cannam@144 403
cannam@144 404 PluginLoader::PluginKeyList list = loader->listPlugins();
cannam@144 405 for (size_t i = 0; i < list.size(); ++i) {
cannam@144 406 string thislibname = list[i].substr(0, list[i].find(':'));
cannam@144 407 if (thislibname != mylibname) continue;
cannam@144 408 Plugin *plugin = loader->loadPlugin(list[i], 44100);
cannam@144 409 if (!plugin) {
cannam@144 410 cerr << "ERROR: Plugin \"" << list[i] << "\" could not be loaded" << endl;
cannam@144 411 exit(1);
cannam@144 412 }
cannam@144 413 plugins.push_back(plugin);
cannam@144 414 }
cannam@151 415
cannam@151 416 if (plugins.empty()) {
cannam@151 417 cerr << "ERROR: Plugin library \"" << mylibname << "\" does not exist, could not be opened, or contains no plugins" << endl;
cannam@151 418 exit(1);
cannam@151 419 }
cannam@151 420
cannam@144 421 } else { // pluginName is a plugin
cannam@144 422
cannam@144 423 Plugin *plugin = loader->loadPlugin(pluginName, size_t(44100));
cannam@144 424 if (!plugin) {
cannam@144 425 cerr << "ERROR: Plugin \"" << pluginName << "\" could not be loaded" << endl;
cannam@144 426 exit(1);
cannam@144 427 }
cannam@144 428 plugins.push_back(plugin);
cannam@144 429 }
cannam@144 430
cannam@144 431 ++argidx;
cannam@144 432 }
cannam@138 433
cannam@144 434 cout << describe(plugins, pluginBundleBaseURI, describerURI, libname) << endl;
cannam@138 435
cannam@138 436 return 0;
cannam@138 437 }
cannam@138 438
cannam@138 439