Mercurial > hg > sv-dependency-builds
comparison src/vamp-plugin-sdk-2.5/rdf/generator/vamp-rdf-template-generator.cpp @ 108:1813f30f2f15
Update Vamp plugin SDK to 2.5
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Thu, 09 May 2013 10:52:46 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
107:71c914cf6201 | 108:1813f30f2f15 |
---|---|
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 << "vamp-rdf-template-generator: Create a skeleton RDF description file describing" << endl; | |
40 cerr << "a Vamp plugin library using the Vamp ontology." << endl; | |
41 cerr << endl; | |
42 cerr << "Usage:" << endl; | |
43 cerr << " vamp-rdf-template-generator -i vamp:soname[:plugin] [vamp:soname[:plugin] ...]" << endl; | |
44 cerr << " vamp-rdf-template-generator PLUGIN_BASE_URI [ -m YOUR_URI ] [vamp:]soname[:plugin] [[vamp:]soname[:plugin] ...]" << endl; | |
45 cerr << endl; | |
46 cerr << "Example:" << endl; | |
47 cerr << " vamp-rdf-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 | |
252 bool haveBinNames = false; | |
253 for (unsigned int i=0; i < o.binNames.size(); i++) { | |
254 if (o.binNames[i] != "") { | |
255 haveBinNames = true; | |
256 break; | |
257 } | |
258 } | |
259 | |
260 if (haveBinNames) { | |
261 res+=" vamp:bin_names ("; | |
262 | |
263 unsigned int i; | |
264 for (i=0; i+1 < o.binNames.size(); i++) | |
265 res+=" \""+o.binNames[i]+"\""; | |
266 if (i < o.binNames.size()) | |
267 res+=" \""+o.binNames[i]+"\""; | |
268 res+=");\n"; | |
269 } | |
270 } | |
271 | |
272 res+=" vamp:sample_type vamp:VariableSampleRate ;\n"; | |
273 if (o.sampleRate > 0.0f) | |
274 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n"; | |
275 | |
276 } | |
277 | |
278 //If we do not have SparseOutput, then we have DenseOutput. TrackLevelOutput can not be inferred from the plugin directly without actually | |
279 //running the plugin. | |
280 else{ | |
281 | |
282 res=\ | |
283 "plugbase:"+plugin->getIdentifier()+"_output_"+o.identifier+" a vamp:DenseOutput ;\n\ | |
284 vamp:identifier \""+o.identifier+"\" ;\n\ | |
285 dc:title \""+o.name+"\" ;\n\ | |
286 dc:description \"\"\""+o.description+"\"\"\" ;\n\ | |
287 vamp:fixed_bin_count \""+(o.hasFixedBinCount == 1 ? "true" : "false")+"\" ;\n\ | |
288 vamp:unit \""+(o.unit)+"\" ;\n"; | |
289 | |
290 | |
291 //another type of output | |
292 if(o.isQuantized){ | |
293 | |
294 res+=" a vamp:QuantizedOutput ;\n"; | |
295 res+=" vamp:quantize_step "+to_string(o.quantizeStep)+" ;\n"; | |
296 } | |
297 | |
298 //and yet another type | |
299 if(o.hasKnownExtents){ | |
300 | |
301 res+=" a vamp:KnownExtentsOutput ;\n"; | |
302 res+=" vamp:min_value "+to_string(o.minValue)+" ;\n"; | |
303 res+=" vamp:max_value "+to_string(o.maxValue)+" ;\n"; | |
304 } | |
305 | |
306 // FIXME ? Bin names may vary based on plugin setup, so including them here might be misleading... | |
307 if (o.hasFixedBinCount) | |
308 { | |
309 res+=" vamp:bin_count "+to_string(o.binCount)+" ;\n"; | |
310 | |
311 bool haveBinNames = false; | |
312 for (unsigned int i=0; i < o.binNames.size(); i++) { | |
313 if (o.binNames[i] != "") { | |
314 haveBinNames = true; | |
315 break; | |
316 } | |
317 } | |
318 | |
319 if (haveBinNames) { | |
320 res+=" vamp:bin_names ("; | |
321 | |
322 unsigned int i; | |
323 for (i=0; i+1 < o.binNames.size(); i++) | |
324 res+=" \""+o.binNames[i]+"\""; | |
325 if (i < o.binNames.size()) | |
326 res+=" \""+o.binNames[i]+"\""; | |
327 res+=");\n"; | |
328 } | |
329 } | |
330 | |
331 else if (o.sampleType == Plugin::OutputDescriptor::FixedSampleRate) | |
332 { | |
333 res+=" vamp:sample_type vamp:FixedSampleRate ;\n"; | |
334 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n"; | |
335 } | |
336 else if (o.sampleType == Plugin::OutputDescriptor::OneSamplePerStep) | |
337 res+=" vamp:sample_type vamp:OneSamplePerStep ;\n"; | |
338 else | |
339 { | |
340 cerr<<"Incomprehensible sampleType for output descriptor "+o.identifier<<" !"<<endl; | |
341 exit(1); | |
342 } | |
343 } | |
344 | |
345 //There is no way to know this in advance, but we can use the km a bit for this. | |
346 res+="# vamp:computes_event_type <Place event type URI here and uncomment> ;\n"; | |
347 res+="# vamp:computes_feature <Place feature attribute URI here and uncomment> ;\n"; | |
348 res+="# vamp:computes_signal_type <Place signal type URI here and uncomment> ;\n"; | |
349 res+=" .\n"; | |
350 | |
351 return res; | |
352 } | |
353 | |
354 string describe(vector<Plugin *> plugins, string pluginBundleBaseURI, | |
355 string describerURI, string libname) | |
356 { | |
357 string res = describe_namespaces(pluginBundleBaseURI, libname); | |
358 | |
359 res += describe_doc(describerURI, pluginBundleBaseURI, libname); | |
360 | |
361 res += describe_library(libname, plugins); | |
362 | |
363 for (size_t i = 0; i < plugins.size(); ++i) { | |
364 | |
365 Plugin *plugin = plugins[i]; | |
366 | |
367 res += describe_plugin(plugin); | |
368 | |
369 Plugin::ParameterList params = plugin->getParameterDescriptors(); | |
370 for (Plugin::ParameterList::const_iterator i = params.begin(); i != params.end(); i++) | |
371 res += describe_param(plugin, *i); | |
372 | |
373 Plugin::OutputList outputs = plugin->getOutputDescriptors(); | |
374 for (Plugin::OutputList::const_iterator i = outputs.begin(); i!= outputs.end(); i++) | |
375 res += describe_output(plugin, *i); | |
376 } | |
377 | |
378 return res; | |
379 } | |
380 | |
381 int main(int argc, char **argv) | |
382 { | |
383 if (argc < 3) usage(); | |
384 | |
385 bool interactive = false; | |
386 if (!strcmp(argv[1], "-i")) interactive = true; | |
387 | |
388 if (!interactive && argc < 3) usage(); | |
389 | |
390 string pluginBundleBaseURI, describerURI; | |
391 | |
392 int argidx = 2; | |
393 | |
394 if (!interactive) { | |
395 pluginBundleBaseURI = argv[1]; | |
396 if (!strcmp(argv[2], "-m")) { | |
397 if (argc < 5) usage(); | |
398 describerURI = argv[3]; | |
399 argidx = 4; | |
400 } | |
401 } else { | |
402 cerr << "Please enter the base URI for the plugin bundle : "; | |
403 getline(cin, pluginBundleBaseURI); | |
404 cerr << "Please enter your URI (empty to omit) : "; | |
405 getline(cin, describerURI); | |
406 } | |
407 | |
408 vector<Plugin *> plugins; | |
409 string libname; | |
410 | |
411 PluginLoader *loader = PluginLoader::getInstance(); | |
412 | |
413 while (argidx < argc) { | |
414 | |
415 string pluginName = argv[argidx]; | |
416 | |
417 if (pluginName.substr(0, 5) == "vamp:") { | |
418 pluginName = pluginName.substr(5); | |
419 } | |
420 | |
421 string mylibname = pluginName.substr(0, pluginName.find(':')); | |
422 | |
423 if (libname == "") libname = mylibname; | |
424 else if (libname != mylibname) { | |
425 cerr << "ERROR: All plugins specified on command line must originate in the same library" << endl; | |
426 exit(1); | |
427 } | |
428 | |
429 if (mylibname == pluginName) { // pluginName is a library, not a plugin | |
430 | |
431 PluginLoader::PluginKeyList list = loader->listPlugins(); | |
432 for (size_t i = 0; i < list.size(); ++i) { | |
433 string thislibname = list[i].substr(0, list[i].find(':')); | |
434 if (thislibname != mylibname) continue; | |
435 Plugin *plugin = loader->loadPlugin(list[i], 44100); | |
436 if (!plugin) { | |
437 cerr << "ERROR: Plugin \"" << list[i] << "\" could not be loaded" << endl; | |
438 exit(1); | |
439 } | |
440 plugins.push_back(plugin); | |
441 } | |
442 | |
443 if (plugins.empty()) { | |
444 cerr << "ERROR: Plugin library \"" << mylibname << "\" does not exist, could not be opened, or contains no plugins" << endl; | |
445 exit(1); | |
446 } | |
447 | |
448 } else { // pluginName is a plugin | |
449 | |
450 Plugin *plugin = loader->loadPlugin(pluginName, size_t(44100)); | |
451 if (!plugin) { | |
452 cerr << "ERROR: Plugin \"" << pluginName << "\" could not be loaded" << endl; | |
453 exit(1); | |
454 } | |
455 plugins.push_back(plugin); | |
456 } | |
457 | |
458 ++argidx; | |
459 } | |
460 | |
461 cout << describe(plugins, pluginBundleBaseURI, describerURI, libname) << endl; | |
462 | |
463 return 0; | |
464 } | |
465 | |
466 |