# vamp-simple-host.cpp

Go to the documentation of this file.

    00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
    00002
    00003 /*
    00004     Vamp
    00005
    00006     An API for audio analysis and feature extraction plugins.
    00007
    00008     Centre for Digital Music, Queen Mary, University of London.
    00009     Copyright 2006 Chris Cannam, copyright 2007-2008 QMUL.
    00010
    00011     Permission is hereby granted, free of charge, to any person
    00012     obtaining a copy of this software and associated documentation
    00013     files (the "Software"), to deal in the Software without
    00014     restriction, including without limitation the rights to use, copy,
    00015     modify, merge, publish, distribute, sublicense, and/or sell copies
    00016     of the Software, and to permit persons to whom the Software is
    00017     furnished to do so, subject to the following conditions:
    00018
    00019     The above copyright notice and this permission notice shall be
    00020     included in all copies or substantial portions of the Software.
    00021
    00022     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    00023     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    00024     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    00025     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
    00026     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
    00027     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    00028     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    00029
    00030     Except as contained in this notice, the names of the Centre for
    00031     Digital Music; Queen Mary, University of London; and Chris Cannam
    00032     shall not be used in advertising or otherwise to promote the sale,
    00033     use or other dealings in this Software without prior written
    00034     authorization.
    00035 */
    00036
    00037
    00038 /*
    00039  * This "simple" Vamp plugin host is no longer as simple as it was; it
    00040  * now has a lot of options and includes a lot of code to handle the
    00041  * various useful listing modes it supports.
    00042  *
    00043  * However, the runPlugin function still contains a reasonable
    00044  * implementation of a fairly generic Vamp plugin host capable of
    00045  * evaluating a given output on a given plugin for a sound file read
    00046  * via libsndfile.
    00047  */
    00048
    00049 #include <vamp-hostsdk/PluginHostAdapter.h>
    00050 #include <vamp-hostsdk/PluginInputDomainAdapter.h>
    00051 #include <vamp-hostsdk/PluginLoader.h>
    00052
    00053 #include <iostream>
    00054 #include <fstream>
    00055 #include <set>
    00056 #include <sndfile.h>
    00057
    00058 #include <cstring>
    00059 #include <cstdlib>
    00060
    00061 #include "system.h"
    00062
    00063 #include <cmath>
    00064
    00065 using namespace std;
    00066
    00067 using Vamp::Plugin;
    00068 using Vamp::PluginHostAdapter;
    00069 using Vamp::RealTime;
    00070 using Vamp::HostExt::PluginLoader;
    00071 using Vamp::HostExt::PluginWrapper;
    00072 using Vamp::HostExt::PluginInputDomainAdapter;
    00073
    00074 #define HOST_VERSION "1.4"
    00075
    00076 enum Verbosity {
    00077     PluginIds,
    00078     PluginOutputIds,
    00079     PluginInformation,
    00080     PluginInformationDetailed
    00081 };
    00082
    00083 void printFeatures(int, int, int, Plugin::FeatureSet, ofstream *, bool frames);
    00084 void transformInput(float *, size_t);
    00085 void fft(unsigned int, bool, double *, double *, double *, double *);
    00086 void printPluginPath(bool verbose);
    00087 void printPluginCategoryList();
    00088 void enumeratePlugins(Verbosity);
    00089 void listPluginsInLibrary(string soname);
    00090 int runPlugin(string myname, string soname, string id, string output,
    00091               int outputNo, string inputFile, string outfilename, bool frames);
    00092
    00093 void usage(const char *name)
    00094 {
    00095     cerr << "\n"
    00096          << name << ": A command-line host for Vamp audio analysis plugins.\n\n"
    00097         "Centre for Digital Music, Queen Mary, University of London.\n"
    00098         "Copyright 2006-2009 Chris Cannam and QMUL.\n"
    00099         "Freely redistributable; published under a BSD-style license.\n\n"
    00100         "Usage:\n\n"
    00101         "  " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin[:output] file.wav [-o out.txt]\n"
    00102         "  " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin file.wav [outputno] [-o out.txt]\n\n"
    00103         "    -- Load plugin id \"plugin\" from \"pluginlibrary\" and run it on the\n"
    00104         "       audio data in \"file.wav\", retrieving the named \"output\", or output\n"
    00105         "       number \"outputno\" (the first output by default) and dumping it to\n"
    00106         "       standard output, or to \"out.txt\" if the -o option is given.\n\n"
    00107         "       \"pluginlibrary\" should be a library name, not a file path; the\n"
    00108         "       standard Vamp library search path will be used to locate it.  If\n"
    00109         "       a file path is supplied, the directory part(s) will be ignored.\n\n"
    00110         "       If the -s option is given, results will be labelled with the audio\n"
    00111         "       sample frame at which they occur. Otherwise, they will be labelled\n"
    00112         "       with time in seconds.\n\n"
    00113         "  " << name << " -l\n"
    00114         "  " << name << " --list\n\n"
    00115         "    -- List the plugin libraries and Vamp plugins in the library search path\n"
    00116         "       in a verbose human-readable format.\n\n"
    00117         "  " << name << " --list-full\n\n"
    00118         "    -- List all data reported by all the Vamp plugins in the library search\n"
    00119         "       path in a very verbose human-readable format.\n\n"
    00120         "  " << name << " --list-ids\n\n"
    00121         "    -- List the plugins in the search path in a terse machine-readable format,\n"
    00122         "       in the form vamp:soname:identifier.\n\n"
    00123         "  " << name << " --list-outputs\n\n"
    00124         "    -- List the outputs for plugins in the search path in a machine-readable\n"
    00125         "       format, in the form vamp:soname:identifier:output.\n\n"
    00126         "  " << name << " --list-by-category\n\n"
    00127         "    -- List the plugins as a plugin index by category, in a machine-readable\n"
    00128         "       format.  The format may change in future releases.\n\n"
    00129         "  " << name << " -p\n\n"
    00130         "    -- Print out the Vamp library search path.\n\n"
    00131         "  " << name << " -v\n\n"
    00132         "    -- Display version information only.\n"
    00133          << endl;
    00134     exit(2);
    00135 }
    00136
    00137 int main(int argc, char **argv)
    00138 {
    00139     char *scooter = argv[0];
    00140     char *name = 0;
    00141     while (scooter && *scooter) {
    00142         if (*scooter == '/' || *scooter == '\\') name = ++scooter;
    00143         else ++scooter;
    00144     }
    00145     if (!name || !*name) name = argv[0];
    00146
    00147     if (argc < 2) usage(name);
    00148
    00149     if (argc == 2) {
    00150
    00151         if (!strcmp(argv[1], "-v")) {
    00152
    00153             cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl
    00154                  << "Vamp API version: " << VAMP_API_VERSION << endl
    00155                  << "Vamp SDK version: " << VAMP_SDK_VERSION << endl;
    00156             return 0;
    00157
    00158         } else if (!strcmp(argv[1], "-l") || !strcmp(argv[1], "--list")) {
    00159
    00160             printPluginPath(true);
    00161             enumeratePlugins(PluginInformation);
    00162             return 0;
    00163
    00164         } else if (!strcmp(argv[1], "--list-full")) {
    00165
    00166             enumeratePlugins(PluginInformationDetailed);
    00167             return 0;
    00168
    00169         } else if (!strcmp(argv[1], "-p")) {
    00170
    00171             printPluginPath(false);
    00172             return 0;
    00173
    00174         } else if (!strcmp(argv[1], "--list-ids")) {
    00175
    00176             enumeratePlugins(PluginIds);
    00177             return 0;
    00178
    00179         } else if (!strcmp(argv[1], "--list-outputs")) {
    00180
    00181             enumeratePlugins(PluginOutputIds);
    00182             return 0;
    00183
    00184         } else if (!strcmp(argv[1], "--list-by-category")) {
    00185
    00186             printPluginCategoryList();
    00187             return 0;
    00188
    00189         } else usage(name);
    00190     }
    00191
    00192     if (argc < 3) usage(name);
    00193
    00194     bool useFrames = false;
    00195
    00196     int base = 1;
    00197     if (!strcmp(argv[1], "-s")) {
    00198         useFrames = true;
    00199         base = 2;
    00200     }
    00201
    00202     string soname = argv[base];
    00203     string wavname = argv[base+1];
    00204     string plugid = "";
    00205     string output = "";
    00206     int outputNo = -1;
    00207     string outfilename;
    00208
    00209     if (argc >= base+3) {
    00210
    00211         int idx = base+2;
    00212
    00213         if (isdigit(*argv[idx])) {
    00214             outputNo = atoi(argv[idx++]);
    00215         }
    00216
    00217         if (argc == idx + 2) {
    00218             if (!strcmp(argv[idx], "-o")) {
    00219                 outfilename = argv[idx+1];
    00220             } else usage(name);
    00221         } else if (argc != idx) {
    00222             (usage(name));
    00223         }
    00224     }
    00225
    00226     cerr << endl << name << ": Running..." << endl;
    00227
    00228     cerr << "Reading file: \"" << wavname << "\", writing to ";
    00229     if (outfilename == "") {
    00230         cerr << "standard output" << endl;
    00231     } else {
    00232         cerr << "\"" << outfilename << "\"" << endl;
    00233     }
    00234
    00235     string::size_type sep = soname.find(':');
    00236
    00237     if (sep != string::npos) {
    00238         plugid = soname.substr(sep + 1);
    00239         soname = soname.substr(0, sep);
    00240
    00241         sep = plugid.find(':');
    00242         if (sep != string::npos) {
    00243             output = plugid.substr(sep + 1);
    00244             plugid = plugid.substr(0, sep);
    00245         }
    00246     }
    00247
    00248     if (plugid == "") {
    00249         usage(name);
    00250     }
    00251
    00252     if (output != "" && outputNo != -1) {
    00253         usage(name);
    00254     }
    00255
    00256     if (output == "" && outputNo == -1) {
    00257         outputNo = 0;
    00258     }
    00259
    00260     return runPlugin(name, soname, plugid, output, outputNo,
    00261                      wavname, outfilename, useFrames);
    00262 }
    00263
    00264
    00265 int runPlugin(string myname, string soname, string id,
    00266               string output, int outputNo, string wavname,
    00267               string outfilename, bool useFrames)
    00268 {
    00269     PluginLoader *loader = PluginLoader::getInstance();
    00270
    00271     PluginLoader::PluginKey key = loader->composePluginKey(soname, id);
    00272
    00273     SNDFILE *sndfile;
    00274     SF_INFO sfinfo;
    00275     memset(&sfinfo, 0, sizeof(SF_INFO));
    00276
    00277     sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo);
    00278     if (!sndfile) {
    00279         cerr << myname << ": ERROR: Failed to open input file \""
    00280              << wavname << "\": " << sf_strerror(sndfile) << endl;
    00281         return 1;
    00282     }
    00283
    00284     ofstream *out = 0;
    00285     if (outfilename != "") {
    00286         out = new ofstream(outfilename.c_str(), ios::out);
    00287         if (!*out) {
    00288             cerr << myname << ": ERROR: Failed to open output file \""
    00289                  << outfilename << "\" for writing" << endl;
    00290             delete out;
    00291             return 1;
    00292         }
    00293     }
    00294
    00295     Plugin *plugin = loader->loadPlugin
    00296         (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL_SAFE);
    00297     if (!plugin) {
    00298         cerr << myname << ": ERROR: Failed to load plugin \"" << id
    00299              << "\" from library \"" << soname << "\"" << endl;
    00300         sf_close(sndfile);
    00301         if (out) {
    00302             out->close();
    00303             delete out;
    00304         }
    00305         return 1;
    00306     }
    00307
    00308     cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl;
    00309
    00310     // Note that the following would be much simpler if we used a
    00311     // PluginBufferingAdapter as well -- i.e. if we had passed
    00312     // PluginLoader::ADAPT_ALL to loader->loadPlugin() above, instead
    00313     // of ADAPT_ALL_SAFE.  Then we could simply specify our own block
    00314     // size, keep the step size equal to the block size, and ignore
    00315     // the plugin's bleatings.  However, there are some issues with
    00316     // using a PluginBufferingAdapter that make the results sometimes
    00317     // technically different from (if effectively the same as) the
    00318     // un-adapted plugin, so we aren't doing that here.  See the
    00319     // PluginBufferingAdapter documentation for details.
    00320
    00321     int blockSize = plugin->getPreferredBlockSize();
    00322     int stepSize = plugin->getPreferredStepSize();
    00323
    00324     if (blockSize == 0) {
    00325         blockSize = 1024;
    00326     }
    00327     if (stepSize == 0) {
    00328         if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
    00329             stepSize = blockSize/2;
    00330         } else {
    00331             stepSize = blockSize;
    00332         }
    00333     } else if (stepSize > blockSize) {
    00334         cerr << "WARNING: stepSize " << stepSize << " > blockSize " << blockSize << ", resetting blockSize to ";
    00335         if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
    00336             blockSize = stepSize * 2;
    00337         } else {
    00338             blockSize = stepSize;
    00339         }
    00340         cerr << blockSize << endl;
    00341     }
    00342
    00343     int channels = sfinfo.channels;
    00344
    00345     float *filebuf = new float[blockSize * channels];
    00346     float **plugbuf = new float*[channels];
    00347     for (int c = 0; c < channels; ++c) plugbuf[c] = new float[blockSize + 2];
    00348
    00349     cerr << "Using block size = " << blockSize << ", step size = "
    00350               << stepSize << endl;
    00351
    00352     // The channel queries here are for informational purposes only --
    00353     // a PluginChannelAdapter is being used automatically behind the
    00354     // scenes, and it will take case of any channel mismatch
    00355
    00356     int minch = plugin->getMinChannelCount();
    00357     int maxch = plugin->getMaxChannelCount();
    00358     cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl;
    00359     cerr << "Sound file has " << channels << " (will mix/augment if necessary)" << endl;
    00360
    00361     Plugin::OutputList outputs = plugin->getOutputDescriptors();
    00362     Plugin::OutputDescriptor od;
    00363
    00364     int returnValue = 1;
    00365     int progress = 0;
    00366
    00367     RealTime rt;
    00368     PluginWrapper *wrapper = 0;
    00369     RealTime adjustment = RealTime::zeroTime;
    00370
    00371     if (outputs.empty()) {
    00372         cerr << "ERROR: Plugin has no outputs!" << endl;
    00373         goto done;
    00374     }
    00375
    00376     if (outputNo < 0) {
    00377
    00378         for (size_t oi = 0; oi < outputs.size(); ++oi) {
    00379             if (outputs[oi].identifier == output) {
    00380                 outputNo = oi;
    00381                 break;
    00382             }
    00383         }
    00384
    00385         if (outputNo < 0) {
    00386             cerr << "ERROR: Non-existent output \"" << output << "\" requested" << endl;
    00387             goto done;
    00388         }
    00389
    00390     } else {
    00391
    00392         if (int(outputs.size()) <= outputNo) {
    00393             cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl;
    00394             goto done;
    00395         }
    00396     }
    00397
    00398     od = outputs[outputNo];
    00399     cerr << "Output is: \"" << od.identifier << "\"" << endl;
    00400
    00401     if (!plugin->initialise(channels, stepSize, blockSize)) {
    00402         cerr << "ERROR: Plugin initialise (channels = " << channels
    00403              << ", stepSize = " << stepSize << ", blockSize = "
    00404              << blockSize << ") failed." << endl;
    00405         goto done;
    00406     }
    00407
    00408     wrapper = dynamic_cast<PluginWrapper *>(plugin);
    00409     if (wrapper) {
    00410         // See documentation for
    00411         // PluginInputDomainAdapter::getTimestampAdjustment
    00412         PluginInputDomainAdapter *ida =
    00413             wrapper->getWrapper<PluginInputDomainAdapter>();
    00414         if (ida) adjustment = ida->getTimestampAdjustment();
    00415     }
    00416
    00417     for (sf_count_t i = 0; i < sfinfo.frames; i += stepSize) {
    00418
    00419         int count;
    00420
    00421         if (sf_seek(sndfile, i, SEEK_SET) < 0) {
    00422             cerr << "ERROR: sf_seek failed: " << sf_strerror(sndfile) << endl;
    00423             break;
    00424         }
    00425
    00426         if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) {
    00427             cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
    00428             break;
    00429         }
    00430
    00431         for (int c = 0; c < channels; ++c) {
    00432             int j = 0;
    00433             while (j < count) {
    00434                 plugbuf[c][j] = filebuf[j * sfinfo.channels + c];
    00435                 ++j;
    00436             }
    00437             while (j < blockSize) {
    00438                 plugbuf[c][j] = 0.0f;
    00439                 ++j;
    00440             }
    00441         }
    00442
    00443         rt = RealTime::frame2RealTime(i, sfinfo.samplerate);
    00444
    00445         printFeatures
    00446             (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
    00447              sfinfo.samplerate, outputNo, plugin->process(plugbuf, rt),
    00448              out, useFrames);
    00449
    00450         int pp = progress;
    00451         progress = lrintf((float(i) / sfinfo.frames) * 100.f);
    00452         if (progress != pp && out) {
    00453             cerr << "\r" << progress << "%";
    00454         }
    00455     }
    00456     if (out) cerr << "\rDone" << endl;
    00457
    00458     rt = RealTime::frame2RealTime(sfinfo.frames, sfinfo.samplerate);
    00459
    00460     printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
    00461                   sfinfo.samplerate, outputNo,
    00462                   plugin->getRemainingFeatures(), out, useFrames);
    00463
    00464     returnValue = 0;
    00465
    00466 done:
    00467     delete plugin;
    00468     if (out) {
    00469         out->close();
    00470         delete out;
    00471     }
    00472     sf_close(sndfile);
    00473     return returnValue;
    00474 }
    00475
    00476 void
    00477 printFeatures(int frame, int sr, int output,
    00478               Plugin::FeatureSet features, ofstream *out, bool useFrames)
    00479 {
    00480     for (unsigned int i = 0; i < features[output].size(); ++i) {
    00481
    00482         if (useFrames) {
    00483
    00484             int displayFrame = frame;
    00485
    00486             if (features[output][i].hasTimestamp) {
    00487                 displayFrame = RealTime::realTime2Frame
    00488                     (features[output][i].timestamp, sr);
    00489             }
    00490
    00491             (out ? *out : cout) << displayFrame;
    00492
    00493             if (features[output][i].hasDuration) {
    00494                 displayFrame = RealTime::realTime2Frame
    00495                     (features[output][i].duration, sr);
    00496                 (out ? *out : cout) << "," << displayFrame;
    00497             }
    00498
    00499             (out ? *out : cout)  << ":";
    00500
    00501         } else {
    00502
    00503             RealTime rt = RealTime::frame2RealTime(frame, sr);
    00504
    00505             if (features[output][i].hasTimestamp) {
    00506                 rt = features[output][i].timestamp;
    00507             }
    00508
    00509             (out ? *out : cout) << rt.toString();
    00510
    00511             if (features[output][i].hasDuration) {
    00512                 rt = features[output][i].duration;
    00513                 (out ? *out : cout) << "," << rt.toString();
    00514             }
    00515
    00516             (out ? *out : cout) << ":";
    00517         }
    00518
    00519         for (unsigned int j = 0; j < features[output][i].values.size(); ++j) {
    00520             (out ? *out : cout) << " " << features[output][i].values[j];
    00521         }
    00522
    00523         (out ? *out : cout) << endl;
    00524     }
    00525 }
    00526
    00527 void
    00528 printPluginPath(bool verbose)
    00529 {
    00530     if (verbose) {
    00531         cout << "\nVamp plugin search path: ";
    00532     }
    00533
    00534     vector<string> path = PluginHostAdapter::getPluginPath();
    00535     for (size_t i = 0; i < path.size(); ++i) {
    00536         if (verbose) {
    00537             cout << "[" << path[i] << "]";
    00538         } else {
    00539             cout << path[i] << endl;
    00540         }
    00541     }
    00542
    00543     if (verbose) cout << endl;
    00544 }
    00545
    00546 static
    00547 string
    00548 header(string text, int level)
    00549 {
    00550     string out = '\n' + text + '\n';
    00551     for (size_t i = 0; i < text.length(); ++i) {
    00552         out += (level == 1 ? '=' : level == 2 ? '-' : '~');
    00553     }
    00554     out += '\n';
    00555     return out;
    00556 }
    00557
    00558 void
    00559 enumeratePlugins(Verbosity verbosity)
    00560 {
    00561     PluginLoader *loader = PluginLoader::getInstance();
    00562
    00563     if (verbosity == PluginInformation) {
    00564         cout << "\nVamp plugin libraries found in search path:" << endl;
    00565     }
    00566
    00567     vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
    00568     typedef multimap<string, PluginLoader::PluginKey>
    00569         LibraryMap;
    00570     LibraryMap libraryMap;
    00571
    00572     for (size_t i = 0; i < plugins.size(); ++i) {
    00573         string path = loader->getLibraryPathForPlugin(plugins[i]);
    00574         libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
    00575     }
    00576
    00577     string prevPath = "";
    00578     int index = 0;
    00579
    00580     for (LibraryMap::iterator i = libraryMap.begin();
    00581          i != libraryMap.end(); ++i) {
    00582
    00583         string path = i->first;
    00584         PluginLoader::PluginKey key = i->second;
    00585
    00586         if (path != prevPath) {
    00587             prevPath = path;
    00588             index = 0;
    00589             if (verbosity == PluginInformation) {
    00590                 cout << "\n  " << path << ":" << endl;
    00591             } else if (verbosity == PluginInformationDetailed) {
    00592                 string::size_type ki = i->second.find(':');
    00593                 string text = "Library \"" + i->second.substr(0, ki) + "\"";
    00594                 cout << "\n" << header(text, 1);
    00595             }
    00596         }
    00597
    00598         Plugin *plugin = loader->loadPlugin(key, 48000);
    00599         if (plugin) {
    00600
    00601             char c = char('A' + index);
    00602             if (c > 'Z') c = char('a' + (index - 26));
    00603
    00604             PluginLoader::PluginCategoryHierarchy category =
    00605                 loader->getPluginCategory(key);
    00606             string catstr;
    00607             if (!category.empty()) {
    00608                 for (size_t ci = 0; ci < category.size(); ++ci) {
    00609                     if (ci > 0) catstr += " > ";
    00610                         catstr += category[ci];
    00611                 }
    00612             }
    00613
    00614             if (verbosity == PluginInformation) {
    00615
    00616                 cout << "    [" << c << "] [v"
    00617                      << plugin->getVampApiVersion() << "] "
    00618                      << plugin->getName() << ", \""
    00619                      << plugin->getIdentifier() << "\"" << " ["
    00620                      << plugin->getMaker() << "]" << endl;
    00621
    00622                 if (catstr != "") {
    00623                     cout << "       > " << catstr << endl;
    00624                 }
    00625
    00626                 if (plugin->getDescription() != "") {
    00627                     cout << "        - " << plugin->getDescription() << endl;
    00628                 }
    00629
    00630             } else if (verbosity == PluginInformationDetailed) {
    00631
    00632                 cout << header(plugin->getName(), 2);
    00633                 cout << " - Identifier:         "
    00634                      << key << endl;
    00635                 cout << " - Plugin Version:     "
    00636                      << plugin->getPluginVersion() << endl;
    00637                 cout << " - Vamp API Version:   "
    00638                      << plugin->getVampApiVersion() << endl;
    00639                 cout << " - Maker:              \""
    00640                      << plugin->getMaker() << "\"" << endl;
    00641                 cout << " - Copyright:          \""
    00642                      << plugin->getCopyright() << "\"" << endl;
    00643                 cout << " - Description:        \""
    00644                      << plugin->getDescription() << "\"" << endl;
    00645                 cout << " - Input Domain:       "
    00646                      << (plugin->getInputDomain() == Vamp::Plugin::TimeDomain ?
    00647                          "Time Domain" : "Frequency Domain") << endl;
    00648                 cout << " - Default Step Size:  "
    00649                      << plugin->getPreferredStepSize() << endl;
    00650                 cout << " - Default Block Size: "
    00651                      << plugin->getPreferredBlockSize() << endl;
    00652                 cout << " - Minimum Channels:   "
    00653                      << plugin->getMinChannelCount() << endl;
    00654                 cout << " - Maximum Channels:   "
    00655                      << plugin->getMaxChannelCount() << endl;
    00656
    00657             } else if (verbosity == PluginIds) {
    00658                 cout << "vamp:" << key << endl;
    00659             }
    00660
    00661             Plugin::OutputList outputs =
    00662                 plugin->getOutputDescriptors();
    00663
    00664             if (verbosity == PluginInformationDetailed) {
    00665
    00666                 Plugin::ParameterList params = plugin->getParameterDescriptors();
    00667                 for (size_t j = 0; j < params.size(); ++j) {
    00668                     Plugin::ParameterDescriptor &pd(params[j]);
    00669                     cout << "\nParameter " << j+1 << ": \"" << pd.name << "\"" << endl;
    00670                     cout << " - Identifier:         " << pd.identifier << endl;
    00671                     cout << " - Description:        \"" << pd.description << "\"" << endl;
    00672                     if (pd.unit != "") {
    00673                         cout << " - Unit:               " << pd.unit << endl;
    00674                     }
    00675                     cout << " - Range:              ";
    00676                     cout << pd.minValue << " -> " << pd.maxValue << endl;
    00677                     cout << " - Default:            ";
    00678                     cout << pd.defaultValue << endl;
    00679                     if (pd.isQuantized) {
    00680                         cout << " - Quantize Step:      "
    00681                              << pd.quantizeStep << endl;
    00682                     }
    00683                     if (!pd.valueNames.empty()) {
    00684                         cout << " - Value Names:        ";
    00685                         for (size_t k = 0; k < pd.valueNames.size(); ++k) {
    00686                             if (k > 0) cout << ", ";
    00687                             cout << "\"" << pd.valueNames[k] << "\"";
    00688                         }
    00689                         cout << endl;
    00690                     }
    00691                 }
    00692
    00693                 if (outputs.empty()) {
    00694                     cout << "\n** Note: This plugin reports no outputs!" << endl;
    00695                 }
    00696                 for (size_t j = 0; j < outputs.size(); ++j) {
    00697                     Plugin::OutputDescriptor &od(outputs[j]);
    00698                     cout << "\nOutput " << j+1 << ": \"" << od.name << "\"" << endl;
    00699                     cout << " - Identifier:         " << od.identifier << endl;
    00700                     cout << " - Description:        \"" << od.description << "\"" << endl;
    00701                     if (od.unit != "") {
    00702                         cout << " - Unit:               " << od.unit << endl;
    00703                     }
    00704                     if (od.hasFixedBinCount) {
    00705                         cout << " - Default Bin Count:  " << od.binCount << endl;
    00706                     }
    00707                     if (!od.binNames.empty()) {
    00708                         bool have = false;
    00709                         for (size_t k = 0; k < od.binNames.size(); ++k) {
    00710                             if (od.binNames[k] != "") {
    00711                                 have = true; break;
    00712                             }
    00713                         }
    00714                         if (have) {
    00715                             cout << " - Bin Names:          ";
    00716                             for (size_t k = 0; k < od.binNames.size(); ++k) {
    00717                                 if (k > 0) cout << ", ";
    00718                                 cout << "\"" << od.binNames[k] << "\"";
    00719                             }
    00720                             cout << endl;
    00721                         }
    00722                     }
    00723                     if (od.hasKnownExtents) {
    00724                         cout << " - Default Extents:    ";
    00725                         cout << od.minValue << " -> " << od.maxValue << endl;
    00726                     }
    00727                     if (od.isQuantized) {
    00728                         cout << " - Quantize Step:      "
    00729                              << od.quantizeStep << endl;
    00730                     }
    00731                     cout << " - Sample Type:        "
    00732                          << (od.sampleType ==
    00733                              Plugin::OutputDescriptor::OneSamplePerStep ?
    00734                              "One Sample Per Step" :
    00735                              od.sampleType ==
    00736                              Plugin::OutputDescriptor::FixedSampleRate ?
    00737                              "Fixed Sample Rate" :
    00738                              "Variable Sample Rate") << endl;
    00739                     if (od.sampleType !=
    00740                         Plugin::OutputDescriptor::OneSamplePerStep) {
    00741                         cout << " - Default Rate:       "
    00742                              << od.sampleRate << endl;
    00743                     }
    00744                     cout << " - Has Duration:       "
    00745                          << (od.hasDuration ? "Yes" : "No") << endl;
    00746                 }
    00747             }
    00748
    00749             if (outputs.size() > 1 || verbosity == PluginOutputIds) {
    00750                 for (size_t j = 0; j < outputs.size(); ++j) {
    00751                     if (verbosity == PluginInformation) {
    00752                         cout << "         (" << j << ") "
    00753                              << outputs[j].name << ", \""
    00754                              << outputs[j].identifier << "\"" << endl;
    00755                         if (outputs[j].description != "") {
    00756                             cout << "             - "
    00757                                  << outputs[j].description << endl;
    00758                         }
    00759                     } else if (verbosity == PluginOutputIds) {
    00760                         cout << "vamp:" << key << ":" << outputs[j].identifier << endl;
    00761                     }
    00762                 }
    00763             }
    00764
    00765             ++index;
    00766
    00767             delete plugin;
    00768         }
    00769     }
    00770
    00771     if (verbosity == PluginInformation ||
    00772         verbosity == PluginInformationDetailed) {
    00773         cout << endl;
    00774     }
    00775 }
    00776
    00777 void
    00778 printPluginCategoryList()
    00779 {
    00780     PluginLoader *loader = PluginLoader::getInstance();
    00781
    00782     vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
    00783
    00784     set<string> printedcats;
    00785
    00786     for (size_t i = 0; i < plugins.size(); ++i) {
    00787
    00788         PluginLoader::PluginKey key = plugins[i];
    00789
    00790         PluginLoader::PluginCategoryHierarchy category =
    00791             loader->getPluginCategory(key);
    00792
    00793         Plugin *plugin = loader->loadPlugin(key, 48000);
    00794         if (!plugin) continue;
    00795
    00796         string catstr = "";
    00797
    00798         if (category.empty()) catstr = '|';
    00799         else {
    00800             for (size_t j = 0; j < category.size(); ++j) {
    00801                 catstr += category[j];
    00802                 catstr += '|';
    00803                 if (printedcats.find(catstr) == printedcats.end()) {
    00804                     std::cout << catstr << std::endl;
    00805                     printedcats.insert(catstr);
    00806                 }
    00807             }
    00808         }
    00809
    00810         std::cout << catstr << key << ":::" << plugin->getName() << ":::" << plugin->getMaker() << ":::" << plugin->getDescription() << std::endl;
    00811     }
    00812 }
    00813