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@205: bool Chris@205: TransformUserConfigurator::getChannelRange(TransformId identifier, Chris@205: Vamp::PluginBase *plugin, Chris@205: int &minChannels, int &maxChannels) Chris@205: { Chris@205: if (plugin && plugin->getType() == "Feature Extraction Plugin") { Chris@205: Vamp::Plugin *vp = static_cast(plugin); Chris@233: SVDEBUG << "TransformUserConfigurator::getChannelRange: is a VP" << endl; Chris@205: minChannels = vp->getMinChannelCount(); Chris@205: maxChannels = vp->getMaxChannelCount(); Chris@205: return true; Chris@205: } else { Chris@233: SVDEBUG << "TransformUserConfigurator::getChannelRange: is not a VP" << 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@205: Transform &transform, Chris@205: Vamp::PluginBase *plugin, Chris@214: Model *&inputModel, Chris@205: AudioPlaySource *source, Chris@205: size_t startFrame, Chris@205: size_t duration, Chris@205: const QMap &modelMap, Chris@205: QStringList candidateModelNames, Chris@205: 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@205: if (FeatureExtractionPluginFactory::instanceFor(id)) { Chris@205: Chris@205: Vamp::Plugin *vp = static_cast(plugin); Chris@205: Chris@205: frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain); Chris@205: Chris@205: std::vector od = Chris@205: vp->getOutputDescriptors(); Chris@205: Chris@228: std::cerr << "configure: looking for output: " << output << std::endl; Chris@205: Chris@205: if (od.size() > 1) { Chris@205: for (size_t i = 0; i < od.size(); ++i) { Chris@205: if (od[i].identifier == output.toStdString()) { Chris@205: outputLabel = od[i].name.c_str(); Chris@205: outputDescription = od[i].description.c_str(); Chris@205: break; Chris@205: } Chris@205: } Chris@205: } Chris@205: Chris@205: } else 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@233: SVDEBUG << "Setting auditioning effect" << endl; Chris@205: source->setAuditioningEffect(rtp); Chris@205: } Chris@205: } Chris@205: Chris@205: int sourceChannels = 1; Chris@205: if (dynamic_cast(inputModel)) { Chris@205: sourceChannels = dynamic_cast(inputModel) Chris@205: ->getChannelCount(); Chris@205: } Chris@205: Chris@205: int minChannels = 1, maxChannels = sourceChannels; Chris@205: getChannelRange(transform.getIdentifier(), plugin, Chris@205: minChannels, maxChannels); Chris@205: Chris@205: int targetChannels = sourceChannels; Chris@205: if (!effect) { Chris@205: if (sourceChannels < minChannels) targetChannels = minChannels; Chris@205: if (sourceChannels > maxChannels) targetChannels = maxChannels; Chris@205: } Chris@205: Chris@205: int defaultChannel = -1; //!!! no longer saved! [was context.channel] Chris@205: Chris@205: PluginParameterDialog *dialog = new PluginParameterDialog(plugin); Chris@205: Chris@205: dialog->setMoreInfoUrl(TransformFactory::getInstance()-> Chris@205: getTransformInfoUrl(transform.getIdentifier())); Chris@205: Chris@205: if (candidateModelNames.size() > 1 && !generator) { Chris@205: dialog->setCandidateInputModels(candidateModelNames, Chris@205: defaultModelName); Chris@205: } Chris@205: Chris@205: if (startFrame != 0 || duration != 0) { Chris@205: dialog->setShowSelectionOnlyOption(true); Chris@205: } Chris@205: Chris@205: if (targetChannels > 0) { Chris@205: dialog->setChannelArrangement(sourceChannels, targetChannels, Chris@205: 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@205: ok = true; Chris@205: } Chris@205: Chris@205: QString selectedInput = dialog->getInputModel(); Chris@205: if (selectedInput != "") { Chris@205: if (modelMap.contains(selectedInput)) { Chris@205: inputModel = modelMap.value(selectedInput); Chris@228: std::cerr << "Found selected input \"" << selectedInput << "\" in model map, result is " << inputModel << std::endl; Chris@205: } else { Chris@228: std::cerr << "Failed to find selected input \"" << selectedInput << "\" in model map" << std::endl; Chris@205: } Chris@205: } else { Chris@228: std::cerr << "Selected input empty: \"" << selectedInput << "\"" << std::endl; Chris@205: } Chris@205: Chris@205: // Write parameters back to transform object Chris@205: TransformFactory::getInstance()-> Chris@205: 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@205: if (dialog->getSelectionOnly()) { Chris@205: transform.setStartTime(RealTime::frame2RealTime Chris@205: (startFrame, inputModel->getSampleRate())); Chris@205: transform.setDuration(RealTime::frame2RealTime Chris@205: (duration, inputModel->getSampleRate())); Chris@205: } Chris@205: } Chris@205: Chris@205: size_t stepSize = 0, blockSize = 0; Chris@205: WindowType windowType = HanningWindow; Chris@205: Chris@205: dialog->getProcessingParameters(stepSize, Chris@205: blockSize, Chris@205: 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@205: source->setAuditioningEffect(0); Chris@205: } Chris@205: Chris@205: return ok; Chris@205: } Chris@205: