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