annotate rdf/generator/template-generator.cpp @ 152:3ec175bf5249

* fix typos, add a remark about descriptor naming
author cannam
date Tue, 24 Jun 2008 15:38:28 +0000
parents 58f4d399a85d
children d7dcc37161e6
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@138 97 foaf:maker [ foaf:name \""+plugin->getMaker()+"\"] ; # FIXME could give plugin author's URI here\n\
cannam@138 98 cc:license <FIXME license for the plugin> ; \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++)
cannam@144 110 res+=" vamp:parameter_descriptor 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@144 115 res+=" vamp:output_descriptor 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???
cannam@148 125 if(p.isQuantized){
cannam@148 126 string res=\
cannam@148 127 "plugbase:"+plugin->getIdentifier()+"_param_"+p.identifier+" a vamp:QuantizedParameterDescriptor ;\n\
cannam@148 128 vamp:identifier \""+p.identifier+"\" ;\n\
cannam@148 129 dc:title \""+p.name+"\" ;\n\
cannam@148 130 dc:format \""+p.unit+"\" ;\n\
cannam@148 131 vamp:min_value "+to_string(p.minValue)+" ;\n\
cannam@148 132 vamp:max_value "+to_string(p.maxValue)+" ;\n\
cannam@148 133 vamp:unit \""+p.unit+"\" ;\n\
cannam@152 134 vamp:quantize_step "+to_string(p.quantizeStep)+" ;\n\
cannam@148 135 vamp:default_value "+to_string(p.defaultValue)+" ;\n\
cannam@148 136 vamp:value_names (";
cannam@148 137
cannam@148 138 unsigned int i;
cannam@148 139 for (i=0; i+1 < p.valueNames.size(); i++)
cannam@148 140 res+=" \""+p.valueNames[i]+"\"";
cannam@148 141 if (i < p.valueNames.size())
cannam@148 142 res+=" \""+p.valueNames[i]+"\"";
cannam@148 143 res+=");\n";
cannam@148 144
cannam@148 145 res+=" .\n";
cannam@148 146
cannam@148 147 return res;
cannam@148 148
cannam@148 149 }else{
cannam@142 150 string res=\
cannam@144 151 "plugbase:"+plugin->getIdentifier()+"_param_"+p.identifier+" a vamp:ParameterDescriptor ;\n\
cannam@138 152 vamp:identifier \""+p.identifier+"\" ;\n\
cannam@138 153 dc:title \""+p.name+"\" ;\n\
cannam@138 154 dc:format \""+p.unit+"\" ;\n\
cannam@139 155 vamp:min_value "+to_string(p.minValue)+" ;\n\
cannam@139 156 vamp:max_value "+to_string(p.maxValue)+" ;\n\
cannam@148 157 vamp:unit \""+p.unit+"\" ;\n\
cannam@148 158 vamp:default_value "+to_string(p.defaultValue)+" ;\n\
cannam@148 159 vamp:value_names (";
cannam@148 160
cannam@148 161 unsigned int i;
cannam@148 162 for (i=0; i+1 < p.valueNames.size(); i++)
cannam@148 163 res+=" \""+p.valueNames[i]+"\"";
cannam@148 164 if (i < p.valueNames.size())
cannam@148 165 res+=" \""+p.valueNames[i]+"\"";
cannam@148 166 res+=");\n";
cannam@148 167
cannam@148 168 res+=" .\n";
cannam@148 169
cannam@142 170 return res;
cannam@148 171
cannam@148 172 }
cannam@138 173 }
cannam@138 174
cannam@144 175 string describe_output(Plugin *plugin, Plugin::OutputDescriptor o)
cannam@138 176 {
cannam@138 177
cannam@142 178 //we need to distinguish here between different output types:
cannam@148 179
cannam@148 180 //Quantize or not
cannam@148 181 //KnownExtents or not
cannam@148 182 //Data output classification:
cannam@142 183 //DenseOutput
cannam@142 184 //SparseOutput
cannam@142 185 //TrackLevelOutput
cannam@139 186
cannam@139 187
cannam@142 188 //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 189
cannam@142 190 string res;
cannam@139 191
cannam@142 192 if (o.sampleType == Plugin::OutputDescriptor::VariableSampleRate)
cannam@142 193 {
cannam@139 194
cannam@142 195 res=\
cannam@144 196 "plugbase:"+plugin->getIdentifier()+"_output_"+o.identifier+" a vamp:SparseOutput ;\n\
cannam@139 197 vamp:identifier \""+o.identifier+"\" ;\n\
cannam@139 198 dc:title \""+o.name+"\" ;\n\
cannam@139 199 dc:description \""+o.description+"\" ;\n\
cannam@139 200 vamp:fixed_bin_count \""+(o.hasFixedBinCount == 1 ? "true" : "false")+"\" ;\n\
cannam@139 201 vamp:unit \""+(o.unit)+"\" ;\n";
cannam@139 202
cannam@148 203
cannam@148 204 //another type of output
cannam@148 205 if(o.isQuantized){
cannam@148 206
cannam@148 207 res+=" a vamp:QuantizedOutput ;\n";
cannam@148 208 res+=" vamp:quantize_step "+to_string(o.quantizeStep)+" ;\n";
cannam@148 209 }
cannam@148 210
cannam@148 211 //and yet another type
cannam@148 212 if(o.hasKnownExtents){
cannam@148 213
cannam@148 214 res+=" a vamp:KnownExtentsOutput ;\n";
cannam@148 215 res+=" vamp:min_value "+to_string(o.minValue)+" ;\n";
cannam@148 216 res+=" vamp:max_value "+to_string(o.maxValue)+" ;\n";
cannam@148 217 }
cannam@139 218
cannam@142 219 // FIXME ? Bin names may vary based on plugin setup, so including them here might be misleading...
cannam@142 220 if (o.hasFixedBinCount)
cannam@142 221 {
cannam@144 222 res+=" vamp:bin_count "+to_string(o.binCount)+" ;\n";
cannam@144 223 res+=" vamp:bin_names (";
cannam@138 224
cannam@142 225 unsigned int i;
cannam@142 226 for (i=0; i+1 < o.binNames.size(); i++)
cannam@142 227 res+=" \""+o.binNames[i]+"\"";
cannam@142 228 if (i < o.binNames.size())
cannam@142 229 res+=" \""+o.binNames[i]+"\"";
cannam@142 230 res+=");\n";
cannam@142 231 }
cannam@148 232
cannam@144 233 res+=" vamp:sample_type vamp:VariableSampleRate ;\n";
cannam@142 234 if (o.sampleRate > 0.0f)
cannam@144 235 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n";
cannam@142 236
cannam@142 237 }
cannam@139 238
cannam@142 239 //If we do not have SparseOutput, then we have DenseOutput. TrackLevelOutput can not be inferred from the plugin directly without actually
cannam@142 240 //running the plugin.
cannam@142 241 else{
cannam@142 242
cannam@142 243 res=\
cannam@144 244 "plugbase:"+plugin->getIdentifier()+"_output_"+o.identifier+" a vamp:DenseOutput ;\n\
cannam@139 245 vamp:identifier \""+o.identifier+"\" ;\n\
cannam@139 246 dc:title \""+o.name+"\" ;\n\
cannam@139 247 dc:description \""+o.description+"\" ;\n\
cannam@139 248 vamp:fixed_bin_count \""+(o.hasFixedBinCount == 1 ? "true" : "false")+"\" ;\n\
cannam@139 249 vamp:unit \""+(o.unit)+"\" ;\n";
cannam@139 250
cannam@139 251
cannam@148 252 //another type of output
cannam@148 253 if(o.isQuantized){
cannam@148 254
cannam@148 255 res+=" a vamp:QuantizedOutput ;\n";
cannam@148 256 res+=" vamp:quantize_step "+to_string(o.quantizeStep)+" ;\n";
cannam@148 257 }
cannam@148 258
cannam@148 259 //and yet another type
cannam@148 260 if(o.hasKnownExtents){
cannam@148 261
cannam@148 262 res+=" a vamp:KnownExtentsOutput ;\n";
cannam@148 263 res+=" vamp:min_value "+to_string(o.minValue)+" ;\n";
cannam@148 264 res+=" vamp:max_value "+to_string(o.maxValue)+" ;\n";
cannam@148 265 }
cannam@139 266
cannam@142 267 // FIXME ? Bin names may vary based on plugin setup, so including them here might be misleading...
cannam@142 268 if (o.hasFixedBinCount)
cannam@142 269 {
cannam@144 270 res+=" vamp:bin_count "+to_string(o.binCount)+" ;\n";
cannam@144 271 res+=" vamp:bin_names (";
cannam@139 272
cannam@142 273 unsigned int i;
cannam@142 274 for (i=0; i+1 < o.binNames.size(); i++)
cannam@142 275 res+=" \""+o.binNames[i]+"\"";
cannam@142 276 if (i < o.binNames.size())
cannam@142 277 res+=" \""+o.binNames[i]+"\"";
cannam@142 278 res+=");\n";
cannam@139 279 }
cannam@139 280
cannam@142 281 else if (o.sampleType == Plugin::OutputDescriptor::FixedSampleRate)
cannam@142 282 {
cannam@144 283 res+=" vamp:sample_type vamp:FixedSampleRate ;\n";
cannam@144 284 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n";
cannam@142 285 }
cannam@142 286 else if (o.sampleType == Plugin::OutputDescriptor::OneSamplePerStep)
cannam@144 287 res+=" vamp:sample_type vamp:OneSamplePerStep ;\n";
cannam@142 288 else
cannam@142 289 {
cannam@142 290 cerr<<"Incomprehensible sampleType for output descriptor "+o.identifier<<" !"<<endl;
cannam@142 291 exit(1);
cannam@142 292 }
cannam@142 293 }
cannam@142 294
cannam@142 295 //There is no way to know this in advance, but we can use the km a bit for this.
cannam@142 296 res+=" vamp:computes_feature_type <FIXME feature type URI> ;\n";
cannam@142 297 res+=" vamp:computes_event_type <FIXME event type URI> ;\n";
cannam@142 298 res+=" .\n";
cannam@142 299
cannam@142 300 return res;
cannam@138 301 }
cannam@139 302
cannam@144 303 string describe(vector<Plugin *> plugins, string pluginBundleBaseURI,
cannam@144 304 string describerURI, string libname)
cannam@138 305 {
cannam@144 306 string res = describe_namespaces(pluginBundleBaseURI, libname);
cannam@138 307
cannam@144 308 res += describe_doc(describerURI, pluginBundleBaseURI, libname);
cannam@138 309
cannam@144 310 res += describe_library(libname, plugins);
cannam@144 311
cannam@144 312 for (size_t i = 0; i < plugins.size(); ++i) {
cannam@144 313
cannam@144 314 Plugin *plugin = plugins[i];
cannam@144 315
cannam@144 316 res += describe_plugin(plugin);
cannam@138 317
cannam@144 318 Plugin::ParameterList params = plugin->getParameterDescriptors();
cannam@144 319 for (Plugin::ParameterList::const_iterator i = params.begin(); i != params.end(); i++)
cannam@144 320 res += describe_param(plugin, *i);
cannam@138 321
cannam@144 322 Plugin::OutputList outputs = plugin->getOutputDescriptors();
cannam@144 323 for (Plugin::OutputList::const_iterator i = outputs.begin(); i!= outputs.end(); i++)
cannam@144 324 res += describe_output(plugin, *i);
cannam@144 325 }
cannam@138 326
cannam@142 327 return res;
cannam@138 328 }
cannam@138 329
cannam@138 330 int main(int argc, char **argv)
cannam@138 331 {
cannam@144 332 if (argc < 3) usage();
cannam@138 333
cannam@144 334 bool interactive = false;
cannam@144 335 if (!strcmp(argv[1], "-i")) interactive = true;
cannam@138 336
cannam@144 337 if (!interactive && argc < 4) usage();
cannam@138 338
cannam@138 339 string pluginBundleBaseURI, describerURI;
cannam@144 340
cannam@144 341 int argidx = 2;
cannam@138 342
cannam@144 343 if (!interactive) {
cannam@138 344 pluginBundleBaseURI = argv[1];
cannam@138 345 describerURI = argv[2];
cannam@144 346 argidx = 3;
cannam@144 347 } else {
cannam@138 348 cerr << "Please enter the base URI for the plugin bundle : ";
cannam@138 349 getline(cin, pluginBundleBaseURI);
cannam@138 350 cerr << "Please enter your URI : ";
cannam@138 351 getline(cin, describerURI);
cannam@138 352 }
cannam@144 353
cannam@144 354 vector<Plugin *> plugins;
cannam@144 355 string libname;
cannam@144 356
cannam@144 357 PluginLoader *loader = PluginLoader::getInstance();
cannam@144 358
cannam@144 359 while (argidx < argc) {
cannam@144 360
cannam@144 361 string pluginName = argv[argidx];
cannam@144 362
cannam@144 363 if (pluginName.substr(0, 5) == "vamp:") {
cannam@144 364 pluginName = pluginName.substr(5);
cannam@144 365 }
cannam@144 366
cannam@144 367 string mylibname = pluginName.substr(0, pluginName.find(':'));
cannam@144 368
cannam@144 369 if (libname == "") libname = mylibname;
cannam@144 370 else if (libname != mylibname) {
cannam@144 371 cerr << "ERROR: All plugins specified on command line must originate in the same library" << endl;
cannam@144 372 exit(1);
cannam@144 373 }
cannam@144 374
cannam@144 375 if (mylibname == pluginName) { // pluginName is a library, not a plugin
cannam@144 376
cannam@144 377 PluginLoader::PluginKeyList list = loader->listPlugins();
cannam@144 378 for (size_t i = 0; i < list.size(); ++i) {
cannam@144 379 string thislibname = list[i].substr(0, list[i].find(':'));
cannam@144 380 if (thislibname != mylibname) continue;
cannam@144 381 Plugin *plugin = loader->loadPlugin(list[i], 44100);
cannam@144 382 if (!plugin) {
cannam@144 383 cerr << "ERROR: Plugin \"" << list[i] << "\" could not be loaded" << endl;
cannam@144 384 exit(1);
cannam@144 385 }
cannam@144 386 plugins.push_back(plugin);
cannam@144 387 }
cannam@151 388
cannam@151 389 if (plugins.empty()) {
cannam@151 390 cerr << "ERROR: Plugin library \"" << mylibname << "\" does not exist, could not be opened, or contains no plugins" << endl;
cannam@151 391 exit(1);
cannam@151 392 }
cannam@151 393
cannam@144 394 } else { // pluginName is a plugin
cannam@144 395
cannam@144 396 Plugin *plugin = loader->loadPlugin(pluginName, size_t(44100));
cannam@144 397 if (!plugin) {
cannam@144 398 cerr << "ERROR: Plugin \"" << pluginName << "\" could not be loaded" << endl;
cannam@144 399 exit(1);
cannam@144 400 }
cannam@144 401 plugins.push_back(plugin);
cannam@144 402 }
cannam@144 403
cannam@144 404 ++argidx;
cannam@144 405 }
cannam@138 406
cannam@144 407 cout << describe(plugins, pluginBundleBaseURI, describerURI, libname) << endl;
cannam@138 408
cannam@138 409 return 0;
cannam@138 410 }
cannam@138 411
cannam@138 412