TransformUserConfigurator.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
16 
17 #include "transform/TransformFactory.h"
18 
19 #include "widgets/PluginParameterDialog.h"
20 
21 #include "plugin/FeatureExtractionPluginFactory.h"
22 #include "plugin/RealTimePluginFactory.h"
23 #include "plugin/RealTimePluginInstance.h"
24 
25 #include "data/model/DenseTimeValueModel.h"
26 
27 #include <vamp-hostsdk/Plugin.h>
28 
29 #include <QStringList>
30 
31 #include <typeinfo>
32 
33 static QWidget *parentWidget = nullptr;
34 
35 void
37 {
38  parentWidget = w;
39 }
40 
41 bool
43  std::shared_ptr<Vamp::PluginBase> plugin,
44  int &minChannels, int &maxChannels)
45 {
46  if (plugin && plugin->getType() == "Feature Extraction Plugin") {
47  auto vp = std::dynamic_pointer_cast<Vamp::Plugin>(plugin);
48  if (vp) {
49  SVDEBUG << "TransformUserConfigurator::getChannelRange: is a Vamp plugin" << endl;
50  minChannels = int(vp->getMinChannelCount());
51  maxChannels = int(vp->getMaxChannelCount());
52  return true;
53  } else {
54  SVCERR << "TransformUserConfigurator::getChannelRange: inconsistent plugin identity!" << endl;
55  return false;
56  }
57  } else {
58  SVDEBUG << "TransformUserConfigurator::getChannelRange: is not a Vamp plugin" << endl;
59  return TransformFactory::getInstance()->
60  getTransformChannelRange(identifier, minChannels, maxChannels);
61  }
62 }
63 
64 bool
65 TransformUserConfigurator::configure(ModelTransformer::Input &input,
66  Transform &transform,
67  std::shared_ptr<Vamp::PluginBase> plugin,
68  ModelId &inputModel,
69  AudioPlaySource *source,
70  sv_frame_t startFrame,
71  sv_frame_t duration,
72  const QMap<QString, ModelId> &modelMap,
73  QStringList candidateModelNames,
74  QString defaultModelName)
75 {
76  bool ok = false;
77  QString id = transform.getPluginIdentifier();
78  QString output = transform.getOutput();
79  QString outputLabel = "";
80  QString outputDescription = "";
81 
82  bool frequency = false;
83  bool effect = false;
84  bool generator = false;
85 
86  if (!plugin) return false;
87 
88  SVDEBUG << "TransformUserConfigurator::configure: identifier " << id << endl;
89 
90  if (RealTimePluginFactory::instanceFor(id)) {
91 
92  RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
93  RealTimePluginDescriptor desc = factory->getPluginDescriptor(id);
94 
95  if (desc.audioInputPortCount > 0 &&
96  desc.audioOutputPortCount > 0 &&
97  !desc.isSynth) {
98  effect = true;
99  }
100 
101  if (desc.audioInputPortCount == 0) {
102  generator = true;
103  }
104 
105  if (output != "A") {
106  int outputNo = output.toInt();
107  if (outputNo >= 0 && outputNo < int(desc.controlOutputPortCount)) {
108  outputLabel = desc.controlOutputPortNames[outputNo].c_str();
109  }
110  }
111 
112  auto auditionable = std::dynamic_pointer_cast<Auditionable>(plugin);
113 
114  if (effect && source && auditionable) {
115  SVDEBUG << "Setting auditioning effect" << endl;
116  source->setAuditioningEffect(auditionable);
117  }
118 
119  } else {
120 
121  auto vp = std::dynamic_pointer_cast<Vamp::Plugin>(plugin);
122 
123  frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
124 
125  std::vector<Vamp::Plugin::OutputDescriptor> od =
126  vp->getOutputDescriptors();
127 
128  if (od.size() > 1) {
129  for (size_t i = 0; i < od.size(); ++i) {
130  if (od[i].identifier == output.toStdString()) {
131  outputLabel = od[i].name.c_str();
132  outputDescription = od[i].description.c_str();
133  break;
134  }
135  }
136  }
137  }
138 
139  int sourceChannels = 1;
140 
141  if (auto dtvm = ModelById::getAs<DenseTimeValueModel>(inputModel)) {
142  sourceChannels = dtvm->getChannelCount();
143  }
144 
145  int minChannels = 1, maxChannels = sourceChannels;
146  getChannelRange(transform.getIdentifier(), plugin,
147  minChannels, maxChannels);
148 
149  int targetChannels = sourceChannels;
150  if (!effect) {
151  if (sourceChannels < minChannels) targetChannels = minChannels;
152  if (sourceChannels > maxChannels) targetChannels = maxChannels;
153  }
154 
155  int defaultChannel = -1;
156 
157  PluginParameterDialog *dialog = new PluginParameterDialog
158  (plugin, parentWidget);
159 
160  dialog->setMoreInfoUrl(TransformFactory::getInstance()->
161  getTransformProvider(transform.getIdentifier())
162  .infoUrl);
163 
164  if (candidateModelNames.size() > 1 && !generator) {
165  dialog->setCandidateInputModels(candidateModelNames,
166  defaultModelName);
167  }
168 
169  if (startFrame != 0 || duration != 0) {
170  dialog->setShowSelectionOnlyOption(true);
171  }
172 
173  if (targetChannels > 0) {
174  dialog->setChannelArrangement(sourceChannels, targetChannels,
175  defaultChannel);
176  }
177 
178  dialog->setOutputLabel(outputLabel, outputDescription);
179 
180  dialog->setShowProcessingOptions(true, frequency);
181 
182  if (dialog->exec() == QDialog::Accepted) {
183  ok = true;
184  }
185 
186  QString selectedInput = dialog->getInputModel();
187  if (selectedInput != "") {
188  if (modelMap.contains(selectedInput)) {
189  inputModel = modelMap.value(selectedInput);
190  SVDEBUG << "Found selected input \"" << selectedInput << "\" in model map, result is " << inputModel << endl;
191  } else {
192  SVDEBUG << "Failed to find selected input \"" << selectedInput << "\" in model map" << endl;
193  }
194  } else {
195  SVDEBUG << "Selected input empty: \"" << selectedInput << "\"" << endl;
196  }
197 
198  // Write parameters back to transform object
199  TransformFactory::getInstance()->
200  setParametersFromPlugin(transform, plugin);
201 
202  input.setChannel(dialog->getChannel());
203 
205  //objects and input objects and stuff rather than passing
206  //around all this misc stuff, but that's for tomorrow
207  //(whenever that may be)
208 
209  sv_samplerate_t sampleRate = 0;
210  if (auto m = ModelById::get(inputModel)) {
211  sampleRate = m->getSampleRate();
212  }
213 
214  if (startFrame != 0 || duration != 0) {
215  if (dialog->getSelectionOnly() && sampleRate != 0) {
216  transform.setStartTime
217  (RealTime::frame2RealTime(startFrame, sampleRate));
218  transform.setDuration
219  (RealTime::frame2RealTime(duration, sampleRate));
220  }
221  }
222 
223  int stepSize = 0, blockSize = 0;
224  WindowType windowType = HanningWindow;
225 
226  dialog->getProcessingParameters(stepSize,
227  blockSize,
228  windowType);
229 
230  transform.setStepSize(stepSize);
231  transform.setBlockSize(blockSize);
232  transform.setWindowType(windowType);
233 
234  delete dialog;
235 
236  if (effect && source) {
237  source->setAuditioningEffect({});
238  }
239 
240  return ok;
241 }
242 
static QWidget * parentWidget
bool getChannelRange(TransformId identifier, std::shared_ptr< Vamp::PluginBase > plugin, int &min, int &max)
bool configure(ModelTransformer::Input &input, Transform &transform, std::shared_ptr< Vamp::PluginBase > plugin, ModelId &inputModel, AudioPlaySource *source, sv_frame_t startFrame, sv_frame_t duration, const QMap< QString, ModelId > &modelMap, QStringList candidateModelNames, QString defaultModelName) override
static void setParentWidget(QWidget *)