Chris@205: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@205: Chris@205: /* Chris@205: Sonic Visualiser Chris@205: An audio file viewer and annotation editor. Chris@205: Centre for Digital Music, Queen Mary, University of London. Chris@205: Chris@205: This program is free software; you can redistribute it and/or Chris@205: modify it under the terms of the GNU General Public License as Chris@205: published by the Free Software Foundation; either version 2 of the Chris@205: License, or (at your option) any later version. See the file Chris@205: COPYING included with this distribution for more information. Chris@205: */ Chris@205: Chris@205: #include "TransformUserConfigurator.h" Chris@205: Chris@205: #include "transform/TransformFactory.h" Chris@205: Chris@205: #include "widgets/PluginParameterDialog.h" Chris@205: Chris@205: #include "plugin/FeatureExtractionPluginFactory.h" Chris@205: #include "plugin/RealTimePluginFactory.h" Chris@205: #include "plugin/RealTimePluginInstance.h" Chris@205: Chris@205: #include "data/model/DenseTimeValueModel.h" Chris@205: Chris@205: #include Chris@205: Chris@205: #include Chris@205: Chris@205: #include Chris@205: Chris@636: static QWidget *parentWidget = nullptr; Chris@395: Chris@395: void Chris@395: TransformUserConfigurator::setParentWidget(QWidget *w) Chris@395: { Chris@395: parentWidget = w; Chris@395: } Chris@395: Chris@205: bool Chris@205: TransformUserConfigurator::getChannelRange(TransformId identifier, Chris@595: Vamp::PluginBase *plugin, Chris@595: int &minChannels, int &maxChannels) Chris@205: { Chris@205: if (plugin && plugin->getType() == "Feature Extraction Plugin") { Chris@595: Vamp::Plugin *vp = static_cast(plugin); Chris@595: SVDEBUG << "TransformUserConfigurator::getChannelRange: is a Vamp plugin" << endl; Chris@436: minChannels = int(vp->getMinChannelCount()); Chris@436: maxChannels = int(vp->getMaxChannelCount()); Chris@205: return true; Chris@205: } else { Chris@595: SVDEBUG << "TransformUserConfigurator::getChannelRange: is not a Vamp plugin" << endl; Chris@205: return TransformFactory::getInstance()-> Chris@205: getTransformChannelRange(identifier, minChannels, maxChannels); Chris@205: } Chris@205: } Chris@205: Chris@205: bool Chris@205: TransformUserConfigurator::configure(ModelTransformer::Input &input, Chris@595: Transform &transform, Chris@595: Vamp::PluginBase *plugin, Chris@214: Model *&inputModel, Chris@595: AudioPlaySource *source, Chris@595: sv_frame_t startFrame, Chris@595: sv_frame_t duration, Chris@595: const QMap &modelMap, Chris@595: QStringList candidateModelNames, Chris@595: QString defaultModelName) Chris@205: { Chris@205: bool ok = false; Chris@205: QString id = transform.getPluginIdentifier(); Chris@205: QString output = transform.getOutput(); Chris@205: QString outputLabel = ""; Chris@205: QString outputDescription = ""; Chris@205: Chris@205: bool frequency = false; Chris@205: bool effect = false; Chris@205: bool generator = false; Chris@205: Chris@205: if (!plugin) return false; Chris@205: Chris@536: SVDEBUG << "TransformUserConfigurator::configure: identifier " << id << endl; Chris@536: Chris@529: if (RealTimePluginFactory::instanceFor(id)) { Chris@205: Chris@205: RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id); Chris@205: const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id); Chris@205: Chris@205: if (desc->audioInputPortCount > 0 && Chris@205: desc->audioOutputPortCount > 0 && Chris@205: !desc->isSynth) { Chris@205: effect = true; Chris@205: } Chris@205: Chris@205: if (desc->audioInputPortCount == 0) { Chris@205: generator = true; Chris@205: } Chris@205: Chris@205: if (output != "A") { Chris@205: int outputNo = output.toInt(); Chris@205: if (outputNo >= 0 && outputNo < int(desc->controlOutputPortCount)) { Chris@205: outputLabel = desc->controlOutputPortNames[outputNo].c_str(); Chris@205: } Chris@205: } Chris@205: Chris@205: RealTimePluginInstance *rtp = Chris@205: static_cast(plugin); Chris@205: Chris@205: if (effect && source) { Chris@595: SVDEBUG << "Setting auditioning effect" << endl; Chris@205: source->setAuditioningEffect(rtp); Chris@205: } Chris@529: Chris@529: } else { Chris@529: Chris@529: Vamp::Plugin *vp = static_cast(plugin); Chris@529: Chris@595: frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain); Chris@529: Chris@595: std::vector od = Chris@595: vp->getOutputDescriptors(); Chris@529: Chris@595: // cerr << "configure: looking for output: " << output << endl; Chris@529: Chris@595: if (od.size() > 1) { Chris@595: for (size_t i = 0; i < od.size(); ++i) { Chris@595: if (od[i].identifier == output.toStdString()) { Chris@595: outputLabel = od[i].name.c_str(); Chris@595: outputDescription = od[i].description.c_str(); Chris@595: break; Chris@595: } Chris@595: } Chris@529: } Chris@205: } Chris@529: Chris@205: int sourceChannels = 1; Chris@205: if (dynamic_cast(inputModel)) { Chris@595: sourceChannels = dynamic_cast(inputModel) Chris@595: ->getChannelCount(); Chris@205: } Chris@205: Chris@205: int minChannels = 1, maxChannels = sourceChannels; Chris@205: getChannelRange(transform.getIdentifier(), plugin, Chris@595: minChannels, maxChannels); Chris@205: Chris@205: int targetChannels = sourceChannels; Chris@205: if (!effect) { Chris@595: if (sourceChannels < minChannels) targetChannels = minChannels; Chris@595: if (sourceChannels > maxChannels) targetChannels = maxChannels; Chris@205: } Chris@205: Chris@205: int defaultChannel = -1; //!!! no longer saved! [was context.channel] Chris@205: Chris@395: PluginParameterDialog *dialog = new PluginParameterDialog Chris@395: (plugin, parentWidget); Chris@205: Chris@205: dialog->setMoreInfoUrl(TransformFactory::getInstance()-> Chris@595: getTransformInfoUrl(transform.getIdentifier())); Chris@205: Chris@205: if (candidateModelNames.size() > 1 && !generator) { Chris@595: dialog->setCandidateInputModels(candidateModelNames, Chris@595: defaultModelName); Chris@205: } Chris@205: Chris@205: if (startFrame != 0 || duration != 0) { Chris@595: dialog->setShowSelectionOnlyOption(true); Chris@205: } Chris@205: Chris@205: if (targetChannels > 0) { Chris@595: dialog->setChannelArrangement(sourceChannels, targetChannels, Chris@595: defaultChannel); Chris@205: } Chris@205: Chris@205: dialog->setOutputLabel(outputLabel, outputDescription); Chris@205: Chris@205: dialog->setShowProcessingOptions(true, frequency); Chris@205: Chris@205: if (dialog->exec() == QDialog::Accepted) { Chris@595: ok = true; Chris@205: } Chris@205: Chris@205: QString selectedInput = dialog->getInputModel(); Chris@205: if (selectedInput != "") { Chris@595: if (modelMap.contains(selectedInput)) { Chris@595: inputModel = modelMap.value(selectedInput); Chris@595: SVDEBUG << "Found selected input \"" << selectedInput << "\" in model map, result is " << inputModel << endl; Chris@595: } else { Chris@595: SVDEBUG << "Failed to find selected input \"" << selectedInput << "\" in model map" << endl; Chris@595: } Chris@205: } else { Chris@595: SVDEBUG << "Selected input empty: \"" << selectedInput << "\"" << endl; Chris@205: } Chris@205: Chris@205: // Write parameters back to transform object Chris@205: TransformFactory::getInstance()-> Chris@595: setParametersFromPlugin(transform, plugin); Chris@205: Chris@205: input.setChannel(dialog->getChannel()); Chris@205: Chris@205: //!!! The dialog ought to be taking & returning transform Chris@205: //objects and input objects and stuff rather than passing Chris@205: //around all this misc stuff, but that's for tomorrow Chris@205: //(whenever that may be) Chris@205: Chris@205: if (startFrame != 0 || duration != 0) { Chris@595: if (dialog->getSelectionOnly()) { Chris@595: transform.setStartTime(RealTime::frame2RealTime Chris@595: (startFrame, inputModel->getSampleRate())); Chris@595: transform.setDuration(RealTime::frame2RealTime Chris@595: (duration, inputModel->getSampleRate())); Chris@595: } Chris@205: } Chris@205: Chris@366: int stepSize = 0, blockSize = 0; Chris@205: WindowType windowType = HanningWindow; Chris@205: Chris@205: dialog->getProcessingParameters(stepSize, Chris@595: blockSize, Chris@595: windowType); Chris@205: Chris@205: transform.setStepSize(stepSize); Chris@205: transform.setBlockSize(blockSize); Chris@205: transform.setWindowType(windowType); Chris@205: Chris@205: delete dialog; Chris@205: Chris@205: if (effect && source) { Chris@636: source->setAuditioningEffect(nullptr); Chris@205: } Chris@205: Chris@205: return ok; Chris@205: } Chris@205: