changeset 66:7afcfe666910

* Modify to use Vamp SDK for proper feature extraction plugins. Requires that the vamp-plugin-sdk directory tree be present below plugin/ (it's separate in Subversion).
author Chris Cannam
date Fri, 31 Mar 2006 15:56:35 +0000
parents e1aad27029e3
children eb530055ed55
files base/RealTime.h plugin/DSSIPluginFactory.cpp plugin/DSSIPluginInstance.cpp plugin/DSSIPluginInstance.h plugin/FeatureExtractionPlugin.h plugin/FeatureExtractionPluginAdapter.cpp plugin/FeatureExtractionPluginAdapter.h plugin/FeatureExtractionPluginFactory.cpp plugin/FeatureExtractionPluginFactory.h plugin/FeatureExtractionPluginHostAdapter.cpp plugin/FeatureExtractionPluginHostAdapter.h plugin/LADSPAPluginInstance.cpp plugin/LADSPAPluginInstance.h plugin/PluginDescription.h plugin/PluginInstance.cpp plugin/PluginInstance.h plugin/PluginXml.cpp plugin/PluginXml.h plugin/RealTimePluginInstance.h transform/FeatureExtractionPluginTransform.cpp transform/FeatureExtractionPluginTransform.h transform/RealTimePluginTransform.cpp transform/TransformFactory.cpp
diffstat 23 files changed, 503 insertions(+), 1666 deletions(-) [+]
line wrap: on
line diff
--- a/base/RealTime.h	Thu Mar 30 15:00:22 2006 +0000
+++ b/base/RealTime.h	Fri Mar 31 15:56:35 2006 +0000
@@ -21,6 +21,11 @@
 #ifndef _REAL_TIME_H_
 #define _REAL_TIME_H_
 
+#include "vamp-sdk/RealTime.h"
+using Vamp::RealTime;
+
+#ifdef NOT_DEFINED
+
 #include <iostream>
 #include <string>
 
@@ -117,5 +122,7 @@
 };
 
 std::ostream &operator<<(std::ostream &out, const RealTime &rt);
+
+#endif
     
 #endif
--- a/plugin/DSSIPluginFactory.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ b/plugin/DSSIPluginFactory.cpp	Fri Mar 31 15:56:35 2006 +0000
@@ -206,7 +206,10 @@
     if (path == "") {
 	path = "/usr/local/lib/dssi:/usr/lib/dssi";
 	char *home = getenv("HOME");
-	if (home) path = std::string(home) + "/.dssi:" + path;
+	if (home) {
+            path = std::string(home) + "/dssi:" +
+                   std::string(home) + "/.dssi:" + path;
+        }
     }
 
     std::string::size_type index = 0, newindex = 0;
--- a/plugin/DSSIPluginInstance.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ b/plugin/DSSIPluginInstance.cpp	Fri Mar 31 15:56:35 2006 +0000
@@ -253,7 +253,7 @@
 #endif
 
     if (m_latencyPort) {
-	if (!m_run) run(RealTime::zeroTime);
+	if (!m_run) run(Vamp::RealTime::zeroTime);
 	latency = (size_t)(*m_latencyPort + 0.1);
     }
     
@@ -850,7 +850,7 @@
 }
 
 void
