Chris@330: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@330: 
Chris@330: /*
Chris@330:     Sonic Visualiser
Chris@330:     An audio file viewer and annotation editor.
Chris@330:     Centre for Digital Music, Queen Mary, University of London.
Chris@330:     This file copyright 2006 Chris Cannam and QMUL.
Chris@330:    
Chris@330:     This program is free software; you can redistribute it and/or
Chris@330:     modify it under the terms of the GNU General Public License as
Chris@330:     published by the Free Software Foundation; either version 2 of the
Chris@330:     License, or (at your option) any later version.  See the file
Chris@330:     COPYING included with this distribution for more information.
Chris@330: */
Chris@330: 
Chris@330: #include "TransformFactory.h"
Chris@330: 
Chris@330: #include "plugin/FeatureExtractionPluginFactory.h"
Chris@330: #include "plugin/RealTimePluginFactory.h"
Chris@332: #include "plugin/RealTimePluginInstance.h"
Chris@330: #include "plugin/PluginXml.h"
Chris@330: 
Chris@332: #include "vamp-sdk/Plugin.h"
Chris@330: #include "vamp-sdk/PluginHostAdapter.h"
Chris@332: #include "vamp-sdk/hostext/PluginWrapper.h"
Chris@330: 
Chris@330: #include <iostream>
Chris@330: #include <set>
Chris@330: 
Chris@330: #include <QRegExp>
Chris@330: 
Chris@330: TransformFactory *
Chris@330: TransformFactory::m_instance = new TransformFactory;
Chris@330: 
Chris@330: TransformFactory *
Chris@330: TransformFactory::getInstance()
Chris@330: {
Chris@330:     return m_instance;
Chris@330: }
Chris@330: 
Chris@330: TransformFactory::~TransformFactory()
Chris@330: {
Chris@330: }
Chris@330: 
Chris@330: TransformList
Chris@330: TransformFactory::getAllTransforms()
Chris@330: {
Chris@330:     if (m_transforms.empty()) populateTransforms();
Chris@330: 
Chris@330:     std::set<TransformDescription> dset;
Chris@330:     for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330: 	 i != m_transforms.end(); ++i) {
Chris@330: 	dset.insert(i->second);
Chris@330:     }
Chris@330: 
Chris@330:     TransformList list;
Chris@330:     for (std::set<TransformDescription>::const_iterator i = dset.begin();
Chris@330: 	 i != dset.end(); ++i) {
Chris@330: 	list.push_back(*i);
Chris@330:     }
Chris@330: 
Chris@330:     return list;
Chris@330: }
Chris@330: 
Chris@330: std::vector<QString>
Chris@330: TransformFactory::getAllTransformTypes()
Chris@330: {
Chris@330:     if (m_transforms.empty()) populateTransforms();
Chris@330: 
Chris@330:     std::set<QString> types;
Chris@330:     for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330: 	 i != m_transforms.end(); ++i) {
Chris@330:         types.insert(i->second.type);
Chris@330:     }
Chris@330: 
Chris@330:     std::vector<QString> rv;
Chris@330:     for (std::set<QString>::iterator i = types.begin(); i != types.end(); ++i) {
Chris@330:         rv.push_back(*i);
Chris@330:     }
Chris@330: 
Chris@330:     return rv;
Chris@330: }
Chris@330: 
Chris@330: std::vector<QString>
Chris@330: TransformFactory::getTransformCategories(QString transformType)
Chris@330: {
Chris@330:     if (m_transforms.empty()) populateTransforms();
Chris@330: 
Chris@330:     std::set<QString> categories;
Chris@330:     for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330:          i != m_transforms.end(); ++i) {
Chris@330:         if (i->second.type == transformType) {
Chris@330:             categories.insert(i->second.category);
Chris@330:         }
Chris@330:     }
Chris@330: 
Chris@330:     bool haveEmpty = false;
Chris@330:     
Chris@330:     std::vector<QString> rv;
Chris@330:     for (std::set<QString>::iterator i = categories.begin(); 
Chris@330:          i != categories.end(); ++i) {
Chris@330:         if (*i != "") rv.push_back(*i);
Chris@330:         else haveEmpty = true;
Chris@330:     }
Chris@330: 
Chris@330:     if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330: 
Chris@330:     return rv;
Chris@330: }
Chris@330: 
Chris@330: std::vector<QString>
Chris@330: TransformFactory::getTransformMakers(QString transformType)
Chris@330: {
Chris@330:     if (m_transforms.empty()) populateTransforms();
Chris@330: 
Chris@330:     std::set<QString> makers;
Chris@330:     for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330:          i != m_transforms.end(); ++i) {
Chris@330:         if (i->second.type == transformType) {
Chris@330:             makers.insert(i->second.maker);
Chris@330:         }
Chris@330:     }
Chris@330: 
Chris@330:     bool haveEmpty = false;
Chris@330:     
Chris@330:     std::vector<QString> rv;
Chris@330:     for (std::set<QString>::iterator i = makers.begin(); 
Chris@330:          i != makers.end(); ++i) {
Chris@330:         if (*i != "") rv.push_back(*i);
Chris@330:         else haveEmpty = true;
Chris@330:     }
Chris@330: 
Chris@330:     if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330: 
Chris@330:     return rv;
Chris@330: }
Chris@330: 
Chris@330: void
Chris@330: TransformFactory::populateTransforms()
Chris@330: {
Chris@330:     TransformDescriptionMap transforms;
Chris@330: 
Chris@330:     populateFeatureExtractionPlugins(transforms);
Chris@330:     populateRealTimePlugins(transforms);
Chris@330: 
Chris@330:     // disambiguate plugins with similar names
Chris@330: 
Chris@330:     std::map<QString, int> names;
Chris@330:     std::map<QString, QString> pluginSources;
Chris@330:     std::map<QString, QString> pluginMakers;
Chris@330: 
Chris@330:     for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330:          i != transforms.end(); ++i) {
Chris@330: 
Chris@330:         TransformDescription desc = i->second;
Chris@330: 
Chris@330:         QString td = desc.name;
Chris@330:         QString tn = td.section(": ", 0, 0);
Chris@330:         QString pn = desc.identifier.section(":", 1, 1);
Chris@330: 
Chris@330:         if (pluginSources.find(tn) != pluginSources.end()) {
Chris@330:             if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) {
Chris@330:                 ++names[tn];
Chris@330:             }
Chris@330:         } else {
Chris@330:             ++names[tn];
Chris@330:             pluginSources[tn] = pn;
Chris@330:             pluginMakers[tn] = desc.maker;
Chris@330:         }
Chris@330:     }
Chris@330: 
Chris@330:     std::map<QString, int> counts;
Chris@330:     m_transforms.clear();
Chris@330: 
Chris@330:     for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330:          i != transforms.end(); ++i) {
Chris@330: 
Chris@330:         TransformDescription desc = i->second;
Chris@330: 	QString identifier = desc.identifier;
Chris@330:         QString maker = desc.maker;
Chris@330: 
Chris@330:         QString td = desc.name;
Chris@330:         QString tn = td.section(": ", 0, 0);
Chris@330:         QString to = td.section(": ", 1);
Chris@330: 
Chris@330: 	if (names[tn] > 1) {
Chris@330:             maker.replace(QRegExp(tr(" [\\(<].*$")), "");
Chris@330: 	    tn = QString("%1 [%2]").arg(tn).arg(maker);
Chris@330: 	}
Chris@330: 
Chris@330:         if (to != "") {
Chris@330:             desc.name = QString("%1: %2").arg(tn).arg(to);
Chris@330:         } else {
Chris@330:             desc.name = tn;
Chris@330:         }
Chris@330: 
Chris@330: 	m_transforms[identifier] = desc;
Chris@330:     }	    
Chris@330: }
Chris@330: 
Chris@330: void
Chris@330: TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
Chris@330: {
Chris@330:     std::vector<QString> plugs =
Chris@330: 	FeatureExtractionPluginFactory::getAllPluginIdentifiers();
Chris@330: 
Chris@330:     for (size_t i = 0; i < plugs.size(); ++i) {
Chris@330: 
Chris@330: 	QString pluginId = plugs[i];
Chris@330: 
Chris@330: 	FeatureExtractionPluginFactory *factory =
Chris@330: 	    FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@330: 
Chris@330: 	if (!factory) {
Chris@330: 	    std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@330: 	    continue;
Chris@330: 	}
Chris@330: 
Chris@330: 	Vamp::Plugin *plugin = 
Chris@330: 	    factory->instantiatePlugin(pluginId, 48000);
Chris@330: 
Chris@330: 	if (!plugin) {
Chris@330: 	    std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@330: 	    continue;
Chris@330: 	}
Chris@330: 		
Chris@330: 	QString pluginName = plugin->getName().c_str();
Chris@330:         QString category = factory->getPluginCategory(pluginId);
Chris@330: 
Chris@330: 	Vamp::Plugin::OutputList outputs =
Chris@330: 	    plugin->getOutputDescriptors();
Chris@330: 
Chris@330: 	for (size_t j = 0; j < outputs.size(); ++j) {
Chris@330: 
Chris@330: 	    QString transformId = QString("%1:%2")
Chris@330: 		    .arg(pluginId).arg(outputs[j].identifier.c_str());
Chris@330: 
Chris@330: 	    QString userName;
Chris@330:             QString friendlyName;
Chris@330:             QString units = outputs[j].unit.c_str();
Chris@330:             QString description = plugin->getDescription().c_str();
Chris@330:             QString maker = plugin->getMaker().c_str();
Chris@330:             if (maker == "") maker = tr("<unknown maker>");
Chris@330: 
Chris@330:             if (description == "") {
Chris@330:                 if (outputs.size() == 1) {
Chris@330:                     description = tr("Extract features using \"%1\" plugin (from %2)")
Chris@330:                         .arg(pluginName).arg(maker);
Chris@330:                 } else {
Chris@330:                     description = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
Chris@330:                         .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330:                 }
Chris@330:             } else {
Chris@330:                 if (outputs.size() == 1) {
Chris@330:                     description = tr("%1 using \"%2\" plugin (from %3)")
Chris@330:                         .arg(description).arg(pluginName).arg(maker);
Chris@330:                 } else {
Chris@330:                     description = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
Chris@330:                         .arg(description).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
Chris@330:                 }
Chris@330:             }                    
Chris@330: 
Chris@330: 	    if (outputs.size() == 1) {
Chris@330: 		userName = pluginName;
Chris@330:                 friendlyName = pluginName;
Chris@330: 	    } else {
Chris@330: 		userName = QString("%1: %2")
Chris@330: 		    .arg(pluginName)
Chris@330: 		    .arg(outputs[j].name.c_str());
Chris@330:                 friendlyName = outputs[j].name.c_str();
Chris@330: 	    }
Chris@330: 
Chris@330:             bool configurable = (!plugin->getPrograms().empty() ||
Chris@330:                                  !plugin->getParameterDescriptors().empty());
Chris@330: 
Chris@330: //            std::cerr << "Feature extraction plugin transform: " << transformId.toStdString() << std::endl;
Chris@330: 
Chris@330: 	    transforms[transformId] = 
Chris@330:                 TransformDescription(tr("Analysis"),
Chris@332:                                      category,
Chris@332:                                      transformId,
Chris@332:                                      userName,
Chris@332:                                      friendlyName,
Chris@332:                                      description,
Chris@332:                                      maker,
Chris@332:                                      units,
Chris@332:                                      configurable);
Chris@330: 	}
Chris@330: 
Chris@330:         delete plugin;
Chris@330:     }
Chris@330: }
Chris@330: 
Chris@330: void
Chris@330: TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@330: {
Chris@330:     std::vector<QString> plugs =
Chris@330: 	RealTimePluginFactory::getAllPluginIdentifiers();
Chris@330: 
Chris@330:     static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@330: 
Chris@330:     for (size_t i = 0; i < plugs.size(); ++i) {
Chris@330:         
Chris@330: 	QString pluginId = plugs[i];
Chris@330: 
Chris@330:         RealTimePluginFactory *factory =
Chris@330:             RealTimePluginFactory::instanceFor(pluginId);
Chris@330: 
Chris@330: 	if (!factory) {
Chris@330: 	    std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
Chris@330: 	    continue;
Chris@330: 	}
Chris@330: 
Chris@330:         const RealTimePluginDescriptor *descriptor =
Chris@330:             factory->getPluginDescriptor(pluginId);
Chris@330: 
Chris@330:         if (!descriptor) {
Chris@330: 	    std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl;
Chris@330: 	    continue;
Chris@330: 	}
Chris@330: 	
Chris@330: //!!!        if (descriptor->controlOutputPortCount == 0 ||
Chris@330: //            descriptor->audioInputPortCount == 0) continue;
Chris@330: 
Chris@330: //        std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << std::endl;
Chris@330: 	
Chris@330: 	QString pluginName = descriptor->name.c_str();
Chris@330:         QString category = factory->getPluginCategory(pluginId);
Chris@330:         bool configurable = (descriptor->parameterCount > 0);
Chris@330:         QString maker = descriptor->maker.c_str();
Chris@330:         if (maker == "") maker = tr("<unknown maker>");
Chris@330: 
Chris@330:         if (descriptor->audioInputPortCount > 0) {
Chris@330: 
Chris@330:             for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
Chris@330: 
Chris@330:                 QString transformId = QString("%1:%2").arg(pluginId).arg(j);
Chris@330:                 QString userName;
Chris@330:                 QString units;
Chris@330:                 QString portName;
Chris@330: 
Chris@330:                 if (j < descriptor->controlOutputPortNames.size() &&
Chris@330:                     descriptor->controlOutputPortNames[j] != "") {
Chris@330: 
Chris@330:                     portName = descriptor->controlOutputPortNames[j].c_str();
Chris@330: 
Chris@330:                     userName = tr("%1: %2")
Chris@330:                         .arg(pluginName)
Chris@330:                         .arg(portName);
Chris@330: 
Chris@330:                     if (unitRE.indexIn(portName) >= 0) {
Chris@330:                         units = unitRE.cap(1);
Chris@330:                     }
Chris@330: 
Chris@330:                 } else if (descriptor->controlOutputPortCount > 1) {
Chris@330: 
Chris@330:                     userName = tr("%1: Output %2")
Chris@330:                         .arg(pluginName)
Chris@330:                         .arg(j + 1);
Chris@330: 
Chris@330:                 } else {
Chris@330: 
Chris@330:                     userName = pluginName;
Chris@330:                 }
Chris@330: 
Chris@330:                 QString description;
Chris@330: 
Chris@330:                 if (portName != "") {
Chris@330:                     description = tr("Extract \"%1\" data output from \"%2\" effect plugin (from %3)")
Chris@330:                         .arg(portName)
Chris@330:                         .arg(pluginName)
Chris@330:                         .arg(maker);
Chris@330:                 } else {
Chris@330:                     description = tr("Extract data output %1 from \"%2\" effect plugin (from %3)")
Chris@330:                         .arg(j + 1)
Chris@330:                         .arg(pluginName)
Chris@330:                         .arg(maker);
Chris@330:                 }
Chris@330: 
Chris@330:                 transforms[transformId] = 
Chris@330:                     TransformDescription(tr("Effects Data"),
Chris@332:                                          category,
Chris@332:                                          transformId,
Chris@332:                                          userName,
Chris@332:                                          userName,
Chris@332:                                          description,
Chris@332:                                          maker,
Chris@332:                                          units,
Chris@332:                                          configurable);
Chris@330:             }
Chris@330:         }
Chris@330: 
Chris@330:         if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@330: 
Chris@330:             if (descriptor->audioOutputPortCount > 0) {
Chris@330: 
Chris@330:                 QString transformId = QString("%1:A").arg(pluginId);
Chris@330:                 QString type = tr("Effects");
Chris@330: 
Chris@330:                 QString description = tr("Transform audio signal with \"%1\" effect plugin (from %2)")
Chris@330:                     .arg(pluginName)
Chris@330:                     .arg(maker);
Chris@330: 
Chris@330:                 if (descriptor->audioInputPortCount == 0) {
Chris@330:                     type = tr("Generators");
Chris@330:                     QString description = tr("Generate audio signal using \"%1\" plugin (from %2)")
Chris@330:                         .arg(pluginName)
Chris@330:                         .arg(maker);
Chris@330:                 }
Chris@330: 
Chris@330:                 transforms[transformId] =
Chris@330:                     TransformDescription(type,
Chris@332:                                          category,
Chris@332:                                          transformId,
Chris@332:                                          pluginName,
Chris@332:                                          pluginName,
Chris@332:                                          description,
Chris@332:                                          maker,
Chris@332:                                          "",
Chris@332:                                          configurable);
Chris@330:             }
Chris@330:         }
Chris@330:     }
Chris@330: }
Chris@330: 
Chris@330: bool
Chris@330: TransformFactory::haveTransform(TransformId identifier)
Chris@330: {
Chris@333:     if (m_transforms.empty()) populateTransforms();
Chris@330:     return (m_transforms.find(identifier) != m_transforms.end());
Chris@330: }
Chris@330: 
Chris@330: QString
Chris@330: TransformFactory::getTransformName(TransformId identifier)
Chris@330: {
Chris@330:     if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330: 	return m_transforms[identifier].name;
Chris@330:     } else return "";
Chris@330: }
Chris@330: 
Chris@330: QString
Chris@330: TransformFactory::getTransformFriendlyName(TransformId identifier)
Chris@330: {
Chris@330:     if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330: 	return m_transforms[identifier].friendlyName;
Chris@330:     } else return "";
Chris@330: }
Chris@330: 
Chris@330: QString
Chris@330: TransformFactory::getTransformUnits(TransformId identifier)
Chris@330: {
Chris@330:     if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330: 	return m_transforms[identifier].units;
Chris@330:     } else return "";
Chris@330: }
Chris@330: 
Chris@330: bool
Chris@330: TransformFactory::isTransformConfigurable(TransformId identifier)
Chris@330: {
Chris@330:     if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@330: 	return m_transforms[identifier].configurable;
Chris@330:     } else return false;
Chris@330: }
Chris@330: 
Chris@330: bool
Chris@330: TransformFactory::getTransformChannelRange(TransformId identifier,
Chris@330:                                            int &min, int &max)
Chris@330: {
Chris@330:     QString id = identifier.section(':', 0, 2);
Chris@330: 
Chris@330:     if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@330: 
Chris@330:         Vamp::Plugin *plugin = 
Chris@330:             FeatureExtractionPluginFactory::instanceFor(id)->
Chris@330:             instantiatePlugin(id, 48000);
Chris@330:         if (!plugin) return false;
Chris@330: 
Chris@330:         min = plugin->getMinChannelCount();
Chris@330:         max = plugin->getMaxChannelCount();
Chris@330:         delete plugin;
Chris@330: 
Chris@330:         return true;
Chris@330: 
Chris@330:     } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@330: 
Chris@330:         const RealTimePluginDescriptor *descriptor = 
Chris@330:             RealTimePluginFactory::instanceFor(id)->
Chris@330:             getPluginDescriptor(id);
Chris@330:         if (!descriptor) return false;
Chris@330: 
Chris@330:         min = descriptor->audioInputPortCount;
Chris@330:         max = descriptor->audioInputPortCount;
Chris@330: 
Chris@330:         return true;
Chris@330:     }
Chris@330: 
Chris@330:     return false;
Chris@330: }
Chris@332: 
Chris@332: void
Chris@332: TransformFactory::setParametersFromPlugin(Transform &transform,
Chris@332:                                           Vamp::PluginBase *plugin)
Chris@332: {
Chris@332:     Transform::ParameterMap pmap;
Chris@332: 
Chris@332:     Vamp::PluginBase::ParameterList parameters =
Chris@332:         plugin->getParameterDescriptors();
Chris@332: 
Chris@332:     for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@332:          i != parameters.end(); ++i) {
Chris@332:         pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier);
Chris@332:     }
Chris@332: 
Chris@332:     transform.setParameters(pmap);
Chris@332: 
Chris@332:     if (plugin->getPrograms().empty()) {
Chris@332:         transform.setProgram("");
Chris@332:     } else {
Chris@332:         transform.setProgram(plugin->getCurrentProgram().c_str());
Chris@332:     }
Chris@332: 
Chris@332:     RealTimePluginInstance *rtpi =
Chris@332:         dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@332: 
Chris@332:     Transform::ConfigurationMap cmap;
Chris@332: 
Chris@332:     if (rtpi) {
Chris@332: 
Chris@332:         RealTimePluginInstance::ConfigurationPairMap configurePairs =
Chris@332:             rtpi->getConfigurePairs();
Chris@332: 
Chris@332:         for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i
Chris@332:                  = configurePairs.begin(); i != configurePairs.end(); ++i) {
Chris@332:             cmap[i->first.c_str()] = i->second.c_str();
Chris@332:         }
Chris@332:     }
Chris@332: 
Chris@332:     transform.setConfiguration(cmap);
Chris@332: }
Chris@332: 
Chris@332: void
Chris@332: TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
Chris@332:                                                   Vamp::PluginBase *plugin)
Chris@332: {
Chris@332:     const Vamp::Plugin *vp = dynamic_cast<const Vamp::Plugin *>(plugin);
Chris@332:     if (!vp) {
Chris@332: //        std::cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << std::endl;
Chris@332:         vp = dynamic_cast<const Vamp::PluginHostAdapter *>(plugin); //!!! why?
Chris@332: }
Chris@332:     if (!vp) {
Chris@332: //        std::cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << std::endl;
Chris@332:         vp = dynamic_cast<const Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
Chris@332:     }
Chris@332:     if (!vp) {
Chris@332: //        std::cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << std::endl;
Chris@332:     }
Chris@332: 
Chris@332:     if (!vp) {
Chris@332:         // time domain input for real-time effects plugin
Chris@332:         if (!transform.getBlockSize()) {
Chris@332:             if (!transform.getStepSize()) transform.setStepSize(1024);
Chris@332:             transform.setBlockSize(transform.getStepSize());
Chris@332:         } else {
Chris@332:             transform.setStepSize(transform.getBlockSize());
Chris@332:         }
Chris@332:     } else {
Chris@332:         Vamp::Plugin::InputDomain domain = vp->getInputDomain();
Chris@332:         if (!transform.getStepSize()) {
Chris@332:             transform.setStepSize(vp->getPreferredStepSize());
Chris@332:         }
Chris@332:         if (!transform.getBlockSize()) {
Chris@332:             transform.setBlockSize(vp->getPreferredBlockSize());
Chris@332:         }
Chris@332:         if (!transform.getBlockSize()) {
Chris@332:             transform.setBlockSize(1024);
Chris@332:         }
Chris@332:         if (!transform.getStepSize()) {
Chris@332:             if (domain == Vamp::Plugin::FrequencyDomain) {
Chris@332: //                std::cerr << "frequency domain, step = " << blockSize/2 << std::endl;
Chris@332:                 transform.setStepSize(transform.getBlockSize()/2);
Chris@332:             } else {
Chris@332: //                std::cerr << "time domain, step = " << blockSize/2 << std::endl;
Chris@332:                 transform.setStepSize(transform.getBlockSize());
Chris@332:             }
Chris@332:         }
Chris@332:     }
Chris@332: }
Chris@332: 
Chris@332: Transform
Chris@332: TransformFactory::getDefaultTransformFor(TransformId id, size_t rate)
Chris@332: {
Chris@332:     Transform t;
Chris@332:     t.setIdentifier(id);
Chris@332:     
Chris@332:     if (rate == 0) {
Chris@332:         rate = 44100;
Chris@332:     } else {
Chris@332:         t.setSampleRate(rate);
Chris@332:     }
Chris@332: 
Chris@332:     QString pluginId = t.getPluginIdentifier();
Chris@332: 
Chris@332:     if (t.getType() == Transform::FeatureExtraction) {
Chris@332: 
Chris@332:         FeatureExtractionPluginFactory *factory = 
Chris@332:             FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@332: 
Chris@332:         Vamp::Plugin *plugin = factory->instantiatePlugin
Chris@332:             (pluginId, rate);
Chris@332: 
Chris@332:         if (plugin) {
Chris@332:             setParametersFromPlugin(t, plugin);
Chris@332:             makeContextConsistentWithPlugin(t, plugin);
Chris@332:             delete plugin;
Chris@332:         }
Chris@332: 
Chris@332:     } else {
Chris@332: 
Chris@332:         RealTimePluginFactory *factory = 
Chris@332:             RealTimePluginFactory::instanceFor(pluginId);
Chris@332:             
Chris@332:         RealTimePluginInstance *plugin = factory->instantiatePlugin
Chris@332:             (pluginId, 0, 0, rate, 1024, 1);
Chris@332:         
Chris@332:         if (plugin) {
Chris@332:             setParametersFromPlugin(t, plugin);
Chris@332:             makeContextConsistentWithPlugin(t, plugin);
Chris@332:             delete plugin;
Chris@332:         }
Chris@332:     }
Chris@332: 
Chris@332:     return t;
Chris@332: }
Chris@332: