annotate widgets/PluginParameterBox.cpp @ 607:5b72899d692b

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