svgui
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam and QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "PluginParameterBox.h" 00017 00018 #include "AudioDial.h" 00019 00020 #include "plugin/PluginXml.h" 00021 #include "plugin/RealTimePluginInstance.h" // for PortHint stuff 00022 00023 #include "base/RangeMapper.h" 00024 00025 #include <QDoubleSpinBox> 00026 #include <QGridLayout> 00027 #include <QComboBox> 00028 #include <QCheckBox> 00029 #include <QLayout> 00030 #include <QLabel> 00031 00032 #include <iostream> 00033 #include <string> 00034 00035 #include <cmath> 00036 00037 PluginParameterBox::PluginParameterBox(Vamp::PluginBase *plugin, QWidget *parent) : 00038 QFrame(parent), 00039 m_plugin(plugin), 00040 m_programCombo(0) 00041 { 00042 m_layout = new QGridLayout; 00043 setLayout(m_layout); 00044 populate(); 00045 } 00046 00047 PluginParameterBox::~PluginParameterBox() 00048 { 00049 } 00050 00051 void 00052 PluginParameterBox::populate() 00053 { 00054 Vamp::PluginBase::ParameterList params = m_plugin->getParameterDescriptors(); 00055 m_programs = m_plugin->getPrograms(); 00056 00057 m_params.clear(); 00058 00059 if (params.empty() && m_programs.empty()) { 00060 m_layout->addWidget 00061 (new QLabel(tr("This plugin has no adjustable parameters.")), 00062 0, 0); 00063 } 00064 00065 int offset = 0; 00066 00067 if (!m_programs.empty()) { 00068 00069 std::string currentProgram = m_plugin->getCurrentProgram(); 00070 00071 m_programCombo = new QComboBox; 00072 m_programCombo->setMaxVisibleItems 00073 (m_programs.size() < 25 ? m_programs.size() : 20); 00074 00075 for (size_t i = 0; i < m_programs.size(); ++i) { 00076 m_programCombo->addItem(m_programs[i].c_str()); 00077 if (m_programs[i] == currentProgram) { 00078 m_programCombo->setCurrentIndex(i); 00079 } 00080 } 00081 00082 m_layout->addWidget(new QLabel(tr("Program")), 0, 0); 00083 m_layout->addWidget(m_programCombo, 0, 1, 1, 2); 00084 00085 connect(m_programCombo, SIGNAL(currentIndexChanged(const QString &)), 00086 this, SLOT(programComboChanged(const QString &))); 00087 00088 offset = 1; 00089 } 00090 00091 for (size_t i = 0; i < params.size(); ++i) { 00092 00093 QString identifier = params[i].identifier.c_str(); 00094 QString name = params[i].name.c_str(); 00095 QString unit = params[i].unit.c_str(); 00096 00097 float min = params[i].minValue; 00098 float max = params[i].maxValue; 00099 float deft = params[i].defaultValue; 00100 float value = m_plugin->getParameter(params[i].identifier); 00101 00102 int hint = PortHint::NoHint; 00103 RealTimePluginInstance *rtpi = dynamic_cast<RealTimePluginInstance *> 00104 (m_plugin); 00105 if (rtpi) { 00106 hint = rtpi->getParameterDisplayHint(i); 00107 } 00108 00109 float qtz = 0.0; 00110 if (params[i].isQuantized) qtz = params[i].quantizeStep; 00111 00112 // cerr << "PluginParameterBox: hint = " << hint << ", min = " << min << ", max = " 00113 // << max << ", qtz = " << qtz << endl; 00114 00115 std::vector<std::string> valueNames = params[i].valueNames; 00116 00117 // construct an integer range 00118 00119 int imin = 0, imax = 100; 00120 00121 if (!(hint & PortHint::Logarithmic)) { 00122 if (qtz > 0.0) { 00123 imax = lrintf((max - min) / qtz); 00124 } else { 00125 qtz = (max - min) / 100.0; 00126 } 00127 } 00128 00130 // an integer! 00131 00132 QLabel *label = new QLabel(name); 00133 if (params[i].description != "") { 00134 label->setToolTip(QString("<qt>%1</qt>") 00135 .arg(params[i].description.c_str()) 00136 .replace("\n", "<br>")); 00137 } 00138 m_layout->addWidget(label, i + offset, 0); 00139 00140 ParamRec rec; 00141 rec.param = params[i]; 00142 rec.dial = 0; 00143 rec.spin = 0; 00144 rec.check = 0; 00145 rec.combo = 0; 00146 00147 if (params[i].isQuantized && !valueNames.empty()) { 00148 00149 QComboBox *combobox = new QComboBox; 00150 combobox->setObjectName(identifier); 00151 for (unsigned int j = 0; j < valueNames.size(); ++j) { 00152 combobox->addItem(valueNames[j].c_str()); 00153 if ((unsigned int)(lrintf(fabsf((value - min) / qtz))) == j) { 00154 combobox->setCurrentIndex(j); 00155 } 00156 } 00157 connect(combobox, SIGNAL(activated(int)), 00158 this, SLOT(dialChanged(int))); 00159 m_layout->addWidget(combobox, i + offset, 1, 1, 2); 00160 rec.combo = combobox; 00161 00162 } else if (min == 0.0 && max == 1.0 && qtz == 1.0) { 00163 00164 QCheckBox *checkbox = new QCheckBox; 00165 checkbox->setObjectName(identifier); 00166 checkbox->setCheckState(value < 0.5 ? Qt::Unchecked : Qt::Checked); 00167 connect(checkbox, SIGNAL(stateChanged(int)), 00168 this, SLOT(checkBoxChanged(int))); 00169 m_layout->addWidget(checkbox, i + offset, 2); 00170 rec.check = checkbox; 00171 00172 } else { 00173 00174 AudioDial *dial = new AudioDial; 00175 dial->setObjectName(name); 00176 dial->setMinimum(imin); 00177 dial->setMaximum(imax); 00178 dial->setPageStep(1); 00179 dial->setNotchesVisible((imax - imin) <= 12); 00181 // dial->setValue(lrintf((value - min) / qtz)); 00182 dial->setFixedWidth(32); 00183 dial->setFixedHeight(32); 00184 RangeMapper *rm = 0; 00185 if (hint & PortHint::Logarithmic) { 00186 rm = new LogRangeMapper(imin, imax, min, max, unit); 00187 } else { 00188 rm = new LinearRangeMapper(imin, imax, min, max, unit); 00189 } 00190 dial->setRangeMapper(rm); 00191 dial->setDefaultValue(rm->getPositionForValue(deft)); 00192 dial->setValue(rm->getPositionForValue(value)); 00193 dial->setShowToolTip(true); 00194 connect(dial, SIGNAL(valueChanged(int)), 00195 this, SLOT(dialChanged(int))); 00196 m_layout->addWidget(dial, i + offset, 1); 00197 00198 QDoubleSpinBox *spinbox = new QDoubleSpinBox; 00199 spinbox->setObjectName(identifier); 00200 spinbox->setMinimum(min); 00201 spinbox->setMaximum(max); 00202 spinbox->setSuffix(QString(" %1").arg(unit)); 00203 if (qtz != 0) spinbox->setSingleStep(qtz); 00204 spinbox->setValue(value); 00205 spinbox->setDecimals(4); 00206 connect(spinbox, SIGNAL(valueChanged(double)), 00207 this, SLOT(spinBoxChanged(double))); 00208 m_layout->addWidget(spinbox, i + offset, 2); 00209 rec.dial = dial; 00210 rec.spin = spinbox; 00211 } 00212 00213 m_params[identifier] = rec; 00214 m_nameMap[name] = identifier; 00215 } 00216 } 00217 00218 void 00219 PluginParameterBox::dialChanged(int ival) 00220 { 00221 QObject *obj = sender(); 00222 QString identifier = obj->objectName(); 00223 00224 if (m_params.find(identifier) == m_params.end() && 00225 m_nameMap.find(identifier) != m_nameMap.end()) { 00226 identifier = m_nameMap[identifier]; 00227 } 00228 00229 if (m_params.find(identifier) == m_params.end()) { 00230 cerr << "WARNING: PluginParameterBox::dialChanged: Unknown parameter \"" << identifier << "\"" << endl; 00231 return; 00232 } 00233 00234 Vamp::PluginBase::ParameterDescriptor params = m_params[identifier].param; 00235 00236 float min = params.minValue; 00237 float max = params.maxValue; 00238 00239 float newValue; 00240 00241 float qtz = 0.0; 00242 if (params.isQuantized) qtz = params.quantizeStep; 00243 00244 AudioDial *ad = dynamic_cast<AudioDial *>(obj); 00245 00246 if (ad && ad->rangeMapper()) { 00247 00248 newValue = ad->mappedValue(); 00249 if (newValue < min) newValue = min; 00250 if (newValue > max) newValue = max; 00251 if (qtz != 0.0) { 00252 ival = lrintf((newValue - min) / qtz); 00253 newValue = min + ival * qtz; 00254 } 00255 00256 } else { 00257 if (qtz == 0.0) { 00258 qtz = (max - min) / 100.0; 00259 } 00260 newValue = min + ival * qtz; 00261 } 00262 00263 // SVDEBUG << "PluginParameterBox::dialChanged: newValue = " << newValue << endl; 00264 00265 QDoubleSpinBox *spin = m_params[identifier].spin; 00266 if (spin) { 00267 spin->blockSignals(true); 00268 spin->setValue(newValue); 00269 spin->blockSignals(false); 00270 } 00271 00272 // SVDEBUG << "setting plugin parameter \"" << identifier << "\" to value " << newValue << endl; 00273 00274 m_plugin->setParameter(identifier.toStdString(), newValue); 00275 00276 updateProgramCombo(); 00277 00278 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString()); 00279 } 00280 00281 void 00282 PluginParameterBox::checkBoxChanged(int state) 00283 { 00284 QObject *obj = sender(); 00285 QString identifier = obj->objectName(); 00286 00287 if (m_params.find(identifier) == m_params.end() && 00288 m_nameMap.find(identifier) != m_nameMap.end()) { 00289 identifier = m_nameMap[identifier]; 00290 } 00291 00292 if (m_params.find(identifier) == m_params.end()) { 00293 cerr << "WARNING: PluginParameterBox::checkBoxChanged: Unknown parameter \"" << identifier << "\"" << endl; 00294 return; 00295 } 00296 00297 Vamp::PluginBase::ParameterDescriptor params = m_params[identifier].param; 00298 00299 if (state) m_plugin->setParameter(identifier.toStdString(), 1.0); 00300 else m_plugin->setParameter(identifier.toStdString(), 0.0); 00301 00302 updateProgramCombo(); 00303 00304 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString()); 00305 } 00306 00307 void 00308 PluginParameterBox::spinBoxChanged(double value) 00309 { 00310 QObject *obj = sender(); 00311 QString identifier = obj->objectName(); 00312 00313 if (m_params.find(identifier) == m_params.end() && 00314 m_nameMap.find(identifier) != m_nameMap.end()) { 00315 identifier = m_nameMap[identifier]; 00316 } 00317 00318 if (m_params.find(identifier) == m_params.end()) { 00319 cerr << "WARNING: PluginParameterBox::spinBoxChanged: Unknown parameter \"" << identifier << "\"" << endl; 00320 return; 00321 } 00322 00323 Vamp::PluginBase::ParameterDescriptor params = m_params[identifier].param; 00324 00325 float min = params.minValue; 00326 float max = params.maxValue; 00327 00328 float qtz = 0.0; 00329 if (params.isQuantized) qtz = params.quantizeStep; 00330 00331 if (qtz > 0.0) { 00332 int step = lrintf((value - min) / qtz); 00333 value = min + step * qtz; 00334 } 00335 00336 // int imax = 100; 00337 00338 if (qtz > 0.0) { 00339 // imax = lrintf((max - min) / qtz); 00340 } else { 00341 qtz = (max - min) / 100.0; 00342 } 00343 00344 int ival = lrintf((value - min) / qtz); 00345 00346 AudioDial *dial = m_params[identifier].dial; 00347 if (dial) { 00348 dial->blockSignals(true); 00349 if (dial->rangeMapper()) { 00350 dial->setMappedValue(value); 00351 } else { 00352 dial->setValue(ival); 00353 } 00354 dial->blockSignals(false); 00355 } 00356 00357 SVDEBUG << "setting plugin parameter \"" << identifier << "\" to value " << value << endl; 00358 00359 m_plugin->setParameter(identifier.toStdString(), value); 00360 00361 updateProgramCombo(); 00362 00363 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString()); 00364 } 00365 00366 void 00367 PluginParameterBox::programComboChanged(const QString &newProgram) 00368 { 00369 m_plugin->selectProgram(newProgram.toStdString()); 00370 00371 for (std::map<QString, ParamRec>::iterator i = m_params.begin(); 00372 i != m_params.end(); ++i) { 00373 00374 Vamp::PluginBase::ParameterDescriptor ¶m = i->second.param; 00375 float value = m_plugin->getParameter(param.identifier); 00376 00377 if (i->second.spin) { 00378 i->second.spin->blockSignals(true); 00379 i->second.spin->setValue(value); 00380 i->second.spin->blockSignals(false); 00381 } 00382 00383 if (i->second.dial) { 00384 00385 float min = param.minValue; 00386 float max = param.maxValue; 00387 00388 float qtz = 0.0; 00389 if (param.isQuantized) qtz = param.quantizeStep; 00390 00391 if (qtz == 0.0) { 00392 qtz = (max - min) / 100.0; 00393 } 00394 00395 i->second.dial->blockSignals(true); 00396 i->second.dial->setValue(lrintf((value - min) / qtz)); 00397 i->second.dial->blockSignals(false); 00398 } 00399 00400 if (i->second.combo) { 00401 i->second.combo->blockSignals(true); 00402 i->second.combo->setCurrentIndex(lrintf(value)); 00403 i->second.combo->blockSignals(false); 00404 } 00405 00406 if (i->second.check) { 00407 i->second.check->blockSignals(true); 00408 i->second.check->setCheckState(value < 0.5 ? Qt::Unchecked : Qt::Checked); 00409 i->second.check->blockSignals(false); 00410 } 00411 } 00412 00413 emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString()); 00414 } 00415 00416 void 00417 PluginParameterBox::updateProgramCombo() 00418 { 00419 if (!m_programCombo || m_programs.empty()) return; 00420 00421 std::string currentProgram = m_plugin->getCurrentProgram(); 00422 00423 for (size_t i = 0; i < m_programs.size(); ++i) { 00424 if (m_programs[i] == currentProgram) { 00425 m_programCombo->setCurrentIndex(i); 00426 } 00427 } 00428 } 00429 00430