comparison rdf/generator/vamp-rdf-template-generator.cpp @ 250:a8c8fe602eec

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