kwave  18.07.70
VolumeDialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  VolumeDialog.cpp - dialog for the "volume" plugin
3  -------------------
4  begin : Sun Oct 27 2002
5  copyright : (C) 2001 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 #include "math.h"
20 
21 #include <QColor>
22 #include <QPainter>
23 #include <QPushButton>
24 #include <QRadioButton>
25 #include <QSlider>
26 #include <QSpinBox>
27 
28 #include <KHelpClient>
29 #include <KLocalizedString>
30 
31 #include "libkwave/String.h"
32 #include "libkwave/Utils.h"
33 
34 #include "libgui/CurveWidget.h"
35 #include "libgui/ImageView.h"
37 #include "libgui/OverViewCache.h"
38 #include "libgui/ScaleWidget.h"
39 
40 #include "VolumeDialog.h"
41 
42 //***************************************************************************
44  Kwave::OverViewCache *overview_cache)
45  :QDialog(parent), Ui::VolumeDlg(), m_factor(1.0), m_mode(MODE_DECIBEL),
46  m_enable_updates(true), m_overview_cache(overview_cache)
47 {
48  setupUi(this);
49  setModal(true);
50 
51  // process changed in mode selection
52  connect(rbFactor, SIGNAL(toggled(bool)),
53  this, SLOT(modeChanged(bool)));
54  connect(rbPercentage, SIGNAL(toggled(bool)),
55  this, SLOT(modeChanged(bool)));
56  connect(rbLogarithmic, SIGNAL(toggled(bool)),
57  this, SLOT(modeChanged(bool)));
58 
59  // changes in the slider or spinbox
60  connect(slider, SIGNAL(valueChanged(int)),
61  this, SLOT(sliderChanged(int)));
62  connect(spinbox, SIGNAL(valueChanged(int)),
63  this, SLOT(spinboxChanged(int)));
64 
65  // force activation of the layout
66  layout()->activate();
67 
68  // give the preview image a odd height, for better symmetry
69  int h = preview->height();
70  if (~h & 1) h++;
71  preview->setFixedHeight(h);
72 
73  // set the initial size of the dialog
74  h = (sizeHint().height() * 12) / 10;
75  int w = (3 * h) / 4;
76  if (sizeHint().width() > w) w = sizeHint().width();
77  setFixedSize(w, h);
78 
79  // set default: +3dB
80  setMode(m_mode);
81  updateDisplay(+1.412538);
82 
83  // set the focus onto the "OK" button
84  buttonBox->button(QDialogButtonBox::Ok)->setFocus();
85 }
86 
87 //***************************************************************************
89 {
90 }
91 
92 //***************************************************************************
94 {
95  double value = m_factor;
96  m_mode = mode;
97  bool old_enable_updates = m_enable_updates;
98  m_enable_updates = false;
99 
100  switch (m_mode) {
101  case MODE_FACTOR: {
102  rbFactor->setChecked(true);
103  slider->setMinimum(-9);
104  slider->setMaximum(+9);
105  slider->setPageStep(1);
106  slider->setTickInterval(1);
107  spinbox->setMinimum(-10);
108  spinbox->setMaximum(+10);
109  break;
110  }
111  case MODE_PERCENT: {
112  rbPercentage->setChecked(true);
113 
114  slider->setMinimum(1);
115  slider->setMaximum(10*100);
116  slider->setPageStep(100);
117  slider->setTickInterval(1*100);
118  spinbox->setMinimum(1);
119  spinbox->setMaximum(+10*100);
120  break;
121  }
122  case MODE_DECIBEL: {
123  rbLogarithmic->setChecked(true);
124 
125  slider->setMinimum(-21);
126  slider->setMaximum(+21);
127  slider->setPageStep(6);
128  slider->setTickInterval(6);
129  spinbox->setMinimum(-21);
130  spinbox->setMaximum(+21);
131  break;
132  }
133  }
134 
135  // update the value in the display
136  updateDisplay(value);
137  m_enable_updates = old_enable_updates;
138 }
139 
140 //***************************************************************************
142 {
143  bool old_enable_updates = m_enable_updates;
144  m_enable_updates = false;
145 
146  if (rbFactor->isChecked()) setMode(MODE_FACTOR);
147  if (rbPercentage->isChecked()) setMode(MODE_PERCENT);
148  if (rbLogarithmic->isChecked()) setMode(MODE_DECIBEL);
149 
150  m_enable_updates = old_enable_updates;
151 }
152 
153 //***************************************************************************
155 {
156  int new_spinbox_value = 0;
157  int new_slider_value = 0;
158  bool old_enable_updates = m_enable_updates;
159  m_enable_updates = false;
160 
161  if (!qFuzzyCompare(m_factor, value)) {
162  // take over the new factor
163  m_factor = value;
164 
165  // update the preview widget
166  if (m_overview_cache && preview) {
167  int width = preview->width();
168  int height = preview->height();
169  QColor fg = Qt::white;
170  QColor bg = Qt::black;
171 
172  // get the raw preview image
173  QImage image = m_overview_cache->getOverView(
174  width, height, fg, bg, m_factor);
175 
176  // color transformation: mark the peaks in light red
177  int middle = height >> 1;
178  int red = Kwave::toInt(middle * 0.841); // -1.5dB
179  int orange = Kwave::toInt(middle * 0.707); // -3.0dB
180 
181  QPainter p;
182  p.begin(&image);
183  for (int y = 0; y < height; y++) {
184  QColor color;
185 
186  if (y == middle) {
187  // zero line
188  p.setCompositionMode(QPainter::CompositionMode_SourceOver);
189  color = Qt::green;
190  } else {
191  p.setCompositionMode(QPainter::CompositionMode_Multiply);
192  if ((y < middle - red) || (y > middle + red))
193  // "red" level, -1.5dB from border
194  color = Qt::red;
195  else if ((y < middle - orange) || (y > middle + orange))
196  // "orange" level, -3.0dB from border
197  color = Qt::yellow;
198  else
199  // "normal" level
200  color = preview->palette().light().color();
201  }
202 
203  p.setPen(color);
204  p.drawLine(0, y, width-1, y);
205  }
206  p.end();
207 
208  // update the image view
209  preview->setImage(image);
210  }
211  }
212 
213  switch (m_mode) {
214  case MODE_FACTOR: {
215  // -1 => /2
216  // 0 => x1
217  // +1 => x2
218  if (Kwave::toInt(rint(m_factor)) >= 1) {
219  // greater or equal to one -> multiply
220  int new_value = Kwave::toInt(rint(value));
221  spinbox->setPrefix(_("x "));
222  spinbox->setSuffix(_(""));
223  spinbox->setInverse(false);
224 
225  new_spinbox_value = new_value;
226  new_slider_value = new_value-1;
227  } else {
228  // less than one -> divide
229  int new_value = Kwave::toInt(rint(-1.0 / value));
230 
231  spinbox->setPrefix(_("1/"));
232  spinbox->setSuffix(_(""));
233  spinbox->setInverse(true);
234 
235  new_spinbox_value = -1*new_value;
236  new_slider_value = (new_value+1);
237  }
238 
239  m_enable_updates = old_enable_updates;
240  break;
241  // return;
242  }
243  case MODE_PERCENT: {
244  // factor 1.0 means 100%
245  new_spinbox_value = Kwave::toInt(rint(value * 100.0));
246  new_slider_value = new_spinbox_value;
247  spinbox->setPrefix(_(""));
248  spinbox->setSuffix(_("%"));
249  spinbox->setInverse(false);
250  break;
251  }
252  case MODE_DECIBEL: {
253  // factor 1.0 means 0dB
254  new_slider_value = Kwave::toInt(rint(20.0 * log10(value)));
255  new_spinbox_value = new_slider_value;
256  if (new_spinbox_value >= 0) {
257  spinbox->setPrefix(new_spinbox_value ? _("+") : _("+/- "));
258  } else {
259  // negative value
260  spinbox->setPrefix(_(""));
261  }
262  spinbox->setSuffix(_(" ") + i18n("dB"));
263  spinbox->setInverse(false);
264  break;
265  }
266  }
267 
268  // update the spinbox
269  if (spinbox->value() != new_spinbox_value) spinbox->setValue(new_spinbox_value);
270 
271  // update the slider, it's inverse => top=maximum, bottom=minimum !
272  int sv = slider->maximum() + slider->minimum() - new_slider_value;
273  if (slider->value() != sv) slider->setValue(sv);
274 
275  m_enable_updates = old_enable_updates;
276 }
277 
278 //***************************************************************************
280 {
281  if (!m_enable_updates) return;
282 
283  int sv = slider->maximum() + slider->minimum() - pos;
284 // qDebug("sliderChanged(%d), sv=%d",pos,sv); // ###
285  switch (m_mode) {
286  case MODE_FACTOR: {
287  double factor = m_factor;
288  // -1 <=> /2
289  // 0 <=> x1
290  // +1 <=> x2
291  if (sv >= 0) {
292  factor = (sv + 1);
293  } else {
294  factor = -1.0 / static_cast<double>(sv - 1);
295  }
296 // qDebug("factor=%g, sv=%d",factor, sv);
297  updateDisplay(factor);
298  break;
299  }
300  case MODE_PERCENT:
301  spinboxChanged(sv);
302  break;
303  case MODE_DECIBEL:
304  spinboxChanged(sv);
305  break;
306  }
307 
308 }
309 
310 //***************************************************************************
312 {
313  if (!m_enable_updates) return;
314 // qDebug("spinboxChanged(%d)",pos); // ###
315 
316  int sv = spinbox->value();
317  double factor = m_factor;
318 
319  switch (m_mode) {
320  case MODE_FACTOR: {
321  // multiply or divide by factor
322  // -1 <=> /2
323  // 0 <=> x1
324  // +1 <=> x2
325  if (factor >= 1) {
326  factor = sv ? sv : 0.5;
327  } else {
328  if (!sv) sv = 1;
329  factor = 1.0 / static_cast<double>(sv);
330  }
331  break;
332  }
333  case MODE_PERCENT: {
334  // percentage
335  factor = static_cast<double>(pos) / 100.0;
336  break;
337  }
338  case MODE_DECIBEL: {
339  // decibel
340  factor = pow(10.0, pos / 20.0);
341  break;
342  }
343  }
344 
345  updateDisplay(factor);
346 }
347 
348 //***************************************************************************
350 {
351  QStringList list;
352  list << QString::number(m_factor);
353  list << QString::number(static_cast<int>(m_mode));
354  return list;
355 }
356 
357 //***************************************************************************
359 {
360  // evaluate the parameter list
361  double factor = params[0].toDouble();
362  switch (params[1].toUInt()) {
363  case 0: m_mode = MODE_FACTOR; break;
364  case 1: m_mode = MODE_PERCENT; break;
365  case 2: m_mode = MODE_DECIBEL; break;
366  default: m_mode = MODE_DECIBEL;
367  }
368 
369  // update mode, using default factor 1.0
370  m_factor = 1.0; // works with every mode
371  setMode(m_mode);
372 
373  // update factor
374  updateDisplay(factor);
375 }
376 
377 
378 //***************************************************************************
380 {
381  KHelpClient::invokeHelp(_("plugin_sect_volume"));
382 }
383 
384 //***************************************************************************
385 //***************************************************************************
virtual QImage getOverView(int width, int height, const QColor &fg, const QColor &bg, double gain=1.0)
void sliderChanged(int pos)
void updateDisplay(double value)
void setParams(QStringList &params)
VolumeDialog(QWidget *parent, Kwave::OverViewCache *overview_cache)
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
int toInt(T x)
Definition: Utils.h:127
void setMode(Mode mode)
#define _(m)
Definition: memcpy.c:66
Kwave::OverViewCache * m_overview_cache
Definition: VolumeDialog.h:102
void spinboxChanged(int pos)
QStringList params()