annotate rdf/generator/template-generator.cpp @ 159:64709b340651

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