changeset 332:13e5870040e6

* some tidying, and put some actual work in TransformFactory
author Chris Cannam
date Wed, 07 Nov 2007 14:53:12 +0000
parents f620ce48c950
children 1afaf98dbf11
files plugin/RealTimePluginInstance.h plugin/transform/ModelTransformerFactory.cpp plugin/transform/ModelTransformerFactory.h plugin/transform/Transform.cpp plugin/transform/TransformFactory.cpp plugin/transform/TransformFactory.h
diffstat 6 files changed, 219 insertions(+), 559 deletions(-) [+]
line wrap: on
line diff
--- a/plugin/RealTimePluginInstance.h	Wed Nov 07 12:59:01 2007 +0000
+++ b/plugin/RealTimePluginInstance.h	Wed Nov 07 14:53:12 2007 +0000
@@ -133,7 +133,8 @@
 
     virtual std::string getType() const { return "Real-Time Plugin"; }
 
-    virtual std::map<std::string, std::string> getConfigurePairs() {
+    typedef std::map<std::string, std::string> ConfigurationPairMap;
+    virtual ConfigurationPairMap getConfigurePairs() {
         return m_configurationData;
     }
 
@@ -144,7 +145,7 @@
     RealTimePluginFactory *m_factory;
     QString m_identifier;
 
-    std::map<std::string, std::string> m_configurationData;
+    ConfigurationPairMap m_configurationData;
 
     friend class PluginFactory;
 };
--- a/plugin/transform/ModelTransformerFactory.cpp	Wed Nov 07 12:59:01 2007 +0000
+++ b/plugin/transform/ModelTransformerFactory.cpp	Wed Nov 07 14:53:12 2007 +0000
@@ -18,6 +18,8 @@
 #include "FeatureExtractionModelTransformer.h"
 #include "RealTimeEffectModelTransformer.h"
 
+#include "TransformFactory.h"
+
 #include "plugin/FeatureExtractionPluginFactory.h"
 #include "plugin/RealTimePluginFactory.h"
 #include "plugin/PluginXml.h"
@@ -48,463 +50,9 @@
 {
 }
 
-TransformList
-ModelTransformerFactory::getAllTransforms()
-{
-    if (m_transforms.empty()) populateTransforms();
-
-    std::set<TransformDescription> dset;
-    for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
-	 i != m_transforms.end(); ++i) {
-	dset.insert(i->second);
-    }
-
-    TransformList list;
-    for (std::set<TransformDescription>::const_iterator i = dset.begin();
-	 i != dset.end(); ++i) {
-	list.push_back(*i);
-    }
-
-    return list;
-}
-
-std::vector<QString>
-ModelTransformerFactory::getAllTransformerTypes()
-{
-    if (m_transforms.empty()) populateTransforms();
-
-    std::set<QString> types;
-    for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
-	 i != m_transforms.end(); ++i) {
-        types.insert(i->second.type);
-    }
-
-    std::vector<QString> rv;
-    for (std::set<QString>::iterator i = types.begin(); i != types.end(); ++i) {
-        rv.push_back(*i);
-    }
-
-    return rv;
-}
-
-std::vector<QString>
-ModelTransformerFactory::getTransformerCategories(QString transformType)
-{
-    if (m_transforms.empty()) populateTransforms();
-
-    std::set<QString> categories;
-    for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
-         i != m_transforms.end(); ++i) {
-        if (i->second.type == transformType) {
-            categories.insert(i->second.category);
-        }
-    }
-
-    bool haveEmpty = false;
-    
-    std::vector<QString> rv;
-    for (std::set<QString>::iterator i = categories.begin(); 
-         i != categories.end(); ++i) {
-        if (*i != "") rv.push_back(*i);
-        else haveEmpty = true;
-    }
-
-    if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
-
-    return rv;
-}
-
-std::vector<QString>
-ModelTransformerFactory::getTransformerMakers(QString transformType)
-{
-    if (m_transforms.empty()) populateTransforms();
-
-    std::set<QString> makers;
-    for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
-         i != m_transforms.end(); ++i) {
-        if (i->second.type == transformType) {
-            makers.insert(i->second.maker);
-        }
-    }
-
-    bool haveEmpty = false;
-    
-    std::vector<QString> rv;
-    for (std::set<QString>::iterator i = makers.begin(); 
-         i != makers.end(); ++i) {
-        if (*i != "") rv.push_back(*i);
-        else haveEmpty = true;
-    }
-
-    if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
-
-    return rv;
-}
-
-void
-ModelTransformerFactory::populateTransforms()
-{
-    TransformDescriptionMap transforms;
-
-    populateFeatureExtractionPlugins(transforms);
-    populateRealTimePlugins(transforms);
-
-    // disambiguate plugins with similar names
-
-    std::map<QString, int> names;
-    std::map<QString, QString> pluginSources;
-    std::map<QString, QString> pluginMakers;
-
-    for (TransformDescriptionMap::iterator i = transforms.begin();
-         i != transforms.end(); ++i) {
-
-        TransformDescription desc = i->second;
-
-        QString td = desc.name;
-        QString tn = td.section(": ", 0, 0);
-        QString pn = desc.identifier.section(":", 1, 1);
-
-        if (pluginSources.find(tn) != pluginSources.end()) {
-            if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) {
-                ++names[tn];
-            }
-        } else {
-            ++names[tn];
-            pluginSources[tn] = pn;
-            pluginMakers[tn] = desc.maker;
-        }
-    }
-
-    std::map<QString, int> counts;
-    m_transforms.clear();
-
-    for (TransformDescriptionMap::iterator i = transforms.begin();
-         i != transforms.end(); ++i) {
-
-        TransformDescription desc = i->second;
-	QString identifier = desc.identifier;
-        QString maker = desc.maker;
-
-        QString td = desc.name;
-        QString tn = td.section(": ", 0, 0);
-        QString to = td.section(": ", 1);
-
-	if (names[tn] > 1) {
-            maker.replace(QRegExp(tr(" [\\(<].*$")), "");
-	    tn = QString("%1 [%2]").arg(tn).arg(maker);
-	}
-
-        if (to != "") {
-            desc.name = QString("%1: %2").arg(tn).arg(to);
-        } else {
-            desc.name = tn;
-        }
-
-	m_transforms[identifier] = desc;
-    }	    
-}
-
-void
-ModelTransformerFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
-{
-    std::vector<QString> plugs =
-	FeatureExtractionPluginFactory::getAllPluginIdentifiers();
-
-    for (size_t i = 0; i < plugs.size(); ++i) {
-
-	QString pluginId = plugs[i];
-
-	FeatureExtractionPluginFactory *factory =
-	    FeatureExtractionPluginFactory::instanceFor(pluginId);
-
-	if (!factory) {
-	    std::cerr << "WARNING: ModelTransformerFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
-	    continue;
-	}
-
-	Vamp::Plugin *plugin = 
-	    factory->instantiatePlugin(pluginId, 48000);
-
-	if (!plugin) {
-	    std::cerr << "WARNING: ModelTransformerFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl;
-	    continue;
-	}
-		
-	QString pluginName = plugin->getName().c_str();
-        QString category = factory->getPluginCategory(pluginId);
-
-	Vamp::Plugin::OutputList outputs =
-	    plugin->getOutputDescriptors();
-
-	for (size_t j = 0; j < outputs.size(); ++j) {
-
-	    QString transformId = QString("%1:%2")
-		    .arg(pluginId).arg(outputs[j].identifier.c_str());
-
-	    QString userName;
-            QString friendlyName;
-            QString units = outputs[j].unit.c_str();
-            QString description = plugin->getDescription().c_str();
-            QString maker = plugin->getMaker().c_str();
-            if (maker == "") maker = tr("<unknown maker>");
-
-            if (description == "") {
-                if (outputs.size() == 1) {
-                    description = tr("Extract features using \"%1\" plugin (from %2)")
-                        .arg(pluginName).arg(maker);
-                } else {
-                    description = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
-                        .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
-                }
-            } else {
-                if (outputs.size() == 1) {
-                    description = tr("%1 using \"%2\" plugin (from %3)")
-                        .arg(description).arg(pluginName).arg(maker);
-                } else {
-                    description = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
-                        .arg(description).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
-                }
-            }                    
-
-	    if (outputs.size() == 1) {
-		userName = pluginName;
-                friendlyName = pluginName;
-	    } else {
-		userName = QString("%1: %2")
-		    .arg(pluginName)
-		    .arg(outputs[j].name.c_str());
-                friendlyName = outputs[j].name.c_str();
-	    }
-
-            bool configurable = (!plugin->getPrograms().empty() ||
-                                 !plugin->getParameterDescriptors().empty());
-
-//            std::cerr << "Feature extraction plugin transform: " << transformId.toStdString() << std::endl;
-
-	    transforms[transformId] = 
-                TransformDescription(tr("Analysis"),
-                              category,
-                              transformId,
-                              userName,
-                              friendlyName,
-                              description,
-                              maker,
-                              units,
-                              configurable);
-	}
-
-        delete plugin;
-    }
-}
-
-void
-ModelTransformerFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
-{
-    std::vector<QString> plugs =
-	RealTimePluginFactory::getAllPluginIdentifiers();
-
-    static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
-
-    for (size_t i = 0; i < plugs.size(); ++i) {
-        
-	QString pluginId = plugs[i];
-
-        RealTimePluginFactory *factory =
-            RealTimePluginFactory::instanceFor(pluginId);
-
-	if (!factory) {
-	    std::cerr << "WARNING: ModelTransformerFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
-	    continue;
-	}
-
-        const RealTimePluginDescriptor *descriptor =
-            factory->getPluginDescriptor(pluginId);
-
-        if (!descriptor) {
-	    std::cerr << "WARNING: ModelTransformerFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl;
-	    continue;
-	}
-	
-//!!!        if (descriptor->controlOutputPortCount == 0 ||
-//            descriptor->audioInputPortCount == 0) continue;
-
-//        std::cout << "ModelTransformerFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << std::endl;
-	
-	QString pluginName = descriptor->name.c_str();
-        QString category = factory->getPluginCategory(pluginId);
-        bool configurable = (descriptor->parameterCount > 0);
-        QString maker = descriptor->maker.c_str();
-        if (maker == "") maker = tr("<unknown maker>");
-
-        if (descriptor->audioInputPortCount > 0) {
-
-            for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
-
-                QString transformId = QString("%1:%2").arg(pluginId).arg(j);
-                QString userName;
-                QString units;
-                QString portName;
-
-                if (j < descriptor->controlOutputPortNames.size() &&
-                    descriptor->controlOutputPortNames[j] != "") {
-
-                    portName = descriptor->controlOutputPortNames[j].c_str();
-
-                    userName = tr("%1: %2")
-                        .arg(pluginName)
-                        .arg(portName);
-
-                    if (unitRE.indexIn(portName) >= 0) {
-                        units = unitRE.cap(1);
-                    }
-
-                } else if (descriptor->controlOutputPortCount > 1) {
-
-                    userName = tr("%1: Output %2")
-                        .arg(pluginName)
-                        .arg(j + 1);
-
-                } else {
-
-                    userName = pluginName;
-                }
-
-                QString description;
-
-                if (portName != "") {
-                    description = tr("Extract \"%1\" data output from \"%2\" effect plugin (from %3)")
-                        .arg(portName)
-                        .arg(pluginName)
-                        .arg(maker);
-                } else {
-                    description = tr("Extract data output %1 from \"%2\" effect plugin (from %3)")
-                        .arg(j + 1)
-                        .arg(pluginName)
-                        .arg(maker);
-                }
-
-                transforms[transformId] = 
-                    TransformDescription(tr("Effects Data"),
-                                  category,
-                                  transformId,
-                                  userName,
-                                  userName,
-                                  description,
-                                  maker,
-                                  units,
-                                  configurable);
-            }
-        }
-
-        if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
-
-            if (descriptor->audioOutputPortCount > 0) {
-
-                QString transformId = QString("%1:A").arg(pluginId);
-                QString type = tr("Effects");
-
-                QString description = tr("Transformer audio signal with \"%1\" effect plugin (from %2)")
-                    .arg(pluginName)
-                    .arg(maker);
-
-                if (descriptor->audioInputPortCount == 0) {
-                    type = tr("Generators");
-                    QString description = tr("Generate audio signal using \"%1\" plugin (from %2)")
-                        .arg(pluginName)
-                        .arg(maker);
-                }
-
-                transforms[transformId] =
-                    TransformDescription(type,
-                                  category,
-                                  transformId,
-                                  pluginName,
-                                  pluginName,
-                                  description,
-                                  maker,
-                                  "",
-                                  configurable);
-            }
-        }
-    }
-}
-
-bool
-ModelTransformerFactory::haveTransformer(TransformId identifier)
-{
-    return (m_transforms.find(identifier) != m_transforms.end());
-}
-
-QString
-ModelTransformerFactory::getTransformerName(TransformId identifier)
-{
-    if (m_transforms.find(identifier) != m_transforms.end()) {
-	return m_transforms[identifier].name;
-    } else return "";
-}
-
-QString
-ModelTransformerFactory::getTransformerFriendlyName(TransformId identifier)
-{
-    if (m_transforms.find(identifier) != m_transforms.end()) {
-	return m_transforms[identifier].friendlyName;
-    } else return "";
-}
-
-QString
-ModelTransformerFactory::getTransformerUnits(TransformId identifier)
-{
-    if (m_transforms.find(identifier) != m_transforms.end()) {
-	return m_transforms[identifier].units;
-    } else return "";
-}
-
-bool
-ModelTransformerFactory::isTransformerConfigurable(TransformId identifier)
-{
-    if (m_transforms.find(identifier) != m_transforms.end()) {
-	return m_transforms[identifier].configurable;
-    } else return false;
-}
-
-bool
-ModelTransformerFactory::getTransformerChannelRange(TransformId identifier,
-                                           int &min, int &max)
-{
-    QString id = identifier.section(':', 0, 2);
-
-    if (FeatureExtractionPluginFactory::instanceFor(id)) {
-
-        Vamp::Plugin *plugin = 
-            FeatureExtractionPluginFactory::instanceFor(id)->
-            instantiatePlugin(id, 48000);
-        if (!plugin) return false;
-
-        min = plugin->getMinChannelCount();
-        max = plugin->getMaxChannelCount();
-        delete plugin;
-
-        return true;
-
-    } else if (RealTimePluginFactory::instanceFor(id)) {
-
-        const RealTimePluginDescriptor *descriptor = 
-            RealTimePluginFactory::instanceFor(id)->
-            getPluginDescriptor(id);
-        if (!descriptor) return false;
-
-        min = descriptor->audioInputPortCount;
-        max = descriptor->audioInputPortCount;
-
-        return true;
-    }
-
-    return false;
-}
-
 bool
 ModelTransformerFactory::getChannelRange(TransformId identifier, Vamp::PluginBase *plugin,
-                                  int &minChannels, int &maxChannels)
+                                         int &minChannels, int &maxChannels)
 {
     Vamp::Plugin *vp = 0;
     if ((vp = dynamic_cast<Vamp::Plugin *>(plugin)) ||
@@ -513,7 +61,8 @@
         maxChannels = vp->getMaxChannelCount();
         return true;
     } else {
-        return getTransformerChannelRange(identifier, minChannels, maxChannels);
+        return TransformFactory::getInstance()->
+            getTransformChannelRange(identifier, minChannels, maxChannels);
     }
 }
 
@@ -752,19 +301,13 @@
     QString output = identifier.section(':', 3);
 
     if (FeatureExtractionPluginFactory::instanceFor(id)) {
-        transformer = new FeatureExtractionModelTransformer(inputModel,
-                                                            id,
-                                                            context,
-                                                            configurationXml,
-                                                            output);
+        transformer = new FeatureExtractionModelTransformer
+            (inputModel, id, context, configurationXml, output);
     } else if (RealTimePluginFactory::instanceFor(id)) {
-        transformer = new RealTimeEffectModelTransformer(inputModel,
-                                                         id,
-                                                         context,
-                                                         configurationXml,
-                                                         getTransformerUnits(identifier),
-                                                         output == "A" ? -1 :
-                                                         output.toInt());
+        transformer = new RealTimeEffectModelTransformer
+            (inputModel, id, context, configurationXml,
+             TransformFactory::getInstance()->getTransformUnits(identifier),
+             output == "A" ? -1 : output.toInt());
     } else {
         std::cerr << "ModelTransformerFactory::createTransformer: Unknown transform \""
                   << identifier.toStdString() << "\"" << std::endl;
@@ -794,7 +337,9 @@
 
     if (model) {
         QString imn = inputModel->objectName();
-        QString trn = getTransformerFriendlyName(identifier);
+        QString trn =
+            TransformFactory::getInstance()->getTransformFriendlyName
+            (identifier);
         if (imn != "") {
             if (trn != "") {
                 model->setObjectName(tr("%1: %2").arg(imn).arg(trn));
--- a/plugin/transform/ModelTransformerFactory.h	Wed Nov 07 12:59:01 2007 +0000
+++ b/plugin/transform/ModelTransformerFactory.h	Wed Nov 07 14:53:12 2007 +0000
@@ -30,10 +30,6 @@
 
 class AudioCallbackPlaySource;
 
-//!!! split into TransformFactory (information about available
-// transforms, create default Transform for each transform ID etc) and
-// TransformerFactory (create Transformers to apply transforms)
-
 class ModelTransformerFactory : public QObject
 {
     Q_OBJECT
@@ -43,13 +39,6 @@
 
     static ModelTransformerFactory *getInstance();
 
-    TransformList getAllTransforms();
-
-    std::vector<QString> getAllTransformerTypes();
-
-    std::vector<QString> getTransformerCategories(QString transformType);
-    std::vector<QString> getTransformerMakers(QString transformType);
-
     /**
      * Get a configuration XML string for the given transform (by
      * asking the user, most likely).  Returns the selected input
@@ -58,19 +47,19 @@
      * audition effects plugins, if provided.
      */
     Model *getConfigurationForTransformer(TransformId identifier,
-                                        const std::vector<Model *> &candidateInputModels,
-                                        PluginTransformer::ExecutionContext &context,
-                                        QString &configurationXml,
-                                        AudioCallbackPlaySource *source = 0,
-                                        size_t startFrame = 0,
-                                        size_t duration = 0);
+                                          const std::vector<Model *> &candidateInputModels,
+                                          PluginTransformer::ExecutionContext &context,
+                                          QString &configurationXml,
+                                          AudioCallbackPlaySource *source = 0,
+                                          size_t startFrame = 0,
+                                          size_t duration = 0);
 
     /**
      * Get the default execution context for the given transform
      * and input model (if known).
      */
     PluginTransformer::ExecutionContext getDefaultContextForTransformer(TransformId identifier,
-                                                                    Model *inputModel = 0);
+                                                                        Model *inputModel = 0);
 
     /**
      * Return the output model resulting from applying the named
@@ -89,40 +78,6 @@
                      const PluginTransformer::ExecutionContext &context,
                      QString configurationXml = "");
 
-    /**
-     * Return true if the given transform is known.
-     */
-    bool haveTransformer(TransformId identifier);
-
-    /**
-     * Full name of a transform, suitable for putting on a menu.
-     */
-    QString getTransformerName(TransformId identifier);
-
-    /**
-     * Brief but friendly name of a transform, suitable for use
-     * as the name of the output layer.
-     */
-    QString getTransformerFriendlyName(TransformId identifier);
-
-    QString getTransformerUnits(TransformId identifier);
-
-    /**
-     * Return true if the transform has any configurable parameters,
-     * i.e. if getConfigurationForTransformer can ever return a non-trivial
-     * (not equivalent to empty) configuration string.
-     */
-    bool isTransformerConfigurable(TransformId identifier);
-
-    /**
-     * If the transform has a prescribed number or range of channel
-     * inputs, return true and set minChannels and maxChannels to the
-     * minimum and maximum number of channel inputs the transform can
-     * accept.  Return false if it doesn't care.
-     */
-    bool getTransformerChannelRange(TransformId identifier,
-                                  int &minChannels, int &maxChannels);
-	
 protected slots:
     void transformerFinished();
 
@@ -136,16 +91,9 @@
     typedef std::map<TransformId, QString> TransformerConfigurationMap;
     TransformerConfigurationMap m_lastConfigurations;
 
-    typedef std::map<TransformId, TransformDescription> TransformDescriptionMap;
-    TransformDescriptionMap m_transforms;
-
     typedef std::set<ModelTransformer *> TransformerSet;
     TransformerSet m_runningTransformers;
 
-    void populateTransforms();
-    void populateFeatureExtractionPlugins(TransformDescriptionMap &);
-    void populateRealTimePlugins(TransformDescriptionMap &);
-
     bool getChannelRange(TransformId identifier,
                          Vamp::PluginBase *plugin, int &min, int &max);
 
--- a/plugin/transform/Transform.cpp	Wed Nov 07 12:59:01 2007 +0000
+++ b/plugin/transform/Transform.cpp	Wed Nov 07 14:53:12 2007 +0000
@@ -17,6 +17,8 @@
 
 #include "plugin/PluginIdentifier.h"
 
+#include "plugin/FeatureExtractionPluginFactory.h"
+
 Transform::Transform() :
     m_stepSize(0),
     m_blockSize(0),
@@ -50,10 +52,13 @@
 Transform::Type
 Transform::getType() const
 {
-    QString type, soName, label, output;
-    parseIdentifier(m_id, type, soName, label, output);
-    if (type == "vamp") return FeatureExtraction; //!!! lousy
-    else return RealTimeEffect;
+    if (FeatureExtractionPluginFactory::instanceFor(getPluginIdentifier())) {
+        return FeatureExtraction;
+    } else {
+        // We don't have an unknown/invalid return value, so always
+        // return this
+        return RealTimeEffect;
+    }
 }
 
 QString
--- a/plugin/transform/TransformFactory.cpp	Wed Nov 07 12:59:01 2007 +0000
+++ b/plugin/transform/TransformFactory.cpp	Wed Nov 07 14:53:12 2007 +0000
@@ -17,9 +17,12 @@
 
 #include "plugin/FeatureExtractionPluginFactory.h"
 #include "plugin/RealTimePluginFactory.h"
+#include "plugin/RealTimePluginInstance.h"
 #include "plugin/PluginXml.h"
 
+#include "vamp-sdk/Plugin.h"
 #include "vamp-sdk/PluginHostAdapter.h"
+#include "vamp-sdk/hostext/PluginWrapper.h"
 
 #include <iostream>
 #include <set>
@@ -274,14 +277,14 @@
 
 	    transforms[transformId] = 
                 TransformDescription(tr("Analysis"),
-                              category,
-                              transformId,
-                              userName,
-                              friendlyName,
-                              description,
-                              maker,
-                              units,
-                              configurable);
+                                     category,
+                                     transformId,
+                                     userName,
+                                     friendlyName,
+                                     description,
+                                     maker,
+                                     units,
+                                     configurable);
 	}
 
         delete plugin;
@@ -376,14 +379,14 @@
 
                 transforms[transformId] = 
                     TransformDescription(tr("Effects Data"),
-                                  category,
-                                  transformId,
-                                  userName,
-                                  userName,
-                                  description,
-                                  maker,
-                                  units,
-                                  configurable);
+                                         category,
+                                         transformId,
+                                         userName,
+                                         userName,
+                                         description,
+                                         maker,
+                                         units,
+                                         configurable);
             }
         }
 
@@ -407,14 +410,14 @@
 
                 transforms[transformId] =
                     TransformDescription(type,
-                                  category,
-                                  transformId,
-                                  pluginName,
-                                  pluginName,
-                                  description,
-                                  maker,
-                                  "",
-                                  configurable);
+                                         category,
+                                         transformId,
+                                         pluginName,
+                                         pluginName,
+                                         description,
+                                         maker,
+                                         "",
+                                         configurable);
             }
         }
     }
@@ -492,3 +495,139 @@
 
     return false;
 }
+
+void
+TransformFactory::setParametersFromPlugin(Transform &transform,
+                                          Vamp::PluginBase *plugin)
+{
+    Transform::ParameterMap pmap;
+
+    Vamp::PluginBase::ParameterList parameters =
+        plugin->getParameterDescriptors();
+
+    for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
+         i != parameters.end(); ++i) {
+        pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier);
+    }
+
+    transform.setParameters(pmap);
+
+    if (plugin->getPrograms().empty()) {
+        transform.setProgram("");
+    } else {
+        transform.setProgram(plugin->getCurrentProgram().c_str());
+    }
+
+    RealTimePluginInstance *rtpi =
+        dynamic_cast<RealTimePluginInstance *>(plugin);
+
+    Transform::ConfigurationMap cmap;
+
+    if (rtpi) {
+
+        RealTimePluginInstance::ConfigurationPairMap configurePairs =
+            rtpi->getConfigurePairs();
+
+        for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i
+                 = configurePairs.begin(); i != configurePairs.end(); ++i) {
+            cmap[i->first.c_str()] = i->second.c_str();
+        }
+    }
+
+    transform.setConfiguration(cmap);
+}
+
+void
+TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
+                                                  Vamp::PluginBase *plugin)
+{
+    const Vamp::Plugin *vp = dynamic_cast<const Vamp::Plugin *>(plugin);
+    if (!vp) {
+//        std::cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << std::endl;
+        vp = dynamic_cast<const Vamp::PluginHostAdapter *>(plugin); //!!! why?
+}
+    if (!vp) {
+//        std::cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << std::endl;
+        vp = dynamic_cast<const Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
+    }
+    if (!vp) {
+//        std::cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << std::endl;
+    }
+
+    if (!vp) {
+        // time domain input for real-time effects plugin
+        if (!transform.getBlockSize()) {
+            if (!transform.getStepSize()) transform.setStepSize(1024);
+            transform.setBlockSize(transform.getStepSize());
+        } else {
+            transform.setStepSize(transform.getBlockSize());
+        }
+    } else {
+        Vamp::Plugin::InputDomain domain = vp->getInputDomain();
+        if (!transform.getStepSize()) {
+            transform.setStepSize(vp->getPreferredStepSize());
+        }
+        if (!transform.getBlockSize()) {
+            transform.setBlockSize(vp->getPreferredBlockSize());
+        }
+        if (!transform.getBlockSize()) {
+            transform.setBlockSize(1024);
+        }
+        if (!transform.getStepSize()) {
+            if (domain == Vamp::Plugin::FrequencyDomain) {
+//                std::cerr << "frequency domain, step = " << blockSize/2 << std::endl;
+                transform.setStepSize(transform.getBlockSize()/2);
+            } else {
+//                std::cerr << "time domain, step = " << blockSize/2 << std::endl;
+                transform.setStepSize(transform.getBlockSize());
+            }
+        }
+    }
+}
+
+Transform
+TransformFactory::getDefaultTransformFor(TransformId id, size_t rate)
+{
+    Transform t;
+    t.setIdentifier(id);
+    
+    if (rate == 0) {
+        rate = 44100;
+    } else {
+        t.setSampleRate(rate);
+    }
+
+    QString pluginId = t.getPluginIdentifier();
+
+    if (t.getType() == Transform::FeatureExtraction) {
+
+        FeatureExtractionPluginFactory *factory = 
+            FeatureExtractionPluginFactory::instanceFor(pluginId);
+
+        Vamp::Plugin *plugin = factory->instantiatePlugin
+            (pluginId, rate);
+
+        if (plugin) {
+            setParametersFromPlugin(t, plugin);
+            makeContextConsistentWithPlugin(t, plugin);
+            delete plugin;
+        }
+
+    } else {
+
+        RealTimePluginFactory *factory = 
+            RealTimePluginFactory::instanceFor(pluginId);
+            
+        RealTimePluginInstance *plugin = factory->instantiatePlugin
+            (pluginId, 0, 0, rate, 1024, 1);
+        
+        if (plugin) {
+            setParametersFromPlugin(t, plugin);
+            makeContextConsistentWithPlugin(t, plugin);
+            delete plugin;
+        }
+    }
+
+    return t;
+}
+
--- a/plugin/transform/TransformFactory.h	Wed Nov 07 12:59:01 2007 +0000
+++ b/plugin/transform/TransformFactory.h	Wed Nov 07 14:53:12 2007 +0000
@@ -72,7 +72,29 @@
      */
     bool getTransformChannelRange(TransformId identifier,
                                   int &minChannels, int &maxChannels);
-	
+
+    /**
+     * Set the plugin parameters, program and configuration strings on
+     * the given Transform object from the given plugin instance.
+     * Note that no check is made whether the plugin is actually the
+     * "correct" one for the transform.
+     */
+    void setParametersFromPlugin(Transform &transform, Vamp::PluginBase *plugin);
+
+    /**
+     * If the given Transform object has no processing step and block
+     * sizes set, set them to appropriate defaults for the given
+     * plugin.
+     */
+    void makeContextConsistentWithPlugin(Transform &transform, Vamp::PluginBase *plugin); 
+
+    /**
+     * A single transform ID can lead to many possible Transforms,
+     * with different parameters and execution context settings.
+     * Return the default one for the given transform.
+     */
+    Transform getDefaultTransformFor(TransformId identifier, size_t rate = 0);
+
 protected:
     typedef std::map<TransformId, TransformDescription> TransformDescriptionMap;
     TransformDescriptionMap m_transforms;