Chris@60: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@60: Chris@60: /* Chris@60: Sonic Visualiser Chris@60: An audio file viewer and annotation editor. Chris@60: Centre for Digital Music, Queen Mary, University of London. Chris@60: This file copyright 2006 Chris Cannam. Chris@60: Chris@60: This program is free software; you can redistribute it and/or Chris@60: modify it under the terms of the GNU General Public License as Chris@60: published by the Free Software Foundation; either version 2 of the Chris@60: License, or (at your option) any later version. See the file Chris@60: COPYING included with this distribution for more information. Chris@60: */ Chris@60: Chris@60: #include "PluginParameterBox.h" Chris@60: Chris@60: #include "AudioDial.h" Chris@60: Chris@71: #include "plugin/PluginXml.h" Chris@71: Chris@60: #include Chris@60: #include Chris@63: #include Chris@63: #include Chris@60: #include Chris@60: #include Chris@60: Chris@60: #include Chris@60: #include Chris@60: Chris@78: #include Chris@78: Chris@71: PluginParameterBox::PluginParameterBox(Vamp::PluginBase *plugin, QWidget *parent) : Chris@62: QFrame(parent), Chris@60: m_plugin(plugin) Chris@60: { Chris@60: m_layout = new QGridLayout; Chris@60: setLayout(m_layout); Chris@60: populate(); Chris@60: } Chris@60: Chris@60: PluginParameterBox::~PluginParameterBox() Chris@60: { Chris@60: } Chris@60: Chris@60: void Chris@60: PluginParameterBox::populate() Chris@60: { Chris@71: Vamp::PluginBase::ParameterList params = m_plugin->getParameterDescriptors(); Chris@71: Vamp::PluginBase::ProgramList programs = m_plugin->getPrograms(); Chris@60: Chris@60: m_params.clear(); Chris@60: Chris@63: if (params.empty() && programs.empty()) { Chris@62: m_layout->addWidget Chris@62: (new QLabel(tr("This plugin has no adjustable parameters.")), Chris@62: 0, 0); Chris@62: } Chris@62: Chris@63: int offset = 0; Chris@63: Chris@63: if (!programs.empty()) { Chris@63: Chris@63: std::string currentProgram = m_plugin->getCurrentProgram(); Chris@63: Chris@63: QComboBox *programCombo = new QComboBox; Chris@63: programCombo->setMaxVisibleItems(20); Chris@63: Chris@63: for (int i = 0; i < programs.size(); ++i) { Chris@63: programCombo->addItem(programs[i].c_str()); Chris@63: if (programs[i] == currentProgram) { Chris@63: programCombo->setCurrentIndex(i); Chris@63: } Chris@63: } Chris@63: Chris@63: m_layout->addWidget(new QLabel(tr("Program")), 0, 0); Chris@63: m_layout->addWidget(programCombo, 0, 1, 1, 2); Chris@63: Chris@63: connect(programCombo, SIGNAL(currentIndexChanged(const QString &)), Chris@63: this, SLOT(programComboChanged(const QString &))); Chris@63: Chris@63: offset = 1; Chris@63: } Chris@63: Chris@60: for (size_t i = 0; i < params.size(); ++i) { Chris@60: Chris@60: QString name = params[i].name.c_str(); Chris@60: QString description = params[i].description.c_str(); Chris@60: QString unit = params[i].unit.c_str(); Chris@60: Chris@60: float min = params[i].minValue; Chris@60: float max = params[i].maxValue; Chris@60: float deft = params[i].defaultValue; Chris@62: float value = m_plugin->getParameter(params[i].name); Chris@60: Chris@60: float qtz = 0.0; Chris@60: if (params[i].isQuantized) qtz = params[i].quantizeStep; Chris@60: Chris@74: std::vector valueNames = params[i].valueNames; Chris@74: Chris@60: // construct an integer range Chris@60: Chris@60: int imin = 0, imax = 100; Chris@60: Chris@60: if (qtz > 0.0) { Chris@60: imax = int((max - min) / qtz); Chris@60: } else { Chris@60: qtz = (max - min) / 100.0; Chris@60: } Chris@60: Chris@60: //!!! would be nice to ensure the default value corresponds to Chris@60: // an integer! Chris@60: Chris@60: QLabel *label = new QLabel(description); Chris@63: m_layout->addWidget(label, i + offset, 0); Chris@60: Chris@60: ParamRec rec; Chris@60: rec.param = params[i]; Chris@63: rec.dial = 0; Chris@63: rec.spin = 0; Chris@63: rec.check = 0; Chris@74: rec.combo = 0; Chris@63: Chris@74: if (params[i].isQuantized && !valueNames.empty()) { Chris@74: Chris@74: QComboBox *combobox = new QComboBox; Chris@74: combobox->setObjectName(name); Chris@74: for (unsigned int j = 0; j < valueNames.size(); ++j) { Chris@74: combobox->addItem(valueNames[j].c_str()); Chris@74: if (lrintf((value - min) / qtz) == j) { Chris@74: combobox->setCurrentIndex(j); Chris@74: } Chris@74: } Chris@74: connect(combobox, SIGNAL(activated(int)), Chris@74: this, SLOT(dialChanged(int))); Chris@74: m_layout->addWidget(combobox, i + offset, 1, 1, 2); Chris@74: rec.combo = combobox; Chris@74: Chris@74: } else if (min == 0.0 && max == 1.0 && qtz == 1.0) { Chris@63: Chris@63: QCheckBox *checkbox = new QCheckBox; Chris@63: checkbox->setObjectName(name); Chris@63: checkbox->setCheckState(value == 0.0 ? Qt::Unchecked : Qt::Checked); Chris@63: connect(checkbox, SIGNAL(stateChanged(int)), Chris@63: this, SLOT(checkBoxChanged(int))); Chris@63: m_layout->addWidget(checkbox, i + offset, 2); Chris@63: rec.check = checkbox; Chris@63: Chris@63: } else { Chris@63: Chris@63: AudioDial *dial = new AudioDial; Chris@63: dial->setObjectName(name); Chris@63: dial->setMinimum(imin); Chris@63: dial->setMaximum(imax); Chris@63: dial->setPageStep(1); Chris@63: dial->setNotchesVisible((imax - imin) <= 12); Chris@74: dial->setDefaultValue(lrintf((deft - min) / qtz)); Chris@74: dial->setValue(lrintf((value - min) / qtz)); Chris@63: dial->setFixedWidth(32); Chris@63: dial->setFixedHeight(32); Chris@63: connect(dial, SIGNAL(valueChanged(int)), Chris@63: this, SLOT(dialChanged(int))); Chris@63: m_layout->addWidget(dial, i + offset, 1); Chris@63: Chris@63: QDoubleSpinBox *spinbox = new QDoubleSpinBox; Chris@63: spinbox->setObjectName(name); Chris@63: spinbox->setMinimum(min); Chris@63: spinbox->setMaximum(max); Chris@63: spinbox->setSuffix(QString(" %1").arg(unit)); Chris@63: spinbox->setSingleStep(qtz); Chris@63: spinbox->setValue(value); Chris@103: spinbox->setDecimals(4); Chris@63: connect(spinbox, SIGNAL(valueChanged(double)), Chris@63: this, SLOT(spinBoxChanged(double))); Chris@63: m_layout->addWidget(spinbox, i + offset, 2); Chris@63: rec.dial = dial; Chris@63: rec.spin = spinbox; Chris@63: } Chris@63: Chris@60: m_params[name] = rec; Chris@60: } Chris@60: } Chris@60: Chris@60: void Chris@60: PluginParameterBox::dialChanged(int ival) Chris@60: { Chris@60: QObject *obj = sender(); Chris@60: QString name = obj->objectName(); Chris@60: Chris@60: if (m_params.find(name) == m_params.end()) { Chris@60: std::cerr << "WARNING: PluginParameterBox::dialChanged: Unknown parameter \"" << name.toStdString() << "\"" << std::endl; Chris@60: return; Chris@60: } Chris@60: Chris@71: Vamp::PluginBase::ParameterDescriptor params = m_params[name].param; Chris@60: Chris@60: float min = params.minValue; Chris@60: float max = params.maxValue; Chris@60: Chris@60: float qtz = 0.0; Chris@60: if (params.isQuantized) qtz = params.quantizeStep; Chris@60: Chris@60: if (qtz == 0.0) { Chris@60: qtz = (max - min) / 100.0; Chris@60: } Chris@60: Chris@60: float newValue = min + ival * qtz; Chris@60: Chris@60: QDoubleSpinBox *spin = m_params[name].spin; Chris@63: if (spin) { Chris@63: spin->blockSignals(true); Chris@63: spin->setValue(newValue); Chris@63: spin->blockSignals(false); Chris@63: } Chris@60: Chris@60: m_plugin->setParameter(name.toStdString(), newValue); Chris@64: Chris@71: emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString()); Chris@60: } Chris@60: Chris@60: void Chris@63: PluginParameterBox::checkBoxChanged(int state) Chris@63: { Chris@63: QObject *obj = sender(); Chris@63: QString name = obj->objectName(); Chris@63: Chris@63: if (m_params.find(name) == m_params.end()) { Chris@63: std::cerr << "WARNING: PluginParameterBox::checkBoxChanged: Unknown parameter \"" << name.toStdString() << "\"" << std::endl; Chris@63: return; Chris@63: } Chris@63: Chris@71: Vamp::PluginBase::ParameterDescriptor params = m_params[name].param; Chris@63: Chris@63: if (state) m_plugin->setParameter(name.toStdString(), 1.0); Chris@63: else m_plugin->setParameter(name.toStdString(), 0.0); Chris@64: Chris@71: emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString()); Chris@63: } Chris@63: Chris@63: void Chris@60: PluginParameterBox::spinBoxChanged(double value) Chris@60: { Chris@60: QObject *obj = sender(); Chris@60: QString name = obj->objectName(); Chris@60: Chris@60: if (m_params.find(name) == m_params.end()) { Chris@60: std::cerr << "WARNING: PluginParameterBox::spinBoxChanged: Unknown parameter \"" << name.toStdString() << "\"" << std::endl; Chris@60: return; Chris@60: } Chris@60: Chris@71: Vamp::PluginBase::ParameterDescriptor params = m_params[name].param; Chris@60: Chris@60: float min = params.minValue; Chris@60: float max = params.maxValue; Chris@60: Chris@60: float qtz = 0.0; Chris@60: if (params.isQuantized) qtz = params.quantizeStep; Chris@60: Chris@60: if (qtz > 0.0) { Chris@60: int step = int((value - min) / qtz); Chris@60: value = min + step * qtz; Chris@60: } Chris@60: Chris@60: int imin = 0, imax = 100; Chris@60: Chris@60: if (qtz > 0.0) { Chris@60: imax = int((max - min) / qtz); Chris@60: } else { Chris@60: qtz = (max - min) / 100.0; Chris@60: } Chris@60: Chris@60: int ival = (value - min) / qtz; Chris@60: Chris@60: AudioDial *dial = m_params[name].dial; Chris@63: if (dial) { Chris@63: dial->blockSignals(true); Chris@63: dial->setValue(ival); Chris@63: dial->blockSignals(false); Chris@63: } Chris@60: Chris@60: m_plugin->setParameter(name.toStdString(), value); Chris@64: Chris@71: emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString()); Chris@60: } Chris@60: Chris@63: void Chris@63: PluginParameterBox::programComboChanged(const QString &newProgram) Chris@63: { Chris@63: m_plugin->selectProgram(newProgram.toStdString()); Chris@60: Chris@63: for (std::map::iterator i = m_params.begin(); Chris@63: i != m_params.end(); ++i) { Chris@63: Chris@71: Vamp::PluginBase::ParameterDescriptor ¶m = i->second.param; Chris@63: float value = m_plugin->getParameter(param.name); Chris@63: Chris@63: if (i->second.spin) { Chris@63: i->second.spin->blockSignals(true); Chris@63: i->second.spin->setValue(value); Chris@63: i->second.spin->blockSignals(false); Chris@63: } Chris@63: Chris@63: if (i->second.dial) { Chris@63: Chris@63: float min = param.minValue; Chris@63: float max = param.maxValue; Chris@63: Chris@63: float qtz = 0.0; Chris@63: if (param.isQuantized) qtz = param.quantizeStep; Chris@63: Chris@63: if (qtz == 0.0) { Chris@63: qtz = (max - min) / 100.0; Chris@63: } Chris@63: Chris@63: i->second.dial->blockSignals(true); Chris@74: i->second.dial->setValue(lrintf((value - min) / qtz)); Chris@63: i->second.dial->blockSignals(false); Chris@63: } Chris@74: Chris@74: if (i->second.combo) { Chris@74: i->second.combo->blockSignals(true); Chris@74: i->second.combo->setCurrentIndex(value); Chris@74: i->second.combo->blockSignals(false); Chris@74: } Chris@63: } Chris@64: Chris@71: emit pluginConfigurationChanged(PluginXml(m_plugin).toXmlString()); Chris@63: } Chris@63: