annotate widgets/PluginParameterBox.cpp @ 194:d13e209bfa94

...
author Chris Cannam
date Fri, 26 Jan 2007 17:20:58 +0000
parents 42118892f428
children a5b3c9f580c1
rev   line source
Chris@60 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@60 2
Chris@60 3 /*
Chris@60 4 Sonic Visualiser
Chris@60 5 An audio file viewer and annotation editor.
Chris@60 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@60 8
Chris@60 9 This program is free software; you can redistribute it and/or
Chris@60 10 modify it under the terms of the GNU General Public License as
Chris@60 11 published by the Free Software Foundation; either version 2 of the
Chris@60 12 License, or (at your option) any later version. See the file
Chris@60 13 COPYING included with this distribution for more information.
Chris@60 14 */
Chris@60 15
Chris@60 16 #include "PluginParameterBox.h"
Chris@60 17
Chris@60 18 #include "AudioDial.h"
Chris@60 19
Chris@71 20 #include "plugin/PluginXml.h"
Chris@71 21
Chris@167 22 #include "base/RangeMapper.h"
Chris@167 23
Chris@60 24 #include <QDoubleSpinBox>
Chris@60 25 #include <QGridLayout>
Chris@63 26 #include <QComboBox>
Chris@63 27 #include <QCheckBox>
Chris@60 28 #include <QLayout>
Chris@60 29 #include <QLabel>
Chris@60 30
Chris@60 31 #include <iostream>
Chris@60 32 #include <string>
Chris@60 33
Chris@78 34 #include <cmath>
Chris@78 35
Chris@71 36 PluginParameterBox::PluginParameterBox(Vamp::PluginBase *plugin, QWidget *parent) :
Chris@62 37 QFrame(parent),
Chris@60 38 m_plugin(plugin)
Chris@60 39 {
Chris@60 40 m_layout = new QGridLayout;
Chris@60 41 setLayout(m_layout);
Chris@60 42 populate();
Chris@60 43 }
Chris@60 44
Chris@60 45 PluginParameterBox::~PluginParameterBox()
Chris@60 46 {
Chris@60 47 }
Chris@60 48
Chris@60 49 void
Chris@60 50 PluginParameterBox::populate()
Chris@60 51 {
Chris@71 52 Vamp::PluginBase::ParameterList params = m_plugin->getParameterDescriptors();
Chris@71 53 Vamp::PluginBase::ProgramList programs = m_plugin->getPrograms();
Chris@60 54
Chris@60 55 m_params.clear();
Chris@60 56
Chris@63 57 if (params.empty() && programs.empty()) {
Chris@62 58 m_layout->addWidget
Chris@62 59 (new QLabel(tr("This plugin has no adjustable parameters.")),
Chris@62 60 0, 0);
Chris@62 61 }
Chris@62 62
Chris@63 63 int offset = 0;
Chris@63 64
Chris@63 65 if (!programs.empty()) {
Chris@63 66
Chris@63 67 std::string currentProgram = m_plugin->getCurrentProgram();
Chris@63 68
Chris@63 69 QComboBox *programCombo = new QComboBox;
Chris@63 70 programCombo->setMaxVisibleItems(20);
Chris@63 71
Chris@63 72 for (int i = 0; i < programs.size(); ++i) {
Chris@63 73 programCombo->addItem(programs[i].c_str());
Chris@63 74 if (programs[i] == currentProgram) {
Chris@63 75 programCombo->setCurrentIndex(i);
Chris@63 76 }
Chris@63 77 }
Chris@63 78
Chris@63 79 m_layout->addWidget(new QLabel(tr("Program")), 0, 0);
Chris@63 80 m_layout->addWidget(programCombo, 0, 1, 1, 2);
Chris@63 81
Chris@63 82 connect(programCombo, SIGNAL(currentIndexChanged(const QString &)),
Chris@63 83 this, SLOT(programComboChanged(const QString &)));
Chris@63 84
Chris@63 85 offset = 1;
Chris@63 86 }
Chris@63 87
Chris@60 88 for (size_t i = 0; i < params.size(); ++i) {
Chris@60 89
Chris@60 90 QString name = params[i].name.c_str();
Chris@60 91 QString description = params[i].description.c_str();
Chris@60 92 QString unit = params[i].unit.c_str();
Chris@60 93
Chris@60 94 float min = params[i].minValue;
Chris@60 95 float max = params[i].maxValue;
Chris@60 96 float deft = params[i].defaultValue;
Chris@62 97 float value = m_plugin->getParameter(params[i].name);
Chris@60 98
Chris@60 99 float qtz = 0.0;
Chris@60 100 if (params[i].isQuantized) qtz = params[i].quantizeStep;
Chris@60 101
Chris@74 102 std::vector<std::string> valueNames = params[i].valueNames;
Chris@74 103
Chris@60 104 // construct an integer range
Chris@60 105
Chris@60 106 int imin = 0, imax = 100;
Chris@60 107
Chris@60 108 if (qtz > 0.0) {
Chris@60 109 imax = int((max - min) / qtz);
Chris@60 110 } else {
Chris@60 111 qtz = (max - min) / 100.0;
Chris@60 112 }
Chris@60 113
Chris@60 114 //!!! would be nice to ensure the default value corresponds to
Chris@60 115 // an integer!
Chris@60 116
Chris@60 117 QLabel *label = new QLabel(description);
Chris@63 118 m_layout->addWidget(label, i + offset, 0);
Chris@60 119
Chris@60 120 ParamRec rec;
Chris@60 121 rec.param = params[i];
Chris@63 122 rec.dial = 0;
Chris@63 123 rec.spin = 0;
Chris@63 124 rec.check = 0;
Chris@74 125 rec.combo = 0;
Chris@63 126
Chris@74 127 if (params[i].isQuantized && !valueNames.empty()) {
Chris@74 128
Chris@74 129 QComboBox *combobox = new QComboBox;
Chris@74 130 combobox->setObjectName(name);
Chris@74 131 for (unsigned int j = 0; j < valueNames.size(); ++j) {
Chris@74 132 combobox->addItem(valueNames[j].c_str());
Chris@74 133 if (lrintf((value - min) / qtz) == j) {
Chris@74 134 combobox->setCurrentIndex(j);
Chris@74 135 }
Chris@74 136 }
Chris@74 137 connect(combobox, SIGNAL(activated(int)),
Chris@74 138 this, SLOT(dialChanged(int)));
Chris@74 139 m_layout->addWidget(combobox, i + offset, 1, 1, 2);
Chris@74 140 rec.combo = combobox;
Chris@74 141
Chris@74 142 } else if (min == 0.0 && max == 1.0 && qtz == 1.0) {
Chris@63 143
Chris@63 144 QCheckBox *checkbox = new QCheckBox;
Chris@63 145 checkbox->setObjectName(name);
Chris@63 146 checkbox->setCheckState(value == 0.0 ? Qt::Unchecked : Qt::Checked);
Chris@63 147 connect(checkbox, SIGNAL(stateChanged(int)),
Chris@63 148 this, SLOT(checkBoxChanged(int)));
Chris@63 149 m_layout->addWidget(checkbox, i + offset, 2);
Chris@63 150 rec.check = checkbox;
Chris@63 151
Chris@63 152 } else {
Chris@63 153
Chris@63 154 AudioDial *dial = new AudioDial;
Chris@167 155 dial->setObjectName(description);
Chris@63 156 dial->setMinimum(imin);
Chris@63 157 dial->setMaximum(imax);
Chris@63 158 dial->setPageStep(1);
Chris@63 159 dial->setNotchesVisible((imax - imin) <= 12);
Chris@74 160 dial->setDefaultValue(lrintf((deft - min) / qtz));
Chris@74 161 dial->setValue(lrintf((value - min) / qtz));
Chris@63 162 dial->setFixedWidth(32);
Chris@63 163 dial->setFixedHeight(32);
Chris@167 164 dial->setRangeMapper(new LinearRangeMapper
Chris@167 165 (imin, imax, min, max, unit));
Chris@168 166 dial->setShowToolTip(true);
Chris@63 167 connect(dial, SIGNAL(valueChanged(int)),
Chris@63 168 this, SLOT(dialChanged(int)));
Chris@63 169 m_layout->addWidget(dial, i + offset, 1);
Chris@63 170
Chris@63 171 QDoubleSpinBox *spinbox = new QDoubleSpinBox;
Chris@63 172 spinbox->setObjectName(name);
Chris@63 173 spinbox->setMinimum(min);
Chris@63 174 spinbox->setMaximum(max);
Chris@63 175 spinbox->setSuffix(QString(" %1").arg(unit));
Chris@63 176 spinbox->setSingleStep(qtz);
Chris@63 177 spinbox->setValue(value);
Chris@103 178 spinbox->setDecimals(4);
Chris@63 179 connect(spinbox, SIGNAL(valueChanged(double)),
Chris@63 180 this, SLOT(spinBoxChanged(double)));
Chris@63 181 m_layout->addWidget(spinbox, i + offset, 2);
Chris@63 182 rec.dial = dial;
Chris@63 183 rec.spin = spinbox;
Chris@63 184 }
Chris@63 185
Chris@60 186 m_params[name] = rec;
Chris@167 187 m_descriptionMap[description] = name;
Chris@60 188 }
Chris@60 189 }
Chris@60 190
Chris@60 191 void
Chris@60 192 PluginParameterBox::dialChanged(int ival)
Chris@60 193 {
Chris@60 194 QObject *obj = sender();
Chris@60 195 QString name = obj->objectName();
Chris@60 196
Chris@167 197 if (m_params.find(name) == m_params.end() &&
Chris@167 198 m_descriptionMap.find(name) != m_descriptionMap.end()) {
Chris@167 199 name = m_descriptionMap[name];
Chris@167 200 }
Chris@167 201
Chris@60 202 if (m_params.find(name) == m_params.end()) {
Chris@60 203 std::cerr << "WARNING: PluginParameterBox::dialChanged: Unknown parameter \"" << name.toStdString() << "\"" << std::endl;
Chris@60 204 return;
Chris@60 205 }
Chris@60 206
Chris@71 207 Vamp::PluginBase::ParameterDescriptor params = m_params[name].param;
Chris@60 208
Chris@60 209 float min = params.minValue;
Chris@60 210 float max = params.maxValue;
Chris@60 211
Chris@168 212 float newValue;
Chris@168 213
Chris@60 214 float qtz = 0.0;
Chris@60 215 if (params.isQuantized) qtz = params.quantizeStep;
Chris@168 216
Chris@168 217 AudioDial *ad = dynamic_cast<AudioDial *>(obj);
Chris@60 218
Chris@168 219 if (ad && ad->rangeMapper()) {
Chris@168 220
Chris@168 221 newValue = ad->mappedValue();
Chris@168 222 if (newValue < min) newValue = min;
Chris@168 223 if (newValue > max) newValue = max;
Chris@168 224 if (qtz != 0.0) {
Chris@168 225 ival = lrintf((newValue - min) / qtz);
Chris@168 226 newValue = min + ival * qtz;
Chris@168 227 }
Chris@168 228
Chris@168 229 } else {
Chris@168 230 if (qtz == 0.0) {
Chris@168 231 qtz = (max - min) / 100.0;
Chris@168 232 }
Chris@168 233 newValue = min + ival * qtz;
Chris@60 234 }
Chris@60 235
Chris@60 236 QDoubleSpinBox *spin = m_params[name].spin;
Chris@63 237 if (spin) {
Chris@63 238 spin->blockSignals(true);
Chris@63 239 spin->setValue(newValue);
Chris@63 240 spin->blockSignals(false);
Chris@63 241 }
Chris@60 242
Chris@60 243 m_plugin->setParameter(name.toStdString(), newValue);
Chris@64 244
Chris@71 245 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
Chris@60 246 }
Chris@60 247
Chris@60 248 void
Chris@63 249 PluginParameterBox::checkBoxChanged(int state)
Chris@63 250 {
Chris@63 251 QObject *obj = sender();
Chris@63 252 QString name = obj->objectName();
Chris@63 253
Chris@167 254 if (m_params.find(name) == m_params.end() &&
Chris@167 255 m_descriptionMap.find(name) != m_descriptionMap.end()) {
Chris@167 256 name = m_descriptionMap[name];
Chris@167 257 }
Chris@167 258
Chris@63 259 if (m_params.find(name) == m_params.end()) {
Chris@63 260 std::cerr << "WARNING: PluginParameterBox::checkBoxChanged: Unknown parameter \"" << name.toStdString() << "\"" << std::endl;
Chris@63 261 return;
Chris@63 262 }
Chris@63 263
Chris@71 264 Vamp::PluginBase::ParameterDescriptor params = m_params[name].param;
Chris@63 265
Chris@63 266 if (state) m_plugin->setParameter(name.toStdString(), 1.0);
Chris@63 267 else m_plugin->setParameter(name.toStdString(), 0.0);
Chris@64 268
Chris@71 269 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
Chris@63 270 }
Chris@63 271
Chris@63 272 void
Chris@60 273 PluginParameterBox::spinBoxChanged(double value)
Chris@60 274 {
Chris@60 275 QObject *obj = sender();
Chris@60 276 QString name = obj->objectName();
Chris@60 277
Chris@167 278 if (m_params.find(name) == m_params.end() &&
Chris@167 279 m_descriptionMap.find(name) != m_descriptionMap.end()) {
Chris@167 280 name = m_descriptionMap[name];
Chris@167 281 }
Chris@167 282
Chris@60 283 if (m_params.find(name) == m_params.end()) {
Chris@60 284 std::cerr << "WARNING: PluginParameterBox::spinBoxChanged: Unknown parameter \"" << name.toStdString() << "\"" << std::endl;
Chris@60 285 return;
Chris@60 286 }
Chris@60 287
Chris@71 288 Vamp::PluginBase::ParameterDescriptor params = m_params[name].param;
Chris@60 289
Chris@60 290 float min = params.minValue;
Chris@60 291 float max = params.maxValue;
Chris@60 292
Chris@60 293 float qtz = 0.0;
Chris@60 294 if (params.isQuantized) qtz = params.quantizeStep;
Chris@60 295
Chris@60 296 if (qtz > 0.0) {
Chris@60 297 int step = int((value - min) / qtz);
Chris@60 298 value = min + step * qtz;
Chris@60 299 }
Chris@60 300
Chris@60 301 int imin = 0, imax = 100;
Chris@60 302
Chris@60 303 if (qtz > 0.0) {
Chris@60 304 imax = int((max - min) / qtz);
Chris@60 305 } else {
Chris@60 306 qtz = (max - min) / 100.0;
Chris@60 307 }
Chris@60 308
Chris@60 309 int ival = (value - min) / qtz;
Chris@60 310
Chris@60 311 AudioDial *dial = m_params[name].dial;
Chris@63 312 if (dial) {
Chris@63 313 dial->blockSignals(true);
Chris@63 314 dial->setValue(ival);
Chris@63 315 dial->blockSignals(false);
Chris@63 316 }
Chris@60 317
Chris@60 318 m_plugin->setParameter(name.toStdString(), value);
Chris@64 319
Chris@71 320 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
Chris@60 321 }
Chris@60 322
Chris@63 323 void
Chris@63 324 PluginParameterBox::programComboChanged(const QString &newProgram)
Chris@63 325 {
Chris@63 326 m_plugin->selectProgram(newProgram.toStdString());
Chris@60 327
Chris@63 328 for (std::map<QString, ParamRec>::iterator i = m_params.begin();
Chris@63 329 i != m_params.end(); ++i) {
Chris@63 330
Chris@71 331 Vamp::PluginBase::ParameterDescriptor &param = i->second.param;
Chris@63 332 float value = m_plugin->getParameter(param.name);
Chris@63 333
Chris@63 334 if (i->second.spin) {
Chris@63 335 i->second.spin->blockSignals(true);
Chris@63 336 i->second.spin->setValue(value);
Chris@63 337 i->second.spin->blockSignals(false);
Chris@63 338 }
Chris@63 339
Chris@63 340 if (i->second.dial) {
Chris@63 341
Chris@63 342 float min = param.minValue;
Chris@63 343 float max = param.maxValue;
Chris@63 344
Chris@63 345 float qtz = 0.0;
Chris@63 346 if (param.isQuantized) qtz = param.quantizeStep;
Chris@63 347
Chris@63 348 if (qtz == 0.0) {
Chris@63 349 qtz = (max - min) / 100.0;
Chris@63 350 }
Chris@63 351
Chris@63 352 i->second.dial->blockSignals(true);
Chris@74 353 i->second.dial->setValue(lrintf((value - min) / qtz));
Chris@63 354 i->second.dial->blockSignals(false);
Chris@63 355 }
Chris@74 356
Chris@74 357 if (i->second.combo) {
Chris@74 358 i->second.combo->blockSignals(true);
Chris@74 359 i->second.combo->setCurrentIndex(value);
Chris@74 360 i->second.combo->blockSignals(false);
Chris@74 361 }
Chris@63 362 }
Chris@64 363
Chris@71 364 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
Chris@63 365 }
Chris@63 366