annotate rdf/generator/template-generator.cpp @ 140:a6cfe3d9f752

* Load plugins with RTLD_GLOBAL -- otherwise Vampy plugins will be unable to load additional modules (for some reason I don't fully understand)
author cannam
date Thu, 19 Jun 2008 15:12:41 +0000
parents bb46b8bd213a
children 8e3a5f779d89
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 /*
cannam@138 30
cannam@138 31 usage:
cannam@138 32
cannam@138 33 template-generator vamp:aubioonset:onsets
cannam@138 34
cannam@138 35 */
cannam@138 36
cannam@138 37 string programURI = "http://www.vamp-plugins.org/doap.rdf#template-generator";
cannam@138 38
cannam@138 39 void usage()
cannam@138 40 {
cannam@138 41 cerr << "usage: template-generator [PLUGIN_BASE_URI YOUR_URI] vamp:soname:plugin[:output]" << endl;
cannam@138 42 exit(2);
cannam@138 43 }
cannam@138 44
cannam@138 45 template <class T>
cannam@138 46 inline string to_string (const T& t)
cannam@138 47 {
cannam@138 48 std::stringstream ss;
cannam@138 49 ss << t;
cannam@138 50 return ss.str();
cannam@138 51 }
cannam@138 52
cannam@138 53 string describe_namespaces(Plugin* plugin, string pluginBundleBaseURI)
cannam@138 54 {
cannam@138 55 string res=\
cannam@138 56 "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\
cannam@138 57 @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n\
cannam@139 58 @prefix vamp: <http://www.purl.org/ontology/vamp/> .\n\
cannam@139 59 @prefix vampex: <http://www.purl.org/ontology/vamp/examples/> .\n\
cannam@138 60 @prefix plugbase: <"+pluginBundleBaseURI+"> .\n\
cannam@138 61 @prefix owl: <http://www.w3.org/2002/07/owl#> .\n\
cannam@138 62 @prefix dc: <http://purl.org/dc/elements/1.1/> .\n\
cannam@138 63 @prefix af: <http://purl.org/ontology/af/> .\n\
cannam@138 64 @prefix foaf: <http://xmlns.com/foaf/0.1/> .\n\
cannam@138 65 @prefix cc: <http://web.resource.org/cc/> .\n\
cannam@138 66 @prefix thisplug: <"+pluginBundleBaseURI+plugin->getIdentifier()+"#> .\n\
cannam@138 67 @prefix : <> .\n\n";
cannam@138 68
cannam@138 69 return res;
cannam@138 70 }
cannam@138 71
cannam@138 72 string describe_doc(Plugin* plugin, string describerURI)
cannam@138 73 {
cannam@138 74 string res=\
cannam@138 75 "<> a vamp:PluginDescription ;\n\
cannam@138 76 foaf:maker <"+describerURI+"> ;\n\
cannam@138 77 foaf:maker <"+programURI+"> ;\n\
cannam@138 78 foaf:primaryTopic plugbase:"+plugin->getIdentifier()+" .\n\n";
cannam@138 79 return res;
cannam@138 80 }
cannam@138 81
cannam@138 82
cannam@138 83 string describe_plugin(Plugin* plugin)
cannam@138 84 {
cannam@138 85 string res=\
cannam@138 86 "plugbase:"+plugin->getIdentifier()+" a vamp:Plugin ;\n\
cannam@138 87 dc:title \""+plugin->getName()+"\" ;\n\
cannam@139 88 vamp:name \""+plugin->getName()+"\" ;\n\
cannam@138 89 dc:description \""+plugin->getDescription()+"\" ;\n\
cannam@138 90 foaf:maker [ foaf:name \""+plugin->getMaker()+"\"] ; # FIXME could give plugin author's URI here\n\
cannam@138 91 cc:license <FIXME license for the plugin> ; \n\
cannam@138 92 vamp:identifier \""+plugin->getIdentifier()+"\" ;\n\
cannam@138 93 vamp:vamp_API_version vamp:api_version_"+to_string(plugin->getVampApiVersion())+" ;\n\
cannam@138 94 owl:versionInfo \""+to_string(plugin->getPluginVersion())+"\" ;\n";
cannam@138 95 if (plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain)
cannam@138 96 res+=" vamp:input_domain vamp:FrequencyDomain ;\n\n";
cannam@138 97 else
cannam@138 98 res+=" vamp:input_domain vamp:TimeDomain ;\n\n";
cannam@138 99
cannam@138 100
cannam@138 101 Plugin::ParameterList params = plugin->getParameterDescriptors();
cannam@138 102 for (Plugin::ParameterList::const_iterator i = params.begin(); i != params.end(); i++)
cannam@138 103 res+=" vamp:parameter_descriptor thisplug:param_"+(*i).identifier+" ;\n";
cannam@138 104 res+="\n";
cannam@138 105
cannam@138 106 Plugin::OutputList outputs = plugin->getOutputDescriptors();
cannam@138 107 for (Plugin::OutputList::const_iterator i = outputs.begin(); i!= outputs.end(); i++)
cannam@138 108 res+=" vamp:output_descriptor thisplug:output_"+(*i).identifier+" ;\n";
cannam@138 109 res+=" .\n";
cannam@138 110
cannam@138 111 return res;
cannam@138 112 }
cannam@138 113
cannam@138 114 string describe_param(Plugin::ParameterDescriptor p)
cannam@138 115 {
cannam@138 116 string res=\
cannam@138 117 "thisplug:param_"+p.identifier+" a vamp:ParameterDescriptor ;\n\
cannam@138 118 vamp:identifier \""+p.identifier+"\" ;\n\
cannam@138 119 dc:title \""+p.name+"\" ;\n\
cannam@138 120 dc:format \""+p.unit+"\" ;\n\
cannam@139 121 vamp:min_value "+to_string(p.minValue)+" ;\n\
cannam@139 122 vamp:max_value "+to_string(p.maxValue)+" ;\n\
cannam@139 123 vamp:default_value "+to_string(p.defaultValue)+" .\n\n";
cannam@138 124 return res;
cannam@138 125 }
cannam@138 126
cannam@138 127 string describe_output(Plugin::OutputDescriptor o)
cannam@138 128 {
cannam@138 129
cannam@139 130 //we need to distinguish here between different output types:
cannam@139 131 //DenseOutput
cannam@139 132 //SparseOutput
cannam@139 133 //TrackLevelOutput
cannam@139 134
cannam@139 135
cannam@139 136 //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 137
cannam@139 138 string res;
cannam@139 139
cannam@139 140 if (o.sampleType == Plugin::OutputDescriptor::VariableSampleRate)
cannam@138 141 {
cannam@139 142
cannam@139 143 res=\
cannam@139 144 "thisplug:output_"+o.identifier+" a vamp:SparseOutput ;\n\
cannam@139 145 vamp:identifier \""+o.identifier+"\" ;\n\
cannam@139 146 dc:title \""+o.name+"\" ;\n\
cannam@139 147 dc:description \""+o.description+"\" ;\n\
cannam@139 148 vamp:fixed_bin_count \""+(o.hasFixedBinCount == 1 ? "true" : "false")+"\" ;\n\
cannam@139 149 vamp:is_quantized \""+(o.isQuantized == 1 ? "true" : "false")+"\" ;\n\
cannam@139 150 vamp:unit \""+(o.unit)+"\" ;\n";
cannam@139 151
cannam@139 152
cannam@139 153
cannam@139 154 // FIXME ? Bin names may vary based on plugin setup, so including them here might be misleading...
cannam@139 155 if (o.hasFixedBinCount)
cannam@139 156 {
cannam@139 157 res+=" vamp:bin_count "+to_string(o.binCount)+" ;\n";
cannam@139 158 res+=" vamp:bin_names (";
cannam@138 159
cannam@138 160 unsigned int i;
cannam@138 161 for (i=0; i+1 < o.binNames.size(); i++)
cannam@138 162 res+=" \""+o.binNames[i]+"\"";
cannam@138 163 if (i < o.binNames.size())
cannam@138 164 res+=" \""+o.binNames[i]+"\"";
cannam@138 165 res+=");\n";
cannam@139 166 }
cannam@139 167
cannam@139 168 if (o.isQuantized)
cannam@139 169 {
cannam@139 170 res+=" vamp:quantize_step "+to_string(o.quantizeStep)+" ;\n";
cannam@139 171 }
cannam@139 172
cannam@139 173 res+=" vamp:sample_type vamp:VariableSampleRate ;\n";
cannam@138 174 if (o.sampleRate > 0.0f)
cannam@138 175 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n";
cannam@139 176
cannam@139 177 }
cannam@138 178
cannam@139 179 //If we do not have SparseOutput, then we have DenseOutput. TrackLevelOutput can not be inferred from the plugin directly without actually
cannam@139 180 //running the plugin.
cannam@139 181 else{
cannam@139 182
cannam@139 183 res=\
cannam@139 184 "thisplug:output_"+o.identifier+" a vamp:DenseOutput ;\n\
cannam@139 185 vamp:identifier \""+o.identifier+"\" ;\n\
cannam@139 186 dc:title \""+o.name+"\" ;\n\
cannam@139 187 dc:description \""+o.description+"\" ;\n\
cannam@139 188 vamp:fixed_bin_count \""+(o.hasFixedBinCount == 1 ? "true" : "false")+"\" ;\n\
cannam@139 189 vamp:is_quantised \""+(o.isQuantized == 1 ? "true" : "false")+"\" ;\n\
cannam@139 190 vamp:unit \""+(o.unit)+"\" ;\n";
cannam@139 191
cannam@139 192
cannam@139 193
cannam@139 194 // FIXME ? Bin names may vary based on plugin setup, so including them here might be misleading...
cannam@139 195 if (o.hasFixedBinCount)
cannam@139 196 {
cannam@139 197 res+=" vamp:bin_count "+to_string(o.binCount)+" ;\n";
cannam@139 198 res+=" vamp:bin_names (";
cannam@139 199
cannam@139 200 unsigned int i;
cannam@139 201 for (i=0; i+1 < o.binNames.size(); i++)
cannam@139 202 res+=" \""+o.binNames[i]+"\"";
cannam@139 203 if (i < o.binNames.size())
cannam@139 204 res+=" \""+o.binNames[i]+"\"";
cannam@139 205 res+=");\n";
cannam@139 206 }
cannam@139 207
cannam@139 208 if (o.isQuantized)
cannam@139 209 {
cannam@139 210 res+=" vamp:quantize_step "+to_string(o.quantizeStep)+" ;\n";
cannam@139 211 }
cannam@139 212
cannam@139 213
cannam@139 214 else if (o.sampleType == Plugin::OutputDescriptor::FixedSampleRate)
cannam@139 215 {
cannam@139 216 res+=" vamp:sample_type vamp:FixedSampleRate ;\n";
cannam@139 217 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n";
cannam@139 218 }
cannam@139 219 else if (o.sampleType == Plugin::OutputDescriptor::OneSamplePerStep)
cannam@139 220 res+=" vamp:sample_type vamp:OneSamplePerStep ;\n";
cannam@139 221 else
cannam@139 222 {
cannam@139 223 cerr<<"Incomprehensible sampleType for output descriptor "+o.identifier<<" !"<<endl;
cannam@139 224 exit(1);
cannam@139 225 }
cannam@139 226 }
cannam@139 227
cannam@139 228 //There is no way to know this in advance, but we can use the km a bit for this.
cannam@138 229 res+=" vamp:computes_feature_type <FIXME feature type URI> ;\n";
cannam@138 230 res+=" vamp:computes_event_type <FIXME event type URI> ;\n";
cannam@138 231 res+=" .\n";
cannam@138 232
cannam@138 233 return res;
cannam@138 234 }
cannam@139 235
cannam@138 236 string describe(Plugin* plugin, string pluginBundleBaseURI, string describerURI)
cannam@138 237 {
cannam@138 238 string res = describe_namespaces(plugin, pluginBundleBaseURI);
cannam@138 239
cannam@138 240 res += describe_doc(plugin, describerURI);
cannam@138 241
cannam@138 242 res += describe_plugin(plugin);
cannam@138 243
cannam@138 244 Plugin::ParameterList params = plugin->getParameterDescriptors();
cannam@138 245 for (Plugin::ParameterList::const_iterator i = params.begin(); i != params.end(); i++)
cannam@138 246 res += describe_param(*i);
cannam@138 247
cannam@138 248 Plugin::OutputList outputs = plugin->getOutputDescriptors();
cannam@138 249 for (Plugin::OutputList::const_iterator i = outputs.begin(); i!= outputs.end(); i++)
cannam@138 250 res += describe_output(*i);
cannam@138 251
cannam@138 252 return res;
cannam@138 253 }
cannam@138 254
cannam@138 255 int main(int argc, char **argv)
cannam@138 256 {
cannam@138 257 if (argc != 2 && argc != 4) usage();
cannam@138 258
cannam@138 259 std::string pluginName = argv[argc-1];
cannam@138 260
cannam@138 261 if (pluginName.substr(0, 5) == "vamp:") {
cannam@138 262 pluginName = pluginName.substr(5);
cannam@138 263 }
cannam@138 264
cannam@138 265 Vamp::Plugin *plugin = PluginLoader::getInstance()->loadPlugin
cannam@138 266 (pluginName, size_t(44100), PluginLoader::ADAPT_ALL_SAFE);
cannam@138 267
cannam@138 268 if (!plugin) {
cannam@138 269 cerr << "ERROR: Plugin \"" << pluginName << "\" could not be loaded" << endl;
cannam@138 270 exit(1);
cannam@138 271 }
cannam@138 272
cannam@138 273 string pluginBundleBaseURI, describerURI;
cannam@138 274
cannam@138 275 if (argc == 4)
cannam@138 276 {
cannam@138 277 pluginBundleBaseURI = argv[1];
cannam@138 278 describerURI = argv[2];
cannam@138 279 }
cannam@138 280 else
cannam@138 281 {
cannam@138 282 cerr << "Please enter the base URI for the plugin bundle : ";
cannam@138 283 getline(cin, pluginBundleBaseURI);
cannam@138 284 cerr << "Please enter your URI : ";
cannam@138 285 getline(cin, describerURI);
cannam@138 286 }
cannam@138 287
cannam@138 288 cout << describe(plugin, pluginBundleBaseURI, describerURI) << endl;
cannam@138 289
cannam@138 290 return 0;
cannam@138 291 }
cannam@138 292
cannam@138 293