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 

Generated on Tue Dec 29 17:12:02 2009 for VampPluginSDK by  doxygen 1.6.1