svapp  1.9
TransformUserConfigurator.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     
00008     This program is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU General Public License as
00010     published by the Free Software Foundation; either version 2 of the
00011     License, or (at your option) any later version.  See the file
00012     COPYING included with this distribution for more information.
00013 */
00014 
00015 #include "TransformUserConfigurator.h"
00016 
00017 #include "transform/TransformFactory.h"
00018 
00019 #include "widgets/PluginParameterDialog.h"
00020 
00021 #include "plugin/FeatureExtractionPluginFactory.h"
00022 #include "plugin/RealTimePluginFactory.h"
00023 #include "plugin/RealTimePluginInstance.h"
00024 
00025 #include "data/model/DenseTimeValueModel.h"
00026 
00027 #include <vamp-hostsdk/Plugin.h>
00028 
00029 #include <QStringList>
00030 
00031 #include <typeinfo>
00032 
00033 static QWidget *parentWidget = 0;
00034 
00035 void
00036 TransformUserConfigurator::setParentWidget(QWidget *w)
00037 {
00038     parentWidget = w;
00039 }
00040 
00041 bool
00042 TransformUserConfigurator::getChannelRange(TransformId identifier,
00043                                            Vamp::PluginBase *plugin,
00044                                            int &minChannels, int &maxChannels)
00045 {
00046     if (plugin && plugin->getType() == "Feature Extraction Plugin") {
00047         Vamp::Plugin *vp = static_cast<Vamp::Plugin *>(plugin);
00048         SVDEBUG << "TransformUserConfigurator::getChannelRange: is a VP" << endl;
00049         minChannels = vp->getMinChannelCount();
00050         maxChannels = vp->getMaxChannelCount();
00051         return true;
00052     } else {
00053         SVDEBUG << "TransformUserConfigurator::getChannelRange: is not a VP" << endl;
00054         return TransformFactory::getInstance()->
00055             getTransformChannelRange(identifier, minChannels, maxChannels);
00056     }
00057 }
00058 
00059 bool
00060 TransformUserConfigurator::configure(ModelTransformer::Input &input,
00061                                      Transform &transform,
00062                                      Vamp::PluginBase *plugin,
00063                                      Model *&inputModel,
00064                                      AudioPlaySource *source,
00065                                      int startFrame,
00066                                      int duration,
00067                                      const QMap<QString, Model *> &modelMap,
00068                                      QStringList candidateModelNames,
00069                                      QString defaultModelName)
00070 {
00071     bool ok = false;
00072     QString id = transform.getPluginIdentifier();
00073     QString output = transform.getOutput();
00074     QString outputLabel = "";
00075     QString outputDescription = "";
00076 
00077     bool frequency = false;
00078     bool effect = false;
00079     bool generator = false;
00080 
00081     if (!plugin) return false;
00082 
00083     if (FeatureExtractionPluginFactory::instanceFor(id)) {
00084 
00085         Vamp::Plugin *vp = static_cast<Vamp::Plugin *>(plugin);
00086 
00087         frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
00088 
00089         std::vector<Vamp::Plugin::OutputDescriptor> od =
00090             vp->getOutputDescriptors();
00091 
00092         cerr << "configure: looking for output: " << output << endl;
00093 
00094         if (od.size() > 1) {
00095             for (size_t i = 0; i < od.size(); ++i) {
00096                 if (od[i].identifier == output.toStdString()) {
00097                     outputLabel = od[i].name.c_str();
00098                     outputDescription = od[i].description.c_str();
00099                     break;
00100                 }
00101             }
00102         }
00103 
00104     } else if (RealTimePluginFactory::instanceFor(id)) {
00105 
00106         RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
00107         const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id);
00108 
00109         if (desc->audioInputPortCount > 0 && 
00110             desc->audioOutputPortCount > 0 &&
00111             !desc->isSynth) {
00112             effect = true;
00113         }
00114 
00115         if (desc->audioInputPortCount == 0) {
00116             generator = true;
00117         }
00118 
00119         if (output != "A") {
00120             int outputNo = output.toInt();
00121             if (outputNo >= 0 && outputNo < int(desc->controlOutputPortCount)) {
00122                 outputLabel = desc->controlOutputPortNames[outputNo].c_str();
00123             }
00124         }
00125 
00126         RealTimePluginInstance *rtp =
00127             static_cast<RealTimePluginInstance *>(plugin);
00128 
00129         if (effect && source) {
00130             SVDEBUG << "Setting auditioning effect" << endl;
00131             source->setAuditioningEffect(rtp);
00132         }
00133     }
00134 
00135     int sourceChannels = 1;
00136     if (dynamic_cast<DenseTimeValueModel *>(inputModel)) {
00137         sourceChannels = dynamic_cast<DenseTimeValueModel *>(inputModel)
00138             ->getChannelCount();
00139     }
00140 
00141     int minChannels = 1, maxChannels = sourceChannels;
00142     getChannelRange(transform.getIdentifier(), plugin,
00143                     minChannels, maxChannels);
00144 
00145     int targetChannels = sourceChannels;
00146     if (!effect) {
00147         if (sourceChannels < minChannels) targetChannels = minChannels;
00148         if (sourceChannels > maxChannels) targetChannels = maxChannels;
00149     }
00150 
00151     int defaultChannel = -1; 
00152 
00153     PluginParameterDialog *dialog = new PluginParameterDialog
00154         (plugin, parentWidget);
00155 
00156     dialog->setMoreInfoUrl(TransformFactory::getInstance()->
00157                            getTransformInfoUrl(transform.getIdentifier()));
00158 
00159     if (candidateModelNames.size() > 1 && !generator) {
00160         dialog->setCandidateInputModels(candidateModelNames,
00161                                         defaultModelName);
00162     }
00163 
00164     if (startFrame != 0 || duration != 0) {
00165         dialog->setShowSelectionOnlyOption(true);
00166     }
00167 
00168     if (targetChannels > 0) {
00169         dialog->setChannelArrangement(sourceChannels, targetChannels,
00170                                       defaultChannel);
00171     }
00172         
00173     dialog->setOutputLabel(outputLabel, outputDescription);
00174         
00175     dialog->setShowProcessingOptions(true, frequency);
00176 
00177     if (dialog->exec() == QDialog::Accepted) {
00178         ok = true;
00179     }
00180 
00181     QString selectedInput = dialog->getInputModel();
00182     if (selectedInput != "") {
00183         if (modelMap.contains(selectedInput)) {
00184             inputModel = modelMap.value(selectedInput);
00185             cerr << "Found selected input \"" << selectedInput << "\" in model map, result is " << inputModel << endl;
00186         } else {
00187             cerr << "Failed to find selected input \"" << selectedInput << "\" in model map" << endl;
00188         }
00189     } else {
00190         cerr << "Selected input empty: \"" << selectedInput << "\"" << endl;
00191     }
00192         
00193     // Write parameters back to transform object
00194     TransformFactory::getInstance()->
00195         setParametersFromPlugin(transform, plugin);
00196 
00197     input.setChannel(dialog->getChannel());
00198         
00200     //objects and input objects and stuff rather than passing
00201     //around all this misc stuff, but that's for tomorrow
00202     //(whenever that may be)
00203 
00204     if (startFrame != 0 || duration != 0) {
00205         if (dialog->getSelectionOnly()) {
00206             transform.setStartTime(RealTime::frame2RealTime
00207                                    (startFrame, inputModel->getSampleRate()));
00208             transform.setDuration(RealTime::frame2RealTime
00209                                   (duration, inputModel->getSampleRate()));
00210         }
00211     }
00212 
00213     int stepSize = 0, blockSize = 0;
00214     WindowType windowType = HanningWindow;
00215 
00216     dialog->getProcessingParameters(stepSize,
00217                                     blockSize,
00218                                     windowType);
00219 
00220     transform.setStepSize(stepSize);
00221     transform.setBlockSize(blockSize);
00222     transform.setWindowType(windowType);
00223 
00224     delete dialog;
00225 
00226     if (effect && source) {
00227         source->setAuditioningEffect(0);
00228     }
00229 
00230     return ok;
00231 }
00232