annotate widgets/PluginParameterBox.cpp @ 151:8f51db2434dc

* Pull alphabetical categorisation code out into a SubdividingMenu class
author Chris Cannam
date Mon, 25 Sep 2006 11:21:12 +0000
parents 5064eeb1c76f
children 53b9c7656798
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@60 7 This file copyright 2006 Chris Cannam.
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@60 22 #include <QDoubleSpinBox>
Chris@60 23 #include <QGridLayout>
Chris@63 24 #include <QComboBox>
Chris@63 25 #include <QCheckBox>
Chris@60 26 #include <QLayout>
Chris@60 27 #include <QLabel>
Chris@60 28
Chris@60 29 #include <iostream>
Chris@60 30 #include <string>
Chris@60 31
Chris@78 32 #include <cmath>
Chris@78 33
Chris@71 34 PluginParameterBox::PluginParameterBox(Vamp::PluginBase *plugin, QWidget *parent) :
Chris@62 35 QFrame(parent),
Chris@60 36 m_plugin(plugin)
Chris@60 37 {
Chris@60 38 m_layout = new QGridLayout;
Chris@60 39 setLayout(m_layout);
Chris@60 40 populate();
Chris@60 41 }
Chris@60 42
Chris@60 43 PluginParameterBox::~PluginParameterBox()
Chris@60 44 {
Chris@60 45 }
Chris@60 46
Chris@60 47 void
Chris@60 48 PluginParameterBox::populate()
Chris@60 49 {
Chris@71 50 Vamp::PluginBase::ParameterList params = m_plugin->getParameterDescriptors();
Chris@71 51 Vamp::PluginBase::ProgramList programs = m_plugin->getPrograms();
Chris@60 52
Chris@60 53 m_params.clear();
Chris@60 54
Chris@63 55 if (params.empty() && programs.empty()) {
Chris@62 56 m_layout->addWidget
Chris@62 57 (new QLabel(tr("This plugin has no adjustable parameters.")),
Chris@62 58 0, 0);
Chris@62 59 }
Chris@62 60
Chris@63 61 int offset = 0;
Chris@63 62
Chris@63 63 if (!programs.empty()) {
Chris@63 64
Chris@63 65 std::string currentProgram = m_plugin->getCurrentProgram();
Chris@63 66
Chris@63 67 QComboBox *programCombo = new QComboBox;
Chris@63 68 programCombo->setMaxVisibleItems(20);
Chris@63 69
Chris@63 70 for (int i = 0; i < programs.size(); ++i) {
Chris@63 71 programCombo->addItem(programs[i].c_str());
Chris@63 72 if (programs[i] == currentProgram) {
Chris@63 73 programCombo->setCurrentIndex(i);
Chris@63 74 }
Chris@63 75 }
Chris@63 76
Chris@63 77 m_layout->addWidget(new QLabel(tr("Program")), 0, 0);
Chris@63 78 m_layout->addWidget(programCombo, 0, 1, 1, 2);
Chris@63 79
Chris@63 80 connect(programCombo, SIGNAL(currentIndexChanged(const QString &)),
Chris@63 81 this, SLOT(programComboChanged(const QString &)));
Chris@63 82
Chris@63 83 offset = 1;
Chris@63 84 }
Chris@63 85
Chris@60 86 for (size_t i = 0; i < params.size(); ++i) {
Chris@60 87
Chris@60 88 QString name = params[i].name.c_str();
Chris@60 89 QString description = params[i].description.c_str();
Chris@60 90 QString unit = params[i].unit.c_str();
Chris@60 91
Chris@60 92 float min = params[i].minValue;
Chris@60 93 float max = params[i].maxValue;
Chris@60 94 float deft = params[i].defaultValue;
Chris@62 95 float value = m_plugin->getParameter(params[i].name);
Chris@60 96
Chris@60 97 float qtz = 0.0;
Chris@60 98 if (params[i].isQuantized) qtz = params[i].quantizeStep;
Chris@60 99
Chris@74 100 std::vector<std::string> valueNames = params[i].valueNames;
Chris@74 101
Chris@60 102 // construct an integer range
Chris@60 103
Chris@60 104 int imin = 0, imax = 100;
Chris@60 105
Chris@60 106 if (qtz > 0.0) {
Chris@60 107 imax = int((max - min) / qtz);
Chris@60 108 } else {
Chris@60 109 qtz = (max - min) / 100.0;
Chris@60 110 }
Chris@60 111
Chris@60 112 //!!! would be nice to ensure the default value corresponds to
Chris@60 113 // an integer!
Chris@60 114
Chris@60 115 QLabel *label = new QLabel(description);
Chris@63 116 m_layout->addWidget(label, i + offset, 0);
Chris@60 117
Chris@60 118 ParamRec rec;
Chris@60 119 rec.param = params[i];
Chris@63 120 rec.dial = 0;
Chris@63 121 rec.spin = 0;
Chris@63 122 rec.check = 0;
Chris@74 123 rec.combo = 0;
Chris@63 124
Chris@74 125 if (params[i].isQuantized && !valueNames.empty()) {
Chris@74 126
Chris@74 127 QComboBox *combobox = new QComboBox;
Chris@74 128 combobox->setObjectName(name);
Chris@74 129 for (unsigned int j = 0; j < valueNames.size(); ++j) {
Chris@74 130 combobox->addItem(valueNames[j].c_str());
Chris@74 131 if (lrintf((value - min) / qtz) == j) {
Chris@74 132 combobox->setCurrentIndex(j);
Chris@74 133 }
Chris@74 134 }
Chris@74 135 connect(combobox, SIGNAL(activated(int)),
Chris@74 136 this, SLOT(dialChanged(int)));
Chris@74 137 m_layout->addWidget(combobox, i + offset, 1, 1, 2);
Chris@74 138 rec.combo = combobox;
Chris@74 139
Chris@74 140 } else if (min == 0.0 && max == 1.0 && qtz == 1.0) {
Chris@63 141
Chris@63 142 QCheckBox *checkbox = new QCheckBox;
Chris@63 143 checkbox->setObjectName(name);
Chris@63 144 checkbox->setCheckState(value == 0.0 ? Qt::Unchecked : Qt::Checked);
Chris@63 145 connect(checkbox, SIGNAL(stateChanged(int)),
Chris@63 146 this, SLOT(checkBoxChanged(int)));
Chris@63 147 m_layout->addWidget(checkbox, i + offset, 2);
Chris@63 148 rec.check = checkbox;
Chris@63 149
Chris@63 150 } else {
Chris@63 151
Chris@63 152 AudioDial *dial = new AudioDial;
Chris@63 153 dial->setObjectName(name);
Chris@63 154 dial->setMinimum(imin);
Chris@63 155 dial->setMaximum(imax);
Chris@63 156 dial->setPageStep(1);
Chris@63 157 dial->setNotchesVisible((imax - imin) <= 12);
Chris@74 158 dial->setDefaultValue(lrintf((deft - min) / qtz));
Chris@74 159 dial->setValue(lrintf((value - min) / qtz));
Chris@63 160 dial->setFixedWidth(32);
Chris@63 161 dial->setFixedHeight(32);
Chris@63 162 connect(dial, SIGNAL(valueChanged(int)),
Chris@63 163 this, SLOT(dialChanged(int)));
Chris@63 164 m_layout->addWidget(dial, i + offset, 1);
Chris@63 165
Chris@63 166 QDoubleSpinBox *spinbox = new QDoubleSpinBox;
Chris@63 167 spinbox->setObjectName(name);
Chris@63 168 spinbox->setMinimum(min);
Chris@63 169 spinbox->setMaximum(max);
Chris@63 170 spinbox->setSuffix(QString(" %1").arg(unit));
Chris@63 171 spinbox->setSingleStep(qtz);
Chris@63 172 spinbox->setValue(value);
Chris@103 173 spinbox->setDecimals(4);
Chris@63 174 connect(spinbox, SIGNAL(valueChanged(double)),
Chris@63 175 this, SLOT(spinBoxChanged(double)));
Chris@63 176 m_layout->addWidget(spinbox, i + offset, 2);
Chris@63 177 rec.dial = dial;
Chris@63 178 rec.spin = spinbox;
Chris@63 179 }
Chris@63 180
Chris@60 181 m_params[name] = rec;
Chris@60 182 }
Chris@60 183 }
Chris@60 184
Chris@60 185 void
Chris@60 186 PluginParameterBox::dialChanged(int ival)
Chris@60 187 {
Chris@60 188 QObject *obj = sender();
Chris@60 189 QString name = obj->objectName();
Chris@60 190
Chris@60 191 if (m_params.find(name) == m_params.end()) {
Chris@60 192 std::cerr << "WARNING: PluginParameterBox::dialChanged: Unknown parameter \"" << name.toStdString() << "\"" << std::endl;
Chris@60 193 return;
Chris@60 194 }
Chris@60 195
Chris@71 196 Vamp::PluginBase::ParameterDescriptor params = m_params[name].param;
Chris@60 197
Chris@60 198 float min = params.minValue;
Chris@60 199 float max = params.maxValue;
Chris@60 200
Chris@60 201 float qtz = 0.0;
Chris@60 202 if (params.isQuantized) qtz = params.quantizeStep;
Chris@60 203
Chris@60 204 if (qtz == 0.0) {
Chris@60 205 qtz = (max - min) / 100.0;
Chris@60 206 }
Chris@60 207
Chris@60 208 float newValue = min + ival * qtz;
Chris@60 209
Chris@60 210 QDoubleSpinBox *spin = m_params[name].spin;
Chris@63 211 if (spin) {
Chris@63 212 spin->blockSignals(true);
Chris@63 213 spin->setValue(newValue);
Chris@63 214 spin->blockSignals(false);
Chris@63 215 }
Chris@60 216
Chris@60 217 m_plugin->setParameter(name.toStdString(), newValue);
Chris@64 218
Chris@71 219 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
Chris@60 220 }
Chris@60 221
Chris@60 222 void
Chris@63 223 PluginParameterBox::checkBoxChanged(int state)
Chris@63 224 {
Chris@63 225 QObject *obj = sender();
Chris@63 226 QString name = obj->objectName();
Chris@63 227
Chris@63 228 if (m_params.find(name) == m_params.end()) {
Chris@63 229 std::cerr << "WARNING: PluginParameterBox::checkBoxChanged: Unknown parameter \"" << name.toStdString() << "\"" << std::endl;
Chris@63 230 return;
Chris@63 231 }
Chris@63 232
Chris@71 233 Vamp::PluginBase::ParameterDescriptor params = m_params[name].param;
Chris@63 234
Chris@63 235 if (state) m_plugin->setParameter(name.toStdString(), 1.0);
Chris@63 236 else m_plugin->setParameter(name.toStdString(), 0.0);
Chris@64 237
Chris@71 238 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
Chris@63 239 }
Chris@63 240
Chris@63 241 void
Chris@60 242 PluginParameterBox::spinBoxChanged(double value)
Chris@60 243 {
Chris@60 244 QObject *obj = sender();
Chris@60 245 QString name = obj->objectName();
Chris@60 246
Chris@60 247 if (m_params.find(name) == m_params.end()) {
Chris@60 248 std::cerr << "WARNING: PluginParameterBox::spinBoxChanged: Unknown parameter \"" << name.toStdString() << "\"" << std::endl;
Chris@60 249 return;
Chris@60 250 }
Chris@60 251
Chris@71 252 Vamp::PluginBase::ParameterDescriptor params = m_params[name].param;
Chris@60 253
Chris@60 254 float min = params.minValue;
Chris@60 255 float max = params.maxValue;
Chris@60 256
Chris@60 257 float qtz = 0.0;
Chris@60 258 if (params.isQuantized) qtz = params.quantizeStep;
Chris@60 259
Chris@60 260 if (qtz > 0.0) {
Chris@60 261 int step = int((value - min) / qtz);
Chris@60 262 value = min + step * qtz;
Chris@60 263 }
Chris@60 264
Chris@60 265 int imin = 0, imax = 100;
Chris@60 266
Chris@60 267 if (qtz > 0.0) {
Chris@60 268 imax = int((max - min) / qtz);
Chris@60 269 } else {
Chris@60 270 qtz = (max - min) / 100.0;
Chris@60 271 }
Chris@60 272
Chris@60 273 int ival = (value - min) / qtz;
Chris@60 274
Chris@60 275 AudioDial *dial = m_params[name].dial;
Chris@63 276 if (dial) {
Chris@63 277 dial->blockSignals(true);
Chris@63 278 dial->setValue(ival);
Chris@63 279 dial->blockSignals(false);
Chris@63 280 }
Chris@60 281
Chris@60 282 m_plugin->setParameter(name.toStdString(), value);
Chris@64 283
Chris@71 284 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
Chris@60 285 }
Chris@60 286
Chris@63 287 void
Chris@63 288 PluginParameterBox::programComboChanged(const QString &newProgram)
Chris@63 289 {
Chris@63 290 m_plugin->selectProgram(newProgram.toStdString());
Chris@60 291
Chris@63 292 for (std::map<QString, ParamRec>::iterator i = m_params.begin();
Chris@63 293 i != m_params.end(); ++i) {
Chris@63 294
Chris@71 295 Vamp::PluginBase::ParameterDescriptor &param = i->second.param;
Chris@63 296 float value = m_plugin->getParameter(param.name);
Chris@63 297
Chris@63 298 if (i->second.spin) {
Chris@63 299 i->second.spin->blockSignals(true);
Chris@63 300 i->second.spin->setValue(value);
Chris@63 301 i->second.spin->blockSignals(false);
Chris@63 302 }
Chris@63 303
Chris@63 304 if (i->second.dial) {
Chris@63 305
Chris@63 306 float min = param.minValue;
Chris@63 307 float max = param.maxValue;
Chris@63 308
Chris@63 309 float qtz = 0.0;
Chris@63 310 if (param.isQuantized) qtz = param.quantizeStep;
Chris@63 311
Chris@63 312 if (qtz == 0.0) {
Chris@63 313 qtz = (max - min) / 100.0;
Chris@63 314 }
Chris@63 315
Chris@63 316 i->second.dial->blockSignals(true);
Chris@74 317 i->second.dial->setValue(lrintf((value - min) / qtz));
Chris@63 318 i->second.dial->blockSignals(false);
Chris@63 319 }
Chris@74 320
Chris@74 321 if (i->second.combo) {
Chris@74 322 i->second.combo->blockSignals(true);
Chris@74 323 i->second.combo->setCurrentIndex(value);
Chris@74 324 i->second.combo->blockSignals(false);
Chris@74 325 }
Chris@63 326 }
Chris@64 327
Chris@71 328 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
Chris@63 329 }
Chris@63 330