PluginParameterBox.cpp

Go to the documentation of this file.
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         std::cerr << "PluginParameterBox: hint = " << hint << ", min = " << min << ", max = "
00113                   << max << ", qtz = " << qtz << std::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 = int((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(params[i].description.c_str());
00135         }
00136         m_layout->addWidget(label, i + offset, 0);
00137 
00138         ParamRec rec;
00139         rec.param = params[i];
00140         rec.dial = 0;
00141         rec.spin = 0;
00142         rec.check = 0;
00143         rec.combo = 0;
00144         
00145         if (params[i].isQuantized && !valueNames.empty()) {
00146             
00147             QComboBox *combobox = new QComboBox;
00148             combobox->setObjectName(identifier);
00149             for (unsigned int j = 0; j < valueNames.size(); ++j) {
00150                 combobox->addItem(valueNames[j].c_str());
00151                 if ((unsigned int)(lrintf(fabsf((value - min) / qtz))) == j) {
00152                     combobox->setCurrentIndex(j);
00153                 }
00154             }
00155             connect(combobox, SIGNAL(activated(int)),
00156                     this, SLOT(dialChanged(int)));
00157             m_layout->addWidget(combobox, i + offset, 1, 1, 2);
00158             rec.combo = combobox;
00159 
00160         } else if (min == 0.0 && max == 1.0 && qtz == 1.0) {
00161             
00162             QCheckBox *checkbox = new QCheckBox;
00163             checkbox->setObjectName(identifier);
00164             checkbox->setCheckState(value < 0.5 ? Qt::Unchecked : Qt::Checked);
00165             connect(checkbox, SIGNAL(stateChanged(int)),
00166                     this, SLOT(checkBoxChanged(int)));
00167             m_layout->addWidget(checkbox, i + offset, 2);
00168             rec.check = checkbox;
00169 
00170         } else {
00171             
00172             AudioDial *dial = new AudioDial;
00173             dial->setObjectName(name);
00174             dial->setMinimum(imin);
00175             dial->setMaximum(imax);
00176             dial->setPageStep(1);
00177             dial->setNotchesVisible((imax - imin) <= 12);
00179 //            dial->setValue(lrintf((value - min) / qtz));
00180             dial->setFixedWidth(32);
00181             dial->setFixedHeight(32);
00182             RangeMapper *rm = 0;
00183             if (hint & PortHint::Logarithmic) {
00184                 rm = new LogRangeMapper(imin, imax, min, max, unit);
00185             } else {
00186                 rm = new LinearRangeMapper(imin, imax, min, max, unit);
00187             }
00188             dial->setRangeMapper(rm);
00189             dial->setDefaultValue(rm->getPositionForValue(deft));
00190             dial->setValue(rm->getPositionForValue(value));
00191             dial->setShowToolTip(true);
00192             connect(dial, SIGNAL(valueChanged(int)),
00193                     this, SLOT(dialChanged(int)));
00194             m_layout->addWidget(dial, i + offset, 1);
00195 
00196             QDoubleSpinBox *spinbox = new QDoubleSpinBox;
00197             spinbox->setObjectName(identifier);
00198             spinbox->setMinimum(min);
00199             spinbox->setMaximum(max);
00200             spinbox->setSuffix(QString(" %1").arg(unit));
00201             if (qtz != 0) spinbox->setSingleStep(qtz);
00202             spinbox->setValue(value);
00203             spinbox->setDecimals(4);
00204             connect(spinbox, SIGNAL(valueChanged(double)),
00205                     this, SLOT(spinBoxChanged(double)));
00206             m_layout->addWidget(spinbox, i + offset, 2);
00207             rec.dial = dial;
00208             rec.spin = spinbox;
00209         }
00210 
00211         m_params[identifier] = rec;
00212         m_nameMap[name] = identifier;
00213     }
00214 }
00215 
00216 void
00217 PluginParameterBox::dialChanged(int ival)
00218 {
00219     QObject *obj = sender();
00220     QString identifier = obj->objectName();
00221 
00222     if (m_params.find(identifier) == m_params.end() &&
00223         m_nameMap.find(identifier) != m_nameMap.end()) {
00224         identifier = m_nameMap[identifier];
00225     }
00226 
00227     if (m_params.find(identifier) == m_params.end()) {
00228         std::cerr << "WARNING: PluginParameterBox::dialChanged: Unknown parameter \"" << identifier.toStdString() << "\"" << std::endl;
00229         return;
00230     }
00231 
00232     Vamp::PluginBase::ParameterDescriptor params = m_params[identifier].param;
00233 
00234     float min = params.minValue;
00235     float max = params.maxValue;
00236 
00237     float newValue;
00238 
00239     float qtz = 0.0;
00240     if (params.isQuantized) qtz = params.quantizeStep;
00241 
00242     AudioDial *ad = dynamic_cast<AudioDial *>(obj);
00243     
00244     if (ad && ad->rangeMapper()) {
00245         
00246         newValue = ad->mappedValue();
00247         if (newValue < min) newValue = min;
00248         if (newValue > max) newValue = max;
00249         if (qtz != 0.0) {
00250             ival = lrintf((newValue - min) / qtz);
00251             newValue = min + ival * qtz;
00252         }
00253 
00254     } else {
00255         if (qtz == 0.0) {
00256             qtz = (max - min) / 100.0;
00257         }
00258         newValue = min + ival * qtz;
00259     }
00260 
00261     std::cerr << "PluginParameterBox::dialChanged: newValue = " << newValue << std::endl;
00262 
00263     QDoubleSpinBox *spin = m_params[identifier].spin;
00264     if (spin) {
00265         spin->blockSignals(true);
00266         spin->setValue(newValue);
00267         spin->blockSignals(false);
00268     }
00269 
00270     m_plugin->setParameter(identifier.toStdString(), newValue);
00271 
00272     updateProgramCombo();
00273 
00274     emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
00275 }
00276 
00277 void
00278 PluginParameterBox::checkBoxChanged(int state)
00279 {
00280     QObject *obj = sender();
00281     QString identifier = obj->objectName();
00282 
00283     if (m_params.find(identifier) == m_params.end() &&
00284         m_nameMap.find(identifier) != m_nameMap.end()) {
00285         identifier = m_nameMap[identifier];
00286     }
00287 
00288     if (m_params.find(identifier) == m_params.end()) {
00289         std::cerr << "WARNING: PluginParameterBox::checkBoxChanged: Unknown parameter \"" << identifier.toStdString() << "\"" << std::endl;
00290         return;
00291     }
00292 
00293     Vamp::PluginBase::ParameterDescriptor params = m_params[identifier].param;
00294 
00295     if (state) m_plugin->setParameter(identifier.toStdString(), 1.0);
00296     else m_plugin->setParameter(identifier.toStdString(), 0.0);
00297 
00298     updateProgramCombo();
00299 
00300     emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
00301 }
00302 
00303 void
00304 PluginParameterBox::spinBoxChanged(double value)
00305 {
00306     QObject *obj = sender();
00307     QString identifier = obj->objectName();
00308 
00309     if (m_params.find(identifier) == m_params.end() &&
00310         m_nameMap.find(identifier) != m_nameMap.end()) {
00311         identifier = m_nameMap[identifier];
00312     }
00313 
00314     if (m_params.find(identifier) == m_params.end()) {
00315         std::cerr << "WARNING: PluginParameterBox::spinBoxChanged: Unknown parameter \"" << identifier.toStdString() << "\"" << std::endl;
00316         return;
00317     }
00318 
00319     Vamp::PluginBase::ParameterDescriptor params = m_params[identifier].param;
00320 
00321     float min = params.minValue;
00322     float max = params.maxValue;
00323 
00324     float qtz = 0.0;
00325     if (params.isQuantized) qtz = params.quantizeStep;
00326     
00327     if (qtz > 0.0) {
00328         int step = int((value - min) / qtz);
00329         value = min + step * qtz;
00330     }
00331 
00332     int imax = 100;
00333     
00334     if (qtz > 0.0) {
00335         imax = int((max - min) / qtz);
00336     } else {
00337         qtz = (max - min) / 100.0;
00338     }
00339 
00340     int ival = lrintf((value - min) / qtz);
00341 
00342     AudioDial *dial = m_params[identifier].dial;
00343     if (dial) {
00344         dial->blockSignals(true);
00345         if (dial->rangeMapper()) {
00346             dial->setMappedValue(value);
00347         } else {
00348             dial->setValue(ival);
00349         }
00350         dial->blockSignals(false);
00351     }
00352 
00353     m_plugin->setParameter(identifier.toStdString(), value);
00354 
00355     updateProgramCombo();
00356 
00357     emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
00358 }
00359 
00360 void
00361 PluginParameterBox::programComboChanged(const QString &newProgram)
00362 {
00363     m_plugin->selectProgram(newProgram.toStdString());
00364 
00365     for (std::map<QString, ParamRec>::iterator i = m_params.begin();
00366          i != m_params.end(); ++i) {
00367 
00368         Vamp::PluginBase::ParameterDescriptor &param = i->second.param;
00369         float value = m_plugin->getParameter(param.identifier);
00370 
00371         if (i->second.spin) {
00372             i->second.spin->blockSignals(true);
00373             i->second.spin->setValue(value);
00374             i->second.spin->blockSignals(false);
00375         }
00376 
00377         if (i->second.dial) {
00378 
00379             float min = param.minValue;
00380             float max = param.maxValue;
00381 
00382             float qtz = 0.0;
00383             if (param.isQuantized) qtz = param.quantizeStep;
00384 
00385             if (qtz == 0.0) {
00386                 qtz = (max - min) / 100.0;
00387             }
00388 
00389             i->second.dial->blockSignals(true);
00390             i->second.dial->setValue(lrintf((value - min) / qtz));
00391             i->second.dial->blockSignals(false);
00392         }
00393 
00394         if (i->second.combo) {
00395             i->second.combo->blockSignals(true);
00396             i->second.combo->setCurrentIndex(lrintf(value));
00397             i->second.combo->blockSignals(false);
00398         }
00399 
00400         if (i->second.check) {
00401             i->second.check->blockSignals(true);
00402             i->second.check->setCheckState(value < 0.5 ? Qt::Unchecked : Qt::Checked);
00403             i->second.check->blockSignals(false);
00404         }            
00405     }
00406 
00407     emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString());
00408 }
00409 
00410 void
00411 PluginParameterBox::updateProgramCombo()
00412 {
00413     if (!m_programCombo || m_programs.empty()) return;
00414 
00415     std::string currentProgram = m_plugin->getCurrentProgram();
00416 
00417     for (size_t i = 0; i < m_programs.size(); ++i) {
00418         if (m_programs[i] == currentProgram) {
00419             m_programCombo->setCurrentIndex(i);
00420         }
00421     }
00422 }
00423 
00424 

Generated on Wed Feb 20 15:45:27 2008 for SonicVisualiser by  doxygen 1.5.1