1 /***************************************************************************
2 NewSignalDialog.cpp - dialog for the "newsignal" plugin
3 -------------------
4 begin : Wed Jul 18 2001
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
20 #include <math.h>
21 #include <stdlib.h>
22
23 #include <limits>
24
25 #include <QLabel>
26 #include <QLayout>
27 #include <QPushButton>
28 #include <QRadioButton>
29 #include <QSlider>
30 #include <QSpinBox>
31 #include <QString>
32 #include <QTimer>
33
34 #include <KComboBox>
35 #include <KHelpClient>
36 #include <KLocalizedString>
37
38 #include "libkwave/String.h"
39 #include "libkwave/Utils.h"
40
41 #include "NewSignalDialog.h"
42
43 //***************************************************************************
NewSignalDialog(QWidget * parent,sample_index_t samples,unsigned int rate,unsigned int bits,unsigned int tracks,bool by_time)44 Kwave::NewSignalDialog::NewSignalDialog(QWidget *parent, sample_index_t samples,
45 unsigned int rate, unsigned int bits, unsigned int tracks,
46 bool by_time)
47 :QDialog(parent), Ui::NewSigDlg(), m_timer(this), m_recursive(false)
48 {
49
50 setupUi(this);
51 setModal(true);
52
53 edSamples->setRange(0, std::numeric_limits<int>::max());
54 edSamples->setSingleStep(1);
55
56 // connect the timer for the sample edit
57 connect(&m_timer, SIGNAL(timeout()), this, SLOT(checkNewSampleEdit()));
58 connect(rbTime, SIGNAL(toggled(bool)),
59 this, SLOT(rbTimeToggled(bool)));
60
61 // connect the file format controls
62 connect(cbSampleRate, SIGNAL(editTextChanged(QString)),
63 this, SLOT(sampleRateChanged(QString)));
64 connect(sbChannels, SIGNAL(valueChanged(int)),
65 this, SLOT(tracksChanged(int)));
66 connect(sbResolution, SIGNAL(valueChanged(int)),
67 this, SLOT(checkTimeAndLengthInfo(int)));
68
69 // connect the time controls
70 connect(sbSeconds, SIGNAL(valueChanged(int)),
71 this, SLOT(timeChanged(int)));
72 connect(sbMinutes, SIGNAL(valueChanged(int)),
73 this, SLOT(timeChanged(int)));
74 connect(sbHours, SIGNAL(valueChanged(int)),
75 this, SLOT(timeChanged(int)));
76
77 // selection by number of samples
78 connect(slideLength,SIGNAL(valueChanged(int)),
79 this, SLOT(setLengthPercentage(int)));
80
81 // selection by percentage of maximum possible length
82 connect(edSamples, SIGNAL(valueChanged(int)),
83 this, SLOT(samplesChanged(int)));
84
85 // help button
86 connect(buttonBox->button(QDialogButtonBox::Help), SIGNAL(clicked()),
87 this, SLOT(invokeHelp()));
88
89 // pre-initialize the size
90 setMaximumHeight(sizeHint().height());
91 setMaximumWidth(sizeHint().width());
92
93 // initialize the controls
94 cbSampleRate->setEditText(QString::number(rate));
95 sbResolution->setValue(bits);
96 sbChannels->setValue(tracks);
97 if (by_time) {
98 rbSamples->setChecked(false);
99 rbTime->setChecked(true);
100 setHMS(samples);
101 edSamples->setEnabled(false);
102 sbHours->setEnabled(true);
103 sbMinutes->setEnabled(true);
104 sbSeconds->setEnabled(true);
105 } else {
106 // by samples
107 rbTime->setChecked(false);
108 rbSamples->setChecked(true);
109 edSamples->setValue(Kwave::toInt(samples));
110 edSamples->setEnabled(true);
111 sbHours->setEnabled(false);
112 sbMinutes->setEnabled(false);
113 sbSeconds->setEnabled(false);
114 }
115
116 tracksChanged(0);
117 checkTimeAndLengthInfo(0);
118
119 // that dialog is big enough, limit it to it's optimal size
120 setFixedHeight(sizeHint().height());
121 setFixedWidth(sizeHint().width());
122
123 // set the focus onto the "OK" button
124 buttonBox->button(QDialogButtonBox::Ok)->setFocus();
125 }
126
127 //***************************************************************************
samples()128 sample_index_t Kwave::NewSignalDialog::samples()
129 {
130 return static_cast<sample_index_t>(edSamples->value());
131 }
132
133 //***************************************************************************
rate()134 double Kwave::NewSignalDialog::rate()
135 {
136 bool ok;
137 double r = cbSampleRate->currentText().toDouble(&ok);
138 if (!ok) r = 0;
139 return r;
140 }
141
142 //***************************************************************************
checkNewSampleEdit()143 void Kwave::NewSignalDialog::checkNewSampleEdit()
144 {
145 static int last_samples = -1;
146 if (edSamples->value() != last_samples) {
147 last_samples = edSamples->value();
148 samplesChanged(last_samples);
149 }
150 }
151
152 //***************************************************************************
tracks()153 unsigned int Kwave::NewSignalDialog::tracks()
154 {
155 return sbChannels->value();
156 }
157
158 //***************************************************************************
bitsPerSample()159 unsigned int Kwave::NewSignalDialog::bitsPerSample()
160 {
161 int res = sbResolution->value();
162 if (res < 8) res = 8;
163 return res;
164 }
165
166 //***************************************************************************
byTime()167 bool Kwave::NewSignalDialog::byTime()
168 {
169 return rbTime->isChecked();
170 }
171
172 //***************************************************************************
maxSamples()173 sample_index_t Kwave::NewSignalDialog::maxSamples()
174 {
175 unsigned int bytes_per_sample = bitsPerSample() >> 3;
176
177 /*
178 * NOTE: this limitation to INT_MAX instead of UINT_MAX is
179 * only needed because some gui elements like
180 * QSpinBox cannot handle more :-(
181 */
182 const sample_index_t max_file_size = std::numeric_limits<int>::max();
183
184 return (max_file_size / tracks() / bytes_per_sample);
185 }
186
187 //***************************************************************************
rbTimeToggled(bool)188 void Kwave::NewSignalDialog::rbTimeToggled(bool)
189 {
190 if (rbTime->isChecked()) {
191 m_timer.stop();
192 } else {
193 // activate the sample edit timer
194 m_timer.setSingleShot(false);
195 m_timer.start(100);
196 }
197 }
198
199 //***************************************************************************
checkTimeAndLengthInfo(int)200 void Kwave::NewSignalDialog::checkTimeAndLengthInfo(int)
201 {
202 (rbTime->isChecked()) ? timeChanged(0) : samplesChanged(0);
203 }
204
205 //***************************************************************************
timeChanged(int)206 void Kwave::NewSignalDialog::timeChanged(int)
207 {
208 if (m_recursive) return; // don't do recursive processing
209 if (!rbTime->isChecked()) return;
210 if ((rate() <= 0) || !tracks() || (bitsPerSample() < 8)) return;
211 m_recursive = true;
212
213 // get current time and correct wrap-overs
214 int seconds = sbSeconds->value();
215 int minutes = sbMinutes->value();
216 int hours = sbHours->value();
217 if ((seconds < 0) && ((minutes > 0) || (hours > 0)) ) {
218 sbSeconds->setValue(59);
219 sbMinutes->stepDown();
220 minutes--;
221 } else if (seconds < 0) {
222 sbSeconds->setValue(0);
223 } else if (seconds > 59) {
224 sbSeconds->setValue(0);
225 sbMinutes->stepUp();
226 minutes++;
227 }
228
229 if ((minutes < 0) && (hours > 0)) {
230 sbMinutes->setValue(59);
231 sbHours->stepDown();
232 hours--;
233 } else if (minutes < 0) {
234 sbMinutes->setValue(0);
235 } else if (minutes > 59) {
236 sbMinutes->setValue(0);
237 sbHours->stepUp();
238 hours++;
239 }
240 seconds = sbSeconds->value();
241 minutes = sbMinutes->value();
242 hours = sbHours->value();
243 minutes += 60 * hours;
244 seconds += 60 * minutes;
245
246 // limit the current number of samples
247 sample_index_t max_samples = maxSamples();
248 sample_index_t samples = static_cast<sample_index_t>(ceil(
249 static_cast<double>(seconds) * rate()));
250
251 if (samples > max_samples) {
252 // wrap down to the maximum allowed number of samples
253 samples = max_samples;
254 setHMS(samples);
255 }
256
257 // update the other controls
258 edSamples->setValue(Kwave::toInt(samples));
259 slideLength->setValue(Kwave::toInt(100.0 *
260 static_cast<double>(samples) / static_cast<double>(max_samples)));
261 updateFileSize();
262 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(samples > 0);
263
264 m_recursive = false;
265 }
266
267 //***************************************************************************
samplesChanged(int)268 void Kwave::NewSignalDialog::samplesChanged(int)
269 {
270 if (m_recursive) return; // don't do recursive processing
271 if (!rbSamples->isChecked()) return;
272 m_recursive = true;
273
274 sample_index_t samples = edSamples->value();
275 sample_index_t max_samples = maxSamples();
276
277 if (samples > max_samples) {
278 samples = max_samples;
279 edSamples->setValue(Kwave::toInt(samples));
280 }
281
282 // update the other controls
283 setHMS(samples);
284 slideLength->setValue(Kwave::toInt(100.0 *
285 static_cast<double>(samples) / static_cast<double>(max_samples)));
286 updateFileSize();
287 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(samples > 0);
288
289 m_recursive = false;
290 }
291
292 //***************************************************************************
sampleRateChanged(const QString &)293 void Kwave::NewSignalDialog::sampleRateChanged(const QString&)
294 {
295 checkTimeAndLengthInfo(0);
296 }
297
298 //***************************************************************************
tracksChanged(int)299 void Kwave::NewSignalDialog::tracksChanged(int)
300 {
301 switch (tracks()) {
302 case 1:
303 lblTracksVerbose->setText(i18n("(Mono)"));
304 break;
305 case 2:
306 lblTracksVerbose->setText(i18n("(Stereo)"));
307 break;
308 case 4:
309 lblTracksVerbose->setText(i18n("(Quadro)"));
310 break;
311 default:
312 lblTracksVerbose->setText(_(""));
313 break;
314 }
315 checkTimeAndLengthInfo(0);
316 }
317
318 //***************************************************************************
updateFileSize()319 void Kwave::NewSignalDialog::updateFileSize()
320 {
321 double samples = static_cast<double>(edSamples->value());
322 double mbytes = samples * static_cast<double>(tracks()) *
323 static_cast<double>(bitsPerSample() >> 3);
324 mbytes /= 1024.0; // to kilobytes
325 mbytes /= 1024.0; // to megabytes
326
327 QString str_bytes;
328 str_bytes.setNum(mbytes, 'f', (mbytes >= 10.0) ? 1 : 3);
329 lblFileSize->setText(i18n("(Resulting file size: %1 MB)", str_bytes));
330 }
331
332 //***************************************************************************
setLengthPercentage(int percent)333 void Kwave::NewSignalDialog::setLengthPercentage(int percent)
334 {
335 if (m_recursive) return; // don't do recursive processing
336 if (rate() <= 0) return;
337 m_recursive = true;
338
339 sample_index_t samples = static_cast<sample_index_t>(
340 static_cast<double>(maxSamples()) *
341 static_cast<double>(percent) / 100.0);
342
343 // update the other controls
344 setHMS(samples);
345 edSamples->setValue(Kwave::toInt(samples));
346 updateFileSize();
347 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(samples > 0);
348
349 m_recursive = false;
350 }
351
352 //***************************************************************************
setHMS(sample_index_t & samples)353 void Kwave::NewSignalDialog::setHMS(sample_index_t &samples)
354 {
355 double rate = this->rate();
356 if (rate <= 0.0) return;
357
358 // TODO: support for 64 bit
359 if (samples > maxSamples()) samples = maxSamples();
360
361 int total_sec = Kwave::toInt(ceil(static_cast<double>(samples) / rate));
362 int hours = total_sec / (60*60);
363 int minutes = (total_sec / 60) % 60;
364 int seconds = total_sec % 60;
365
366 sbHours->setValue(hours);
367 sbMinutes->setValue(minutes);
368 sbSeconds->setValue(seconds);
369 }
370
371 //***************************************************************************
invokeHelp()372 void Kwave::NewSignalDialog::invokeHelp()
373 {
374 KHelpClient::invokeHelp(_("newsignal"));
375 }
376
377 //***************************************************************************
378 //***************************************************************************
379