annotate rdf/generator/template-generator.cpp @ 211:caa9d07bb9bd

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