1 /*************************************************************************
2 RecordDialog.cpp - dialog window for controlling audio recording
3 -------------------
4 begin : Wed Aug 20 2003
5 copyright : (C) 2003 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 <new>
21
22 #include <QCheckBox>
23 #include <QDateTimeEdit>
24 #include <QGroupBox>
25 #include <QIcon>
26 #include <QLabel>
27 #include <QLatin1Char>
28 #include <QPixmap>
29 #include <QPointer>
30 #include <QProgressBar>
31 #include <QPushButton>
32 #include <QSlider>
33 #include <QSpinBox>
34 #include <QStatusBar>
35 #include <QTabWidget>
36 #include <QTreeView>
37 #include <QTreeWidget>
38 #include <QTreeWidgetItem>
39 #include <QVector>
40
41 #include <KComboBox>
42 #include <KHelpClient>
43 #include <KLocalizedString>
44 #include <KIconLoader>
45 #include <KIconTheme>
46
47 #include "libkwave/Compression.h"
48 #include "libkwave/SampleFormat.h"
49 #include "libkwave/String.h"
50 #include "libkwave/Utils.h"
51
52 #include "libgui/FileDialog.h"
53 #include "libgui/HMSTimeWidget.h"
54
55 #include "LevelMeter.h"
56 #include "RecordDevice.h"
57 #include "RecordDialog.h"
58 #include "RecordParams.h"
59 #include "RecordState.h"
60
61 // status bar icons
62 #include "ledgreen.xpm"
63 #include "ledlightgreen.xpm"
64 #include "ledred.xpm"
65 #include "ledyellow.xpm"
66 #include "ok.xpm"
67 #include "stop_hand.xpm"
68 #include "walk_r1.xpm"
69 #include "walk_r2.xpm"
70 #include "walk_r3.xpm"
71 #include "walk_r4.xpm"
72 #include "walk_r5.xpm"
73 #include "walk_r6.xpm"
74 #include "walk_r7.xpm"
75 #include "walk_r8.xpm"
76
77 /* some macros, for laziness ;-) */
78 #define SETUP(enabled,property,check,value) \
79 check->setChecked(m_params.enabled); \
80 value->setValue(m_params.property); \
81
82 #define STD_SETUP(enabled,property,control) \
83 SETUP(enabled,property,chk##control,sb##control); \
84 sb##control->setEnabled(chk##control->isEnabled() && \
85 chk##control->isChecked());
86
87 #define STD_SETUP_SLIDER(enabled,property,control) \
88 STD_SETUP(enabled,property,control); \
89 sl##control->setEnabled(sb##control->isEnabled());
90
91 //***************************************************************************
RecordDialog(QWidget * parent,QStringList & params,Kwave::RecordController * controller,Kwave::RecordDialog::Mode mode)92 Kwave::RecordDialog::RecordDialog(QWidget *parent, QStringList ¶ms,
93 Kwave::RecordController *controller,
94 Kwave::RecordDialog::Mode mode)
95 :QDialog(parent), Ui::RecordDlg(), m_methods_map(),
96 m_file_filter(), m_devices_list_map(),
97 m_state(Kwave::REC_EMPTY), m_params(),
98 m_supported_resolutions(), m_buffer_progress_count(0),
99 m_buffer_progress_total(0), m_buffer_progress_timer(this),
100 m_record_enabled(true), m_samples_recorded(0),
101 m_enable_setDevice(true), m_state_icon_widget(Q_NULLPTR)
102 {
103 m_status_bar.m_state = Q_NULLPTR;
104 m_status_bar.m_time = Q_NULLPTR;
105 m_status_bar.m_sample_rate = Q_NULLPTR;
106 m_status_bar.m_bits_per_sample = Q_NULLPTR;
107 m_status_bar.m_tracks = Q_NULLPTR;
108
109 setupUi(this);
110
111 /* get initial parameters */
112 m_params.fromList(params);
113
114 /* set the icons of the record control buttons */
115 btNew->setIcon( QIcon::fromTheme(_("document-new")));
116 btStop->setIcon( QIcon::fromTheme(_("kwave_player_stop")));
117 btPause->setIcon( QIcon::fromTheme(_("kwave_player_pause")));
118 btRecord->setIcon(QIcon::fromTheme(_("kwave_player_record")));
119
120 // fill the combo box with playback methods
121 unsigned int index=0;
122 for (index = 0; index < m_methods_map.count(); ++index) {
123 cbMethod->addItem(m_methods_map.description(index, true));
124 }
125 cbMethod->setEnabled(cbMethod->count() > 1);
126
127 /* --- set up all controls with their default/startup values --- */
128
129 // pre-record
130 STD_SETUP_SLIDER(pre_record_enabled, pre_record_time, RecordPre)
131 connect(chkRecordPre, SIGNAL(toggled(bool)),
132 this, SLOT(preRecordingChecked(bool)));
133 connect(sbRecordPre, SIGNAL(valueChanged(int)),
134 this, SLOT(preRecordingTimeChanged(int)));
135
136 // record time (duration)
137 STD_SETUP(record_time_limited, record_time, RecordTime)
138
139 // start time (date & time)
140 chkRecordStartTime->setChecked(m_params.start_time_enabled);
141 startTime->setDateTime(m_params.start_time);
142
143 // record trigger
144 STD_SETUP_SLIDER(record_trigger_enabled, record_trigger, RecordTrigger)
145
146 // amplification
147 STD_SETUP_SLIDER(amplification_enabled, amplification, LevelAmplify)
148
149 // AGC
150 STD_SETUP_SLIDER(agc_enabled, agc_decay, LevelAGC)
151
152 // fade in
153 STD_SETUP(fade_in_enabled, fade_in_time, LevelFadeIn)
154
155 // fade out
156 STD_SETUP(fade_out_enabled, fade_out_time, LevelFadeOut)
157
158 // sample rate, bits per sample, track
159 // -> will be initialized later, by the plugin
160
161 // number of buffers
162 slSourceBufferCount->setValue(m_params.buffer_count);
163
164 // power of buffer size
165 slSourceBufferSize->setValue(m_params.buffer_size);
166 sourceBufferSizeChanged(m_params.buffer_size);
167
168 // after this point all controls have their initial values
169
170 /* --- connect some missing low level GUI functionality --- */
171
172 connect(cbMethod, SIGNAL(activated(int)),
173 this, SLOT(methodSelected(int)));
174
175 // record buffer size and count
176 slSourceBufferCount->setValue(m_params.buffer_count);
177 slSourceBufferSize->setValue(m_params.buffer_size);
178 connect(slSourceBufferSize, SIGNAL(valueChanged(int)),
179 this, SLOT(sourceBufferSizeChanged(int)));
180 connect(slSourceBufferCount, SIGNAL(valueChanged(int)),
181 this, SLOT(sourceBufferCountChanged(int)));
182
183 // device treeview
184 connect(listDevices,
185 SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
186 SLOT(listEntrySelected(QTreeWidgetItem*,QTreeWidgetItem*)));
187 connect(listDevices, SIGNAL(itemExpanded(QTreeWidgetItem*)),
188 SLOT(listItemExpanded(QTreeWidgetItem*)));
189 connect(listDevices, SIGNAL(focusLost()),
190 SLOT(updateListSelection()));
191
192 // "select device..." button
193 connect(btSourceSelect, SIGNAL(clicked()),
194 this, SLOT(selectRecordDevice()));
195 connect(cbDevice, SIGNAL(activated(QString)),
196 this, SLOT(setDevice(QString)));
197
198 // setup controls
199 connect(chkRecordTime, SIGNAL(toggled(bool)),
200 this, SLOT(recordTimeChecked(bool)));
201 connect(sbRecordTime, SIGNAL(valueChanged(int)),
202 this, SLOT(recordTimeChanged(int)));
203
204 connect(chkRecordStartTime, SIGNAL(toggled(bool)),
205 this, SLOT(startTimeChecked(bool)));
206 connect(startTime, SIGNAL(dateTimeChanged(QDateTime)),
207 this, SLOT(startTimeChanged(QDateTime)));
208
209 connect(chkRecordTrigger, SIGNAL(toggled(bool)),
210 this, SLOT(triggerChecked(bool)));
211 connect(sbRecordTrigger, SIGNAL(valueChanged(int)),
212 this, SLOT(triggerChanged(int)));
213
214 connect(cbFormatSampleRate, SIGNAL(editTextChanged(QString)),
215 this, SLOT(sampleRateChanged(QString)));
216 connect(cbFormatSampleRate, SIGNAL(activated(QString)),
217 this, SLOT(sampleRateChanged(QString)));
218
219 connect(sbFormatTracks, SIGNAL(valueChanged(int)),
220 this, SLOT(tracksChanged(int)));
221
222 connect(cbFormatCompression, SIGNAL(activated(int)),
223 this, SLOT(compressionChanged(int)));
224
225 connect(sbFormatResolution, SIGNAL(valueChanged(int)),
226 this, SLOT(bitsPerSampleChanged(int)));
227
228 connect(cbFormatSampleFormat, SIGNAL(activated(int)),
229 this, SLOT(sampleFormatChanged(int)));
230
231 // connect the buttons to the record controller
232 connect(btNew, SIGNAL(clicked()),
233 controller, SLOT(actionReset()));
234 connect(btStop, SIGNAL(clicked()),
235 controller, SLOT(actionStop()));
236 connect(btPause, SIGNAL(clicked()),
237 controller, SLOT(actionPause()));
238 connect(btRecord, SIGNAL(clicked()),
239 controller, SLOT(actionStart()));
240
241 // stop recording when the window gets closed
242 connect(this, SIGNAL(rejected()), controller, SLOT(actionStop()));
243 connect(this, SIGNAL(accepted()), controller, SLOT(actionStop()));
244
245 // connect the notifications/commands of the record controller
246 connect(controller, SIGNAL(stateChanged(Kwave::RecordState)),
247 this, SLOT(setState(Kwave::RecordState)));
248
249 // timer for updating the buffer progress bar
250 connect(&m_buffer_progress_timer, SIGNAL(timeout()),
251 this, SLOT(updateBufferProgressBar()));
252
253 // help button
254 connect(buttonBox->button(QDialogButtonBox::Help), SIGNAL(clicked()),
255 this, SLOT(invokeHelp()));
256
257 // status bar
258 m_state_icon_widget = new(std::nothrow) Kwave::StatusWidget(this);
259 Q_ASSERT(m_state_icon_widget);
260 if (!m_state_icon_widget) return;
261
262 m_state_icon_widget->setFixedSize(16, 16);
263 lbl_state->addWidget(m_state_icon_widget);
264
265 m_status_bar.m_state = new(std::nothrow) QLabel(_(" "));
266 Q_ASSERT(m_status_bar.m_state);
267 if (!m_status_bar.m_state) return;
268 m_status_bar.m_state->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
269 lbl_state->addWidget(m_status_bar.m_state);
270
271 m_status_bar.m_time = new(std::nothrow) QLabel(_(" "));
272 Q_ASSERT(m_status_bar.m_time);
273 if (!m_status_bar.m_time) return;
274 m_status_bar.m_time->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
275 lbl_state->addWidget(m_status_bar.m_time);
276
277 m_status_bar.m_sample_rate = new(std::nothrow) QLabel(_(" "));
278 Q_ASSERT(m_status_bar.m_sample_rate);
279 if (!m_status_bar.m_sample_rate) return;
280 m_status_bar.m_sample_rate->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
281 lbl_state->addWidget(m_status_bar.m_sample_rate);
282
283 m_status_bar.m_bits_per_sample = new(std::nothrow) QLabel(_(" "));
284 Q_ASSERT(m_status_bar.m_bits_per_sample);
285 if (!m_status_bar.m_bits_per_sample) return;
286 m_status_bar.m_bits_per_sample->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
287 lbl_state->addWidget(m_status_bar.m_bits_per_sample);
288
289 m_status_bar.m_tracks = new(std::nothrow) QLabel(_(" "));
290 Q_ASSERT(m_status_bar.m_tracks);
291 if (!m_status_bar.m_tracks) return;
292 m_status_bar.m_tracks->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
293 lbl_state->addWidget(m_status_bar.m_tracks);
294
295 m_state_icon_widget->setFixedSize(16, lbl_state->childrenRect().height());
296
297 // set the initial state of the dialog to "Reset/Empty"
298 setState(Kwave::REC_EMPTY);
299
300 // disable the "level" tab, it is not implemented yet
301 tabRecord->setCurrentIndex(1);
302 QWidget *page = tabRecord->currentWidget();
303 tabRecord->setCurrentIndex(0);
304 if (page) delete page;
305
306 // add the "Done" button manually, otherwise it would have "Cancel" semantic
307 QPushButton *bt_done =
308 buttonBox->addButton(i18n("&Done"), QDialogButtonBox::AcceptRole);
309 Q_ASSERT(bt_done);
310 if (!bt_done) return;
311 connect(bt_done, SIGNAL(clicked(bool)), this, SLOT(accept()));
312
313 switch (mode)
314 {
315 case Kwave::RecordDialog::SETTINGS_FORMAT:
316 tabRecord->setCurrentIndex(1);
317 break;
318 case Kwave::RecordDialog::SETTINGS_SOURCE:
319 tabRecord->setCurrentIndex(2);
320 break;
321 case Kwave::RecordDialog::START_RECORDING: /* FALLTHROUGH */
322 case Kwave::RecordDialog::SETTINGS_DEFAULT: /* FALLTHROUGH */
323 default:
324 tabRecord->setCurrentIndex(0);
325 // set the focus onto the "Record" button
326 btRecord->setFocus();
327 break;
328 }
329 }
330
331 //***************************************************************************
~RecordDialog()332 Kwave::RecordDialog::~RecordDialog()
333 {
334 updateBufferState(0,0);
335 }
336
337 //***************************************************************************
params()338 Kwave::RecordParams &Kwave::RecordDialog::params()
339 {
340 return m_params;
341 }
342
343 //***************************************************************************
setMethod(Kwave::record_method_t method)344 void Kwave::RecordDialog::setMethod(Kwave::record_method_t method)
345 {
346 m_params.method = method;
347 cbMethod->setCurrentIndex(m_methods_map.findFromData(
348 m_params.method));
349 }
350
351 //***************************************************************************
methodSelected(int index)352 void Kwave::RecordDialog::methodSelected(int index)
353 {
354 Kwave::record_method_t method = m_methods_map.data(index);
355 // qDebug("RecordDialog::methodSelected(%d) - %d", index, (int)method);
356
357 Q_ASSERT(method > Kwave::RECORD_NONE);
358 Q_ASSERT(method < Kwave::RECORD_INVALID);
359 if (method <= Kwave::RECORD_NONE) return;
360 if (method >= Kwave::RECORD_INVALID) return;
361
362 if (method != m_params.method) {
363 setMethod(method);
364 emit sigMethodChanged(method);
365 }
366 }
367
368 //***************************************************************************
setSupportedDevices(QStringList devices)369 void Kwave::RecordDialog::setSupportedDevices(QStringList devices)
370 {
371 // qDebug("RecordDialog::setSupportedDevices(QStringList devices)");
372 Q_ASSERT(cbDevice);
373 Q_ASSERT(listDevices);
374 if (!cbDevice || !listDevices) return;
375 QString current_device = m_params.device_name;
376
377 // disable all that noisy stuff that comes from modifying the
378 // device controls...
379 m_enable_setDevice = false;
380
381 KIconLoader *icon_loader = KIconLoader::global();
382
383 cbDevice->clearEditText();
384 cbDevice->clear();
385 listDevices->clear();
386
387 if (devices.contains(_("#EDIT#"))) {
388 devices.removeAll(_("#EDIT#"));
389 cbDevice->setEditable(true);
390 } else {
391 cbDevice->setEditable(false);
392 }
393
394 if (devices.contains(_("#SELECT#"))) {
395 devices.removeAll(_("#SELECT#"));
396 btSourceSelect->setEnabled(true);
397 btSourceSelect->show();
398 } else {
399 btSourceSelect->setEnabled(false);
400 btSourceSelect->hide();
401 }
402
403 if (devices.contains(_("#TREE#"))) {
404 // treeview mode
405 devices.removeAll(_("#TREE#"));
406 listDevices->setEnabled(true);
407 cbDevice->setEnabled(false);
408 cbDevice->hide();
409 m_devices_list_map.clear();
410
411 // build a tree with all nodes in the list
412 foreach (QString dev_id, devices) {
413 QTreeWidgetItem *parent = Q_NULLPTR;
414
415 QStringList list = dev_id.split(_("||"), Qt::KeepEmptyParts);
416 foreach (QString token, list) {
417 QTreeWidgetItem *item = Q_NULLPTR;
418
419 // split the icon name from the token
420 QString icon_name;
421 int pos = token.indexOf(QLatin1Char('|'));
422 if (pos > 0) {
423 icon_name = token.mid(pos+1);
424 token = token.left(pos);
425 }
426
427 // find the first item with the same text
428 // and the same root
429 if (parent) {
430 for (int i = 0; i < parent->childCount(); i++) {
431 QTreeWidgetItem *node = parent->child(i);
432 if (node && node->text(0) == token) {
433 item = node;
434 break;
435 }
436 }
437 } else {
438 QList<QTreeWidgetItem *> matches =
439 listDevices->findItems(token, Qt::MatchExactly);
440 if (matches.count())
441 item = matches.takeFirst();
442 }
443
444 if (item) {
445 // already in the list
446 parent = item;
447 } else if (parent) {
448 // new leaf, add to the parent
449 item = new(std::nothrow) QTreeWidgetItem(parent);
450 Q_ASSERT(item);
451 if (item) {
452 item->setText(0, token);
453 m_devices_list_map.insert(item, dev_id);
454 }
455
456 parent->setExpanded(true);
457 parent->setFlags(parent->flags() &
458 ~(Qt::ItemIsUserCheckable | Qt::ItemIsSelectable));
459 if (m_devices_list_map.contains(parent)) {
460 // make the parent not selectable
461 m_devices_list_map.remove(parent);
462 }
463 } else {
464 // new root node
465 item = new(std::nothrow) QTreeWidgetItem(listDevices);
466 Q_ASSERT(item);
467 if (item) {
468 item->setText(0, token);
469 m_devices_list_map.insert(item, dev_id);
470 }
471 }
472
473 if (item && icon_name.length() && icon_loader) {
474 QIcon icon = icon_loader->loadIcon(
475 icon_name, KIconLoader::User);
476 item->setIcon(0, icon);
477 }
478
479 // use the current item as parent for the next pass
480 parent = item;
481 }
482 }
483 } else {
484 // combo box mode
485 cbDevice->addItems(devices);
486 cbDevice->show();
487 listDevices->setEnabled(false);
488
489 if (devices.contains(current_device)) {
490 // current device is in the list
491 cbDevice->setCurrentIndex(cbDevice->findText(current_device));
492 } else {
493 if (cbDevice->isEditable() && current_device.length()) {
494 // user defined device name
495 cbDevice->setEditText(current_device);
496 } else if (devices.count()) {
497 // one or more other possibilities -> take the first one
498 cbDevice->setCurrentIndex(0);
499 } else {
500 // empty list of possibilities
501 cbDevice->clearEditText();
502 cbDevice->clear();
503 }
504 }
505 cbDevice->setEnabled(devices.count() > 1);
506 }
507
508 // enable changes in the device controls again
509 m_enable_setDevice = true;
510 }
511
512 //***************************************************************************
listEntrySelected(QTreeWidgetItem * current,QTreeWidgetItem * previous)513 void Kwave::RecordDialog::listEntrySelected(QTreeWidgetItem *current,
514 QTreeWidgetItem *previous)
515 {
516 Q_ASSERT(listDevices);
517 Q_UNUSED(previous)
518 if (!current || !listDevices) return;
519
520 if (m_devices_list_map.contains(current))
521 setDevice(m_devices_list_map[current]);
522 }
523
524 //***************************************************************************
listItemExpanded(QTreeWidgetItem * item)525 void Kwave::RecordDialog::listItemExpanded(QTreeWidgetItem *item)
526 {
527 Q_UNUSED(item)
528 updateListSelection();
529 }
530
531 //***************************************************************************
updateListSelection()532 void Kwave::RecordDialog::updateListSelection()
533 {
534 // set the current device again, otherwise nothing will be selected
535 setDevice(m_params.device_name);
536 }
537
538 //***************************************************************************
setDevice(const QString & device)539 void Kwave::RecordDialog::setDevice(const QString &device)
540 {
541 Q_ASSERT(cbDevice);
542 Q_ASSERT(listDevices);
543 if (!cbDevice || !listDevices) return;
544
545 bool device_changed = (device != m_params.device_name);
546 m_params.device_name = device;
547 // qDebug("RecordDialog::setDevice(%s)", device.local8Bit().data());
548
549 if (listDevices->isEnabled()) {
550 // treeview mode
551 QTreeWidgetItem *node = m_devices_list_map.key(device, Q_NULLPTR);
552 if (node) {
553 node->setSelected(true);
554 listDevices->scrollToItem(node);
555 listDevices->setCurrentItem(node);
556 }
557 } else if (cbDevice->isEditable() && device.length()) {
558 // user defined device name
559 if (!device.isEmpty() && (cbDevice->currentText() != device)) {
560 cbDevice->setCurrentIndex(cbDevice->findText(device));
561 cbDevice->setEditText(device);
562 }
563 } else {
564 // just take one from the list
565 if (cbDevice->findText(device) >= 0) {
566 cbDevice->setCurrentIndex(cbDevice->findText(device));
567 } else if (cbDevice->count()) {
568 cbDevice->setCurrentIndex(0);
569 }
570 }
571
572 if (device_changed) emit sigDeviceChanged(device);
573 }
574
575 //***************************************************************************
sourceBufferCountChanged(int value)576 void Kwave::RecordDialog::sourceBufferCountChanged(int value)
577 {
578 Q_ASSERT(value >= 4);
579 Q_ASSERT(value <= 64);
580 if (value < 4) value = 4;
581 if (value > 64) value = 64;
582
583 // take the value into our struct
584 m_params.buffer_count = value;
585 emit sigBuffersChanged();
586 }
587
588 //***************************************************************************
sourceBufferSizeChanged(int value)589 void Kwave::RecordDialog::sourceBufferSizeChanged(int value)
590 {
591 Q_ASSERT(value >= 10);
592 Q_ASSERT(value <= 18);
593 if (value < 10) value = 10;
594 if (value > 18) value = 18;
595
596 // take the value into our struct
597 m_params.buffer_size = value;
598
599 // update the text
600 unsigned int buffer_size = (1 << value);
601 txtSourceBuffer->setText(i18n("%1 samples", buffer_size));
602
603 emit sigBuffersChanged();
604 }
605
606 //***************************************************************************
setFileFilter(const QString & filter)607 void Kwave::RecordDialog::setFileFilter(const QString &filter)
608 {
609 m_file_filter = filter;
610 if (btSourceSelect) btSourceSelect->setEnabled(m_file_filter.length());
611 }
612
613 //***************************************************************************
selectRecordDevice()614 void Kwave::RecordDialog::selectRecordDevice()
615 {
616 if (!m_enable_setDevice) return;
617
618 QString filter;
619 filter += _("dsp*|") + i18n("OSS record device (dsp*)");
620 filter += _("\nadsp*|") + i18n("ALSA record device (adsp*)");
621 filter += _("\n*|") + i18n("Any device (*)");
622
623 QPointer<Kwave::FileDialog> dlg = new(std::nothrow) Kwave::FileDialog(
624 _("kfiledialog:///kwave_record_device"),
625 Kwave::FileDialog::OpenFile, filter, this,
626 QUrl(_("file:/dev"))
627 );
628 if (!dlg) return;
629 dlg->setWindowTitle(i18n("Select Record Device"));
630 if (!m_params.device_name.startsWith(_("#")))
631 dlg->selectUrl(QUrl(_("file:") + m_params.device_name));
632 else
633 dlg->selectUrl(QUrl(_("file:/dev/*")));
634 if ((dlg->exec() == QDialog::Accepted) && dlg) {
635 // selected new device
636 QString new_device = dlg->selectedUrl().path();
637 if (new_device != m_params.device_name)
638 emit sigDeviceChanged(new_device);
639 }
640 delete dlg;
641 }
642
643 //***************************************************************************
rate2string(double rate) const644 QString Kwave::RecordDialog::rate2string(double rate) const
645 {
646 QLocale locale;
647 const QString dot = locale.decimalPoint();
648 const QString tsep = locale.groupSeparator();
649
650 // format number with 3 digits
651 QString s = locale.toString(rate, 'f', 3);
652
653 // remove thousands separator (looks ugly)
654 s.remove(tsep);
655
656 // remove trailing zeroes
657 while (s.endsWith(_("0"))) s.remove(s.length()-1, 1);
658
659 // remove decimal point if necessary
660 if (s.endsWith(dot)) s.remove(s.length()-1, 1);
661
662 return s;
663 }
664
665 //***************************************************************************
string2rate(const QString & rate) const666 double Kwave::RecordDialog::string2rate(const QString &rate) const
667 {
668 QLocale locale;
669 const QString s = rate;
670 double r;
671 bool ok;
672 r = locale.toDouble(rate, &ok);
673 Q_ASSERT(ok);
674 if (!ok) return s.toDouble();
675
676 return r;
677 }
678
679 //***************************************************************************
setSupportedTracks(unsigned int min,unsigned int max)680 void Kwave::RecordDialog::setSupportedTracks(unsigned int min,
681 unsigned int max)
682 {
683 Q_ASSERT(sbFormatTracks);
684 if (!sbFormatTracks) return;
685
686 if ((min == max) || (!max)) {
687 sbFormatTracks->setEnabled(false);
688 return;
689 } else
690 sbFormatTracks->setEnabled(true);
691
692 if (sbFormatTracks->value() < sbFormatTracks->minimum()) {
693 sbFormatTracks->setMaximum(max);
694 sbFormatTracks->setMinimum(min);
695 } else {
696 sbFormatTracks->setMinimum(min);
697 sbFormatTracks->setMaximum(max);
698 }
699
700 }
701
702 //***************************************************************************
setTracks(unsigned int tracks)703 void Kwave::RecordDialog::setTracks(unsigned int tracks)
704 {
705 // qDebug("+++ RecordDialog::setTracks(%u)", tracks);
706 Q_ASSERT(sbFormatTracks);
707 Q_ASSERT(m_status_bar.m_tracks);
708 if (!sbFormatTracks || !m_status_bar.m_tracks) return;
709 if (!tracks) return;
710
711 m_params.tracks = tracks;
712 QString tracks_str;
713
714 switch (tracks) {
715 case 1:
716 tracks_str = i18n("Mono");
717 break;
718 case 2:
719 tracks_str = i18n("Stereo");
720 break;
721 case 4:
722 tracks_str = i18n("Quadro");
723 break;
724 default:
725 tracks_str = _("");
726 }
727
728 if (tracks_str.length()) {
729 lblTracksVerbose->setText(_("(") + tracks_str + _(")"));
730 m_status_bar.m_tracks->setText(tracks_str);
731 } else {
732 lblTracksVerbose->setText(_(""));
733 m_status_bar.m_tracks->setText(i18n("%1 tracks", tracks));
734 }
735
736 sbFormatTracks->setValue(tracks);
737 }
738
739 //***************************************************************************
tracksChanged(int tracks)740 void Kwave::RecordDialog::tracksChanged(int tracks)
741 {
742 if (tracks < 1) return; // no device
743 if (tracks == Kwave::toInt(m_params.tracks)) return;
744
745 m_params.tracks = tracks;
746 emit sigTracksChanged(tracks);
747 }
748
749 //***************************************************************************
setSupportedSampleRates(const QList<double> & rates)750 void Kwave::RecordDialog::setSupportedSampleRates(const QList<double> &rates)
751 {
752 Q_ASSERT(cbFormatSampleRate);
753 if (!cbFormatSampleRate) return;
754
755 cbFormatSampleRate->clearEditText();
756 cbFormatSampleRate->setEditable(false);
757 cbFormatSampleRate->clear();
758
759 foreach (double r, rates) {
760 QString rate = rate2string(r);
761 Q_ASSERT(rate.length());
762 if (!rate.length()) continue; // string was zero?
763 cbFormatSampleRate->addItem(rate);
764 }
765
766 bool have_choice = (cbFormatSampleRate->count() > 1);
767 cbFormatSampleRate->setEnabled(have_choice);
768 }
769
770 //***************************************************************************
setSampleRate(double new_rate)771 void Kwave::RecordDialog::setSampleRate(double new_rate)
772 {
773 Q_ASSERT(cbFormatSampleRate);
774 Q_ASSERT(m_status_bar.m_sample_rate);
775 if (!cbFormatSampleRate || !m_status_bar.m_sample_rate) return;
776
777 if (new_rate <= 0) {
778 cbFormatSampleRate->setEnabled(false);
779 return;
780 } else {
781 bool have_choice = (cbFormatSampleRate->count() > 1);
782 cbFormatSampleRate->setEnabled(have_choice);
783 m_params.sample_rate = new_rate;
784 }
785
786 QString rate;
787 rate = rate2string(new_rate);
788 cbFormatSampleRate->setCurrentItem(rate, true);
789 m_status_bar.m_sample_rate->setText(i18n("%1 Hz", rate));
790 }
791
792 //***************************************************************************
sampleRateChanged(const QString & rate)793 void Kwave::RecordDialog::sampleRateChanged(const QString &rate)
794 {
795 if (!rate.length()) return; // no rate selected, combo box clear
796 double sample_rate = string2rate(rate);
797 if (qFuzzyCompare(sample_rate, m_params.sample_rate)) return;
798
799 m_params.sample_rate = sample_rate;
800 emit sampleRateChanged(sample_rate);
801 }
802
803 //***************************************************************************
setSupportedCompressions(const QList<Kwave::Compression::Type> & comps)804 void Kwave::RecordDialog::setSupportedCompressions(
805 const QList<Kwave::Compression::Type> &comps
806 )
807 {
808 Q_ASSERT(cbFormatCompression);
809 if (!cbFormatCompression) return;
810
811 cbFormatCompression->clear();
812
813 if (comps.isEmpty()) {
814 // no compressions -> add "none" manually
815 const Kwave::Compression comp(Kwave::Compression::NONE);
816 cbFormatCompression->addItem(comp.name());
817 } else {
818 foreach (Kwave::Compression::Type c, comps) {
819 const Kwave::Compression comp(c);
820 cbFormatCompression->addItem(comp.name(), comp.toInt());
821 }
822 }
823
824 bool have_choice = (cbFormatCompression->count() > 1);
825 cbFormatCompression->setEnabled(have_choice);
826 }
827
828 //***************************************************************************
setCompression(int compression)829 void Kwave::RecordDialog::setCompression(int compression)
830 {
831 Q_ASSERT(cbFormatCompression);
832 if (!cbFormatCompression) return;
833
834 if (compression < 0) {
835 cbFormatCompression->setEnabled(false);
836 return;
837 } else {
838 bool have_choice = (cbFormatCompression->count() > 1);
839 cbFormatCompression->setEnabled(have_choice);
840 m_params.compression = Kwave::Compression::fromInt(compression);
841 }
842
843 const Kwave::Compression comp(Kwave::Compression::fromInt(compression));
844 cbFormatCompression->setCurrentItem(comp.name(), true);
845 }
846
847 //***************************************************************************
compressionChanged(int index)848 void Kwave::RecordDialog::compressionChanged(int index)
849 {
850 Kwave::Compression::Type compression = Kwave::Compression::fromInt(
851 cbFormatCompression->itemData(index).toInt());
852 if (compression != m_params.compression)
853 emit sigCompressionChanged(compression);
854 }
855
856 //***************************************************************************
setSupportedBits(const QList<unsigned int> & bits)857 void Kwave::RecordDialog::setSupportedBits(const QList<unsigned int> &bits)
858 {
859 Q_ASSERT(sbFormatResolution);
860 if (!sbFormatResolution) return;
861
862 m_supported_resolutions = bits;
863 if (bits.count()) {
864 sbFormatResolution->setMinimum(bits.first());
865 sbFormatResolution->setMaximum(bits.last());
866 }
867
868 // enable only if there is a choice
869 sbFormatResolution->setEnabled(bits.count() > 1);
870 }
871
872 //***************************************************************************
setBitsPerSample(unsigned int bits)873 void Kwave::RecordDialog::setBitsPerSample(unsigned int bits)
874 {
875 Q_ASSERT(sbFormatResolution);
876 Q_ASSERT(m_status_bar.m_bits_per_sample);
877 if (!sbFormatResolution || !m_status_bar.m_bits_per_sample) return;
878
879 if (!bits ) {
880 sbFormatResolution->setEnabled(false);
881 return;
882 } else {
883 sbFormatResolution->setEnabled(m_supported_resolutions.count() > 1);
884 m_params.bits_per_sample = bits;
885 }
886
887 m_status_bar.m_bits_per_sample->setText(i18n("%1 bit", bits));
888 sbFormatResolution->setValue(bits);
889 }
890
891 //***************************************************************************
bitsPerSampleChanged(int bits)892 void Kwave::RecordDialog::bitsPerSampleChanged(int bits)
893 {
894 if (bits < 1) return; // no device
895 int last = m_params.bits_per_sample;
896 if (bits == last) return;
897
898 // round up or down to the next supported resolution in bits per sample
899 if (!m_supported_resolutions.isEmpty()) {
900 if (bits > last) {
901 // step up to the next supported value
902 QListIterator<unsigned int> it(m_supported_resolutions);
903 while (it.hasNext()) {
904 bits = it.next();
905 if (bits > last) break;
906 }
907 if (bits < last) bits = m_supported_resolutions.last();
908 } else {
909 // step down to the next supported value
910 QListIterator<unsigned int> it(m_supported_resolutions);
911 it.toBack();
912 while (it.hasPrevious()) {
913 bits = it.previous();
914 if (bits < last) break;
915 }
916 if (bits > last) bits = m_supported_resolutions.first();
917 }
918 }
919
920 m_params.bits_per_sample = bits;
921
922 if (sbFormatResolution && (bits != sbFormatResolution->value()))
923 sbFormatResolution->setValue(bits);
924
925 emit sigBitsPerSampleChanged(bits);
926 }
927
928 //***************************************************************************
setSupportedSampleFormats(const QList<Kwave::SampleFormat::Format> & formats)929 void Kwave::RecordDialog::setSupportedSampleFormats(
930 const QList<Kwave::SampleFormat::Format> &formats)
931 {
932 Q_ASSERT(cbFormatSampleFormat);
933 if (!cbFormatSampleFormat) return;
934
935 cbFormatSampleFormat->clear();
936 Kwave::SampleFormat::Map types;
937 foreach (Kwave::SampleFormat::Format format, formats) {
938 int index = types.findFromData(format);
939 cbFormatSampleFormat->addItem(
940 types.description(index, true),
941 Kwave::SampleFormat(format).toInt()
942 );
943 }
944
945 bool have_choice = (cbFormatSampleFormat->count() > 1);
946 cbFormatSampleFormat->setEnabled(have_choice);
947 }
948
949 //***************************************************************************
setSampleFormat(Kwave::SampleFormat::Format sample_format)950 void Kwave::RecordDialog::setSampleFormat(
951 Kwave::SampleFormat::Format sample_format)
952 {
953 Q_ASSERT(cbFormatSampleFormat);
954 if (!cbFormatSampleFormat) return;
955
956 if (sample_format == Kwave::SampleFormat::Unknown) {
957 cbFormatSampleFormat->setEnabled(false);
958 return;
959 } else {
960 bool have_choice = (cbFormatSampleFormat->count() > 1);
961 cbFormatSampleFormat->setEnabled(have_choice);
962 m_params.sample_format = sample_format;
963 }
964
965 int cb_index = cbFormatSampleFormat->findData(
966 Kwave::SampleFormat(sample_format).toInt());
967 cbFormatSampleFormat->setCurrentIndex(cb_index);
968 }
969
970 //***************************************************************************
sampleFormatChanged(int index)971 void Kwave::RecordDialog::sampleFormatChanged(int index)
972 {
973 Q_ASSERT(cbFormatSampleFormat);
974 if (!cbFormatSampleFormat) return;
975
976 Kwave::SampleFormat format;
977 format.fromInt(cbFormatSampleFormat->itemData(index).toInt());
978
979 if (format == m_params.sample_format) return;
980
981 emit sigSampleFormatChanged(format);
982 }
983
984 //***************************************************************************
setState(Kwave::RecordState state)985 void Kwave::RecordDialog::setState(Kwave::RecordState state)
986 {
987 Q_ASSERT(m_status_bar.m_state);
988 if (!m_status_bar.m_state) return;
989
990 bool enable_new = false;
991 bool enable_pause = false;
992 bool enable_stop = false;
993 bool enable_record = false;
994 bool enable_settings = false;
995 bool enable_trigger = false;
996 QString state_text = _("");
997 QVector<QPixmap> pixmaps;
998 unsigned int animation_time = 500;
999
1000 m_state = state;
1001 switch (state) {
1002 case Kwave::REC_UNINITIALIZED:
1003 state_text = i18n("Please check the source device settings...");
1004 enable_new = true;
1005 enable_pause = false;
1006 enable_stop = false;
1007 enable_record = false;
1008 enable_settings = true;
1009 enable_trigger = true;
1010 pixmaps.push_back(QPixmap(stop_hand_xpm));
1011 pixmaps.push_back(QPixmap(ledred_xpm));
1012 m_status_bar.m_time->setText(_(""));
1013 break;
1014 case Kwave::REC_EMPTY:
1015 state_text = i18n("(empty)");
1016 enable_new = true;
1017 enable_pause = false;
1018 enable_stop = false;
1019 enable_record = m_params.device_name.length();
1020 enable_settings = true;
1021 enable_trigger = true;
1022 pixmaps.push_back(QPixmap(ledgreen_xpm));
1023 m_status_bar.m_time->setText(_(""));
1024 break;
1025 case Kwave::REC_BUFFERING:
1026 state_text = i18n("Buffering...");
1027 enable_new = true; /* throw away current FIFO content */
1028 enable_pause = false;
1029 enable_stop = true;
1030 enable_record = true; /* acts as "trigger now" */
1031 enable_settings = false;
1032 enable_trigger = true;
1033 pixmaps.push_back(QPixmap(ledgreen_xpm));
1034 pixmaps.push_back(QPixmap(ledlightgreen_xpm));
1035 break;
1036 case Kwave::REC_PRERECORDING:
1037 state_text = i18n("Prerecording...");
1038 enable_new = false;
1039 enable_pause = false;
1040 enable_stop = true;
1041 enable_record = true;
1042 enable_settings = false;
1043 enable_trigger = true;
1044 pixmaps.push_back(QPixmap(ledgreen_xpm));
1045 pixmaps.push_back(QPixmap(ledlightgreen_xpm));
1046 break;
1047 case Kwave::REC_WAITING_FOR_TRIGGER:
1048 state_text = i18n("Waiting for trigger...");
1049 enable_new = false;
1050 enable_pause = false;
1051 enable_stop = true;
1052 enable_record = true; /* acts as "trigger now" */
1053 enable_settings = false;
1054 enable_trigger = true;
1055 pixmaps.push_back(QPixmap(ledgreen_xpm));
1056 pixmaps.push_back(QPixmap(ledlightgreen_xpm));
1057 break;
1058 case Kwave::REC_RECORDING:
1059 state_text = i18n("Recording...");
1060 enable_new = false;
1061 enable_pause = true;
1062 enable_stop = true;
1063 enable_record = false;
1064 enable_settings = false;
1065 enable_trigger = false;
1066 pixmaps.push_back(QPixmap(walk_r1_xpm));
1067 pixmaps.push_back(QPixmap(walk_r2_xpm));
1068 pixmaps.push_back(QPixmap(walk_r3_xpm));
1069 pixmaps.push_back(QPixmap(walk_r4_xpm));
1070 pixmaps.push_back(QPixmap(walk_r5_xpm));
1071 pixmaps.push_back(QPixmap(walk_r6_xpm));
1072 pixmaps.push_back(QPixmap(walk_r7_xpm));
1073 pixmaps.push_back(QPixmap(walk_r8_xpm));
1074 animation_time = 100;
1075 break;
1076 case Kwave::REC_PAUSED:
1077 state_text = i18n("Paused");
1078 enable_new = true; /* start again */
1079 enable_pause = true; /* used for "continue" */
1080 enable_stop = true;
1081 enable_record = true; /* used for "continue" */
1082 enable_settings = false;
1083 enable_trigger = false;
1084 pixmaps.push_back(QPixmap(ledgreen_xpm));
1085 pixmaps.push_back(QPixmap(ledyellow_xpm));
1086 break;
1087 case Kwave::REC_DONE:
1088 state_text = i18n("Done");
1089 enable_new = true;
1090 enable_pause = false;
1091 enable_stop = false;
1092 enable_record = true;
1093 enable_settings = true;
1094 enable_trigger = true;
1095 pixmaps.push_back(QPixmap(ok_xpm));
1096 break;
1097 }
1098 m_status_bar.m_state->setText(state_text);
1099 m_state_icon_widget->setPixmaps(pixmaps, animation_time);
1100
1101 // enable/disable the record control buttons
1102 btNew->setEnabled(enable_new);
1103 btPause->setEnabled(enable_pause);
1104 btStop->setEnabled(enable_stop);
1105 m_record_enabled = enable_record;
1106 updateRecordButton();
1107
1108 // enable disable all controls (groups) for setup
1109 chkRecordPre->setEnabled(enable_settings);
1110 sbRecordPre->setEnabled(enable_settings &&
1111 chkRecordPre->isChecked());
1112 slRecordPre->setEnabled(enable_settings &&
1113 chkRecordPre->isChecked());
1114
1115 chkRecordStartTime->setEnabled(enable_settings);
1116 chkRecordTime->setEnabled(enable_settings);
1117 sbRecordTime->setEnabled(enable_settings &&
1118 chkRecordTime->isChecked());
1119 chkRecordTrigger->setEnabled(enable_settings);
1120
1121 // it is not really necessary to disable these ;-)
1122 sbRecordTrigger->setEnabled(enable_trigger &&
1123 chkRecordTrigger->isChecked());
1124 slRecordTrigger->setEnabled(enable_trigger &&
1125 chkRecordTrigger->isChecked());
1126 startTime->setEnabled(enable_settings &&
1127 chkRecordStartTime->isChecked());
1128
1129 grpFormat->setEnabled(enable_settings);
1130 grpSource->setEnabled(enable_settings);
1131
1132 }
1133
1134 //***************************************************************************
updateBufferState(unsigned int count,unsigned int total)1135 void Kwave::RecordDialog::updateBufferState(unsigned int count,
1136 unsigned int total)
1137 {
1138 Q_ASSERT(progress_bar);
1139 Q_ASSERT(m_status_bar.m_state);
1140 if (!progress_bar || !m_status_bar.m_state) return;
1141
1142 if (total == 0) {
1143 // we are done: stop update timer and reset buffer percentage
1144 m_buffer_progress_timer.stop();
1145 m_buffer_progress_count = 0;
1146 m_buffer_progress_total = 0;
1147 progress_bar->setTextVisible(false);
1148 progress_bar->setMinimum(0);
1149 progress_bar->setMaximum(100);
1150 progress_bar->setValue(0);
1151 progress_bar->reset();
1152 } else {
1153 m_buffer_progress_count = count;
1154 m_buffer_progress_total = total;
1155
1156 if (!m_buffer_progress_timer.isActive())
1157 updateBufferProgressBar();
1158 }
1159
1160 // update recording time
1161 QString txt;
1162 switch (m_state) {
1163 case Kwave::REC_UNINITIALIZED:
1164 case Kwave::REC_EMPTY:
1165 case Kwave::REC_BUFFERING:
1166 case Kwave::REC_PRERECORDING:
1167 txt = _("");
1168 break;
1169 case Kwave::REC_WAITING_FOR_TRIGGER: {
1170 txt = _("");
1171 QString state_text;
1172 QDateTime now = QDateTime::currentDateTime();
1173 QDateTime t_start = m_params.start_time;
1174
1175 if (m_params.start_time_enabled && (now < t_start)) {
1176 // waiting for start time to come...
1177
1178 int s = Kwave::toInt(now.secsTo(t_start));
1179 int m = s / 60;
1180 s %= 60;
1181 int h = m / 60;
1182 m %= 60;
1183 int d = h / 24;
1184 h %= 24;
1185
1186 QString days = (d) ?
1187 i18np("one day ", "%1 days ", d) : _("");
1188 QString hours = (h) ?
1189 i18np("one hour ", "%1 hours ", h) : _("");
1190 QString minutes = (m) ?
1191 i18np("one minute ", "%1 minutes ", m) : _("");
1192 QString seconds =
1193 (d | h | m) ?
1194 i18np("and %1 second", "and %1 seconds", s) :
1195 i18np("%1 second", "%1 seconds", s);
1196
1197 state_text = i18nc(
1198 "%1=days; %2=hours; %3=minutes; %4=seconds",
1199 "Waiting for start in %1%2%3%4...",
1200 days, hours, minutes, seconds);
1201 } else {
1202 // waiting for trigger...
1203 state_text = i18n("Waiting for trigger...");
1204 }
1205 m_status_bar.m_state->setText(state_text);
1206
1207 break;
1208 }
1209 case Kwave::REC_RECORDING:
1210 case Kwave::REC_PAUSED:
1211 case Kwave::REC_DONE: {
1212 if (m_samples_recorded > 1) {
1213 double rate = m_params.sample_rate;
1214 double ms = (rate > 0) ?
1215 ((static_cast<double>(m_samples_recorded) / rate) * 1E3)
1216 : 0;
1217 txt = _(" ") +
1218 i18n("Length: %1", Kwave::ms2string(ms)) +
1219 _(" ") + i18n("(%1 samples)",
1220 Kwave::samples2string(m_samples_recorded));
1221 } else txt = _("");
1222 break;
1223 }
1224 }
1225 m_status_bar.m_time->setText(txt);
1226 }
1227
1228 //***************************************************************************
preRecordingChecked(bool enabled)1229 void Kwave::RecordDialog::preRecordingChecked(bool enabled)
1230 {
1231 m_params.pre_record_enabled = enabled;
1232 emit sigPreRecordingChanged(enabled);
1233 }
1234
1235 //***************************************************************************
preRecordingTimeChanged(int time)1236 void Kwave::RecordDialog::preRecordingTimeChanged(int time)
1237 {
1238 m_params.pre_record_time = time;
1239 }
1240
1241 //***************************************************************************
recordTimeChecked(bool limited)1242 void Kwave::RecordDialog::recordTimeChecked(bool limited)
1243 {
1244 m_params.record_time_limited = limited;
1245 emit sigRecordTimeChanged(limited ? sbRecordTime->value() : -1);
1246 }
1247
1248 //***************************************************************************
recordTimeChanged(int limit)1249 void Kwave::RecordDialog::recordTimeChanged(int limit)
1250 {
1251 m_params.record_time = limit;
1252 emit sigRecordTimeChanged(chkRecordTime->isChecked() ?
1253 limit : -1);
1254 updateRecordButton();
1255 }
1256
1257 //***************************************************************************
startTimeChecked(bool enabled)1258 void Kwave::RecordDialog::startTimeChecked(bool enabled)
1259 {
1260 m_params.start_time_enabled = enabled;
1261 emit sigTriggerChanged(enabled || m_params.record_trigger_enabled);
1262 }
1263
1264 //***************************************************************************
startTimeChanged(const QDateTime & datetime)1265 void Kwave::RecordDialog::startTimeChanged(const QDateTime &datetime)
1266 {
1267 m_params.start_time = datetime;
1268
1269 // force seconds to zero
1270 QTime t = m_params.start_time.time();
1271 t.setHMS(t.hour(), t.minute(), 0, 0);
1272 m_params.start_time.setTime(t);
1273 }
1274
1275 //***************************************************************************
triggerChecked(bool enabled)1276 void Kwave::RecordDialog::triggerChecked(bool enabled)
1277 {
1278 m_params.record_trigger_enabled = enabled;
1279 emit sigTriggerChanged(enabled || m_params.start_time_enabled);
1280 }
1281
1282 //***************************************************************************
triggerChanged(int trigger)1283 void Kwave::RecordDialog::triggerChanged(int trigger)
1284 {
1285 m_params.record_trigger = trigger;
1286 }
1287
1288 //***************************************************************************
updateBufferProgressBar()1289 void Kwave::RecordDialog::updateBufferProgressBar()
1290 {
1291 unsigned int count = m_buffer_progress_count;
1292 unsigned int total = m_buffer_progress_total;
1293 // qDebug("RecordDialog::updateBufferProgressBar(): %u/%u",
1294 // count, total);
1295
1296 /*
1297 * @note: QProgressBar has a bug when handling small numbers,
1298 * therefore we multiply everything by 100
1299 */
1300 progress_bar->setTextVisible(true);
1301 progress_bar->setMinimum(0);
1302 progress_bar->setMaximum(100 * total);
1303 progress_bar->setValue(100 * count);
1304
1305 m_buffer_progress_timer.setSingleShot(true);
1306 m_buffer_progress_timer.setInterval(100);
1307 m_buffer_progress_timer.start();
1308 }
1309
1310 //***************************************************************************
updateEffects(unsigned int track,Kwave::SampleArray & buffer)1311 void Kwave::RecordDialog::updateEffects(unsigned int track,
1312 Kwave::SampleArray &buffer)
1313 {
1314 if (!buffer.size()) return;
1315
1316 if (level_meter) {
1317 level_meter->setTracks(m_params.tracks);
1318 level_meter->setSampleRate(m_params.sample_rate);
1319 level_meter->updateTrack(track, buffer);
1320 }
1321
1322 }
1323
1324 //***************************************************************************
setRecordedSamples(sample_index_t samples_recorded)1325 void Kwave::RecordDialog::setRecordedSamples(sample_index_t samples_recorded)
1326 {
1327 // if (!m_params.record_time_limited) return; // not of interest
1328 m_samples_recorded = samples_recorded;
1329 updateRecordButton();
1330 }
1331
1332 //***************************************************************************
updateRecordButton()1333 void Kwave::RecordDialog::updateRecordButton()
1334 {
1335 bool old_enable = btRecord->isEnabled();
1336 bool new_enable;
1337
1338 // enabled if not disabled by status and also not limited or
1339 // less than the limit has been recorded
1340 new_enable = m_record_enabled && (!m_params.record_time_limited ||
1341 (static_cast<double>(m_samples_recorded) <
1342 m_params.record_time * m_params.sample_rate));
1343
1344 if (new_enable != old_enable) btRecord->setEnabled(new_enable);
1345 }
1346
1347 //***************************************************************************
invokeHelp()1348 void Kwave::RecordDialog::invokeHelp()
1349 {
1350 KHelpClient::invokeHelp(_("recording"));
1351 }
1352
1353 //***************************************************************************
message(const QString & message)1354 void Kwave::RecordDialog::message(const QString &message)
1355 {
1356 if (lbl_state) lbl_state->showMessage(message, 3000);
1357 }
1358
1359 //***************************************************************************
showDevicePage()1360 void Kwave::RecordDialog::showDevicePage()
1361 {
1362 if (tabRecord) tabRecord->setCurrentIndex(2);
1363 }
1364
1365 //***************************************************************************
1366 //***************************************************************************
1367