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