annotate widgets/PluginParameterBox.cpp @ 183:5f86ae638b04

* Omit translucent blue fill for selection rectangles that are superimposed over layers that use colours for meaningful purposes such as the spectrogram (CHARM change request)
author Chris Cannam
date Fri, 24 Nov 2006 16:56:15 +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