PluginParameterDialog.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "PluginParameterDialog.h"
17 
18 #include "PluginParameterBox.h"
19 #include "WindowTypeSelector.h"
20 
21 #include "TextAbbrev.h"
22 #include "IconLoader.h"
23 #include "WidgetScale.h"
24 
25 #include <vamp-hostsdk/Plugin.h>
26 #include <vamp-hostsdk/PluginHostAdapter.h>
27 #include <vamp-hostsdk/PluginWrapper.h>
28 
29 #include <QGridLayout>
30 #include <QLabel>
31 #include <QGroupBox>
32 #include <QHBoxLayout>
33 #include <QVBoxLayout>
34 #include <QScrollArea>
35 #include <QPushButton>
36 #include <QMessageBox>
37 #include <QComboBox>
38 #include <QCheckBox>
39 #include <QSettings>
40 #include <QDialogButtonBox>
41 #include <QDesktopServices>
42 #include <QUrl>
43 
44 #include "base/Debug.h"
45 
46 PluginParameterDialog::PluginParameterDialog(std::shared_ptr<Vamp::PluginBase> plugin,
47  QWidget *parent) :
48  QDialog(parent),
49  m_plugin(plugin),
50  m_channel(-1),
51  m_stepSize(0),
52  m_blockSize(0),
53  m_windowType(HanningWindow),
54  m_parameterBox(nullptr),
55  m_currentSelectionOnly(false)
56 {
57  setWindowTitle(tr("Plugin Parameters"));
58 
59  QGridLayout *grid = new QGridLayout;
60  setLayout(grid);
61 
62  QGroupBox *pluginBox = new QGroupBox;
63  pluginBox->setTitle(plugin->getType().c_str());
64  grid->addWidget(pluginBox, 0, 0);
65 
66  QGridLayout *subgrid = new QGridLayout;
67  pluginBox->setLayout(subgrid);
68 
69  subgrid->setSpacing(0);
70  subgrid->setMargin(10);
71 
72  QFont boldFont(pluginBox->font());
73  boldFont.setBold(true);
74 
75  QFont italicFont(pluginBox->font());
76  italicFont.setItalic(true);
77 
78  QLabel *nameLabel = new QLabel(plugin->getName().c_str());
79  nameLabel->setWordWrap(true);
80  nameLabel->setFont(boldFont);
81 
82  QLabel *makerLabel = new QLabel(plugin->getMaker().c_str());
83  makerLabel->setWordWrap(true);
84 
85  int version = plugin->getPluginVersion();
86  QLabel *versionLabel = new QLabel(QString("%1").arg(version));
87  versionLabel->setWordWrap(true);
88 
89  QLabel *copyrightLabel = new QLabel(plugin->getCopyright().c_str());
90  copyrightLabel->setWordWrap(true);
91 
92  QLabel *descriptionLabel = nullptr;
93  if (plugin->getDescription() != "") {
94  descriptionLabel = new QLabel(plugin->getDescription().c_str());
95  descriptionLabel->setWordWrap(true);
96  descriptionLabel->setFont(italicFont);
97  }
98 
99  int row = 0;
100 
101  QLabel *label = new QLabel(tr("Name:"));
102  label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
103  subgrid->addWidget(label, row, 0);
104  subgrid->addWidget(nameLabel, row, 1);
105 
106  m_moreInfo = new QPushButton;
107  m_moreInfo->setIcon(IconLoader().load("info"));
108  m_moreInfo->setFixedSize(WidgetScale::scaleQSize(QSize(16, 16)));
109  connect(m_moreInfo, SIGNAL(clicked()), this, SLOT(moreInfo()));
110  subgrid->addWidget(m_moreInfo, row, 2, Qt::AlignTop | Qt::AlignRight);
111  m_moreInfo->hide();
112 
113  row++;
114 
115  if (descriptionLabel) {
116  subgrid->addWidget(descriptionLabel, row, 1, 1, 2);
117  row++;
118  }
119 
120  if (version >= 0) {
121  label = new QLabel(tr("Version:"));
122  label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
123  subgrid->addWidget(label, row, 0);
124  subgrid->addWidget(versionLabel, row, 1);
125  row++;
126  }
127 
128  label = new QLabel(tr("Maker:"));
129  label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
130  subgrid->addWidget(label, row, 0);
131  subgrid->addWidget(makerLabel, row, 1);
132  row++;
133 
134  label = new QLabel(tr("Copyright: "));
135  label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
136  subgrid->addWidget(label, row, 0);
137  subgrid->addWidget(copyrightLabel, row, 1);
138  row++;
139 
140  m_outputSpacer = new QLabel;
141  subgrid->addWidget(m_outputSpacer, row, 0);
142  m_outputSpacer->setFixedHeight(7);
143  m_outputSpacer->hide();
144  row++;
145 
146  m_outputLabel = new QLabel(tr("Output:"));
147  m_outputLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
148  subgrid->addWidget(m_outputLabel, row, 0);
149  m_outputValue = new QLabel;
150  m_outputValue->setFont(boldFont);
151  subgrid->addWidget(m_outputValue, row, 1);
152  m_outputLabel->hide();
153  m_outputValue->hide();
154  row++;
155 
156  m_outputDescription = new QLabel;
157  m_outputDescription->setFont(italicFont);
158  subgrid->addWidget(m_outputDescription, row, 1);
159  m_outputDescription->hide();
160  row++;
161 
162  subgrid->setColumnStretch(1, 2);
163 
164  m_inputModelBox = new QGroupBox;
165  m_inputModelBox->setTitle(tr("Input Material"));
166  grid->addWidget(m_inputModelBox, 1, 0);
167 
168  m_inputModels = new QComboBox;
169  QVBoxLayout *inputLayout = new QVBoxLayout;
170  m_inputModelBox->setLayout(inputLayout);
171  inputLayout->addWidget(m_inputModels);
172  m_inputModels->hide();
173 
174  m_selectionOnly = new QCheckBox(tr("Restrict to selection extents"));
175  inputLayout->addWidget(m_selectionOnly);
176  m_selectionOnly->hide();
177 
178  m_inputModelBox->hide();
179 
180  QGroupBox *paramBox = new QGroupBox;
181  paramBox->setTitle(tr("Plugin Parameters"));
182  grid->addWidget(paramBox, 2, 0);
183  grid->setRowStretch(2, 10);
184 
185  QHBoxLayout *paramLayout = new QHBoxLayout;
186  paramLayout->setMargin(0);
187  paramBox->setLayout(paramLayout);
188 
189  QScrollArea *scroll = new QScrollArea;
190  scroll->setWidgetResizable(true);
191  scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
192  scroll->setFrameShape(QFrame::NoFrame);
193  paramLayout->addWidget(scroll);
194 
196  connect(m_parameterBox, SIGNAL(pluginConfigurationChanged(QString)),
197  this, SIGNAL(pluginConfigurationChanged(QString)));
198  scroll->setWidget(m_parameterBox);
199 
200  m_advanced = new QFrame;
201  QVBoxLayout *advancedLayout = new QVBoxLayout;
202  advancedLayout->setMargin(0);
203  m_advanced->setLayout(advancedLayout);
204  grid->addWidget(m_advanced, 3, 0);
205 
206  m_channelBox = new QGroupBox;
207  m_channelBox->setTitle(tr("Channels"));
208  advancedLayout->addWidget(m_channelBox);
209  m_channelBox->setVisible(false);
210  m_haveChannelBoxData = false;
211 
212  m_windowBox = new QGroupBox;
213  m_windowBox->setTitle(tr("Processing"));
214  advancedLayout->addWidget(m_windowBox);
215  m_windowBox->setVisible(false);
216  m_haveWindowBoxData = false;
217 
218  QHBoxLayout *hbox = new QHBoxLayout;
219  grid->addLayout(hbox, 4, 0);
220 
221  m_advancedVisible = false;
222 
223  m_advancedButton = new QPushButton(tr("Advanced >>"));
224  m_advancedButton->setCheckable(true);
225  connect(m_advancedButton, SIGNAL(clicked()), this, SLOT(advancedToggled()));
226 
227  QSettings settings;
228  settings.beginGroup("PluginParameterDialog");
229  m_advancedVisible = settings.value("advancedvisible", false).toBool();
230  settings.endGroup();
231 
232  m_advanced->hide();
233 
234  hbox->addWidget(m_advancedButton);
235  m_advancedButton->hide();
236 
237  QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok |
238  QDialogButtonBox::Cancel);
239  hbox->addWidget(bb);
240  connect(bb, SIGNAL(accepted()), this, SLOT(dialogAccepted()));
241  connect(bb, SIGNAL(rejected()), this, SLOT(reject()));
242  bb->button(QDialogButtonBox::Ok)->setDefault(true);
243 
245 }
246 
248 {
249 }
250 
251 int
253 {
254  show();
256  return QDialog::exec();
257 }
258 
259 
260 void
262  QString description)
263 {
264  if (text == "") {
265  m_outputSpacer->hide();
266  m_outputLabel->hide();
267  m_outputValue->hide();
268  m_outputDescription->hide();
269  } else {
270  m_outputSpacer->show();
271  m_outputValue->setText(text);
272  m_outputValue->setWordWrap(true);
273  m_outputDescription->setText(description);
274  m_outputDescription->setWordWrap(true);
275  m_outputLabel->show();
276  m_outputValue->show();
277  if (description != "") {
278  m_outputDescription->show();
279  } else {
280  m_outputDescription->hide();
281  }
282  }
283 }
284 
285 void
287 {
288  m_moreInfoUrl = moreInfoUrl;
289  if (m_moreInfoUrl != "") {
290  m_moreInfo->show();
291  } else {
292  m_moreInfo->hide();
293  }
294 }
295 
296 void
298  int targetChannels,
299  int defaultChannel)
300 {
301  m_channel = defaultChannel;
302 
303  if (sourceChannels != targetChannels) {
304 
305  // At the moment we can only cope with the case where
306  // sourceChannels > targetChannels and targetChannels == 1
307 
308  if (sourceChannels < targetChannels) {
309 
310  QMessageBox::warning
311  (parentWidget(),
312  tr("Channel mismatch"),
313  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")),
314  QMessageBox::Ok,
315  QMessageBox::NoButton);
316 
317  } else {
318 
319  if (m_haveChannelBoxData) {
320  cerr << "WARNING: PluginParameterDialog::setChannelArrangement: Calling more than once on same dialog is not currently implemented" << endl;
321  return;
322  }
323 
324  QVBoxLayout *channelLayout = new QVBoxLayout;
325  m_channelBox->setLayout(channelLayout);
326 
327  if (targetChannels != 1) {
328 
329  channelLayout->addWidget
330  (new QLabel(tr("This plugin accepts no more than %1 input channels,\nbut %2 are available. Only the first %3 will be used.\n")
331  .arg(targetChannels)
332  .arg(sourceChannels)
333  .arg(targetChannels)));
334 
335  } else {
336 
337  channelLayout->addWidget(new QLabel(tr("This plugin only has a single channel input,\nbut the source has %1 channels.").arg(sourceChannels)));
338 
339  QComboBox *channelCombo = new QComboBox;
340  channelCombo->addItem(tr("Use mean of source channels"));
341  for (int i = 0; i < sourceChannels; ++i) {
342  channelCombo->addItem(tr("Use channel %1 only").arg(i + 1));
343  }
344 
345  connect(channelCombo, SIGNAL(activated(int)),
346  this, SLOT(channelComboChanged(int)));
347 
348  channelLayout->addWidget(channelCombo);
349  }
350 
351  m_channelBox->setVisible(true);
352  m_haveChannelBoxData = true;
353  m_advancedButton->show();
354  }
355  }
356 
358 }
359 
360 void
362  bool showFrequencyDomainOptions)
363 {
364  if (m_haveWindowBoxData) {
365  cerr << "WARNING: PluginParameterDialog::setShowProcessingOptions: Calling more than once on same dialog is not currently implemented" << endl;
366  return;
367  }
368 
369  if (showWindowSize) {
370 
371  auto fePlugin = std::dynamic_pointer_cast<Vamp::Plugin>(m_plugin);
372  int size = 1024;
373  int increment = 1024;
374  if (fePlugin) {
375  size = int(fePlugin->getPreferredBlockSize());
376  cerr << "Feature extraction plugin \"" << fePlugin->getName() << "\" reports preferred block size as " << size << endl;
377  if (size == 0) size = 1024;
378  increment = int(fePlugin->getPreferredStepSize());
379  if (increment == 0) {
380  if (fePlugin->getInputDomain() == Vamp::Plugin::TimeDomain) {
381  increment = size;
382  } else {
383  increment = size/2;
384  }
385  }
386  }
387 
388  QGridLayout *windowLayout = new QGridLayout;
389  m_windowBox->setLayout(windowLayout);
390 
391  if (showFrequencyDomainOptions) {
392  windowLayout->addWidget(new QLabel(tr("Window size:")), 0, 0);
393  } else {
394  windowLayout->addWidget(new QLabel(tr("Audio frames per block:")), 0, 0);
395  }
396 
397  cerr << "size: " << size << ", increment: " << increment << endl;
398 
399  QComboBox *blockSizeCombo = new QComboBox;
400  blockSizeCombo->setEditable(true);
401  bool found = false;
402  for (int i = 0; i < 14; ++i) {
403  int val = 1 << (i + 3);
404  blockSizeCombo->addItem(QString("%1").arg(val));
405  if (val == size) {
406  blockSizeCombo->setCurrentIndex(i);
407  found = true;
408  }
409  }
410  if (!found) {
411  blockSizeCombo->addItem(QString("%1").arg(size));
412  blockSizeCombo->setCurrentIndex(blockSizeCombo->count() - 1);
413  }
414  blockSizeCombo->setValidator(new QIntValidator(1, int(pow(2., 18)), this));
415  connect(blockSizeCombo, SIGNAL(editTextChanged(const QString &)),
416  this, SLOT(blockSizeComboChanged(const QString &)));
417  windowLayout->addWidget(blockSizeCombo, 0, 1);
418 
419  windowLayout->addWidget(new QLabel(tr("Window increment:")), 1, 0);
420 
421  QComboBox *incrementCombo = new QComboBox;
422  incrementCombo->setEditable(true);
423  found = false;
424  for (int i = 0; i < 14; ++i) {
425  int val = 1 << (i + 3);
426  incrementCombo->addItem(QString("%1").arg(val));
427  if (val == increment) {
428  incrementCombo->setCurrentIndex(i);
429  found = true;
430  }
431  }
432  if (!found) {
433  incrementCombo->addItem(QString("%1").arg(increment));
434  incrementCombo->setCurrentIndex(incrementCombo->count() - 1);
435  }
436  incrementCombo->setValidator(new QIntValidator(1, int(pow(2., 18)), this));
437  connect(incrementCombo, SIGNAL(editTextChanged(const QString &)),
438  this, SLOT(incrementComboChanged(const QString &)));
439  windowLayout->addWidget(incrementCombo, 1, 1);
440 
441  if (showFrequencyDomainOptions) {
442 
443  windowLayout->addWidget(new QLabel(tr("Window shape:")), 2, 0);
444  WindowTypeSelector *windowTypeSelector = new WindowTypeSelector;
445  connect(windowTypeSelector, SIGNAL(windowTypeChanged(WindowType)),
446  this, SLOT(windowTypeChanged(WindowType)));
447  windowLayout->addWidget(windowTypeSelector, 2, 1);
448  }
449 
450  m_windowBox->setVisible(true);
451  m_haveWindowBoxData = true;
452  m_advancedButton->show();
453  }
454 
456 }
457 
458 void
460  QString defaultModel)
461 {
462  m_inputModels->clear();
463 
464  QSettings settings;
465  settings.beginGroup("PluginParameterDialog");
466  QString lastModel = settings.value("lastinputmodel").toString();
467  settings.endGroup();
468 
469  if (defaultModel == "") defaultModel = lastModel;
470 
471  m_inputModels->show();
472 
473  m_inputModelList = models;
474  m_inputModels->addItems(TextAbbrev::abbreviate(models, 80));
475  m_inputModels->setCurrentIndex(0);
476 
477  if (defaultModel != "") {
478  for (int i = 0; i < models.size(); ++i) {
479  if (defaultModel == models[i]) {
480  m_inputModels->setCurrentIndex(i);
481  m_currentInputModel = models[i];
482  break;
483  }
484  }
485  }
486 
487  connect(m_inputModels, SIGNAL(activated(int)),
488  this, SLOT(inputModelComboChanged(int)));
489  m_inputModelBox->show();
490 }
491 
492 void
494 {
495  if (!show) {
496  m_selectionOnly->hide();
497  if (!m_inputModels->isVisible()) m_inputModelBox->hide();
498  return;
499  }
500 
501  QSettings settings;
502  settings.beginGroup("PluginParameterDialog");
503  bool lastSelectionOnly = settings.value("lastselectiononly", false).toBool();
504  settings.endGroup();
505 
506  m_selectionOnly->setChecked(lastSelectionOnly);
507  m_currentSelectionOnly = lastSelectionOnly;
508 
509  connect(m_selectionOnly, SIGNAL(stateChanged(int)),
510  this, SLOT(selectionOnlyChanged(int)));
511 
512  m_selectionOnly->show();
513  m_inputModelBox->show();
514 }
515 
516 QString
518 {
519  return m_currentInputModel;
520 }
521 
522 bool
524 {
525  return m_currentSelectionOnly;
526 }
527 
528 void
530 {
531  blockSize = m_blockSize;
532  return;
533 }
534 
535 void
537  int &blockSize,
538  WindowType &windowType) const
539 {
540  stepSize = m_stepSize;
541  blockSize = m_blockSize;
542  windowType = m_windowType;
543  return;
544 }
545 
546 void
548 {
549  m_blockSize = text.toInt();
550  cerr << "Block size changed to " << m_blockSize << endl;
551 }
552 
553 void
555 {
556  m_stepSize = text.toInt();
558  cerr << "Increment changed to " << m_stepSize << endl;
559 }
560 
561 void
563 {
564  m_windowType = type;
565 }
566 
567 void
569 {
570  if (m_moreInfoUrl != "") {
571  QDesktopServices::openUrl(QUrl(m_moreInfoUrl));
572  }
573 }
574 
575 void
577 {
579 }
580 
581 void
583 {
584  if (visible) {
585  m_advancedButton->setText(tr("Advanced <<"));
586  m_advancedButton->setChecked(true);
587  m_advanced->show();
588  } else {
589  m_advanced->hide();
590  m_advancedButton->setText(tr("Advanced >>"));
591  m_advancedButton->setChecked(false);
592  }
593 
594  adjustSize();
595 
596  m_advancedVisible = visible;
597 
598  QSettings settings;
599  settings.beginGroup("PluginParameterDialog");
600  settings.setValue("advancedvisible", visible);
601  settings.endGroup();
602 }
603 
604 void
606 {
607  m_channel = index - 1;
608 }
609 
610 void
612 {
613  if (index >= m_inputModelList.size()) return;
616 }
617 
618 void
620 {
621  if (state == Qt::Checked) {
622  m_currentSelectionOnly = true;
623  } else {
624  m_currentSelectionOnly = false;
625  }
626 }
627 
628 void
630 {
631  QSettings settings;
632  settings.beginGroup("PluginParameterDialog");
633 
634  if (m_inputModels->isVisible()) {
635  settings.setValue("lastinputmodel", getInputModel());
636  }
637 
638  if (m_selectionOnly->isVisible()) {
639  settings.setValue("lastselectiononly", getSelectionOnly());
640  }
641 
642  settings.endGroup();
643 
644  accept();
645 }
646 
void setChannelArrangement(int sourceChannels, int targetChannels, int defaultChannel)
PluginParameterDialog(std::shared_ptr< Vamp::PluginBase > plugin, QWidget *parent=0)
static QString abbreviate(QString text, int maxLength, Policy policy=ElideEnd, bool fuzzy=true, QString ellipsis="")
Abbreviate the given text to the given maximum length (including ellipsis), using the given abbreviat...
Definition: TextAbbrev.cpp:79
void pluginConfigurationChanged(QString)
void getProcessingParameters(int &blockSize) const
!! merge with PluginTransform::ExecutionContext
void inputModelChanged(QString)
static QSize scaleQSize(QSize size)
Definition: WidgetScale.h:58
void windowTypeChanged(WindowType type)
void setCandidateInputModels(const QStringList &names, QString defaultName)
void setShowSelectionOnlyOption(bool show)
void setOutputLabel(QString output, QString description)
PluginParameterBox * m_parameterBox
void setShowProcessingOptions(bool showWindowSize, bool showFrequencyDomainOptions)
void blockSizeComboChanged(const QString &)
void setMoreInfoUrl(QString url)
void incrementComboChanged(const QString &)
std::shared_ptr< Vamp::PluginBase > m_plugin