| 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 |