Chris@62: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@62: Chris@62: /* Chris@62: Sonic Visualiser Chris@62: An audio file viewer and annotation editor. Chris@62: Centre for Digital Music, Queen Mary, University of London. Chris@182: This file copyright 2006 Chris Cannam and QMUL. Chris@62: Chris@62: This program is free software; you can redistribute it and/or Chris@62: modify it under the terms of the GNU General Public License as Chris@62: published by the Free Software Foundation; either version 2 of the Chris@62: License, or (at your option) any later version. See the file Chris@62: COPYING included with this distribution for more information. Chris@62: */ Chris@62: Chris@62: #include "PluginParameterDialog.h" Chris@62: Chris@62: #include "PluginParameterBox.h" Chris@140: #include "WindowTypeSelector.h" Chris@62: Chris@106: #include "vamp-sdk/Plugin.h" Chris@147: #include "vamp-sdk/PluginHostAdapter.h" Chris@106: Chris@62: #include Chris@62: #include Chris@62: #include Chris@62: #include Chris@143: #include Chris@149: #include Chris@62: #include Chris@69: #include Chris@69: #include Chris@143: #include Chris@62: Chris@71: PluginParameterDialog::PluginParameterDialog(Vamp::PluginBase *plugin, Chris@62: QWidget *parent) : Chris@62: QDialog(parent), Chris@62: m_plugin(plugin), Chris@163: m_channel(-1), Chris@145: m_stepSize(0), Chris@145: m_blockSize(0), Chris@145: m_windowType(HanningWindow), Chris@62: m_parameterBox(0) Chris@62: { Chris@122: setWindowTitle(tr("Plugin Parameters")); Chris@122: Chris@62: QGridLayout *grid = new QGridLayout; Chris@62: setLayout(grid); Chris@62: Chris@62: QGroupBox *pluginBox = new QGroupBox; Chris@62: pluginBox->setTitle(tr("Plugin")); Chris@62: grid->addWidget(pluginBox, 0, 0); Chris@62: Chris@62: QGridLayout *subgrid = new QGridLayout; Chris@62: pluginBox->setLayout(subgrid); Chris@62: Chris@63: subgrid->setSpacing(0); Chris@63: subgrid->setMargin(10); Chris@63: Chris@62: QFont font(pluginBox->font()); Chris@62: font.setBold(true); Chris@62: Chris@62: QLabel *nameLabel = new QLabel(plugin->getDescription().c_str()); Chris@146: nameLabel->setWordWrap(true); Chris@62: nameLabel->setFont(font); Chris@62: Chris@62: QLabel *makerLabel = new QLabel(plugin->getMaker().c_str()); Chris@146: makerLabel->setWordWrap(true); Chris@62: Chris@62: QLabel *versionLabel = new QLabel(QString("%1") Chris@62: .arg(plugin->getPluginVersion())); Chris@146: versionLabel->setWordWrap(true); Chris@62: Chris@62: QLabel *copyrightLabel = new QLabel(plugin->getCopyright().c_str()); Chris@146: copyrightLabel->setWordWrap(true); Chris@62: Chris@63: QLabel *typeLabel = new QLabel(plugin->getType().c_str()); Chris@146: typeLabel->setWordWrap(true); Chris@63: typeLabel->setFont(font); Chris@63: Chris@163: int row = 0; Chris@163: Chris@147: QLabel *label = new QLabel(tr("Name:")); Chris@147: label->setAlignment(Qt::AlignTop | Qt::AlignLeft); Chris@163: subgrid->addWidget(label, row, 0); Chris@163: subgrid->addWidget(nameLabel, row, 1); Chris@163: row++; Chris@62: Chris@147: label = new QLabel(tr("Type:")); Chris@147: label->setAlignment(Qt::AlignTop | Qt::AlignLeft); Chris@163: subgrid->addWidget(label, row, 0); Chris@163: subgrid->addWidget(typeLabel, row, 1); Chris@163: row++; Chris@164: Chris@163: m_outputLabel = new QLabel(tr("Output:")); Chris@163: m_outputLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); Chris@163: subgrid->addWidget(m_outputLabel, row, 0); Chris@163: m_outputValue = new QLabel; Chris@163: subgrid->addWidget(m_outputValue, row, 1); Chris@163: m_outputLabel->hide(); Chris@163: m_outputValue->hide(); Chris@163: row++; Chris@62: Chris@147: label = new QLabel(tr("Maker:")); Chris@147: label->setAlignment(Qt::AlignTop | Qt::AlignLeft); Chris@163: subgrid->addWidget(label, row, 0); Chris@163: subgrid->addWidget(makerLabel, row, 1); Chris@163: row++; Chris@63: Chris@147: label = new QLabel(tr("Copyright: ")); Chris@147: label->setAlignment(Qt::AlignTop | Qt::AlignLeft); Chris@163: subgrid->addWidget(label, row, 0); Chris@163: subgrid->addWidget(copyrightLabel, row, 1); Chris@163: row++; Chris@106: Chris@147: label = new QLabel(tr("Version:")); Chris@147: label->setAlignment(Qt::AlignTop | Qt::AlignLeft); Chris@163: subgrid->addWidget(label, row, 0); Chris@163: subgrid->addWidget(versionLabel, row, 1); Chris@163: row++; Chris@62: Chris@62: subgrid->setColumnStretch(1, 2); Chris@62: Chris@164: m_inputModelBox = new QGroupBox; Chris@164: m_inputModelBox->setTitle(tr("Input Source")); Chris@164: grid->addWidget(m_inputModelBox, 1, 0); Chris@164: Chris@164: m_inputModels = new QComboBox; Chris@164: QHBoxLayout *inputLayout = new QHBoxLayout; Chris@164: m_inputModelBox->setLayout(inputLayout); Chris@164: inputLayout->addWidget(m_inputModels); Chris@164: m_inputModelBox->hide(); Chris@164: Chris@62: QGroupBox *paramBox = new QGroupBox; Chris@62: paramBox->setTitle(tr("Plugin Parameters")); Chris@164: grid->addWidget(paramBox, 2, 0); Chris@164: grid->setRowStretch(2, 10); Chris@62: Chris@62: QHBoxLayout *paramLayout = new QHBoxLayout; Chris@63: paramLayout->setMargin(0); Chris@62: paramBox->setLayout(paramLayout); Chris@62: Chris@149: QScrollArea *scroll = new QScrollArea; Chris@149: scroll->setWidgetResizable(true); Chris@149: scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); Chris@149: scroll->setFrameShape(QFrame::NoFrame); Chris@149: paramLayout->addWidget(scroll); Chris@149: Chris@62: m_parameterBox = new PluginParameterBox(m_plugin); Chris@64: connect(m_parameterBox, SIGNAL(pluginConfigurationChanged(QString)), Chris@64: this, SIGNAL(pluginConfigurationChanged(QString))); Chris@149: scroll->setWidget(m_parameterBox); Chris@62: Chris@143: m_advanced = new QFrame; Chris@143: QVBoxLayout *advancedLayout = new QVBoxLayout; Chris@143: advancedLayout->setMargin(0); Chris@143: m_advanced->setLayout(advancedLayout); Chris@164: grid->addWidget(m_advanced, 3, 0); Chris@143: Chris@143: bool haveAdvanced = false; Chris@143: Chris@163: m_channelBox = new QGroupBox; Chris@163: m_channelBox->setTitle(tr("Channels")); Chris@163: advancedLayout->addWidget(m_channelBox); Chris@163: m_channelBox->setVisible(false); Chris@163: m_haveChannelBoxData = false; Chris@163: Chris@163: m_windowBox = new QGroupBox; Chris@163: m_windowBox->setTitle(tr("Processing")); Chris@163: advancedLayout->addWidget(m_windowBox); Chris@163: m_windowBox->setVisible(false); Chris@163: m_haveWindowBoxData = false; Chris@163: Chris@163: QHBoxLayout *hbox = new QHBoxLayout; Chris@163: grid->addLayout(hbox, 4, 0); Chris@163: Chris@163: m_advancedVisible = false; Chris@163: Chris@163: m_advancedButton = new QPushButton(tr("Advanced >>")); Chris@163: m_advancedButton->setCheckable(true); Chris@163: connect(m_advancedButton, SIGNAL(clicked()), this, SLOT(advancedToggled())); Chris@163: Chris@163: QSettings settings; Chris@163: settings.beginGroup("PluginParameterDialog"); Chris@163: m_advancedVisible = settings.value("advancedvisible", false).toBool(); Chris@163: settings.endGroup(); Chris@163: Chris@163: m_advanced->setVisible(false); Chris@163: Chris@163: hbox->addWidget(m_advancedButton); Chris@163: m_advancedButton->hide(); Chris@163: Chris@163: QPushButton *ok = new QPushButton(tr("OK")); Chris@163: QPushButton *cancel = new QPushButton(tr("Cancel")); Chris@163: hbox->addStretch(10); Chris@163: hbox->addWidget(ok); Chris@163: hbox->addWidget(cancel); Chris@163: connect(ok, SIGNAL(clicked()), this, SLOT(accept())); Chris@163: connect(cancel, SIGNAL(clicked()), this, SLOT(reject())); Chris@163: Chris@163: setAdvancedVisible(m_advancedVisible); Chris@163: } Chris@163: Chris@163: PluginParameterDialog::~PluginParameterDialog() Chris@163: { Chris@163: } Chris@163: Chris@163: Chris@163: void Chris@163: PluginParameterDialog::setOutputLabel(QString text) Chris@163: { Chris@163: if (text == "") { Chris@163: m_outputLabel->hide(); Chris@163: m_outputValue->hide(); Chris@163: } else { Chris@163: m_outputValue->setText(text); Chris@163: m_outputValue->setWordWrap(true); Chris@163: m_outputLabel->show(); Chris@163: m_outputValue->show(); Chris@163: } Chris@163: } Chris@163: Chris@163: void Chris@163: PluginParameterDialog::setChannelArrangement(int sourceChannels, Chris@163: int targetChannels, Chris@163: int defaultChannel) Chris@163: { Chris@163: m_channel = defaultChannel; Chris@163: Chris@69: if (sourceChannels != targetChannels) { Chris@69: Chris@69: // At the moment we can only cope with the case where Chris@69: // sourceChannels > targetChannels and targetChannels == 1 Chris@69: Chris@69: if (sourceChannels < targetChannels) { Chris@69: Chris@69: QMessageBox::warning Chris@163: (parentWidget(), Chris@69: tr("Channel mismatch"), Chris@69: tr("This plugin requires at least %1 input channels, but only %2 %3 available. The plugin probably will not work correctly.").arg(targetChannels).arg(sourceChannels).arg(sourceChannels != 1 ? tr("are") : tr("is")), Chris@69: QMessageBox::Ok, Chris@69: QMessageBox::NoButton); Chris@69: Chris@69: } else { Chris@69: Chris@163: if (m_haveChannelBoxData) { Chris@163: std::cerr << "WARNING: PluginParameterDialog::setChannelArrangement: Calling more than once on same dialog is not currently implemented" << std::endl; Chris@163: return; Chris@163: } Chris@69: Chris@69: QVBoxLayout *channelLayout = new QVBoxLayout; Chris@163: m_channelBox->setLayout(channelLayout); Chris@69: Chris@69: if (targetChannels != 1) { Chris@69: Chris@69: channelLayout->addWidget Chris@69: (new QLabel(tr("This plugin accepts no more than %1 input channels,\nbut %2 are available. Only the first %3 will be used.\n") Chris@69: .arg(targetChannels) Chris@69: .arg(sourceChannels) Chris@69: .arg(targetChannels))); Chris@69: Chris@69: } else { Chris@69: Chris@69: channelLayout->addWidget(new QLabel(tr("This plugin only has a single channel input,\nbut the source has %1 channels.").arg(sourceChannels))); Chris@69: Chris@69: QComboBox *channelCombo = new QComboBox; Chris@76: channelCombo->addItem(tr("Use mean of source channels")); Chris@69: for (int i = 0; i < sourceChannels; ++i) { Chris@69: channelCombo->addItem(tr("Use channel %1 only").arg(i + 1)); Chris@69: } Chris@69: Chris@69: connect(channelCombo, SIGNAL(activated(int)), Chris@69: this, SLOT(channelComboChanged(int))); Chris@69: Chris@69: channelLayout->addWidget(channelCombo); Chris@69: } Chris@163: Chris@163: m_channelBox->setVisible(true); Chris@163: m_haveChannelBoxData = true; Chris@163: m_advancedButton->show(); Chris@69: } Chris@69: } Chris@69: Chris@163: setAdvancedVisible(m_advancedVisible); Chris@163: } Chris@163: Chris@163: void Chris@163: PluginParameterDialog::setShowProcessingOptions(bool showWindowSize, Chris@163: bool showFrequencyDomainOptions) Chris@163: { Chris@163: if (m_haveWindowBoxData) { Chris@163: std::cerr << "WARNING: PluginParameterDialog::setShowProcessingOptions: Calling more than once on same dialog is not currently implemented" << std::endl; Chris@163: return; Chris@163: } Chris@163: Chris@140: if (showWindowSize) { Chris@140: Chris@147: Vamp::PluginHostAdapter *fePlugin = dynamic_cast(m_plugin); Chris@140: int size = 1024; Chris@140: int increment = 1024; Chris@140: if (fePlugin) { Chris@140: size = fePlugin->getPreferredBlockSize(); Chris@146: std::cerr << "Feature extraction plugin \"" << fePlugin->getDescription() << "\" reports preferred block size as " << size << std::endl; Chris@140: if (size == 0) size = 1024; Chris@140: increment = fePlugin->getPreferredStepSize(); Chris@146: if (increment == 0) { Chris@146: if (fePlugin->getInputDomain() == Vamp::Plugin::TimeDomain) { Chris@146: increment = size; Chris@146: } else { Chris@146: increment = size/2; Chris@146: } Chris@146: } Chris@140: } Chris@140: Chris@140: QGridLayout *windowLayout = new QGridLayout; Chris@163: m_windowBox->setLayout(windowLayout); Chris@140: Chris@140: if (showFrequencyDomainOptions) { Chris@140: windowLayout->addWidget(new QLabel(tr("Window size:")), 0, 0); Chris@140: } else { Chris@140: windowLayout->addWidget(new QLabel(tr("Audio frames per block:")), 0, 0); Chris@140: } Chris@140: Chris@143: std::cerr << "size: " << size << ", increment: " << increment << std::endl; Chris@143: Chris@140: QComboBox *blockSizeCombo = new QComboBox; Chris@140: blockSizeCombo->setEditable(true); Chris@147: bool found = false; Chris@143: for (int i = 0; i < 14; ++i) { Chris@140: int val = pow(2, i + 3); Chris@140: blockSizeCombo->addItem(QString("%1").arg(val)); Chris@147: if (val == size) { Chris@147: blockSizeCombo->setCurrentIndex(i); Chris@147: found = true; Chris@147: } Chris@147: } Chris@147: if (!found) { Chris@147: blockSizeCombo->addItem(QString("%1").arg(size)); Chris@147: blockSizeCombo->setCurrentIndex(blockSizeCombo->count() - 1); Chris@140: } Chris@143: blockSizeCombo->setValidator(new QIntValidator(1, pow(2, 18), this)); Chris@155: connect(blockSizeCombo, SIGNAL(editTextChanged(const QString &)), Chris@155: this, SLOT(blockSizeComboChanged(const QString &))); Chris@140: windowLayout->addWidget(blockSizeCombo, 0, 1); Chris@140: Chris@148: windowLayout->addWidget(new QLabel(tr("Window increment:")), 1, 0); Chris@148: Chris@148: QComboBox *incrementCombo = new QComboBox; Chris@148: incrementCombo->setEditable(true); Chris@148: found = false; Chris@148: for (int i = 0; i < 14; ++i) { Chris@148: int val = pow(2, i + 3); Chris@148: incrementCombo->addItem(QString("%1").arg(val)); Chris@148: if (val == increment) { Chris@148: incrementCombo->setCurrentIndex(i); Chris@148: found = true; Chris@148: } Chris@148: } Chris@148: if (!found) { Chris@148: incrementCombo->addItem(QString("%1").arg(increment)); Chris@148: incrementCombo->setCurrentIndex(incrementCombo->count() - 1); Chris@148: } Chris@148: incrementCombo->setValidator(new QIntValidator(1, pow(2, 18), this)); Chris@155: connect(incrementCombo, SIGNAL(editTextChanged(const QString &)), Chris@155: this, SLOT(incrementComboChanged(const QString &))); Chris@148: windowLayout->addWidget(incrementCombo, 1, 1); Chris@148: Chris@140: if (showFrequencyDomainOptions) { Chris@140: Chris@140: windowLayout->addWidget(new QLabel(tr("Window shape:")), 2, 0); Chris@140: WindowTypeSelector *windowTypeSelector = new WindowTypeSelector; Chris@171: connect(windowTypeSelector, SIGNAL(windowTypeChanged(WindowType)), Chris@171: this, SLOT(windowTypeChanged(WindowType))); Chris@140: windowLayout->addWidget(windowTypeSelector, 2, 1); Chris@140: } Chris@163: Chris@163: m_windowBox->setVisible(true); Chris@163: m_haveWindowBoxData = true; Chris@163: m_advancedButton->show(); Chris@140: } Chris@140: Chris@163: setAdvancedVisible(m_advancedVisible); Chris@62: } Chris@62: Chris@69: void Chris@164: PluginParameterDialog::setCandidateInputModels(const QStringList &models) Chris@164: { Chris@164: m_inputModels->clear(); Chris@164: m_inputModels->insertItems(0, models); Chris@164: connect(m_inputModels, SIGNAL(activated(const QString &)), Chris@164: this, SIGNAL(inputModelChanged(QString))); Chris@164: m_inputModelBox->show(); Chris@164: } Chris@164: Chris@164: QString Chris@164: PluginParameterDialog::getInputModel() const Chris@164: { Chris@164: return m_inputModels->currentText(); Chris@164: } Chris@164: Chris@164: void Chris@145: PluginParameterDialog::getProcessingParameters(size_t &blockSize) const Chris@145: { Chris@145: blockSize = m_blockSize; Chris@145: return; Chris@145: } Chris@145: Chris@145: void Chris@145: PluginParameterDialog::getProcessingParameters(size_t &stepSize, Chris@145: size_t &blockSize, Chris@145: WindowType &windowType) const Chris@145: { Chris@145: stepSize = m_stepSize; Chris@145: blockSize = m_blockSize; Chris@145: windowType = m_windowType; Chris@146: return; Chris@145: } Chris@145: Chris@145: void Chris@155: PluginParameterDialog::blockSizeComboChanged(const QString &text) Chris@145: { Chris@145: m_blockSize = text.toInt(); Chris@146: std::cerr << "Block size changed to " << m_blockSize << std::endl; Chris@145: } Chris@145: Chris@145: void Chris@155: PluginParameterDialog::incrementComboChanged(const QString &text) Chris@145: { Chris@145: m_stepSize = text.toInt(); Chris@146: //!!! rename increment to step size throughout Chris@147: std::cerr << "Increment changed to " << m_stepSize << std::endl; Chris@145: } Chris@145: Chris@145: void Chris@145: PluginParameterDialog::windowTypeChanged(WindowType type) Chris@145: { Chris@145: m_windowType = type; Chris@145: } Chris@145: Chris@145: void Chris@143: PluginParameterDialog::advancedToggled() Chris@143: { Chris@163: setAdvancedVisible(!m_advancedVisible); Chris@163: } Chris@143: Chris@163: void Chris@163: PluginParameterDialog::setAdvancedVisible(bool visible) Chris@163: { Chris@143: m_advanced->setVisible(visible); Chris@143: Chris@163: if (visible) { Chris@163: m_advancedButton->setText(tr("Advanced <<")); Chris@163: m_advancedButton->setChecked(true); Chris@163: } else { Chris@163: m_advancedButton->setText(tr("Advanced >>")); Chris@163: m_advancedButton->setChecked(false); Chris@163: } Chris@143: Chris@143: QSettings settings; Chris@143: settings.beginGroup("PluginParameterDialog"); Chris@143: settings.setValue("advancedvisible", visible); Chris@143: settings.endGroup(); Chris@143: Chris@143: std::cerr << "resize to " << sizeHint().width() << " x " << sizeHint().height() << std::endl; Chris@143: Chris@149: setMinimumHeight(sizeHint().height()); Chris@163: adjustSize(); Chris@163: Chris@163: m_advancedVisible = visible; Chris@163: Chris@163: // if (visible) setMaximumHeight(sizeHint().height()); Chris@163: // adjustSize(); Chris@143: } Chris@143: Chris@143: void Chris@69: PluginParameterDialog::channelComboChanged(int index) Chris@69: { Chris@69: m_channel = index - 1; Chris@69: } Chris@69: