annotate rdf/generator/vamp-rdf-template-generator.cpp @ 525:8c18bdaad04f c++11-mutex

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