svgui  1.9
PluginParameterBox.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  This file copyright 2006 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "PluginParameterBox.h"
17 
18 #include "AudioDial.h"
19 
20 #include "plugin/PluginXml.h"
21 #include "plugin/RealTimePluginInstance.h" // for PortHint stuff
22 
23 #include "base/RangeMapper.h"
24 
25 #include <QDoubleSpinBox>
26 #include <QGridLayout>
27 #include <QComboBox>
28 #include <QCheckBox>
29 #include <QLayout>
30 #include <QLabel>
31 
32 #include <iostream>
33 #include <string>
34 
35 #include <cmath>
36 
37 PluginParameterBox::PluginParameterBox(Vamp::PluginBase *plugin, QWidget *parent) :
38  QFrame(parent),
39  m_plugin(plugin),
40  m_programCombo(0)
41 {
42  m_layout = new QGridLayout;
43  setLayout(m_layout);
44  populate();
45 }
46 
48 {
49 }
50 
51 void
53 {
54  Vamp::PluginBase::ParameterList params = m_plugin->getParameterDescriptors();
55  m_programs = m_plugin->getPrograms();
56 
57  m_params.clear();
58 
59  if (params.empty() && m_programs.empty()) {
60  m_layout->addWidget
61  (new QLabel(tr("This plugin has no adjustable parameters.")),
62  0, 0);
63  }
64 
65  int offset = 0;
66 
67  if (!m_programs.empty()) {
68 
69  std::string currentProgram = m_plugin->getCurrentProgram();
70 
71  m_programCombo = new QComboBox;
72  m_programCombo->setMaxVisibleItems
73  (m_programs.size() < 25 ? m_programs.size() : 20);
74 
75  for (size_t i = 0; i < m_programs.size(); ++i) {
76  m_programCombo->addItem(m_programs[i].c_str());
77  if (m_programs[i] == currentProgram) {
78  m_programCombo->setCurrentIndex(i);
79  }
80  }
81 
82  m_layout->addWidget(new QLabel(tr("Program")), 0, 0);
83  m_layout->addWidget(m_programCombo, 0, 1, 1, 2);
84 
85  connect(m_programCombo, SIGNAL(currentIndexChanged(const QString &)),
86  this, SLOT(programComboChanged(const QString &)));
87 
88  offset = 1;
89  }
90 
91  for (size_t i = 0; i < params.size(); ++i) {
92 
93  QString identifier = params[i].identifier.c_str();
94  QString name = params[i].name.c_str();
95  QString unit = params[i].unit.c_str();
96 
97  float min = params[i].minValue;
98  float max = params[i].maxValue;
99  float deft = params[i].defaultValue;
100  float value = m_plugin->getParameter(params[i].identifier);
101 
102  int hint = PortHint::NoHint;
103  RealTimePluginInstance *rtpi = dynamic_cast<RealTimePluginInstance *>
104  (m_plugin);
105  if (rtpi) {
106  hint = rtpi->getParameterDisplayHint(i);
107  }
108 
109  float qtz = 0.0;
110  if (params[i].isQuantized) qtz = params[i].quantizeStep;
111 
112 // cerr << "PluginParameterBox: hint = " << hint << ", min = " << min << ", max = "
113 // << max << ", qtz = " << qtz << endl;
114 
115  std::vector<std::string> valueNames = params[i].valueNames;
116 
117  // construct an integer range
118 
119  int imin = 0, imax = 100;
120 
121  if (!(hint & PortHint::Logarithmic)) {
122  if (qtz > 0.0) {
123  imax = lrintf((max - min) / qtz);
124  } else {
125  qtz = (max - min) / 100.0;
126  }
127  }
128 
130  // an integer!
131 
132  QLabel *label = new QLabel(name);
133  if (params[i].description != "") {
134  label->setToolTip(QString("<qt>%1</qt>")
135  .arg(params[i].description.c_str())
136  .replace("\n", "<br>"));
137  }
138  m_layout->addWidget(label, i + offset, 0);
139 
140  ParamRec rec;
141  rec.param = params[i];
142  rec.dial = 0;
143  rec.spin = 0;
144  rec.check = 0;
145  rec.combo = 0;
146 
147  if (params[i].isQuantized && !valueNames.empty()) {
148 
149  QComboBox *combobox = new QComboBox;
150  combobox->setObjectName(identifier);
151  for (unsigned int j = 0; j < valueNames.size(); ++j) {
152  combobox->addItem(valueNames[j].c_str());
153  if ((unsigned int)(lrintf(fabsf((value - min) / qtz))) == j) {
154  combobox->setCurrentIndex(j);
155  }
156  }
157  connect(combobox, SIGNAL(activated(int)),
158  this, SLOT(dialChanged(int)));
159  m_layout->addWidget(combobox, i + offset, 1, 1, 2);
160  rec.combo = combobox;
161 
162  } else if (min == 0.0 && max == 1.0 && qtz == 1.0) {
163 
164  QCheckBox *checkbox = new QCheckBox;
165  checkbox->setObjectName(identifier);
166  checkbox->setCheckState(value < 0.5 ? Qt::Unchecked : Qt::Checked);
167  connect(checkbox, SIGNAL(stateChanged(int)),
168  this, SLOT(checkBoxChanged(int)));
169  m_layout->addWidget(checkbox, i + offset, 2);
170  rec.check = checkbox;
171 
172  } else {
173 
174  AudioDial *dial = new AudioDial;
175  dial->setObjectName(name);
176  dial->setMinimum(imin);
177  dial->setMaximum(imax);
178  dial->setPageStep(1);
179  dial->setNotchesVisible((imax - imin) <= 12);
181 // dial->setValue(lrintf((value - min) / qtz));
182  dial->setFixedWidth(32);
183  dial->setFixedHeight(32);
184  RangeMapper *rm = 0;
185  if (hint & PortHint::Logarithmic) {
186  rm = new LogRangeMapper(imin, imax, min, max, unit);
187  } else {
188  rm = new LinearRangeMapper(imin, imax, min, max, unit);
189  }
190  dial->setRangeMapper(rm);
191  dial->setDefaultValue(rm->getPositionForValue(deft));
192  dial->setValue(rm->getPositionForValue(value));
193  dial->setShowToolTip(true);
194  connect(dial, SIGNAL(valueChanged(int)),
195  this, SLOT(dialChanged(int)));
196  m_layout->addWidget(dial, i + offset, 1);
197 
198  QDoubleSpinBox *spinbox = new QDoubleSpinBox;
199  spinbox->setObjectName(identifier);
200  spinbox->setMinimum(min);
201  spinbox->setMaximum(max);
202  spinbox->setSuffix(QString(" %1").arg(unit));
203  if (qtz != 0) spinbox->setSingleStep(qtz);
204  spinbox->setValue(value);
205  spinbox->setDecimals(4);
206  connect(spinbox, SIGNAL(valueChanged(double)),
207  this, SLOT(spinBoxChanged(double)));
208  m_layout->addWidget(spinbox, i + offset, 2);
209  rec.dial = dial;
210  rec.spin = spinbox;
211  }
212 
213  m_params[identifier] = rec;
214  m_nameMap[name] = identifier;
215  }
216 }
217 
218 void
220 {
221  QObject *obj = sender();
222  QString identifier = obj->objectName();
223 
224  if (m_params.find(identifier) == m_params.end() &&
225  m_nameMap.find(identifier) != m_nameMap.end()) {
226  identifier = m_nameMap[identifier];
227  }
228 
229  if (m_params.find(identifier) == m_params.end()) {
230  cerr << "WARNING: PluginParameterBox::dialChanged: Unknown parameter \"" << identifier << "\"" << endl;
231  return;
232  }
233 
234  Vamp::PluginBase::ParameterDescriptor params = m_params[identifier].param;
235 
236  float min = params.minValue;
237  float max = params.maxValue;
238 
239  float newValue;
240 
241  float qtz = 0.0;
242  if (params.isQuantized) qtz = params.quantizeStep;
243 
244  AudioDial *ad = dynamic_cast<AudioDial *>(obj);
245 
246  if (ad && ad->rangeMapper()) {
247 
248  newValue = ad->mappedValue();
249  if (newValue < min) newValue = min;
250  if (newValue > max) newValue = max;
251  if (qtz != 0.0) {
252  ival = lrintf((newValue - min) / qtz);
253  newValue = min + ival * qtz;
254  }
255 
256  } else {
257  if (qtz == 0.0) {
258  qtz = (max - min) / 100.0;
259  }
260  newValue = min + ival * qtz;
261  }
262 
263 // SVDEBUG << "PluginParameterBox::dialChanged: newValue = " << newValue << endl;
264 
265  QDoubleSpinBox *spin = m_params[identifier].spin;
266  if (spin) {
267  spin->blockSignals(true);
268  spin->setValue(newValue);
269  spin->blockSignals(false);
270  }
271 
272 // SVDEBUG << "setting plugin parameter \"" << identifier << "\" to value " << newValue << endl;
273 
274  m_plugin->setParameter(identifier.toStdString(), newValue);
275 
277 
278  emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
279 }
280 
281 void
283 {
284  QObject *obj = sender();
285  QString identifier = obj->objectName();
286 
287  if (m_params.find(identifier) == m_params.end() &&
288  m_nameMap.find(identifier) != m_nameMap.end()) {
289  identifier = m_nameMap[identifier];
290  }
291 
292  if (m_params.find(identifier) == m_params.end()) {
293  cerr << "WARNING: PluginParameterBox::checkBoxChanged: Unknown parameter \"" << identifier << "\"" << endl;
294  return;
295  }
296 
297  Vamp::PluginBase::ParameterDescriptor params = m_params[identifier].param;
298 
299  if (state) m_plugin->setParameter(identifier.toStdString(), 1.0);
300  else m_plugin->setParameter(identifier.toStdString(), 0.0);
301 
303 
304  emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
305 }
306 
307 void
309 {
310  QObject *obj = sender();
311  QString identifier = obj->objectName();
312 
313  if (m_params.find(identifier) == m_params.end() &&
314  m_nameMap.find(identifier) != m_nameMap.end()) {
315  identifier = m_nameMap[identifier];
316  }
317 
318  if (m_params.find(identifier) == m_params.end()) {
319  cerr << "WARNING: PluginParameterBox::spinBoxChanged: Unknown parameter \"" << identifier << "\"" << endl;
320  return;
321  }
322 
323  Vamp::PluginBase::ParameterDescriptor params = m_params[identifier].param;
324 
325  float min = params.minValue;
326  float max = params.maxValue;
327 
328  float qtz = 0.0;
329  if (params.isQuantized) qtz = params.quantizeStep;
330 
331  if (qtz > 0.0) {
332  int step = lrintf((value - min) / qtz);
333  value = min + step * qtz;
334  }
335 
336 // int imax = 100;
337 
338  if (qtz > 0.0) {
339 // imax = lrintf((max - min) / qtz);
340  } else {
341  qtz = (max - min) / 100.0;
342  }
343 
344  int ival = lrintf((value - min) / qtz);
345 
346  AudioDial *dial = m_params[identifier].dial;
347  if (dial) {
348  dial->blockSignals(true);
349  if (dial->rangeMapper()) {
350  dial->setMappedValue(value);
351  } else {
352  dial->setValue(ival);
353  }
354  dial->blockSignals(false);
355  }
356 
357  SVDEBUG << "setting plugin parameter \"" << identifier << "\" to value " << value << endl;
358 
359  m_plugin->setParameter(identifier.toStdString(), value);
360 
362 
363  emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
364 }
365 
366 void
367 PluginParameterBox::programComboChanged(const QString &newProgram)
368 {
369  m_plugin->selectProgram(newProgram.toStdString());
370 
371  for (std::map<QString, ParamRec>::iterator i = m_params.begin();
372  i != m_params.end(); ++i) {
373 
374  Vamp::PluginBase::ParameterDescriptor &param = i->second.param;
375  float value = m_plugin->getParameter(param.identifier);
376 
377  if (i->second.spin) {
378  i->second.spin->blockSignals(true);
379  i->second.spin->setValue(value);
380  i->second.spin->blockSignals(false);
381  }
382 
383  if (i->second.dial) {
384 
385  float min = param.minValue;
386  float max = param.maxValue;
387 
388  float qtz = 0.0;
389  if (param.isQuantized) qtz = param.quantizeStep;
390 
391  if (qtz == 0.0) {
392  qtz = (max - min) / 100.0;
393  }
394 
395  i->second.dial->blockSignals(true);
396  i->second.dial->setValue(lrintf((value - min) / qtz));
397  i->second.dial->blockSignals(false);
398  }
399 
400  if (i->second.combo) {
401  i->second.combo->blockSignals(true);
402  i->second.combo->setCurrentIndex(lrintf(value));
403  i->second.combo->blockSignals(false);
404  }
405 
406  if (i->second.check) {
407  i->second.check->blockSignals(true);
408  i->second.check->setCheckState(value < 0.5 ? Qt::Unchecked : Qt::Checked);
409  i->second.check->blockSignals(false);
410  }
411  }
412 
413  emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
414 }
415 
416 void
418 {
419  if (!m_programCombo || m_programs.empty()) return;
420 
421  std::string currentProgram = m_plugin->getCurrentProgram();
422 
423  for (size_t i = 0; i < m_programs.size(); ++i) {
424  if (m_programs[i] == currentProgram) {
425  m_programCombo->setCurrentIndex(i);
426  }
427  }
428 }
429 
430 
Vamp::PluginBase * m_plugin
QComboBox * m_programCombo
void setDefaultValue(int defaultValue)
Definition: AudioDial.cpp:339
float mappedValue() const
Definition: AudioDial.cpp:390
void setMappedValue(float mappedValue)
Definition: AudioDial.cpp:361
PluginParameterBox(Vamp::PluginBase *, QWidget *parent=0)
void pluginConfigurationChanged(QString)
std::map< QString, ParamRec > m_params
std::map< QString, QString > m_nameMap
AudioDial is a nicer-looking QDial that by default reacts to mouse movement on horizontal and vertica...
Definition: AudioDial.h:59
QGridLayout * m_layout
void programComboChanged(const QString &)
Vamp::PluginBase::ProgramList m_programs
void setValue(int value)
Definition: AudioDial.cpp:347
Vamp::PluginBase::ParameterDescriptor param
void setRangeMapper(RangeMapper *mapper)
Definition: AudioDial.cpp:100
const RangeMapper * rangeMapper() const
Definition: AudioDial.h:75
void setShowToolTip(bool show)
Definition: AudioDial.cpp:381