-DSSIPluginInstance::sendEvent(const RealTime &eventTime,
+DSSIPluginInstance::sendEvent(const Vamp::RealTime &eventTime,
 			      const void *e)
 {
 #ifdef DEBUG_DSSI_PROCESS
@@ -926,7 +926,7 @@
 }
 
 void
-DSSIPluginInstance::run(const RealTime &blockTime)
+DSSIPluginInstance::run(const Vamp::RealTime &blockTime)
 {
     static snd_seq_event_t localEventBuffer[EVENT_BUFFER_SIZE];
     int evCount = 0;
@@ -980,11 +980,11 @@
 	*ev = m_eventBuffer.peekOne();
 	bool accept = true;
 
-	RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
+	Vamp::RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
 
 	int frameOffset = 0;
 	if (evTime > blockTime) {
-	    frameOffset = RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
+	    frameOffset = Vamp::RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
 	}
 
 #ifdef DEBUG_DSSI_PROCESS
@@ -1084,7 +1084,7 @@
 }
 
 void
-DSSIPluginInstance::runGrouped(const RealTime &blockTime)
+DSSIPluginInstance::runGrouped(const Vamp::RealTime &blockTime)
 {
     // If something else in our group has just been called for this
     // block time (but we haven't) then we should just write out the
@@ -1156,11 +1156,11 @@
 	    *ev = instance->m_eventBuffer.peekOne();
 	    bool accept = true;
 
-	    RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
+	    Vamp::RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
 
 	    int frameOffset = 0;
 	    if (evTime > blockTime) {
-		frameOffset = RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
+		frameOffset = Vamp::RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
 	    }
 
 #ifdef DEBUG_DSSI_PROCESS
--- a/plugin/DSSIPluginInstance.h	Thu Mar 30 15:00:22 2006 +0000
+++ b/plugin/DSSIPluginInstance.h	Fri Mar 31 15:56:35 2006 +0000
@@ -53,7 +53,7 @@
     virtual int getPluginVersion() const;
     virtual std::string getCopyright() const;
 
-    virtual void run(const RealTime &);
+    virtual void run(const Vamp::RealTime &);
 
     virtual unsigned int getParameterCount() const;
     virtual void setParameterValue(unsigned int parameter, float value);
@@ -65,7 +65,7 @@
     virtual void setParameter(std::string, float);
 
     virtual std::string configure(std::string key, std::string value);
-    virtual void sendEvent(const RealTime &eventTime,
+    virtual void sendEvent(const Vamp::RealTime &eventTime,
 			   const void *event);
     virtual void clearEvents();
 
@@ -126,7 +126,7 @@
     void checkProgramCache() const;
 
     void initialiseGroupMembership();
-    void runGrouped(const RealTime &);
+    void runGrouped(const Vamp::RealTime &);
 
     // For use in DSSIPluginFactory (set in the DSSI_Host_Descriptor):
     static int requestMidiSend(LADSPA_Handle instance,
@@ -183,9 +183,9 @@
     bool                      m_bypassed;
     std::string               m_program;
     bool                      m_grouped;
-    RealTime                  m_lastRunTime;
+    Vamp::RealTime            m_lastRunTime;
 
-    RealTime                  m_lastEventSendTime;
+    Vamp::RealTime            m_lastEventSendTime;
     bool                      m_haveLastEventSendTime;
 
     QMutex                    m_processLock;
--- a/plugin/FeatureExtractionPlugin.h	Thu Mar 30 15:00:22 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,318 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _FEATURE_EXTRACTION_PLUGIN_H_
-#define _FEATURE_EXTRACTION_PLUGIN_H_
-
-#include "PluginInstance.h"
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include "base/RealTime.h"
-
-/**
- * FeatureExtractionPlugin is a base class for plugin instance classes
- * that provide feature extraction from audio or related data.
- *
- * In most cases, the input will be audio and the output will be a
- * stream of derived data at a lower sampling resolution than the
- * input.
- *
- * Note that this class inherits several abstract methods from
- * PluginInstance, that must be implemented by the subclass.
- */
-
-/**
- * Plugin Lifecycle
- * ================
- *
- * Feature extraction plugins are managed differently from real-time
- * plugins.  The main difference is that the parameters for a feature
- * extraction plugin are configured before the plugin is used, and do
- * not change during use.
- *
- * 1. Host constructs the plugin, passing it the input sample rate.
- * The plugin may do basic initialisation, but should not do anything
- * computationally expensive at this point.
- *
- * 2. Host may query the plugin's available outputs.
- *
- * 3. Host queries programs and parameter descriptors, and may set
- * some or all of them.  Parameters that are not explicitly set should
- * take their default values as specified in the parameter descriptor.
- * When a program is set, the parameter values may change and the host
- * will re-query them to check.
- *
- * 4. Host queries the preferred step size, block size, number of
- * channels, and the number of values per feature for the plugin's
- * outputs.  These may all vary depending on the parameter values.
- *
- * 5. Plugin is properly initialised with a call to initialise.  This
- * fixes the step size, block size, and number of channels, as well as
- * all of the parameter and program settings.  If the values passed in
- * to initialise do not match the plugin's advertised preferred values
- * from step 4, the plugin may refuse to initialise and return false
- * (although if possible it should accept the new values).
- *
- * 6. Host will repeatedly call the process method to pass in blocks
- * of input data.  This method may return features extracted from that
- * data (if the plugin is causal).
- *
- * 7. Host will call getRemainingFeatures exactly once, after all the
- * input data has been processed.  This may return any non-causal or
- * leftover features.
- *
- * 8. At any point after initialise was called, the host may
- * optionally call the reset method and restart processing.  (This
- * does not mean it can change the parameters, which are fixed from
- * initialise until destruction.)
- *
- * A plugin does not need to handle the case where setParameter or
- * selectProgram is called after initialise has been called.  It's the
- * host's responsibility not to do that.
- */
-
-class FeatureExtractionPlugin : public PluginInstance
-{
-public:
-    /**
-     * Initialise a plugin to prepare it for use with the given number
-     * of input channels, step size (window increment, in sample
-     * frames) and block size (window size, in sample frames).
-     *
-     * The input sample rate should have been already specified at
-     * construction time.
-     * 
-     * Return true for successful initialisation, false if the number
-     * of input channels, step size and/or block size cannot be
-     * supported.
-     */
-    virtual bool initialise(size_t inputChannels,
-			    size_t stepSize,
-			    size_t blockSize) = 0;
-
-    /**
-     * Reset the plugin after use, to prepare it for another clean
-     * run.  Not called for the first initialisation (i.e. initialise
-     * must also do a reset).
-     */
-    virtual void reset() = 0;
-
-    /**
-     * Get the preferred step size (window increment -- the distance
-     * in sample frames between the start frames of consecutive blocks
-     * passed to the process() function) for the plugin.  This should
-     * be called before initialise().
-     */
-    virtual size_t getPreferredStepSize() const = 0;
-
-    /**
-     * Get the preferred block size (window size -- the number of
-     * sample frames passed in each block to the process() function).
-     * This should be called before initialise().
-     */
-    virtual size_t getPreferredBlockSize() const { return getPreferredStepSize(); }
-
-    /**
-     * Get the minimum supported number of input channels.
-     */
-    virtual size_t getMinChannelCount() const { return 1; }
-
-    /**
-     * Get the maximum supported number of input channels.
-     */
-    virtual size_t getMaxChannelCount() const { return 1; }
-
-    struct OutputDescriptor
-    {
-	/**
-	 * The name of the output, in computer-usable form.  Should be
-	 * reasonably short and without whitespace or punctuation.
-	 */
-	std::string name;
-
-	/**
-	 * The human-readable name of the output.
-	 */
-	std::string description;
-
-	/**
-	 * The unit of the output, in human-readable form.
-	 */
-	std::string unit;
-
-	/**
-	 * True if the output has the same number of values per result
-	 * for every output result.  Outputs for which this is false
-	 * are unlikely to be very useful in a general-purpose host.
-	 */
-	bool hasFixedValueCount;
-
-	/**
-	 * The number of values per result of the output.  Undefined
-	 * if hasFixedValueCount is false.  If this is zero, the output
-	 * is point data (i.e. only the time of each output is of
-	 * interest, the value list will be empty).
-	 *
-	 * Note that this gives the number of values of a single
-	 * output result, not of the output stream (which has one more
-	 * dimension: time).
-	 */
-	size_t valueCount;
-
-	/**
-	 * The names of each of the values, if appropriate.  This is
-	 * always optional.
-	 */
-	std::vector<std::string> valueNames;
-
-	/**
-	 * True if the results in the output have a fixed numeric
-	 * range (minimum and maximum values).  Undefined if
-	 * valueCount is zero.
-	 */
-	bool hasKnownExtents;
-
-	/**
-	 * Minimum value of the results in the output.  Undefined if
-	 * hasKnownExtents is false or valueCount is zero.
-	 */
-	float minValue;
-
-	/**
-	 * Maximum value of the results in the output.  Undefined if
-	 * hasKnownExtents is false or valueCount is zero.
-	 */
-	float maxValue;
-
-	/**
-	 * True if the output values are quantized to a particular
-	 * resolution.  Undefined if valueCount is zero.
-	 */
-	bool isQuantized;
-
-	/**
-	 * Quantization resolution of the output values (e.g. 1.0 if
-	 * they are all integers).  Undefined if isQuantized is false
-	 * or valueCount is zero.
-	 */
-	float quantizeStep;
-
-	enum SampleType {
-
-	    /// Results from each process() align with that call's block start
-	    OneSamplePerStep,
-
-	    /// Results are evenly spaced in time (sampleRate specified below)
-	    FixedSampleRate,
-
-	    /// Results are unevenly spaced and have individual timestamps
-	    VariableSampleRate
-	};
-
-	/**
-	 * Positioning in time of the output results.
-	 */
-	SampleType sampleType;
-
-	/**
-	 * Sample rate of the output results.  Undefined if sampleType
-	 * is OneSamplePerStep.
-	 *
-	 * If sampleType is VariableSampleRate and this value is
-	 * non-zero, then it may be used to calculate a resolution for
-	 * the output (i.e. the "duration" of each value, in time).
-	 * It's recommended to set this to zero if that behaviour is
-	 * not desired.
-	 */
-	float sampleRate;
-    };
-
-    typedef std::vector<OutputDescriptor> OutputList;
-
-    /**
-     * Get the outputs of this plugin.  An output's index in this list
-     * is used as its numeric index when looking it up in the
-     * FeatureSet returned from the process() call.
-     */
-    virtual OutputList getOutputDescriptors() const = 0;
-
-    struct Feature
-    {
-	/**
-	 * True if an output feature has its own timestamp.  This is
-	 * mandatory if the output has VariableSampleRate, and is
-	 * likely to be disregarded otherwise.
-	 */
-	bool hasTimestamp;
-
-	/**
-	 * Timestamp of the output feature.  This is mandatory if the
-	 * output has VariableSampleRate, and is likely to be
-	 * disregarded otherwise.  Undefined if hasTimestamp is false.
-	 */
-	RealTime timestamp;
-	
-	/**
-	 * Results for a single sample of this feature.  If the output
-	 * hasFixedValueCount, there must be the same number of values
-	 * as the output's valueCount count.
-	 */
-	std::vector<float> values;
-
-	/**
-	 * Label for the sample of this feature.
-	 */
-	std::string label;
-    };
-
-    typedef std::vector<Feature> FeatureList;
-    typedef std::map<int, FeatureList> FeatureSet; // key is output no
-
-    /**
-     * Process a single block of input data.  inputBuffers points to
-     * one array of floats per input channel, and each of those arrays
-     * contains the blockSize number of samples (the host will
-     * zero-pad as necessary).  The timestamp is the real time in
-     * seconds of the start of the supplied block of samples.
-     *
-     * Return any features that have become available after this
-     * process call.  (These do not necessarily have to fall within
-     * the process block, except for OneSamplePerStep outputs.)
-     */
-    virtual FeatureSet process(float **inputBuffers,
-			       RealTime timestamp) = 0;
-
-    /**
-     * After all blocks have been processed, calculate and return any
-     * remaining features derived from the complete input.
-     */
-    virtual FeatureSet getRemainingFeatures() = 0;
-
-    virtual std::string getType() const { return "Feature Extraction Plugin"; }
-
-protected:
-    FeatureExtractionPlugin(float inputSampleRate) :
-	m_inputSampleRate(inputSampleRate) { }
-
-    float m_inputSampleRate;
-};
-
-#endif
-
-
-
--- a/plugin/FeatureExtractionPluginAdapter.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,439 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-  Sonic Visualiser
-  An audio file viewer and annotation editor.
-  Centre for Digital Music, Queen Mary, University of London.
-  This file copyright 2006 Chris Cannam.
-    
-  This program is free software; you can redistribute it and/or
-  modify it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 2 of the
-  License, or (at your option) any later version.  See the file
-  COPYING included with this distribution for more information.
-*/
-
-#include "FeatureExtractionPluginAdapter.h"
-
-FeatureExtractionPluginAdapterBase::FeatureExtractionPluginAdapterBase() :
-    m_populated(false)
-{
-}
-
-const SVPPluginDescriptor *
-FeatureExtractionPluginAdapterBase::getDescriptor()
-{
-    if (m_populated) return &m_descriptor;
-
-    FeatureExtractionPlugin *plugin = createPlugin(48000);
-
-    m_parameters = plugin->getParameterDescriptors();
-    m_programs = plugin->getPrograms();
-    
-    m_descriptor.name = strdup(plugin->getName().c_str());
-    m_descriptor.description = strdup(plugin->getDescription().c_str());
-    m_descriptor.maker = strdup(plugin->getMaker().c_str());
-    m_descriptor.pluginVersion = plugin->getPluginVersion();
-    m_descriptor.copyright = strdup(plugin->getCopyright().c_str());
-    
-    m_descriptor.parameterCount = m_parameters.size();
-    m_descriptor.parameters = (const SVPParameterDescriptor **)
-        malloc(m_parameters.size() * sizeof(SVPParameterDescriptor));
-    
-    for (unsigned int i = 0; i < m_parameters.size(); ++i) {
-        SVPParameterDescriptor *desc = (SVPParameterDescriptor *)
-            malloc(sizeof(SVPParameterDescriptor));
-        desc->name = strdup(m_parameters[i].name.c_str());
-        desc->description = strdup(m_parameters[i].description.c_str());
-        desc->unit = strdup(m_parameters[i].unit.c_str());
-        desc->minValue = m_parameters[i].minValue;
-        desc->maxValue = m_parameters[i].maxValue;
-        desc->defaultValue = m_parameters[i].defaultValue;
-        desc->isQuantized = m_parameters[i].isQuantized;
-        desc->quantizeStep = m_parameters[i].quantizeStep;
-        m_descriptor.parameters[i] = desc;
-    }
-    
-    m_descriptor.programCount = m_programs.size();
-    m_descriptor.programs = (const char **)
-        malloc(m_programs.size() * sizeof(const char *));
-    
-    for (unsigned int i = 0; i < m_programs.size(); ++i) {
-        m_descriptor.programs[i] = strdup(m_programs[i].c_str());
-    }
-    
-    m_descriptor.instantiate = svpInstantiate;
-    m_descriptor.cleanup = svpCleanup;
-    m_descriptor.initialise = svpInitialise;
-    m_descriptor.reset = svpReset;
-    m_descriptor.getParameter = svpGetParameter;
-    m_descriptor.setParameter = svpSetParameter;
-    m_descriptor.getCurrentProgram = svpGetCurrentProgram;
-    m_descriptor.selectProgram = svpSelectProgram;
-    m_descriptor.getPreferredStepSize = svpGetPreferredStepSize;
-    m_descriptor.getPreferredBlockSize = svpGetPreferredBlockSize;
-    m_descriptor.getMinChannelCount = svpGetMinChannelCount;
-    m_descriptor.getMaxChannelCount = svpGetMaxChannelCount;
-    m_descriptor.getOutputCount = svpGetOutputCount;
-    m_descriptor.getOutputDescriptor = svpGetOutputDescriptor;
-    m_descriptor.releaseOutputDescriptor = svpReleaseOutputDescriptor;
-    m_descriptor.process = svpProcess;
-    m_descriptor.getRemainingFeatures = svpGetRemainingFeatures;
-    m_descriptor.releaseFeatureSet = svpReleaseFeatureSet;
-    
-    m_adapterMap[&m_descriptor] = this;
-
-    delete plugin;
-
-    m_populated = true;
-    return &m_descriptor;
-}
-
-FeatureExtractionPluginAdapterBase::~FeatureExtractionPluginAdapterBase()
-{
-    if (!m_populated) return;
-
-    free((void *)m_descriptor.name);
-    free((void *)m_descriptor.description);
-    free((void *)m_descriptor.maker);
-    free((void *)m_descriptor.copyright);
-        
-    for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) {
-        const SVPParameterDescriptor *desc = m_descriptor.parameters[i];
-        free((void *)desc->name);
-        free((void *)desc->description);
-        free((void *)desc->unit);
-    }
-    free((void *)m_descriptor.parameters);
-
-    for (unsigned int i = 0; i < m_descriptor.programCount; ++i) {
-        free((void *)m_descriptor.programs[i]);
-    }
-    free((void *)m_descriptor.programs);
-
-    m_adapterMap.erase(&m_descriptor);
-}
-
-FeatureExtractionPluginAdapterBase *
-FeatureExtractionPluginAdapterBase::lookupAdapter(SVPPluginHandle handle)
-{
-    AdapterMap::const_iterator i = m_adapterMap.find(handle);
-    if (i == m_adapterMap.end()) return 0;
-    return i->second;
-}
-
-SVPPluginHandle
-FeatureExtractionPluginAdapterBase::svpInstantiate(const SVPPluginDescriptor *desc,
-                                                   float inputSampleRate)
-{
-    if (m_adapterMap.find(desc) == m_adapterMap.end()) return 0;
-    FeatureExtractionPluginAdapterBase *adapter = m_adapterMap[desc];
-    if (desc != &adapter->m_descriptor) return 0;
-
-    FeatureExtractionPlugin *plugin = adapter->createPlugin(inputSampleRate);
-    if (plugin) {
-        m_adapterMap[plugin] = adapter;
-    }
-
-    return plugin;
-}
-
-void
-FeatureExtractionPluginAdapterBase::svpCleanup(SVPPluginHandle handle)
-{
-    FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle);
-    if (!adapter) {
-        delete ((FeatureExtractionPlugin *)handle);
-        return;
-    }
-    adapter->cleanup(((FeatureExtractionPlugin *)handle));
-}
-
-int
-FeatureExtractionPluginAdapterBase::svpInitialise(SVPPluginHandle handle,
-                                                  unsigned int channels,
-                                                  unsigned int stepSize,
-                                                  unsigned int blockSize)
-{
-    bool result = ((FeatureExtractionPlugin *)handle)->initialise
-        (channels, stepSize, blockSize);
-    return result ? 1 : 0;
-}
-
-void
-FeatureExtractionPluginAdapterBase::svpReset(SVPPluginHandle handle) 
-{
-    ((FeatureExtractionPlugin *)handle)->reset();
-}
-
-float
-FeatureExtractionPluginAdapterBase::svpGetParameter(SVPPluginHandle handle,
-                                                    int param) 
-{
-    FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle);
-    if (!adapter) return 0.0;
-    FeatureExtractionPlugin::ParameterList &list = adapter->m_parameters;
-    return ((FeatureExtractionPlugin *)handle)->getParameter(list[param].name);
-}
-
-void
-FeatureExtractionPluginAdapterBase::svpSetParameter(SVPPluginHandle handle,
-                                                    int param, float value)
-{
-    FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle);
-    if (!adapter) return;
-    FeatureExtractionPlugin::ParameterList &list = adapter->m_parameters;
-    ((FeatureExtractionPlugin *)handle)->setParameter(list[param].name, value);
-}
-
-unsigned int
-FeatureExtractionPluginAdapterBase::svpGetCurrentProgram(SVPPluginHandle handle)
-{
-    FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle);
-    if (!adapter) return 0;
-    FeatureExtractionPlugin::ProgramList &list = adapter->m_programs;
-    std::string program = ((FeatureExtractionPlugin *)handle)->getCurrentProgram();
-    for (unsigned int i = 0; i < list.size(); ++i) {
-        if (list[i] == program) return i;
-    }
-    return 0;
-}
-
-void
-FeatureExtractionPluginAdapterBase::svpSelectProgram(SVPPluginHandle handle,
-                                                     unsigned int program)
-{
-    FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle);
-    if (!adapter) return;
-    FeatureExtractionPlugin::ProgramList &list = adapter->m_programs;
-    ((FeatureExtractionPlugin *)handle)->selectProgram(list[program]);
-}
-
-unsigned int
-FeatureExtractionPluginAdapterBase::svpGetPreferredStepSize(SVPPluginHandle handle)
-{
-    return ((FeatureExtractionPlugin *)handle)->getPreferredStepSize();
-}
-
-unsigned int
-FeatureExtractionPluginAdapterBase::svpGetPreferredBlockSize(SVPPluginHandle handle) 
-{
-    return ((FeatureExtractionPlugin *)handle)->getPreferredBlockSize();
-}
-
-unsigned int
-FeatureExtractionPluginAdapterBase::svpGetMinChannelCount(SVPPluginHandle handle)
-{
-    return ((FeatureExtractionPlugin *)handle)->getMinChannelCount();
-}
-
-unsigned int
-FeatureExtractionPluginAdapterBase::svpGetMaxChannelCount(SVPPluginHandle handle)
-{
-    return ((FeatureExtractionPlugin *)handle)->getMaxChannelCount();
-}
-
-unsigned int
-FeatureExtractionPluginAdapterBase::svpGetOutputCount(SVPPluginHandle handle)
-{
-    FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle);
-    if (!adapter) return 0;
-    return adapter->getOutputCount((FeatureExtractionPlugin *)handle);
-}
-
-SVPOutputDescriptor *
-FeatureExtractionPluginAdapterBase::svpGetOutputDescriptor(SVPPluginHandle handle,
-                                                           unsigned int i)
-{
-    FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle);
-    if (!adapter) return 0;
-    return adapter->getOutputDescriptor((FeatureExtractionPlugin *)handle, i);
-}
-
-void
-FeatureExtractionPluginAdapterBase::svpReleaseOutputDescriptor(SVPOutputDescriptor *desc)
-{
-    if (desc->name) free((void *)desc->name);
-    if (desc->description) free((void *)desc->description);
-    if (desc->unit) free((void *)desc->unit);
-    for (unsigned int i = 0; i < desc->valueCount; ++i) {
-        free((void *)desc->valueNames[i]);
-    }
-    if (desc->valueNames) free((void *)desc->valueNames);
-    free((void *)desc);
-}
-
-SVPFeatureList **
-FeatureExtractionPluginAdapterBase::svpProcess(SVPPluginHandle handle,
-                                               float **inputBuffers,
-                                               int sec,
-                                               int nsec)
-{
-    FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle);
-    if (!adapter) return 0;
-    return adapter->process((FeatureExtractionPlugin *)handle,
-                            inputBuffers, sec, nsec);
-}
-
-SVPFeatureList **
-FeatureExtractionPluginAdapterBase::svpGetRemainingFeatures(SVPPluginHandle handle)
-{
-    FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle);
-    if (!adapter) return 0;
-    return adapter->getRemainingFeatures((FeatureExtractionPlugin *)handle);
-}
-
-void
-FeatureExtractionPluginAdapterBase::svpReleaseFeatureSet(SVPFeatureList **fs)
-{
-    if (!fs) return;
-    for (unsigned int i = 0; fs[i]; ++i) {
-        for (unsigned int j = 0; j < fs[i]->featureCount; ++j) {
-            SVPFeature *feature = &fs[i]->features[j];
-            if (feature->values) free((void *)feature->values);
-            if (feature->label) free((void *)feature->label);
-            free((void *)feature);
-        }
-        if (fs[i]->features) free((void *)fs[i]->features);
-        free((void *)fs[i]);
-    }
-    free((void *)fs);
-}
-
-void 
-FeatureExtractionPluginAdapterBase::cleanup(FeatureExtractionPlugin *plugin)
-{
-    if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) {
-        delete m_pluginOutputs[plugin];
-        m_pluginOutputs.erase(plugin);
-    }
-    m_adapterMap.erase(plugin);
-    delete ((FeatureExtractionPlugin *)plugin);
-}
-
-void 
-FeatureExtractionPluginAdapterBase::checkOutputMap(FeatureExtractionPlugin *plugin)
-{
-    if (!m_pluginOutputs[plugin]) {
-        m_pluginOutputs[plugin] = new FeatureExtractionPlugin::OutputList
-            (plugin->getOutputDescriptors());
-    }
-}
-
-unsigned int 
-FeatureExtractionPluginAdapterBase::getOutputCount(FeatureExtractionPlugin *plugin)
-{
-    checkOutputMap(plugin);
-    return m_pluginOutputs[plugin]->size();
-}
-
-SVPOutputDescriptor *
-FeatureExtractionPluginAdapterBase::getOutputDescriptor(FeatureExtractionPlugin *plugin,
-                                                        unsigned int i)
-{
-    checkOutputMap(plugin);
-    FeatureExtractionPlugin::OutputDescriptor &od =
-        (*m_pluginOutputs[plugin])[i];
-
-    SVPOutputDescriptor *desc = (SVPOutputDescriptor *)
-        malloc(sizeof(SVPOutputDescriptor));
-
-    desc->name = strdup(od.name.c_str());
-    desc->description = strdup(od.description.c_str());
-    desc->unit = strdup(od.unit.c_str());
-    desc->hasFixedValueCount = od.hasFixedValueCount;
-    desc->valueCount = od.valueCount;
-
-    desc->valueNames = (const char **)
-        malloc(od.valueCount * sizeof(const char *));
-        
-    for (unsigned int i = 0; i < od.valueCount; ++i) {
-        desc->valueNames[i] = strdup(od.valueNames[i].c_str());
-    }
-
-    desc->hasKnownExtents = od.hasKnownExtents;
-    desc->minValue = od.minValue;
-    desc->maxValue = od.maxValue;
-    desc->isQuantized = od.isQuantized;
-    desc->quantizeStep = od.quantizeStep;
-
-    switch (od.sampleType) {
-    case FeatureExtractionPlugin::OutputDescriptor::OneSamplePerStep:
-        desc->sampleType = svpOneSamplePerStep; break;
-    case FeatureExtractionPlugin::OutputDescriptor::FixedSampleRate:
-        desc->sampleType = svpFixedSampleRate; break;
-    case FeatureExtractionPlugin::OutputDescriptor::VariableSampleRate:
-        desc->sampleType = svpVariableSampleRate; break;
-    }
-
-    desc->sampleRate = od.sampleRate;
-
-    return desc;
-}
-    
-SVPFeatureList **
-FeatureExtractionPluginAdapterBase::process(FeatureExtractionPlugin *plugin,
-                                            float **inputBuffers,
-                                            int sec, int nsec)
-{
-    RealTime rt(sec, nsec);
-    return convertFeatures(plugin->process(inputBuffers, rt));
-}
-    
-SVPFeatureList **
-FeatureExtractionPluginAdapterBase::getRemainingFeatures(FeatureExtractionPlugin *plugin)
-{
-    return convertFeatures(plugin->getRemainingFeatures());
-}
-
-SVPFeatureList **
-FeatureExtractionPluginAdapterBase::convertFeatures(const FeatureExtractionPlugin::FeatureSet &features)
-{
-    unsigned int n = 0;
-    if (features.begin() != features.end()) {
-        FeatureExtractionPlugin::FeatureSet::const_iterator i = features.end();
-        --i;
-        n = i->first + 1;
-    }
-
-    if (!n) return 0;
-
-    SVPFeatureList **fs = (SVPFeatureList **)
-        malloc((n + 1) * sizeof(SVPFeatureList *));
-
-    for (unsigned int i = 0; i < n; ++i) {
-        fs[i] = (SVPFeatureList *)malloc(sizeof(SVPFeatureList));
-        if (features.find(i) == features.end()) {
-            fs[i]->featureCount = 0;
-            fs[i]->features = 0;
-        } else {
-            FeatureExtractionPlugin::FeatureSet::const_iterator fi =
-                features.find(i);
-            const FeatureExtractionPlugin::FeatureList &fl = fi->second;
-            fs[i]->featureCount = fl.size();
-            fs[i]->features = (SVPFeature *)malloc(fl.size() *
-                                                   sizeof(SVPFeature));
-            for (unsigned int j = 0; j < fl.size(); ++j) {
-                fs[i]->features[j].hasTimestamp = fl[j].hasTimestamp;
-                fs[i]->features[j].sec = fl[j].timestamp.sec;
-                fs[i]->features[j].nsec = fl[j].timestamp.nsec;
-                fs[i]->features[j].valueCount = fl[j].values.size();
-                fs[i]->features[j].values = (float *)malloc
-                    (fs[i]->features[j].valueCount * sizeof(float));
-                for (unsigned int k = 0; k < fs[i]->features[j].valueCount; ++k) {
-                    fs[i]->features[j].values[k] = fl[j].values[k];
-                }
-                fs[i]->features[j].label = strdup(fl[j].label.c_str());
-            }
-        }
-    }
-
-    fs[n] = 0;
-
-    return fs;
-}
-
-FeatureExtractionPluginAdapterBase::AdapterMap 
-FeatureExtractionPluginAdapterBase::m_adapterMap;
-
-
--- a/plugin/FeatureExtractionPluginAdapter.h	Thu Mar 30 15:00:22 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _FEATURE_EXTRACTION_PLUGIN_ADAPTER_H_
-#define _FEATURE_EXTRACTION_PLUGIN_ADAPTER_H_
-
-#include "api/svp.h"
-#include "FeatureExtractionPlugin.h"
-
-#include <map>
-
-class FeatureExtractionPluginAdapterBase
-{
-public:
-    virtual ~FeatureExtractionPluginAdapterBase();
-    const SVPPluginDescriptor *getDescriptor();
-
-protected:
-    FeatureExtractionPluginAdapterBase();
-
-    virtual FeatureExtractionPlugin *createPlugin(float inputSampleRate) = 0;
-
-    static SVPPluginHandle svpInstantiate(const SVPPluginDescriptor *desc,
-                                          float inputSampleRate);
-
-    static void svpCleanup(SVPPluginHandle handle);
-
-    static int svpInitialise(SVPPluginHandle handle, unsigned int channels,
-                             unsigned int stepSize, unsigned int blockSize);
-
-    static void svpReset(SVPPluginHandle handle);
-
-    static float svpGetParameter(SVPPluginHandle handle, int param);
-    static void svpSetParameter(SVPPluginHandle handle, int param, float value);
-
-    static unsigned int svpGetCurrentProgram(SVPPluginHandle handle);
-    static void svpSelectProgram(SVPPluginHandle handle, unsigned int program);
-
-    static unsigned int svpGetPreferredStepSize(SVPPluginHandle handle);
-    static unsigned int svpGetPreferredBlockSize(SVPPluginHandle handle);
-    static unsigned int svpGetMinChannelCount(SVPPluginHandle handle);
-    static unsigned int svpGetMaxChannelCount(SVPPluginHandle handle);
-
-    static unsigned int svpGetOutputCount(SVPPluginHandle handle);
-
-    static SVPOutputDescriptor *svpGetOutputDescriptor(SVPPluginHandle handle,
-                                                       unsigned int i);
-
-    static void svpReleaseOutputDescriptor(SVPOutputDescriptor *desc);
-
-    static SVPFeatureList **svpProcess(SVPPluginHandle handle,
-                                       float **inputBuffers,
-                                       int sec,
-                                       int nsec);
-
-    static SVPFeatureList **svpGetRemainingFeatures(SVPPluginHandle handle);
-
-    static void svpReleaseFeatureSet(SVPFeatureList **fs);
-
-    void cleanup(FeatureExtractionPlugin *plugin);
-    void checkOutputMap(FeatureExtractionPlugin *plugin);
-    unsigned int getOutputCount(FeatureExtractionPlugin *plugin);
-    SVPOutputDescriptor *getOutputDescriptor(FeatureExtractionPlugin *plugin,
-                                             unsigned int i);
-    SVPFeatureList **process(FeatureExtractionPlugin *plugin,
-                             float **inputBuffers,
-                             int sec, int nsec);
-    SVPFeatureList **getRemainingFeatures(FeatureExtractionPlugin *plugin);
-    SVPFeatureList **convertFeatures(const FeatureExtractionPlugin::FeatureSet &features);
-    
-    typedef std::map<const void *, FeatureExtractionPluginAdapterBase *> AdapterMap;
-    static AdapterMap m_adapterMap;
-    static FeatureExtractionPluginAdapterBase *lookupAdapter(SVPPluginHandle);
-
-    bool m_populated;
-    SVPPluginDescriptor m_descriptor;
-    FeatureExtractionPlugin::ParameterList m_parameters;
-    FeatureExtractionPlugin::ProgramList m_programs;
-    
-    typedef std::map<FeatureExtractionPlugin *,
-                     FeatureExtractionPlugin::OutputList *> OutputMap;
-    OutputMap m_pluginOutputs;
-
-    typedef std::map<FeatureExtractionPlugin *,
-                     SVPFeature ***> FeatureBufferMap;
-    FeatureBufferMap m_pluginFeatures;
-};
-
-template <typename Plugin>
-class FeatureExtractionPluginAdapter : public FeatureExtractionPluginAdapterBase
-{
-public:
-    FeatureExtractionPluginAdapter() : FeatureExtractionPluginAdapterBase() { }
-    ~FeatureExtractionPluginAdapter() { }
-
-protected:
-    FeatureExtractionPlugin *createPlugin(float inputSampleRate) {
-        Plugin *plugin = new Plugin(inputSampleRate);
-        FeatureExtractionPlugin *fep =
-            dynamic_cast<FeatureExtractionPlugin *>(plugin);
-        if (!fep) {
-            std::cerr << "ERROR: FeatureExtractionPlugin::createPlugin: "
-                      << "Plugin is not a feature extraction plugin"
-                      << std::endl;
-            delete plugin;
-            return 0;
-        }
-        return fep;
-    }
-};
-    
-
-#endif
-
--- a/plugin/FeatureExtractionPluginFactory.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ b/plugin/FeatureExtractionPluginFactory.cpp	Fri Mar 31 15:56:35 2006 +0000
@@ -22,6 +22,15 @@
 #include "plugins/SpectralCentroid.h" //!!!
 #include "plugins/TonalChangeDetect.h" //!!!
 
+#include "vamp/vamp.h"
+#include "vamp-sdk/PluginHostAdapter.h"
+
+#include "base/System.h"
+
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+
 #include <iostream>
 
 static FeatureExtractionPluginFactory *_nativeInstance = 0;
@@ -29,7 +38,7 @@
 FeatureExtractionPluginFactory *
 FeatureExtractionPluginFactory::instance(QString pluginType)
 {
-    if (pluginType == "sv") {
+    if (pluginType == "vamp" || pluginType == "sv") { //!!!
 	if (!_nativeInstance) {
 	    std::cerr << "FeatureExtractionPluginFactory::instance(" << pluginType.toStdString()
 		      << "): creating new FeatureExtractionPluginFactory" << std::endl;
@@ -50,12 +59,43 @@
 }
 
 std::vector<QString>
+FeatureExtractionPluginFactory::getPluginPath()
+{
+    std::vector<QString> path;
+    std::string envPath;
+
+    char *cpath = getenv("Vamp_PATH");
+    if (cpath) envPath = cpath;
+
+    if (envPath == "") {
+        //!!! system dependent
+        envPath = "/usr/local/lib/vamp:/usr/lib/vamp";
+        char *chome = getenv("HOME");
+        if (chome) {
+            envPath = std::string(chome) + "/vamp:" +
+                std::string(chome) + "/.vamp:" + envPath;
+        }
+    }
+
+    std::string::size_type index = 0, newindex = 0;
+
+    while ((newindex = envPath.find(':', index)) < envPath.size()) {
+	path.push_back(envPath.substr(index, newindex - index).c_str());
+	index = newindex + 1;
+    }
+    
+    path.push_back(envPath.substr(index).c_str());
+
+    return path;
+}
+
+std::vector<QString>
 FeatureExtractionPluginFactory::getAllPluginIdentifiers()
 {
     FeatureExtractionPluginFactory *factory;
     std::vector<QString> rv;
     
-    factory = instance("sv");
+    factory = instance("vamp");
     if (factory) {
 	std::vector<QString> tmp = factory->getPluginIdentifiers();
 	for (size_t i = 0; i < tmp.size(); ++i) {
@@ -77,48 +117,196 @@
     rv.push_back("sv:_builtin:zerocrossing"); //!!!
     rv.push_back("sv:_builtin:spectralcentroid"); //!!!
     rv.push_back("sv:_builtin:tonalchange"); //!!!
+
+    std::vector<QString> path = getPluginPath();
+    
+    for (std::vector<QString>::iterator i = path.begin(); i != path.end(); ++i) {
+
+        std::cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: scanning directory " << i->toStdString() << std::endl;
+
+	QDir pluginDir(*i, PLUGIN_GLOB,
+                       QDir::Name | QDir::IgnoreCase,
+                       QDir::Files | QDir::Readable);
+
+	for (unsigned int j = 0; j < pluginDir.count(); ++j) {
+
+            QString soname = pluginDir.filePath(pluginDir[j]);
+
+            void *libraryHandle = DLOPEN(soname, RTLD_LAZY);
+            
+            if (!libraryHandle) {
+                std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname.toStdString() << std::endl;
+                continue;
+            }
+
+            VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
+                DLSYM(libraryHandle, "vampGetPluginDescriptor");
+
+            if (!fn) {
+                std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: No descriptor function in " << soname.toStdString() << std::endl;
+                if (DLCLOSE(libraryHandle) != 0) {
+                    std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname.toStdString() << std::endl;
+                }
+                continue;
+            }
+
+            const VampPluginDescriptor *descriptor = 0;
+            int index = 0;
+
+            while ((descriptor = fn(index))) {
+                QString id = QString("vamp:%1:%2").arg(soname).arg(descriptor->name);
+                rv.push_back(id);
+                std::cerr << "Found id " << id.toStdString() << std::endl;
+                ++index;
+            }
+            
+            if (DLCLOSE(libraryHandle) != 0) {
+                std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname.toStdString() << std::endl;
+            }
+	}
+    }
+
     return rv;
 }
 
-FeatureExtractionPlugin *
+QString
+FeatureExtractionPluginFactory::findPluginFile(QString soname, QString inDir)
+{
+    QString file = "";
+
+    if (inDir != "") {
+
+        QDir dir(inDir, PLUGIN_GLOB,
+                 QDir::Name | QDir::IgnoreCase,
+                 QDir::Files | QDir::Readable);
+        if (!dir.exists()) return "";
+
+        file = dir.filePath(QFileInfo(soname).fileName());
+        if (QFileInfo(file).exists()) {
+            return file;
+        }
+
+	for (unsigned int j = 0; j < dir.count(); ++j) {
+            file = dir.filePath(dir[j]);
+            if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) {
+                return file;
+            }
+        }
+
+        return "";
+
+    } else {
+
+        QFileInfo fi(soname);
+        if (fi.exists()) return soname;
+
+        if (fi.isAbsolute() && fi.absolutePath() != "") {
+            file = findPluginFile(soname, fi.absolutePath());
+            if (file != "") return file;
+        }
+
+        std::vector<QString> path = getPluginPath();
+        for (std::vector<QString>::iterator i = path.begin();
+             i != path.end(); ++i) {
+            if (*i != "") {
+                file = findPluginFile(soname, *i);
+                if (file != "") return file;
+            }
+        }
+
+        return "";
+    }
+}
+
+Vamp::Plugin *
 FeatureExtractionPluginFactory::instantiatePlugin(QString identifier,
 						  float inputSampleRate)
 {
-    QString type, soName, label;
-    PluginIdentifier::parseIdentifier(identifier, type, soName, label);
-    if (type != "sv") {
+    Vamp::Plugin *rv = 0;
+
+    const VampPluginDescriptor *descriptor = 0;
+    int index = 0;
+
+    QString type, soname, label;
+    PluginIdentifier::parseIdentifier(identifier, type, soname, label);
+    if (type != "vamp" && type != "sv") { //!!!
 	std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type.toStdString() << std::endl;
 	return 0;
     }
 
     //!!!
-    if (soName != PluginIdentifier::BUILTIN_PLUGIN_SONAME) {
-	std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Non-built-in plugins not yet supported (paradoxically enough)" << std::endl;
-	return 0;
+    if (type == "sv" && soname == PluginIdentifier::BUILTIN_PLUGIN_SONAME) {
+
+        if (label == "beats") {
+            return new BeatDetector(inputSampleRate); //!!!
+        }
+        
+        if (label == "chromagram") {
+            return new ChromagramPlugin(inputSampleRate); //!!!
+        }
+        
+        if (label == "zerocrossing") {
+            return new ZeroCrossing(inputSampleRate); //!!!
+        }
+        
+        if (label == "spectralcentroid") {
+            return new SpectralCentroid(inputSampleRate); //!!!
+        }
+        
+        if (label == "tonalchange") {
+            return new TonalChangeDetect(inputSampleRate); //!!!
+        }
+        
+        std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Unknown plugin \"" << identifier.toStdString() << "\"" << std::endl;
+        
+        return 0;
     }
 
-    if (label == "beats") {
-	return new BeatDetector(inputSampleRate); //!!!
+    QString found = findPluginFile(soname);
+
+    if (found == "") {
+        std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find library file " << soname.toStdString() << std::endl;
+    } else if (found != soname) {
+        std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: WARNING: Given library name was " << soname.toStdString() << ", found at " << found.toStdString() << std::endl;
     }
 
-    if (label == "chromagram") {
-	return new ChromagramPlugin(inputSampleRate); //!!!
+    soname = found;
+
+    void *libraryHandle = DLOPEN(soname, RTLD_LAZY);
+            
+    if (!libraryHandle) {
+        std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to load library " << soname.toStdString() << std::endl;
+        return 0;
     }
 
-    if (label == "zerocrossing") {
-	return new ZeroCrossing(inputSampleRate); //!!!
+    VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
+        DLSYM(libraryHandle, "vampGetPluginDescriptor");
+    
+    if (!fn) {
+        std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: No descriptor function in " << soname.toStdString() << std::endl;
+        goto done;
     }
 
-    if (label == "spectralcentroid") {
-	return new SpectralCentroid(inputSampleRate); //!!!
+    while ((descriptor = fn(index))) {
+        if (label == descriptor->name) break;
+        ++index;
     }
 
-    if (label == "tonalchange") {
-	return new TonalChangeDetect(inputSampleRate); //!!!
+    if (!descriptor) {
+        std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find plugin \"" << label.toStdString() << "\" in library " << soname.toStdString() << std::endl;
+        goto done;
     }
 
-    std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Unknown plugin \"" << identifier.toStdString() << "\"" << std::endl;
-    
-    return 0;
+    rv = new Vamp::PluginHostAdapter(descriptor, inputSampleRate);
+
+    //!!! need to dlclose() when plugins from a given library are unloaded
+
+done:
+    if (!rv) {
+        if (DLCLOSE(libraryHandle) != 0) {
+            std::cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname.toStdString() << std::endl;
+        }
+    }
+    return rv;
 }
 
--- a/plugin/FeatureExtractionPluginFactory.h	Thu Mar 30 15:00:22 2006 +0000
+++ b/plugin/FeatureExtractionPluginFactory.h	Fri Mar 31 15:56:35 2006 +0000
@@ -19,7 +19,7 @@
 #include <QString>
 #include <vector>
 
-class FeatureExtractionPlugin;
+namespace Vamp { class Plugin; }
 
 class FeatureExtractionPluginFactory
 {
@@ -28,12 +28,16 @@
     static FeatureExtractionPluginFactory *instanceFor(QString identifier);
     static std::vector<QString> getAllPluginIdentifiers();
 
-    std::vector<QString> getPluginIdentifiers();
+    virtual std::vector<QString> getPluginPath();
+
+    virtual std::vector<QString> getPluginIdentifiers();
+
+    virtual QString findPluginFile(QString soname, QString inDir = "");
 
     // We don't set blockSize or channels on this -- they're
     // negotiated and handled via initialize() on the plugin
-    virtual FeatureExtractionPlugin *instantiatePlugin(QString identifier,
-						       float inputSampleRate);
+    virtual Vamp::Plugin *instantiatePlugin(QString identifier,
+                                            float inputSampleRate);
 
 protected:
 };
--- a/plugin/FeatureExtractionPluginHostAdapter.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,278 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#include "FeatureExtractionPluginHostAdapter.h"
-
-FeatureExtractionPluginHostAdapter::FeatureExtractionPluginHostAdapter(const SVPPluginDescriptor *descriptor,
-                                                                       float inputSampleRate) :
-    FeatureExtractionPlugin(inputSampleRate),
-    m_descriptor(descriptor)
-{
-    m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
-}
-
-FeatureExtractionPluginHostAdapter::~FeatureExtractionPluginHostAdapter()
-{
-    if (m_handle) m_descriptor->cleanup(m_handle);
-}
-
-bool
-FeatureExtractionPluginHostAdapter::initialise(size_t channels,
-                                               size_t stepSize,
-                                               size_t blockSize)
-{
-    if (!m_handle) return false;
-    return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
-        true : false;
-}
-
-void
-FeatureExtractionPluginHostAdapter::reset()
-{
-    if (!m_handle) return;
-    m_descriptor->reset(m_handle);
-}
-
-std::string
-FeatureExtractionPluginHostAdapter::getName() const
-{
-    return m_descriptor->name;
-}
-
-std::string
-FeatureExtractionPluginHostAdapter::getDescription() const
-{
-    return m_descriptor->description;
-}
-
-std::string
-FeatureExtractionPluginHostAdapter::getMaker() const
-{
-    return m_descriptor->maker;
-}
-
-int
-FeatureExtractionPluginHostAdapter::getPluginVersion() const
-{
-    return m_descriptor->pluginVersion;
-}
-
-std::string
-FeatureExtractionPluginHostAdapter::getCopyright() const
-{
-    return m_descriptor->copyright;
-}
-
-FeatureExtractionPluginHostAdapter::ParameterList
-FeatureExtractionPluginHostAdapter::getParameterDescriptors() const
-{
-    ParameterList list;
-    for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
-        const SVPParameterDescriptor *spd = m_descriptor->parameters[i];
-        ParameterDescriptor pd;
-        pd.name = spd->name;
-        pd.description = spd->description;
-        pd.unit = spd->unit;
-        pd.minValue = spd->minValue;
-        pd.maxValue = spd->maxValue;
-        pd.defaultValue = spd->defaultValue;
-        pd.isQuantized = spd->isQuantized;
-        pd.quantizeStep = spd->quantizeStep;
-        list.push_back(pd);
-    }
-    return list;
-}
-
-float
-FeatureExtractionPluginHostAdapter::getParameter(std::string param) const
-{
-    if (!m_handle) return 0.0;
-
-    for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
-        if (param == m_descriptor->parameters[i]->name) {
-            return m_descriptor->getParameter(m_handle, i);
-        }
-    }
-
-    return 0.0;
-}
-
-void
-FeatureExtractionPluginHostAdapter::setParameter(std::string param, 
-                                                 float value)
-{
-    if (!m_handle) return;
-
-    for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
-        if (param == m_descriptor->parameters[i]->name) {
-            m_descriptor->setParameter(m_handle, i, value);
-            return;
-        }
-    }
-}
-
-FeatureExtractionPluginHostAdapter::ProgramList
-FeatureExtractionPluginHostAdapter::getPrograms() const
-{
-    ProgramList list;
-    
-    for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
-        list.push_back(m_descriptor->programs[i]);
-    }
-    
-    return list;
-}
-
-std::string
-FeatureExtractionPluginHostAdapter::getCurrentProgram() const
-{
-    if (!m_handle) return "";
-
-    int pn = m_descriptor->getCurrentProgram(m_handle);
-    return m_descriptor->programs[pn];
-}
-
-void
-FeatureExtractionPluginHostAdapter::selectProgram(std::string program)
-{
-    if (!m_handle) return;
-
-    for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
-        if (program == m_descriptor->programs[i]) {
-            m_descriptor->selectProgram(m_handle, i);
-            return;
-        }
-    }
-}
-
-size_t
-FeatureExtractionPluginHostAdapter::getPreferredStepSize() const
-{
-    if (!m_handle) return 0;
-    return m_descriptor->getPreferredStepSize(m_handle);
-}
-
-size_t
-FeatureExtractionPluginHostAdapter::getPreferredBlockSize() const
-{
-    if (!m_handle) return 0;
-    return m_descriptor->getPreferredBlockSize(m_handle);
-}
-
-FeatureExtractionPluginHostAdapter::OutputList
-FeatureExtractionPluginHostAdapter::getOutputDescriptors() const
-{
-    OutputList list;
-    if (!m_handle) return list;
-
-    unsigned int count = m_descriptor->getOutputCount(m_handle);
-
-    for (unsigned int i = 0; i < count; ++i) {
-        SVPOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
-        OutputDescriptor d;
-        d.name = sd->name;
-        d.description = sd->description;
-        d.unit = sd->unit;
-        d.hasFixedValueCount = sd->hasFixedValueCount;
-        d.valueCount = sd->valueCount;
-        for (unsigned int j = 0; j < sd->valueCount; ++j) {
-            d.valueNames.push_back(sd->valueNames[i]);
-        }
-        d.hasKnownExtents = sd->hasKnownExtents;
-        d.minValue = sd->minValue;
-        d.maxValue = sd->maxValue;
-        d.isQuantized = sd->isQuantized;
-        d.quantizeStep = sd->quantizeStep;
-
-        switch (sd->sampleType) {
-        case svpOneSamplePerStep:
-            d.sampleType = OutputDescriptor::OneSamplePerStep; break;
-        case svpFixedSampleRate:
-            d.sampleType = OutputDescriptor::FixedSampleRate; break;
-        case svpVariableSampleRate:
-            d.sampleType = OutputDescriptor::VariableSampleRate; break;
-        }
-
-        d.sampleRate = sd->sampleRate;
-
-        list.push_back(d);
-
-        m_descriptor->releaseOutputDescriptor(sd);
-    }
-
-    return list;
-}
-
-FeatureExtractionPluginHostAdapter::FeatureSet
-FeatureExtractionPluginHostAdapter::process(float **inputBuffers,
-                                            RealTime timestamp)
-{
-    FeatureSet fs;
-    if (!m_handle) return fs;
-
-    int sec = timestamp.sec;
-    int nsec = timestamp.nsec;
-    
-    SVPFeatureList **features = m_descriptor->process(m_handle,
-                                                      inputBuffers,
-                                                      sec, nsec);
-    
-    convertFeatures(features, fs);
-    m_descriptor->releaseFeatureSet(features);
-    return fs;
-}
-
-FeatureExtractionPluginHostAdapter::FeatureSet
-FeatureExtractionPluginHostAdapter::getRemainingFeatures()
-{
-    FeatureSet fs;
-    if (!m_handle) return fs;
-    
-    SVPFeatureList **features = m_descriptor->getRemainingFeatures(m_handle); 
-
-    convertFeatures(features, fs);
-    m_descriptor->releaseFeatureSet(features);
-    return fs;
-}
-
-void
-FeatureExtractionPluginHostAdapter::convertFeatures(SVPFeatureList **features,
-                                                    FeatureSet &fs)
-{
-    for (unsigned int i = 0; features[i]; ++i) {
-        
-        SVPFeatureList &list = *features[i];
-
-        if (list.featureCount > 0) {
-
-            for (unsigned int j = 0; j < list.featureCount; ++j) {
-                
-                Feature feature;
-                feature.hasTimestamp = list.features[j].hasTimestamp;
-                feature.timestamp = RealTime(list.features[j].sec,
-                                             list.features[j].nsec);
-
-                for (unsigned int k = 0; k < list.features[j].valueCount; ++k) {
-                    feature.values.push_back(list.features[j].values[k]);
-                }
-                
-                feature.label = list.features[j].label;
-
-                fs[i].push_back(feature);
-            }
-        }
-    }
-}
-
--- a/plugin/FeatureExtractionPluginHostAdapter.h	Thu Mar 30 15:00:22 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _FEATURE_EXTRACTION_PLUGIN_HOST_ADAPTER_H_
-#define _FEATURE_EXTRACTION_PLUGIN_HOST_ADAPTER_H_
-
-#include "api/svp.h"
-
-#include "FeatureExtractionPlugin.h"
-
-class FeatureExtractionPluginHostAdapter : public FeatureExtractionPlugin
-{
-public:
-    FeatureExtractionPluginHostAdapter(const SVPPluginDescriptor *descriptor,
-                                       float inputSampleRate);
-    virtual ~FeatureExtractionPluginHostAdapter();
-
-    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
-    void reset();
-
-    std::string getName() const;
-    std::string getDescription() const;
-    std::string getMaker() const;
-    int getPluginVersion() const;
-    std::string getCopyright() const;
-
-    ParameterList getParameterDescriptors() const;
-    float getParameter(std::string) const;
-    void setParameter(std::string, float);
-
-    ProgramList getPrograms() const;
-    std::string getCurrentProgram() const;
-    void selectProgram(std::string);
-
-    size_t getPreferredStepSize() const;
-    size_t getPreferredBlockSize() const;
-
-    OutputList getOutputDescriptors() const;
-
-    FeatureSet process(float **inputBuffers, RealTime timestamp);
-
-    FeatureSet getRemainingFeatures();
-
-protected:
-    void convertFeatures(SVPFeatureList **, FeatureSet &);
-
-    const SVPPluginDescriptor *m_descriptor;
-    SVPPluginHandle m_handle;
-};
-
-#endif
-
-
--- a/plugin/LADSPAPluginInstance.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ b/plugin/LADSPAPluginInstance.cpp	Fri Mar 31 15:56:35 2006 +0000
@@ -224,7 +224,7 @@
 LADSPAPluginInstance::getLatency()
 {
     if (m_latencyPort) {
-	if (!m_run) run(RealTime::zeroTime);
+	if (!m_run) run(Vamp::RealTime::zeroTime);
 	if (*m_latencyPort > 0) return (size_t)*m_latencyPort;
     }
     return 0;
@@ -441,7 +441,7 @@
 }
 
 void
-LADSPAPluginInstance::run(const RealTime &)
+LADSPAPluginInstance::run(const Vamp::RealTime &)
 {
     if (!m_descriptor || !m_descriptor->run) return;
 
--- a/plugin/LADSPAPluginInstance.h	Thu Mar 30 15:00:22 2006 +0000
+++ b/plugin/LADSPAPluginInstance.h	Fri Mar 31 15:56:35 2006 +0000
@@ -49,7 +49,7 @@
     virtual int getPluginVersion() const;
     virtual std::string getCopyright() const;
 
-    virtual void run(const RealTime &rt);
+    virtual void run(const Vamp::RealTime &rt);
 
     virtual unsigned int getParameterCount() const;
     virtual void setParameterValue(unsigned int parameter, float value);
--- a/plugin/PluginDescription.h	Thu Mar 30 15:00:22 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _PLUGIN_DESCRIPTION_H_
-#define _PLUGIN_DESCRIPTION_H_
-
-struct PluginDescription
-{
-	
--- a/plugin/PluginInstance.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#include "PluginInstance.h"
-
-#include <QRegExp>
-#include <QXmlAttributes>
-
-#include <QDomDocument>
-#include <QDomElement>
-#include <QDomNamedNodeMap>
-#include <QDomAttr>
-
-#include <iostream>
-
-QString
-PluginInstance::toXmlString(QString indent, QString extraAttributes) const
-{
-    QString s;
-    s += indent;
-
-    s += QString("<plugin name=\"%1\" description=\"%2\" maker=\"%3\" version=\"%4\" copyright=\"%5\" %6 ")
-        .arg(encodeEntities(QString(getName().c_str())))
-        .arg(encodeEntities(QString(getDescription().c_str())))
-        .arg(encodeEntities(QString(getMaker().c_str())))
-        .arg(getPluginVersion())
-        .arg(encodeEntities(QString(getCopyright().c_str())))
-        .arg(extraAttributes);
-
-    if (!getPrograms().empty()) {
-        s += QString("program=\"%1\" ")
-            .arg(encodeEntities(getCurrentProgram().c_str()));
-    }
-
-    ParameterList parameters = getParameterDescriptors();
-
-    for (ParameterList::const_iterator i = parameters.begin();
-         i != parameters.end(); ++i) {
-        s += QString("param-%1=\"%2\" ")
-            .arg(stripInvalidParameterNameCharacters(QString(i->name.c_str())))
-            .arg(getParameter(i->name));
-    }
-
-    s += "/>\n";
-    return s;
-}
-
-#define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR) \
-    QString ATTRIBUTE = attrs.value(#ATTRIBUTE); \
-    if (ATTRIBUTE != "" && ATTRIBUTE != ACCESSOR().c_str()) { \
-        std::cerr << "WARNING: PluginInstance::setParameters: Plugin " \
-                  << #ATTRIBUTE << " does not match (attributes have \"" \
-                  << ATTRIBUTE.toStdString() << "\", my " \
-                  << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << std::endl; \
-    }
-
-void
-PluginInstance::setParameters(const QXmlAttributes &attrs)
-{
-    CHECK_ATTRIBUTE(name, getName);
-    CHECK_ATTRIBUTE(description, getDescription);
-    CHECK_ATTRIBUTE(maker, getMaker);
-    CHECK_ATTRIBUTE(copyright, getCopyright);
-
-    bool ok;
-    int version = attrs.value("version").trimmed().toInt(&ok);
-    if (ok && version != getPluginVersion()) {
-        std::cerr << "WARNING: PluginInstance::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << getPluginVersion() << ")" << std::endl;
-    }
-
-    if (!getPrograms().empty()) {
-        selectProgram(attrs.value("program").toStdString());
-    }
-
-    ParameterList parameters = getParameterDescriptors();
-
-    for (ParameterList::const_iterator i = parameters.begin();
-         i != parameters.end(); ++i) {
-        QString name = QString("param-%1")
-            .arg(stripInvalidParameterNameCharacters
-                 (QString(i->name.c_str())));
-        if (attrs.value(name) == "") {
-            std::cerr << "PluginInstance::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
-            continue;
-        }
-        bool ok;
-        float value = attrs.value(name).trimmed().toFloat(&ok);
-        if (ok) {
-            setParameter(i->name, value);
-        } else {
-            std::cerr << "WARNING: PluginInstance::setParameters: Invalid value \"" << attrs.value(name).toStdString() << "\" for parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
-        }
-    }
-}
-
-void
-PluginInstance::setParametersFromXml(QString xml)
-{
-    QDomDocument doc;
-
-    QString error;
-    int errorLine;
-    int errorColumn;
-
-    if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
-        std::cerr << "PluginInstance::setParametersFromXml: Error in parsing XML: " << error.toStdString() << " at line " << errorLine << ", column " << errorColumn << std::endl;
-        std::cerr << "Input follows:" << std::endl;
-        std::cerr << xml.toStdString() << std::endl;
-        std::cerr << "Input ends." << std::endl;
-        return;
-    }
-
-    QDomElement pluginElt = doc.firstChildElement("plugin");
-    QDomNamedNodeMap attrNodes = pluginElt.attributes();
-    QXmlAttributes attrs;
-
-    for (int i = 0; i < attrNodes.length(); ++i) {
-        QDomAttr attr = attrNodes.item(i).toAttr();
-        if (attr.isNull()) continue;
-        std::cerr << "Adding attribute \"" << attr.name().toStdString()
-                  << "\" with value \"" << attr.value().toStdString() << "\"" << std::endl;
-        attrs.append(attr.name(), "", "", attr.value());
-    }
-
-    setParameters(attrs);
-}
-    
-QString
-PluginInstance::stripInvalidParameterNameCharacters(QString s) const
-{
-    s.replace(QRegExp("[^a-zA-Z0-9_]*"), "");
-    return s;
-}
-
--- a/plugin/PluginInstance.h	Thu Mar 30 15:00:22 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _PLUGIN_INSTANCE_H_
-#define _PLUGIN_INSTANCE_H_
-
-#include <string>
-#include <vector>
-
-#include "base/XmlExportable.h"
-
-class QXmlAttributes;
-
-/**
- * A base class for plugins with optional configurable parameters,
- * programs, etc.
- *
- * This does not provide the necessary interfaces to instantiate or
- * run a plugin -- that depends on the plugin subclass, as different
- * plugin types may have quite different operating structures.  This
- * class just specifies the necessary interface to show editable
- * controls for the plugin to the user.
- */
-
-class PluginInstance : public XmlExportable
-{
-public:
-    /**
-     * Get the computer-usable name of the plugin.  This should be
-     * reasonably short and contain no whitespace or punctuation
-     * characters.  It may be shown to the user, but it won't be the
-     * main method for a user to identify a plugin (that will be the
-     * description, below).
-     */
-    virtual std::string getName() const = 0;
-
-    /**
-     * Get a human-readable description of the plugin.  This should be
-     * self-contained, as it may be shown to the user in isolation
-     * without also showing the plugin's "name".
-     */
-    virtual std::string getDescription() const = 0;
-    
-    /**
-     * Get the name of the author or vendor of the plugin in
-     * human-readable form.
-     */
-    virtual std::string getMaker() const = 0;
-
-    /**
-     * Get the version number of the plugin.
-     */
-    virtual int getPluginVersion() const = 0;
-
-    /**
-     * Get the copyright statement or licensing summary of the plugin.
-     */
-    virtual std::string getCopyright() const = 0;
-
-    /**
-     * Get the type of plugin (e.g. DSSI, etc).  This is likely to be
-     * implemented by the immediate subclass, not by actual plugins.
-     */
-    virtual std::string getType() const = 0;
-
-
-    struct ParameterDescriptor
-    {
-	/**
-	 * The name of the parameter, in computer-usable form.  Should
-	 * be reasonably short, and may only contain the characters
-	 * [a-zA-Z0-9_].
-	 */
-	std::string name;
-
-	/**
-	 * The human-readable name of the parameter.
-	 */
-	std::string description;
-
-	/**
-	 * The unit of the parameter, in human-readable form.
-	 */
-	std::string unit;
-
-	/**
-	 * The minimum value of the parameter.
-	 */
-	float minValue;
-
-	/**
-	 * The maximum value of the parameter.
-	 */
-	float maxValue;
-
-	/**
-	 * The default value of the parameter.
-	 */
-	float defaultValue;
-	
-	/**
-	 * True if the parameter values are quantized to a particular
-	 * resolution.
-	 */
-	bool isQuantized;
-
-	/**
-	 * Quantization resolution of the parameter values (e.g. 1.0
-	 * if they are all integers).  Undefined if isQuantized is
-	 * false.
-	 */
-	float quantizeStep;
-    };
-
-    typedef std::vector<ParameterDescriptor> ParameterList;
-
-    /**
-     * Get the controllable parameters of this plugin.
-     */
-    virtual ParameterList getParameterDescriptors() const {
-	return ParameterList();
-    }
-
-    /**
-     * Get the value of a named parameter.  The argument is the name
-     * field from that parameter's descriptor.
-     */
-    virtual float getParameter(std::string) const { return 0.0; }
-
-    /**
-     * Set a named parameter.  The first argument is the name field
-     * from that parameter's descriptor.
-     */
-    virtual void setParameter(std::string, float) { } 
-
-    
-    typedef std::vector<std::string> ProgramList;
-
-    /**
-     * Get the program settings available in this plugin.
-     * The programs must have unique names.
-     */
-    virtual ProgramList getPrograms() const { return ProgramList(); }
-
-    /**
-     * Get the current program.
-     */
-    virtual std::string getCurrentProgram() const { return ""; }
-
-    /**
-     * Select a program.  (If the given program name is not one of the
-     * available programs, do nothing.)
-     */
-    virtual void selectProgram(std::string) { }
-
-    /**
-     * Export plugin settings to XML.
-     */
-    virtual QString toXmlString(QString indent = "",
-                                QString extraAttributes = "") const;
-
-    /**
-     * Set the parameters and program of a plugin from a set of XML
-     * attributes.  This is a partial inverse of toXmlString.
-     */
-    virtual void setParameters(const QXmlAttributes &);
-
-    /**
-     * Set the parameters and program of a plugin from an XML plugin
-     * element as returned by toXmlString.  This is a partial inverse
-     * of toXmlString.
-     */
-    virtual void setParametersFromXml(QString xml);
-
-protected:
-    QString stripInvalidParameterNameCharacters(QString) const;
-};
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugin/PluginXml.cpp	Fri Mar 31 15:56:35 2006 +0000
@@ -0,0 +1,160 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "PluginXml.h"
+
+#include <QRegExp>
+#include <QXmlAttributes>
+
+#include <QDomDocument>
+#include <QDomElement>
+#include <QDomNamedNodeMap>
+#include <QDomAttr>
+
+#include "vamp-sdk/PluginBase.h"
+
+#include <iostream>
+
+PluginXml::PluginXml(Vamp::PluginBase *plugin) :
+    m_plugin(plugin)
+{
+}
+
+PluginXml::~PluginXml() { }
+
+QString
+PluginXml::toXmlString(QString indent, QString extraAttributes) const
+{
+    QString s;
+    s += indent;
+
+    s += QString("<plugin name=\"%1\" description=\"%2\" maker=\"%3\" version=\"%4\" copyright=\"%5\" %6 ")
+        .arg(encodeEntities(QString(m_plugin->getName().c_str())))
+        .arg(encodeEntities(QString(m_plugin->getDescription().c_str())))
+        .arg(encodeEntities(QString(m_plugin->getMaker().c_str())))
+        .arg(m_plugin->getPluginVersion())
+        .arg(encodeEntities(QString(m_plugin->getCopyright().c_str())))
+        .arg(extraAttributes);
+
+    if (!m_plugin->getPrograms().empty()) {
+        s += QString("program=\"%1\" ")
+            .arg(encodeEntities(m_plugin->getCurrentProgram().c_str()));
+    }
+
+    Vamp::PluginBase::ParameterList parameters =
+        m_plugin->getParameterDescriptors();
+
+    for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
+         i != parameters.end(); ++i) {
+        s += QString("param-%1=\"%2\" ")
+            .arg(stripInvalidParameterNameCharacters(QString(i->name.c_str())))
+            .arg(m_plugin->getParameter(i->name));
+    }
+
+    s += "/>\n";
+    return s;
+}
+
+#define CHECK_ATTRIBUTE(ATTRIBUTE, ACCESSOR) \
+    QString ATTRIBUTE = attrs.value(#ATTRIBUTE); \
+    if (ATTRIBUTE != "" && ATTRIBUTE != ACCESSOR().c_str()) { \
+        std::cerr << "WARNING: PluginXml::setParameters: Plugin " \
+                  << #ATTRIBUTE << " does not match (attributes have \"" \
+                  << ATTRIBUTE.toStdString() << "\", my " \
+                  << #ATTRIBUTE << " is \"" << ACCESSOR() << "\")" << std::endl; \
+    }
+
+void
+PluginXml::setParameters(const QXmlAttributes &attrs)
+{
+    CHECK_ATTRIBUTE(name, m_plugin->getName);
+    CHECK_ATTRIBUTE(description, m_plugin->getDescription);
+    CHECK_ATTRIBUTE(maker, m_plugin->getMaker);
+    CHECK_ATTRIBUTE(copyright, m_plugin->getCopyright);
+
+    bool ok;
+    int version = attrs.value("version").trimmed().toInt(&ok);
+    if (ok && version != m_plugin->getPluginVersion()) {
+        std::cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << std::endl;
+    }
+
+    if (!m_plugin->getPrograms().empty()) {
+        m_plugin->selectProgram(attrs.value("program").toStdString());
+    }
+
+    Vamp::PluginBase::ParameterList parameters =
+        m_plugin->getParameterDescriptors();
+
+    for (Vamp::PluginBase::ParameterList::const_iterator i =
+             parameters.begin(); i != parameters.end(); ++i) {
+
+        QString name = QString("param-%1")
+            .arg(stripInvalidParameterNameCharacters
+                 (QString(i->name.c_str())));
+
+        if (attrs.value(name) == "") {
+            std::cerr << "PluginXml::setParameters: no parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
+            continue;
+        }
+
+        bool ok;
+        float value = attrs.value(name).trimmed().toFloat(&ok);
+        if (ok) {
+            m_plugin->setParameter(i->name, value);
+        } else {
+            std::cerr << "WARNING: PluginXml::setParameters: Invalid value \"" << attrs.value(name).toStdString() << "\" for parameter \"" << i->name << "\" (attribute \"" << name.toStdString() << "\")" << std::endl;
+        }
+    }
+}
+
+void
+PluginXml::setParametersFromXml(QString xml)
+{
+    QDomDocument doc;
+
+    QString error;
+    int errorLine;
+    int errorColumn;
+
+    if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
+        std::cerr << "PluginXml::setParametersFromXml: Error in parsing XML: " << error.toStdString() << " at line " << errorLine << ", column " << errorColumn << std::endl;
+        std::cerr << "Input follows:" << std::endl;
+        std::cerr << xml.toStdString() << std::endl;
+        std::cerr << "Input ends." << std::endl;
+        return;
+    }
+
+    QDomElement pluginElt = doc.firstChildElement("plugin");
+    QDomNamedNodeMap attrNodes = pluginElt.attributes();
+    QXmlAttributes attrs;
+
+    for (unsigned int i = 0; i < attrNodes.length(); ++i) {
+        QDomAttr attr = attrNodes.item(i).toAttr();
+        if (attr.isNull()) continue;
+        std::cerr << "Adding attribute \"" << attr.name().toStdString()
+                  << "\" with value \"" << attr.value().toStdString() << "\"" << std::endl;
+        attrs.append(attr.name(), "", "", attr.value());
+    }
+
+    setParameters(attrs);
+}
+    
+QString
+PluginXml::stripInvalidParameterNameCharacters(QString s) const
+{
+    s.replace(QRegExp("[^a-zA-Z0-9_]*"), "");
+    return s;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugin/PluginXml.h	Fri Mar 31 15:56:35 2006 +0000
@@ -0,0 +1,56 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef _PLUGIN_XML_H_
+#define _PLUGIN_XML_H_
+
+#include "base/XmlExportable.h"
+
+namespace Vamp { class PluginBase; }
+
+class QXmlAttributes;
+
+class PluginXml : public XmlExportable
+{
+public:
+    PluginXml(Vamp::PluginBase *plugin);
+    virtual ~PluginXml();
+
+    /**
+     * Export plugin settings to XML.
+     */
+    virtual QString toXmlString(QString indent = "",
+                                QString extraAttributes = "") const;
+
+    /**
+     * Set the parameters and program of a plugin from a set of XML
+     * attributes.  This is a partial inverse of toXmlString.
+     */
+    virtual void setParameters(const QXmlAttributes &);
+
+    /**
+     * Set the parameters and program of a plugin from an XML plugin
+     * element as returned by toXmlString.  This is a partial inverse
+     * of toXmlString.
+     */
+    virtual void setParametersFromXml(QString xml);
+
+protected:
+    QString stripInvalidParameterNameCharacters(QString) const;
+
+    Vamp::PluginBase *m_plugin;
+};
+
+#endif
--- a/plugin/RealTimePluginInstance.h	Thu Mar 30 15:00:22 2006 +0000
+++ b/plugin/RealTimePluginInstance.h	Fri Mar 31 15:56:35 2006 +0000
@@ -21,15 +21,14 @@
 #ifndef _REALTIME_PLUGIN_INSTANCE_H_
 #define _REALTIME_PLUGIN_INSTANCE_H_
 
-#include "PluginInstance.h"
+#include "vamp-sdk/PluginBase.h"
+#include "vamp-sdk/RealTime.h"
 
 #include <QString>
 #include <QStringList>
 #include <vector>
 #include <string>
 
-#include "base/RealTime.h"
-
 class RealTimePluginFactory;
 	
 /**
@@ -72,7 +71,7 @@
     static const int SampleRate = 8;
 }
 
-class RealTimePluginInstance : public PluginInstance
+class RealTimePluginInstance : public Vamp::PluginBase
 {
 public:
     typedef float sample_t;
@@ -88,7 +87,7 @@
      * may be of interest to synths etc that may have queued events
      * waiting.  Other plugins can ignore it.
      */
-    virtual void run(const RealTime &blockStartTime) = 0;
+    virtual void run(const Vamp::RealTime &blockStartTime) = 0;
     
     virtual size_t getBufferSize() const = 0;
 
@@ -115,7 +114,7 @@
 
     virtual std::string configure(std::string /* key */, std::string /* value */) { return std::string(); }
 
-    virtual void sendEvent(const RealTime & /* eventTime */,
+    virtual void sendEvent(const Vamp::RealTime & /* eventTime */,
 			   const void * /* event */) { }
     virtual void clearEvents() { }
 
--- a/transform/FeatureExtractionPluginTransform.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ b/transform/FeatureExtractionPluginTransform.cpp	Fri Mar 31 15:56:35 2006 +0000
@@ -17,7 +17,8 @@
 #include "FeatureExtractionPluginTransform.h"
 
 #include "plugin/FeatureExtractionPluginFactory.h"
-#include "plugin/FeatureExtractionPlugin.h"
+#include "plugin/PluginXml.h"
+#include "vamp-sdk/Plugin.h"
 
 #include "base/Model.h"
 #include "model/SparseOneDimensionalModel.h"
@@ -58,10 +59,10 @@
     }
 
     if (configurationXml != "") {
-        m_plugin->setParametersFromXml(configurationXml);
+        PluginXml(m_plugin).setParametersFromXml(configurationXml);
     }
 
-    FeatureExtractionPlugin::OutputList outputs =
+    Vamp::Plugin::OutputList outputs =
 	m_plugin->getOutputDescriptors();
 
     if (outputs.empty()) {
@@ -73,7 +74,7 @@
     for (size_t i = 0; i < outputs.size(); ++i) {
 	if (outputName == "" || outputs[i].name == outputName.toStdString()) {
 	    m_outputFeatureNo = i;
-	    m_descriptor = new FeatureExtractionPlugin::OutputDescriptor
+	    m_descriptor = new Vamp::Plugin::OutputDescriptor
 		(outputs[i]);
 	    break;
 	}
@@ -106,17 +107,17 @@
     
     switch (m_descriptor->sampleType) {
 
-    case FeatureExtractionPlugin::OutputDescriptor::VariableSampleRate:
+    case Vamp::Plugin::OutputDescriptor::VariableSampleRate:
 	if (m_descriptor->sampleRate != 0.0) {
 	    modelResolution = size_t(modelRate / m_descriptor->sampleRate + 0.001);
 	}
 	break;
 
-    case FeatureExtractionPlugin::OutputDescriptor::OneSamplePerStep:
+    case Vamp::Plugin::OutputDescriptor::OneSamplePerStep:
 	modelResolution = m_plugin->getPreferredStepSize();
 	break;
 
-    case FeatureExtractionPlugin::OutputDescriptor::FixedSampleRate:
+    case Vamp::Plugin::OutputDescriptor::FixedSampleRate:
 	modelRate = m_descriptor->sampleRate;
 	break;
     }
@@ -130,7 +131,7 @@
 
 	       // We don't have a sparse 3D model
 	       m_descriptor->sampleType ==
-	       FeatureExtractionPlugin::OutputDescriptor::VariableSampleRate) {
+	       Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
 	
         SparseTimeValueModel *model = new SparseTimeValueModel
             (modelRate, modelResolution, minValue, maxValue, false);
@@ -239,11 +240,11 @@
 	    }
 	}
 
-	FeatureExtractionPlugin::FeatureSet features = m_plugin->process
-	    (buffers, RealTime::frame2RealTime(blockFrame, sampleRate));
+	Vamp::Plugin::FeatureSet features = m_plugin->process
+	    (buffers, Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
 
 	for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) {
-	    FeatureExtractionPlugin::Feature feature =
+	    Vamp::Plugin::Feature feature =
 		features[m_outputFeatureNo][fi];
 	    addFeature(blockFrame, feature);
 	}
@@ -256,10 +257,10 @@
 	blockFrame += stepSize;
     }
 
-    FeatureExtractionPlugin::FeatureSet features = m_plugin->getRemainingFeatures();
+    Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures();
 
     for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) {
-	FeatureExtractionPlugin::Feature feature =
+	Vamp::Plugin::Feature feature =
 	    features[m_outputFeatureNo][fi];
 	addFeature(blockFrame, feature);
     }
@@ -270,7 +271,7 @@
 
 void
 FeatureExtractionPluginTransform::addFeature(size_t blockFrame,
-					     const FeatureExtractionPlugin::Feature &feature)
+					     const Vamp::Plugin::Feature &feature)
 {
     size_t inputRate = m_input->getSampleRate();
 
@@ -285,7 +286,7 @@
     size_t frame = blockFrame;
 
     if (m_descriptor->sampleType ==
-	FeatureExtractionPlugin::OutputDescriptor::VariableSampleRate) {
+	Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
 
 	if (!feature.hasTimestamp) {
 	    std::cerr
@@ -294,16 +295,16 @@
 		<< std::endl;
 	    return;
 	} else {
-	    frame = RealTime::realTime2Frame(feature.timestamp, inputRate);
+	    frame = Vamp::RealTime::realTime2Frame(feature.timestamp, inputRate);
 	}
 
     } else if (m_descriptor->sampleType ==
-	       FeatureExtractionPlugin::OutputDescriptor::FixedSampleRate) {
+	       Vamp::Plugin::OutputDescriptor::FixedSampleRate) {
 
 	if (feature.hasTimestamp) {
 	    //!!! warning: sampleRate may be non-integral
-	    frame = RealTime::realTime2Frame(feature.timestamp,
-					     m_descriptor->sampleRate);
+	    frame = Vamp::RealTime::realTime2Frame(feature.timestamp,
+                                                   m_descriptor->sampleRate);
 	} else {
 	    frame = m_output->getEndFrame() + 1;
 	}
@@ -317,7 +318,7 @@
 	
     } else if (valueCount == 1 ||
 	       m_descriptor->sampleType == 
-	       FeatureExtractionPlugin::OutputDescriptor::VariableSampleRate) {
+	       Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
 
 	float value = 0.0;
 	if (feature.values.size() > 0) value = feature.values[0];
@@ -353,7 +354,7 @@
 
     } else if (valueCount == 1 ||
 	       m_descriptor->sampleType ==
-	       FeatureExtractionPlugin::OutputDescriptor::VariableSampleRate) {
+	       Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
 
 	SparseTimeValueModel *model = getOutput<SparseTimeValueModel>();
 	if (!model) return;
--- a/transform/FeatureExtractionPluginTransform.h	Thu Mar 30 15:00:22 2006 +0000
+++ b/transform/FeatureExtractionPluginTransform.h	Fri Mar 31 15:56:35 2006 +0000
@@ -17,7 +17,8 @@
 #define _FEATURE_EXTRACTION_PLUGIN_TRANSFORM_H_
 
 #include "Transform.h"
-#include "FeatureExtractionPlugin.h"
+
+#include "vamp-sdk/Plugin.h"
 
 class DenseTimeValueModel;
 
@@ -34,13 +35,13 @@
 protected:
     virtual void run();
 
-    FeatureExtractionPlugin *m_plugin;
+    Vamp::Plugin *m_plugin;
     int m_channel;
-    FeatureExtractionPlugin::OutputDescriptor *m_descriptor;
+    Vamp::Plugin::OutputDescriptor *m_descriptor;
     int m_outputFeatureNo;
 
     void addFeature(size_t blockFrame,
-		    const FeatureExtractionPlugin::Feature &feature);
+		    const Vamp::Plugin::Feature &feature);
 
     void setCompletion(int);
 
--- a/transform/RealTimePluginTransform.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ b/transform/RealTimePluginTransform.cpp	Fri Mar 31 15:56:35 2006 +0000
@@ -18,6 +18,7 @@
 
 #include "plugin/RealTimePluginFactory.h"
 #include "plugin/RealTimePluginInstance.h"
+#include "plugin/PluginXml.h"
 
 #include "base/Model.h"
 #include "model/SparseTimeValueModel.h"
@@ -61,7 +62,7 @@
     }
 
     if (configurationXml != "") {
-        m_plugin->setParametersFromXml(configurationXml);
+        PluginXml(m_plugin).setParametersFromXml(configurationXml);
     }
 
     if (m_outputNo >= m_plugin->getControlOutputCount()) {
@@ -145,7 +146,7 @@
 	    }
 	}
 
-        m_plugin->run(RealTime::frame2RealTime(blockFrame, sampleRate));
+        m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
 
         float value = m_plugin->getControlOutputValue(m_outputNo);
 
--- a/transform/TransformFactory.cpp	Thu Mar 30 15:00:22 2006 +0000
+++ b/transform/TransformFactory.cpp	Fri Mar 31 15:56:35 2006 +0000
@@ -20,6 +20,7 @@
 
 #include "plugin/FeatureExtractionPluginFactory.h"
 #include "plugin/RealTimePluginFactory.h"
+#include "plugin/PluginXml.h"
 
 #include "widgets/PluginParameterDialog.h"
 
@@ -139,7 +140,7 @@
 	    continue;
 	}
 
-	FeatureExtractionPlugin *plugin = 
+	Vamp::Plugin *plugin = 
 	    factory->instantiatePlugin(pluginId, 48000);
 
 	if (!plugin) {
@@ -148,7 +149,7 @@
 	}
 		
 	QString pluginDescription = plugin->getDescription().c_str();
-	FeatureExtractionPlugin::OutputList outputs =
+	Vamp::Plugin::OutputList outputs =
 	    plugin->getOutputDescriptors();
 
 	for (size_t j = 0; j < outputs.size(); ++j) {
@@ -305,7 +306,7 @@
 
     if (FeatureExtractionPluginFactory::instanceFor(id)) {
 
-        FeatureExtractionPlugin *plugin = 
+        Vamp::Plugin *plugin = 
             FeatureExtractionPluginFactory::instanceFor(id)->
             instantiatePlugin(id, 48000);
         if (!plugin) return false;
@@ -346,7 +347,7 @@
 
     std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl;
 
-    PluginInstance *plugin = 0;
+    Vamp::PluginBase *plugin = 0;
 
     if (FeatureExtractionPluginFactory::instanceFor(id)) {
 
@@ -361,7 +362,7 @@
 
     if (plugin) {
         if (configurationXml != "") {
-            plugin->setParametersFromXml(configurationXml);
+            PluginXml(plugin).setParametersFromXml(configurationXml);
         }
 
         int sourceChannels = 1;
@@ -386,7 +387,7 @@
         if (dialog->exec() == QDialog::Accepted) {
             ok = true;
         }
-        configurationXml = plugin->toXmlString();
+        configurationXml = PluginXml(plugin).toXmlString();
         channel = dialog->getChannel();
         delete dialog;
         delete plugin;