cannam@0: cannam@0:
cannam@0:00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@0: 00002 cannam@0: 00003 /* cannam@0: 00004 Vamp cannam@0: 00005 cannam@0: 00006 An API for audio analysis and feature extraction plugins. cannam@0: 00007 cannam@0: 00008 Centre for Digital Music, Queen Mary, University of London. cannam@0: 00009 Copyright 2006 Chris Cannam. cannam@0: 00010 FFT code from Don Cross's public domain FFT implementation. cannam@0: 00011 cannam@0: 00012 Permission is hereby granted, free of charge, to any person cannam@0: 00013 obtaining a copy of this software and associated documentation cannam@0: 00014 files (the "Software"), to deal in the Software without cannam@0: 00015 restriction, including without limitation the rights to use, copy, cannam@0: 00016 modify, merge, publish, distribute, sublicense, and/or sell copies cannam@0: 00017 of the Software, and to permit persons to whom the Software is cannam@0: 00018 furnished to do so, subject to the following conditions: cannam@0: 00019 cannam@0: 00020 The above copyright notice and this permission notice shall be cannam@0: 00021 included in all copies or substantial portions of the Software. cannam@0: 00022 cannam@0: 00023 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, cannam@0: 00024 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF cannam@0: 00025 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND cannam@0: 00026 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR cannam@0: 00027 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF cannam@0: 00028 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION cannam@0: 00029 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cannam@0: 00030 cannam@0: 00031 Except as contained in this notice, the names of the Centre for cannam@0: 00032 Digital Music; Queen Mary, University of London; and Chris Cannam cannam@0: 00033 shall not be used in advertising or otherwise to promote the sale, cannam@0: 00034 use or other dealings in this Software without prior written cannam@0: 00035 authorization. cannam@0: 00036 */ cannam@0: 00037 cannam@0: 00038 #include "vamp-sdk/PluginHostAdapter.h" cannam@0: 00039 #include "vamp-sdk/hostext/PluginChannelAdapter.h" cannam@0: 00040 #include "vamp-sdk/hostext/PluginInputDomainAdapter.h" cannam@0: 00041 #include "vamp-sdk/hostext/PluginLoader.h" cannam@0: 00042 #include "vamp/vamp.h" cannam@0: 00043 cannam@0: 00044 #include <iostream> cannam@0: 00045 #include <fstream> cannam@0: 00046 #include <set> cannam@0: 00047 #include <sndfile.h> cannam@0: 00048 cannam@0: 00049 #include <cstring> cannam@0: 00050 #include <cstdlib> cannam@0: 00051 cannam@0: 00052 #include "system.h" cannam@0: 00053 cannam@0: 00054 #include <cmath> cannam@0: 00055 cannam@0: 00056 using namespace std; cannam@0: 00057 cannam@0: 00058 using Vamp::Plugin; cannam@0: 00059 using Vamp::PluginHostAdapter; cannam@0: 00060 using Vamp::RealTime; cannam@0: 00061 using Vamp::HostExt::PluginLoader; cannam@0: 00062 cannam@0: 00063 #define HOST_VERSION "1.1" cannam@0: 00064 cannam@0: 00065 enum Verbosity { cannam@0: 00066 PluginIds, cannam@0: 00067 PluginOutputIds, cannam@0: 00068 PluginInformation cannam@0: 00069 }; cannam@0: 00070 cannam@0: 00071 void printFeatures(int, int, int, Plugin::FeatureSet, ofstream *, bool frames); cannam@0: 00072 void transformInput(float *, size_t); cannam@0: 00073 void fft(unsigned int, bool, double *, double *, double *, double *); cannam@0: 00074 void printPluginPath(bool verbose); cannam@0: 00075 void printPluginCategoryList(); cannam@0: 00076 void enumeratePlugins(Verbosity); cannam@0: 00077 void listPluginsInLibrary(string soname); cannam@0: 00078 int runPlugin(string myname, string soname, string id, string output, cannam@0: 00079 int outputNo, string inputFile, string outfilename, bool frames); cannam@0: 00080 cannam@0: 00081 void usage(const char *name) cannam@0: 00082 { cannam@0: 00083 cerr << "\n" cannam@0: 00084 << name << ": A simple Vamp plugin host.\n\n" cannam@0: 00085 "Centre for Digital Music, Queen Mary, University of London.\n" cannam@0: 00086 "Copyright 2006-2007 Chris Cannam and QMUL.\n" cannam@0: 00087 "Freely redistributable; published under a BSD-style license.\n\n" cannam@0: 00088 "Usage:\n\n" cannam@0: 00089 " " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin[:output] file.wav [-o out.txt]\n" cannam@0: 00090 " " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin file.wav [outputno] [-o out.txt]\n\n" cannam@0: 00091 " -- Load plugin id \"plugin\" from \"pluginlibrary\" and run it on the\n" cannam@0: 00092 " audio data in \"file.wav\", retrieving the named \"output\", or output\n" cannam@0: 00093 " number \"outputno\" (the first output by default) and dumping it to\n" cannam@0: 00094 " standard output, or to \"out.txt\" if the -o option is given.\n\n" cannam@0: 00095 " \"pluginlibrary\" should be a library name, not a file path; the\n" cannam@0: 00096 " standard Vamp library search path will be used to locate it. If\n" cannam@0: 00097 " a file path is supplied, the directory part(s) will be ignored.\n\n" cannam@0: 00098 " If the -s option is given, results will be labelled with the audio\n" cannam@0: 00099 " sample frame at which they occur. Otherwise, they will be labelled\n" cannam@0: 00100 " with time in seconds.\n\n" cannam@0: 00101 " " << name << " -l\n\n" cannam@0: 00102 " -- List the plugin libraries and Vamp plugins in the library search path\n" cannam@0: 00103 " in a verbose human-readable format.\n\n" cannam@0: 00104 " " << name << " --list-ids\n\n" cannam@0: 00105 " -- List the plugins in the search path in a terse machine-readable format,\n" cannam@0: 00106 " in the form vamp:soname:identifier.\n\n" cannam@0: 00107 " " << name << " --list-outputs\n\n" cannam@0: 00108 " -- List the outputs for plugins in the search path in a machine-readable\n" cannam@0: 00109 " format, in the form vamp:soname:identifier:output.\n\n" cannam@0: 00110 " " << name << " --list-by-category\n\n" cannam@0: 00111 " -- List the plugins as a plugin index by category, in a machine-readable\n" cannam@0: 00112 " format. The format may change in future releases.\n\n" cannam@0: 00113 " " << name << " -p\n\n" cannam@0: 00114 " -- Print out the Vamp library search path.\n\n" cannam@0: 00115 " " << name << " -v\n\n" cannam@0: 00116 " -- Display version information only.\n" cannam@0: 00117 << endl; cannam@0: 00118 exit(2); cannam@0: 00119 } cannam@0: 00120 cannam@0: 00121 int main(int argc, char **argv) cannam@0: 00122 { cannam@0: 00123 char *scooter = argv[0]; cannam@0: 00124 char *name = 0; cannam@0: 00125 while (scooter && *scooter) { cannam@0: 00126 if (*scooter == '/' || *scooter == '\\') name = ++scooter; cannam@0: 00127 else ++scooter; cannam@0: 00128 } cannam@0: 00129 if (!name || !*name) name = argv[0]; cannam@0: 00130 cannam@0: 00131 if (argc < 2) usage(name); cannam@0: 00132 cannam@0: 00133 if (argc == 2) { cannam@0: 00134 cannam@0: 00135 if (!strcmp(argv[1], "-v")) { cannam@0: 00136 cannam@0: 00137 cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl cannam@0: 00138 << "Vamp API version: " << VAMP_API_VERSION << endl cannam@0: 00139 << "Vamp SDK version: " << VAMP_SDK_VERSION << endl; cannam@0: 00140 return 0; cannam@0: 00141 cannam@0: 00142 } else if (!strcmp(argv[1], "-l")) { cannam@0: 00143 cannam@0: 00144 printPluginPath(true); cannam@0: 00145 enumeratePlugins(PluginInformation); cannam@0: 00146 return 0; cannam@0: 00147 cannam@0: 00148 } else if (!strcmp(argv[1], "-p")) { cannam@0: 00149 cannam@0: 00150 printPluginPath(false); cannam@0: 00151 return 0; cannam@0: 00152 cannam@0: 00153 } else if (!strcmp(argv[1], "--list-ids")) { cannam@0: 00154 cannam@0: 00155 enumeratePlugins(PluginIds); cannam@0: 00156 return 0; cannam@0: 00157 cannam@0: 00158 } else if (!strcmp(argv[1], "--list-outputs")) { cannam@0: 00159 cannam@0: 00160 enumeratePlugins(PluginOutputIds); cannam@0: 00161 return 0; cannam@0: 00162 cannam@0: 00163 } else if (!strcmp(argv[1], "--list-by-category")) { cannam@0: 00164 cannam@0: 00165 printPluginCategoryList(); cannam@0: 00166 return 0; cannam@0: 00167 cannam@0: 00168 } else usage(name); cannam@0: 00169 } cannam@0: 00170 cannam@0: 00171 if (argc < 3) usage(name); cannam@0: 00172 cannam@0: 00173 bool useFrames = false; cannam@0: 00174 cannam@0: 00175 int base = 1; cannam@0: 00176 if (!strcmp(argv[1], "-s")) { cannam@0: 00177 useFrames = true; cannam@0: 00178 base = 2; cannam@0: 00179 } cannam@0: 00180 cannam@0: 00181 string soname = argv[base]; cannam@0: 00182 string wavname = argv[base+1]; cannam@0: 00183 string plugid = ""; cannam@0: 00184 string output = ""; cannam@0: 00185 int outputNo = -1; cannam@0: 00186 string outfilename; cannam@0: 00187 cannam@0: 00188 if (argc >= base+3) { cannam@0: 00189 cannam@0: 00190 int idx = base+2; cannam@0: 00191 cannam@0: 00192 if (isdigit(*argv[idx])) { cannam@0: 00193 outputNo = atoi(argv[idx++]); cannam@0: 00194 } cannam@0: 00195 cannam@0: 00196 if (argc == idx + 2) { cannam@0: 00197 if (!strcmp(argv[idx], "-o")) { cannam@0: 00198 outfilename = argv[idx+1]; cannam@0: 00199 } else usage(name); cannam@0: 00200 } else if (argc != idx) { cannam@0: 00201 (usage(name)); cannam@0: 00202 } cannam@0: 00203 } cannam@0: 00204 cannam@0: 00205 cerr << endl << name << ": Running..." << endl; cannam@0: 00206 cannam@0: 00207 cerr << "Reading file: \"" << wavname << "\", writing to "; cannam@0: 00208 if (outfilename == "") { cannam@0: 00209 cerr << "standard output" << endl; cannam@0: 00210 } else { cannam@0: 00211 cerr << "\"" << outfilename << "\"" << endl; cannam@0: 00212 } cannam@0: 00213 cannam@0: 00214 string::size_type sep = soname.find(':'); cannam@0: 00215 cannam@0: 00216 if (sep != string::npos) { cannam@0: 00217 plugid = soname.substr(sep + 1); cannam@0: 00218 soname = soname.substr(0, sep); cannam@0: 00219 cannam@0: 00220 sep = plugid.find(':'); cannam@0: 00221 if (sep != string::npos) { cannam@0: 00222 output = plugid.substr(sep + 1); cannam@0: 00223 plugid = plugid.substr(0, sep); cannam@0: 00224 } cannam@0: 00225 } cannam@0: 00226 cannam@0: 00227 if (plugid == "") { cannam@0: 00228 usage(name); cannam@0: 00229 } cannam@0: 00230 cannam@0: 00231 if (output != "" && outputNo != -1) { cannam@0: 00232 usage(name); cannam@0: 00233 } cannam@0: 00234 cannam@0: 00235 if (output == "" && outputNo == -1) { cannam@0: 00236 outputNo = 0; cannam@0: 00237 } cannam@0: 00238 cannam@0: 00239 return runPlugin(name, soname, plugid, output, outputNo, cannam@0: 00240 wavname, outfilename, useFrames); cannam@0: 00241 } cannam@0: 00242 cannam@0: 00243 cannam@0: 00244 int runPlugin(string myname, string soname, string id, cannam@0: 00245 string output, int outputNo, string wavname, cannam@0: 00246 string outfilename, bool useFrames) cannam@0: 00247 { cannam@0: 00248 PluginLoader *loader = PluginLoader::getInstance(); cannam@0: 00249 cannam@0: 00250 PluginLoader::PluginKey key = loader->composePluginKey(soname, id); cannam@0: 00251 cannam@0: 00252 SNDFILE *sndfile; cannam@0: 00253 SF_INFO sfinfo; cannam@0: 00254 memset(&sfinfo, 0, sizeof(SF_INFO)); cannam@0: 00255 cannam@0: 00256 sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo); cannam@0: 00257 if (!sndfile) { cannam@0: 00258 cerr << myname << ": ERROR: Failed to open input file \"" cannam@0: 00259 << wavname << "\": " << sf_strerror(sndfile) << endl; cannam@0: 00260 return 1; cannam@0: 00261 } cannam@0: 00262 cannam@0: 00263 ofstream *out = 0; cannam@0: 00264 if (outfilename != "") { cannam@0: 00265 out = new ofstream(outfilename.c_str(), ios::out); cannam@0: 00266 if (!*out) { cannam@0: 00267 cerr << myname << ": ERROR: Failed to open output file \"" cannam@0: 00268 << outfilename << "\" for writing" << endl; cannam@0: 00269 delete out; cannam@0: 00270 return 1; cannam@0: 00271 } cannam@0: 00272 } cannam@0: 00273 cannam@0: 00274 Plugin *plugin = loader->loadPlugin cannam@0: 00275 (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL_SAFE); cannam@0: 00276 if (!plugin) { cannam@0: 00277 cerr << myname << ": ERROR: Failed to load plugin \"" << id cannam@0: 00278 << "\" from library \"" << soname << "\"" << endl; cannam@0: 00279 sf_close(sndfile); cannam@0: 00280 if (out) { cannam@0: 00281 out->close(); cannam@0: 00282 delete out; cannam@0: 00283 } cannam@0: 00284 return 1; cannam@0: 00285 } cannam@0: 00286 cannam@0: 00287 cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl; cannam@0: 00288 cannam@0: 00289 int blockSize = plugin->getPreferredBlockSize(); cannam@0: 00290 int stepSize = plugin->getPreferredStepSize(); cannam@0: 00291 cannam@0: 00292 if (blockSize == 0) { cannam@0: 00293 blockSize = 1024; cannam@0: 00294 } cannam@0: 00295 if (stepSize == 0) { cannam@0: 00296 if (plugin->getInputDomain() == Plugin::FrequencyDomain) { cannam@0: 00297 stepSize = blockSize/2; cannam@0: 00298 } else { cannam@0: 00299 stepSize = blockSize; cannam@0: 00300 } cannam@0: 00301 } else if (stepSize > blockSize) { cannam@0: 00302 cerr << "WARNING: stepSize " << stepSize << " > blockSize " << blockSize << ", resetting blockSize to "; cannam@0: 00303 if (plugin->getInputDomain() == Plugin::FrequencyDomain) { cannam@0: 00304 blockSize = stepSize * 2; cannam@0: 00305 } else { cannam@0: 00306 blockSize = stepSize; cannam@0: 00307 } cannam@0: 00308 cerr << blockSize << endl; cannam@0: 00309 } cannam@0: 00310 cannam@0: 00311 int channels = sfinfo.channels; cannam@0: 00312 cannam@0: 00313 float *filebuf = new float[blockSize * channels]; cannam@0: 00314 float **plugbuf = new float*[channels]; cannam@0: 00315 for (int c = 0; c < channels; ++c) plugbuf[c] = new float[blockSize + 2]; cannam@0: 00316 cannam@0: 00317 cerr << "Using block size = " << blockSize << ", step size = " cannam@0: 00318 << stepSize << endl; cannam@0: 00319 cannam@0: 00320 int minch = plugin->getMinChannelCount(); cannam@0: 00321 int maxch = plugin->getMaxChannelCount(); cannam@0: 00322 cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl; cannam@0: 00323 cerr << "Sound file has " << channels << " (will mix/augment if necessary)" << endl; cannam@0: 00324 cannam@0: 00325 Plugin::OutputList outputs = plugin->getOutputDescriptors(); cannam@0: 00326 Plugin::OutputDescriptor od; cannam@0: 00327 cannam@0: 00328 int returnValue = 1; cannam@0: 00329 int progress = 0; cannam@0: 00330 cannam@0: 00331 if (outputs.empty()) { cannam@0: 00332 cerr << "ERROR: Plugin has no outputs!" << endl; cannam@0: 00333 goto done; cannam@0: 00334 } cannam@0: 00335 cannam@0: 00336 if (outputNo < 0) { cannam@0: 00337 cannam@0: 00338 for (size_t oi = 0; oi < outputs.size(); ++oi) { cannam@0: 00339 if (outputs[oi].identifier == output) { cannam@0: 00340 outputNo = oi; cannam@0: 00341 break; cannam@0: 00342 } cannam@0: 00343 } cannam@0: 00344 cannam@0: 00345 if (outputNo < 0) { cannam@0: 00346 cerr << "ERROR: Non-existent output \"" << output << "\" requested" << endl; cannam@0: 00347 goto done; cannam@0: 00348 } cannam@0: 00349 cannam@0: 00350 } else { cannam@0: 00351 cannam@0: 00352 if (int(outputs.size()) <= outputNo) { cannam@0: 00353 cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl; cannam@0: 00354 goto done; cannam@0: 00355 } cannam@0: 00356 } cannam@0: 00357 cannam@0: 00358 od = outputs[outputNo]; cannam@0: 00359 cerr << "Output is: \"" << od.identifier << "\"" << endl; cannam@0: 00360 cannam@0: 00361 if (!plugin->initialise(channels, stepSize, blockSize)) { cannam@0: 00362 cerr << "ERROR: Plugin initialise (channels = " << channels cannam@0: 00363 << ", stepSize = " << stepSize << ", blockSize = " cannam@0: 00364 << blockSize << ") failed." << endl; cannam@0: 00365 goto done; cannam@0: 00366 } cannam@0: 00367 cannam@0: 00368 for (size_t i = 0; i < sfinfo.frames; i += stepSize) { cannam@0: 00369 cannam@0: 00370 int count; cannam@0: 00371 cannam@0: 00372 if (sf_seek(sndfile, i, SEEK_SET) < 0) { cannam@0: 00373 cerr << "ERROR: sf_seek failed: " << sf_strerror(sndfile) << endl; cannam@0: 00374 break; cannam@0: 00375 } cannam@0: 00376 cannam@0: 00377 if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) { cannam@0: 00378 cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl; cannam@0: 00379 break; cannam@0: 00380 } cannam@0: 00381 cannam@0: 00382 for (int c = 0; c < channels; ++c) { cannam@0: 00383 int j = 0; cannam@0: 00384 while (j < count) { cannam@0: 00385 plugbuf[c][j] = filebuf[j * sfinfo.channels + c]; cannam@0: 00386 ++j; cannam@0: 00387 } cannam@0: 00388 while (j < blockSize) { cannam@0: 00389 plugbuf[c][j] = 0.0f; cannam@0: 00390 ++j; cannam@0: 00391 } cannam@0: 00392 } cannam@0: 00393 cannam@0: 00394 printFeatures cannam@0: 00395 (i, sfinfo.samplerate, outputNo, plugin->process cannam@0: 00396 (plugbuf, RealTime::frame2RealTime(i, sfinfo.samplerate)), cannam@0: 00397 out, useFrames); cannam@0: 00398 cannam@0: 00399 int pp = progress; cannam@0: 00400 progress = lrintf((float(i) / sfinfo.frames) * 100.f); cannam@0: 00401 if (progress != pp && out) { cannam@0: 00402 cerr << "\r" << progress << "%"; cannam@0: 00403 } cannam@0: 00404 } cannam@0: 00405 if (out) cerr << "\rDone" << endl; cannam@0: 00406 cannam@0: 00407 printFeatures(sfinfo.frames, sfinfo.samplerate, outputNo, cannam@0: 00408 plugin->getRemainingFeatures(), out, useFrames); cannam@0: 00409 cannam@0: 00410 returnValue = 0; cannam@0: 00411 cannam@0: 00412 done: cannam@0: 00413 delete plugin; cannam@0: 00414 if (out) { cannam@0: 00415 out->close(); cannam@0: 00416 delete out; cannam@0: 00417 } cannam@0: 00418 sf_close(sndfile); cannam@0: 00419 return returnValue; cannam@0: 00420 } cannam@0: 00421 cannam@0: 00422 void cannam@0: 00423 printFeatures(int frame, int sr, int output, cannam@0: 00424 Plugin::FeatureSet features, ofstream *out, bool useFrames) cannam@0: 00425 { cannam@0: 00426 for (unsigned int i = 0; i < features[output].size(); ++i) { cannam@0: 00427 cannam@0: 00428 if (useFrames) { cannam@0: 00429 cannam@0: 00430 int displayFrame = frame; cannam@0: 00431 cannam@0: 00432 if (features[output][i].hasTimestamp) { cannam@0: 00433 displayFrame = RealTime::realTime2Frame cannam@0: 00434 (features[output][i].timestamp, sr); cannam@0: 00435 } cannam@0: 00436 cannam@0: 00437 (out ? *out : cout) << displayFrame << ":"; cannam@0: 00438 cannam@0: 00439 } else { cannam@0: 00440 cannam@0: 00441 RealTime rt = RealTime::frame2RealTime(frame, sr); cannam@0: 00442 cannam@0: 00443 if (features[output][i].hasTimestamp) { cannam@0: 00444 rt = features[output][i].timestamp; cannam@0: 00445 } cannam@0: 00446 cannam@0: 00447 (out ? *out : cout) << rt.toString() << ":"; cannam@0: 00448 } cannam@0: 00449 cannam@0: 00450 for (unsigned int j = 0; j < features[output][i].values.size(); ++j) { cannam@0: 00451 (out ? *out : cout) << " " << features[output][i].values[j]; cannam@0: 00452 } cannam@0: 00453 cannam@0: 00454 (out ? *out : cout) << endl; cannam@0: 00455 } cannam@0: 00456 } cannam@0: 00457 cannam@0: 00458 void cannam@0: 00459 printPluginPath(bool verbose) cannam@0: 00460 { cannam@0: 00461 if (verbose) { cannam@0: 00462 cout << "\nVamp plugin search path: "; cannam@0: 00463 } cannam@0: 00464 cannam@0: 00465 vector<string> path = PluginHostAdapter::getPluginPath(); cannam@0: 00466 for (size_t i = 0; i < path.size(); ++i) { cannam@0: 00467 if (verbose) { cannam@0: 00468 cout << "[" << path[i] << "]"; cannam@0: 00469 } else { cannam@0: 00470 cout << path[i] << endl; cannam@0: 00471 } cannam@0: 00472 } cannam@0: 00473 cannam@0: 00474 if (verbose) cout << endl; cannam@0: 00475 } cannam@0: 00476 cannam@0: 00477 void cannam@0: 00478 enumeratePlugins(Verbosity verbosity) cannam@0: 00479 { cannam@0: 00480 PluginLoader *loader = PluginLoader::getInstance(); cannam@0: 00481 cannam@0: 00482 if (verbosity == PluginInformation) { cannam@0: 00483 cout << "\nVamp plugin libraries found in search path:" << endl; cannam@0: 00484 } cannam@0: 00485 cannam@0: 00486 vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); cannam@0: 00487 typedef multimap<string, PluginLoader::PluginKey> cannam@0: 00488 LibraryMap; cannam@0: 00489 LibraryMap libraryMap; cannam@0: 00490 cannam@0: 00491 for (size_t i = 0; i < plugins.size(); ++i) { cannam@0: 00492 string path = loader->getLibraryPathForPlugin(plugins[i]); cannam@0: 00493 libraryMap.insert(LibraryMap::value_type(path, plugins[i])); cannam@0: 00494 } cannam@0: 00495 cannam@0: 00496 string prevPath = ""; cannam@0: 00497 int index = 0; cannam@0: 00498 cannam@0: 00499 for (LibraryMap::iterator i = libraryMap.begin(); cannam@0: 00500 i != libraryMap.end(); ++i) { cannam@0: 00501 cannam@0: 00502 string path = i->first; cannam@0: 00503 PluginLoader::PluginKey key = i->second; cannam@0: 00504 cannam@0: 00505 if (path != prevPath) { cannam@0: 00506 prevPath = path; cannam@0: 00507 index = 0; cannam@0: 00508 if (verbosity == PluginInformation) { cannam@0: 00509 cout << "\n " << path << ":" << endl; cannam@0: 00510 } cannam@0: 00511 } cannam@0: 00512 cannam@0: 00513 Plugin *plugin = loader->loadPlugin(key, 48000); cannam@0: 00514 if (plugin) { cannam@0: 00515 cannam@0: 00516 char c = char('A' + index); cannam@0: 00517 if (c > 'Z') c = char('a' + (index - 26)); cannam@0: 00518 cannam@0: 00519 if (verbosity == PluginInformation) { cannam@0: 00520 cannam@0: 00521 cout << " [" << c << "] [v" cannam@0: 00522 << plugin->getVampApiVersion() << "] " cannam@0: 00523 << plugin->getName() << ", \"" cannam@0: 00524 << plugin->getIdentifier() << "\"" << " [" cannam@0: 00525 << plugin->getMaker() << "]" << endl; cannam@0: 00526 cannam@0: 00527 PluginLoader::PluginCategoryHierarchy category = cannam@0: 00528 loader->getPluginCategory(key); cannam@0: 00529 cannam@0: 00530 if (!category.empty()) { cannam@0: 00531 cout << " "; cannam@0: 00532 for (size_t ci = 0; ci < category.size(); ++ci) { cannam@0: 00533 cout << " > " << category[ci]; cannam@0: 00534 } cannam@0: 00535 cout << endl; cannam@0: 00536 } cannam@0: 00537 cannam@0: 00538 if (plugin->getDescription() != "") { cannam@0: 00539 cout << " - " << plugin->getDescription() << endl; cannam@0: 00540 } cannam@0: 00541 cannam@0: 00542 } else if (verbosity == PluginIds) { cannam@0: 00543 cout << "vamp:" << key << endl; cannam@0: 00544 } cannam@0: 00545 cannam@0: 00546 Plugin::OutputList outputs = cannam@0: 00547 plugin->getOutputDescriptors(); cannam@0: 00548 cannam@0: 00549 if (outputs.size() > 1 || verbosity == PluginOutputIds) { cannam@0: 00550 for (size_t j = 0; j < outputs.size(); ++j) { cannam@0: 00551 if (verbosity == PluginInformation) { cannam@0: 00552 cout << " (" << j << ") " cannam@0: 00553 << outputs[j].name << ", \"" cannam@0: 00554 << outputs[j].identifier << "\"" << endl; cannam@0: 00555 if (outputs[j].description != "") { cannam@0: 00556 cout << " - " cannam@0: 00557 << outputs[j].description << endl; cannam@0: 00558 } cannam@0: 00559 } else if (verbosity == PluginOutputIds) { cannam@0: 00560 cout << "vamp:" << key << ":" << outputs[j].identifier << endl; cannam@0: 00561 } cannam@0: 00562 } cannam@0: 00563 } cannam@0: 00564 cannam@0: 00565 ++index; cannam@0: 00566 cannam@0: 00567 delete plugin; cannam@0: 00568 } cannam@0: 00569 } cannam@0: 00570 cannam@0: 00571 if (verbosity == PluginInformation) { cannam@0: 00572 cout << endl; cannam@0: 00573 } cannam@0: 00574 } cannam@0: 00575 cannam@0: 00576 void cannam@0: 00577 printPluginCategoryList() cannam@0: 00578 { cannam@0: 00579 PluginLoader *loader = PluginLoader::getInstance(); cannam@0: 00580 cannam@0: 00581 vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); cannam@0: 00582 cannam@0: 00583 set<string> printedcats; cannam@0: 00584 cannam@0: 00585 for (size_t i = 0; i < plugins.size(); ++i) { cannam@0: 00586 cannam@0: 00587 PluginLoader::PluginKey key = plugins[i]; cannam@0: 00588 cannam@0: 00589 PluginLoader::PluginCategoryHierarchy category = cannam@0: 00590 loader->getPluginCategory(key); cannam@0: 00591 cannam@0: 00592 Plugin *plugin = loader->loadPlugin(key, 48000); cannam@0: 00593 if (!plugin) continue; cannam@0: 00594 cannam@0: 00595 string catstr = ""; cannam@0: 00596 cannam@0: 00597 if (category.empty()) catstr = '|'; cannam@0: 00598 else { cannam@0: 00599 for (size_t j = 0; j < category.size(); ++j) { cannam@0: 00600 catstr += category[j]; cannam@0: 00601 catstr += '|'; cannam@0: 00602 if (printedcats.find(catstr) == printedcats.end()) { cannam@0: 00603 std::cout << catstr << std::endl; cannam@0: 00604 printedcats.insert(catstr); cannam@0: 00605 } cannam@0: 00606 } cannam@0: 00607 } cannam@0: 00608 cannam@0: 00609 std::cout << catstr << key << ":::" << plugin->getName() << ":::" << plugin->getMaker() << ":::" << plugin->getDescription() << std::endl; cannam@0: 00610 } cannam@0: 00611 } cannam@0: 00612 cannam@0: