SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
freedvmodgui.cpp
Go to the documentation of this file.
1 // Copyright (C) 2019 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include <QDockWidget>
19 #include <QMainWindow>
20 #include <QFileDialog>
21 #include <QTime>
22 #include <QDebug>
23 
24 #include "freedvmodgui.h"
25 
26 #include "device/deviceuiset.h"
27 #include "dsp/spectrumvis.h"
28 #include "plugin/pluginapi.h"
29 #include "util/simpleserializer.h"
30 #include "util/db.h"
31 #include "dsp/dspengine.h"
32 #include "dsp/dspcommands.h"
33 #include "gui/crightclickenabler.h"
34 #include "gui/audioselectdialog.h"
36 #include "mainwindow.h"
37 #include "ui_freedvmodgui.h"
38 
40 {
41  FreeDVModGUI* gui = new FreeDVModGUI(pluginAPI, deviceUISet, channelTx);
42  return gui;
43 }
44 
46 {
47  delete this;
48 }
49 
50 void FreeDVModGUI::setName(const QString& name)
51 {
52  setObjectName(name);
53 }
54 
55 QString FreeDVModGUI::getName() const
56 {
57  return objectName();
58 }
59 
62 }
63 
64 void FreeDVModGUI::setCenterFrequency(qint64 centerFrequency)
65 {
66  m_channelMarker.setCenterFrequency(centerFrequency);
68  applySettings();
69 }
70 
72 {
74 }
75 
76 QByteArray FreeDVModGUI::serialize() const
77 {
78  return m_settings.serialize();
79 }
80 
81 bool FreeDVModGUI::deserialize(const QByteArray& data)
82 {
83  if(m_settings.deserialize(data))
84  {
85  qDebug("FreeDVModGUI::deserialize");
87  applyBandwidths(5 - ui->spanLog2->value(), true); // does applySettings(true)
88  return true;
89  }
90  else
91  {
94  applyBandwidths(5 - ui->spanLog2->value(), true); // does applySettings(true)
95  return false;
96  }
97 }
98 
100 {
102  {
103  m_recordSampleRate = ((FreeDVMod::MsgReportFileSourceStreamData&)message).getSampleRate();
104  m_recordLength = ((FreeDVMod::MsgReportFileSourceStreamData&)message).getRecordLength();
105  m_samplesCount = 0;
107  return true;
108  }
110  {
111  m_samplesCount = ((FreeDVMod::MsgReportFileSourceStreamTiming&)message).getSamplesCount();
113  return true;
114  }
115  else if (DSPConfigureAudio::match(message))
116  {
117  qDebug("FreeDVModGUI::handleMessage: DSPConfigureAudio: %d", m_freeDVMod->getModemSampleRate());
118  applyBandwidths(5 - ui->spanLog2->value()); // will update spectrum details with new sample rate
119  return true;
120  }
121  else if (FreeDVMod::MsgConfigureFreeDVMod::match(message))
122  {
124  m_settings = cfg.getSettings();
125  blockApplySettings(true);
126  displaySettings();
127  blockApplySettings(false);
128  return true;
129  }
130  else if (CWKeyer::MsgConfigureCWKeyer::match(message))
131  {
133  ui->cwKeyerGUI->setSettings(cfg.getSettings());
134  ui->cwKeyerGUI->displaySettings();
135  return true;
136  }
137  else
138  {
139  return false;
140  }
141 }
142 
144 {
145  ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
147  applySettings();
148 }
149 
151 {
153  displaySettings();
154  applySettings();
155 }
156 
158 {
159  Message* message;
160 
161  while ((message = getInputMessageQueue()->pop()) != 0)
162  {
163  if (handleMessage(*message))
164  {
165  delete message;
166  }
167  }
168 }
169 
171 {
174  applySettings();
175 }
176 
178 {
179  if ((value < 0) || (value > 4)) {
180  return;
181  }
182 
183  applyBandwidths(5 - value);
184 }
185 
187 {
189  applySettings();
190 }
191 
193 {
194  ui->toneFrequencyText->setText(QString("%1k").arg(value / 100.0, 0, 'f', 2));
195  m_settings.m_toneFrequency = value * 10.0;
196  applySettings();
197 }
198 
200 {
201  ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
202  m_settings.m_volumeFactor = value / 10.0;
203  applySettings();
204 }
205 
207 {
208  m_settings.m_audioMute = checked;
209  applySettings();
210 }
211 
213 {
217  applySettings();
218 }
219 
221 {
222  m_settings.m_playLoop = checked;
223  applySettings();
224 }
225 
227 {
228  ui->tone->setEnabled(!checked); // release other source inputs
229  ui->morseKeyer->setEnabled(!checked);
230  ui->mic->setEnabled(!checked);
232  applySettings();
233  ui->navTimeSlider->setEnabled(!checked);
234  m_enableNavTime = !checked;
235 }
236 
238 {
239  ui->play->setEnabled(!checked); // release other source inputs
240  ui->morseKeyer->setEnabled(!checked);
241  ui->mic->setEnabled(!checked);
243  applySettings();
244 }
245 
247 {
248  ui->play->setEnabled(!checked); // release other source inputs
249  ui->tone->setEnabled(!checked); // release other source inputs
250  ui->mic->setEnabled(!checked);
252  applySettings();
253 }
254 
256 {
257  ui->play->setEnabled(!checked); // release other source inputs
258  ui->morseKeyer->setEnabled(!checked);
259  ui->tone->setEnabled(!checked); // release other source inputs
261  applySettings();
262 }
263 
265 {
266  if (m_enableNavTime && ((value >= 0) && (value <= 100)))
267  {
268  int t_sec = (m_recordLength * value) / 100;
269  QTime t(0, 0, 0, 0);
270  t = t.addSecs(t_sec);
271 
274  }
275 }
276 
278 {
279  (void) checked;
280  QString fileName = QFileDialog::getOpenFileName(this,
281  tr("Open raw audio file"), ".", tr("Raw audio Files (*.raw)"), 0, QFileDialog::DontUseNativeDialog);
282 
283  if (fileName != "")
284  {
285  m_fileName = fileName;
286  ui->recordFileText->setText(m_fileName);
287  ui->play->setEnabled(true);
289  }
290 }
291 
293 {
294  qDebug() << "FileSourceGui::configureFileName: " << m_fileName.toStdString().c_str();
297 }
298 
299 void FreeDVModGUI::onWidgetRolled(QWidget* widget, bool rollDown)
300 {
301  (void) widget;
302  (void) rollDown;
303 }
304 
305 void FreeDVModGUI::onMenuDialogCalled(const QPoint &p)
306 {
308  {
315 
316  dialog.move(p);
317  dialog.exec();
318 
327 
328  setWindowTitle(m_settings.m_title);
330 
331  applySettings();
332  }
333 
335 }
336 
337 FreeDVModGUI::FreeDVModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget* parent) :
338  RollupWidget(parent),
339  ui(new Ui::FreeDVModGUI),
340  m_pluginAPI(pluginAPI),
341  m_deviceUISet(deviceUISet),
342  m_channelMarker(this),
343  m_doApplySettings(true),
344  m_spectrumRate(6000),
345  m_recordLength(0),
346  m_recordSampleRate(48000),
347  m_samplesCount(0),
348  m_tickCount(0),
349  m_enableNavTime(false)
350 {
351  ui->setupUi(this);
352  setAttribute(Qt::WA_DeleteOnClose, true);
353  connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
354  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
355 
356  m_spectrumVis = new SpectrumVis(SDR_TX_SCALEF, ui->glSpectrum);
357  m_freeDVMod = (FreeDVMod*) channelTx;
360 
361  resetToDefaults();
362 
363  ui->glSpectrum->setCenterFrequency(m_spectrumRate/2);
364  ui->glSpectrum->setSampleRate(m_spectrumRate);
365  ui->glSpectrum->setDisplayWaterfall(true);
366  ui->glSpectrum->setDisplayMaxHold(true);
367  ui->glSpectrum->setSsbSpectrum(true);
368  ui->glSpectrum->connectTimer(MainWindow::getInstance()->getMasterTimer());
369 
370  connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
371 
372  CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->mic);
373  connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect()));
374 
375  ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
376  ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
377  ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
378 
381 
385 
386  connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
387 
388  ui->cwKeyerGUI->setCWKeyer(m_freeDVMod->getCWKeyer());
389  ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
390 
392  m_settings.setSpectrumGUI(ui->spectrumGUI);
393  m_settings.setCWKeyerGUI(ui->cwKeyerGUI);
394 
395  connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
396  connect(m_freeDVMod, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int)));
397 
398  displaySettings();
399  applyBandwidths(5 - ui->spanLog2->value(), true); // does applySettings(true)
400 }
401 
403 {
405  delete m_freeDVMod; // TODO: check this: when the GUI closes it has to delete the modulator
406  delete m_spectrumVis;
407  delete ui;
408 }
409 
411 {
412  bool ret = !m_doApplySettings;
413  m_doApplySettings = !block;
414  return ret;
415 }
416 
418 {
419  if (m_doApplySettings)
420  {
424 
427  }
428 }
429 
430 void FreeDVModGUI::applyBandwidths(int spanLog2, bool force)
431 {
432  displayBandwidths(spanLog2);
433  m_settings.m_spanLog2 = spanLog2;
434  applySettings(force);
435 }
436 
438 {
439  m_spectrumRate = m_freeDVMod->getModemSampleRate() / (1<<spanLog2);
440  int bwMax = m_freeDVMod->getModemSampleRate() / (100*(1<<spanLog2));
441 
442  qDebug() << "FreeDVModGUI::displayBandwidths:"
443  << " spanLog2: " << spanLog2
444  << " m_spectrumRate: " << m_spectrumRate
445  << " bwMax: " << bwMax;
446 
447  QString spanStr = QString::number(bwMax/10.0, 'f', 1);
448 
449  ui->spanText->setText(tr("%1k").arg(spanStr));
450  ui->glSpectrum->setCenterFrequency(m_spectrumRate/2);
451  ui->glSpectrum->setSampleRate(m_spectrumRate);
452  ui->glSpectrum->setSsbSpectrum(true);
453  ui->glSpectrum->setLsbDisplay(false);
454 }
455 
457 {
458  m_channelMarker.blockSignals(true);
464  m_channelMarker.blockSignals(false);
466 
468  setWindowTitle(m_channelMarker.getTitle());
469 
470  blockApplySettings(true);
471 
472  ui->freeDVMode->setCurrentIndex((int) m_settings.m_freeDVMode);
473  ui->audioMute->setChecked(m_settings.m_audioMute);
474  ui->playLoop->setChecked(m_settings.m_playLoop);
475 
476  // Prevent uncontrolled triggering of applyBandwidths
477  ui->spanLog2->blockSignals(true);
478  ui->spanLog2->setValue(5 - m_settings.m_spanLog2);
480  ui->spanLog2->blockSignals(false);
481 
482  ui->gaugeInput->setChecked(m_settings.m_gaugeInputElseModem);
483 
484  // The only one of the four signals triggering applyBandwidths will trigger it once only with all other values
485  // set correctly and therefore validate the settings and apply them to dependent widgets
486 
487  ui->deltaFrequency->setValue(m_settings.m_inputFrequencyOffset);
488 
489  ui->toneFrequency->setValue(roundf(m_settings.m_toneFrequency / 10.0));
490  ui->toneFrequencyText->setText(QString("%1k").arg(m_settings.m_toneFrequency / 1000.0, 0, 'f', 2));
491 
492  ui->volume->setValue(m_settings.m_volumeFactor * 10.0);
493  ui->volumeText->setText(QString("%1").arg(m_settings.m_volumeFactor, 0, 'f', 1));
494 
495  ui->tone->setEnabled((m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputTone)
496  || (m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputNone));
497  ui->mic->setEnabled((m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputAudio)
498  || (m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputNone));
499  ui->play->setEnabled((m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputFile)
500  || (m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputNone));
501  ui->morseKeyer->setEnabled((m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputCWTone)
502  || (m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputNone));
503 
504  ui->tone->setChecked(m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputTone);
505  ui->mic->setChecked(m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputAudio);
506  ui->play->setChecked(m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputFile);
507  ui->morseKeyer->setChecked(m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputAF::FreeDVModInputCWTone);
508 
509  blockApplySettings(false);
510 }
511 
513 {
515 }
516 
518 {
520 }
521 
523 {
524  qDebug("FreeDVModGUI::audioSelect");
525  AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName, true); // true for input
526  audioSelect.exec();
527 
528  if (audioSelect.m_selected)
529  {
531  applySettings();
532  }
533 }
534 
536 {
537  double powDb = CalcDb::dbPower(m_freeDVMod->getMagSq());
538  m_channelPowerDbAvg(powDb);
539  ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.asDouble(), 0, 'f', 1));
540 
542  {
545  }
546 }
547 
549 {
550  QTime recordLength(0, 0, 0, 0);
551  recordLength = recordLength.addSecs(m_recordLength);
552  QString s_time = recordLength.toString("HH:mm:ss");
553  ui->recordLengthText->setText(s_time);
555 }
556 
558 {
559  int t_sec = 0;
560  int t_msec = 0;
561 
562  if (m_recordSampleRate > 0)
563  {
564  t_msec = ((m_samplesCount * 1000) / m_recordSampleRate) % 1000;
566  }
567 
568  QTime t(0, 0, 0, 0);
569  t = t.addSecs(t_sec);
570  t = t.addMSecs(t_msec);
571  QString s_timems = t.toString("HH:mm:ss.zzz");
572  QString s_time = t.toString("HH:mm:ss");
573  ui->relTimeText->setText(s_timems);
574 
575  if (!m_enableNavTime)
576  {
577  float posRatio = (float) t_sec / (float) m_recordLength;
578  ui->navTimeSlider->setValue((int) (posRatio * 100.0));
579  }
580 }
MovingAverageUtil< double, double, 20 > m_channelPowerDbAvg
Definition: freedvmodgui.h:73
void removeTxChannelInstance(PluginInstanceGUI *pluginGUI)
std::size_t m_tickCount
Definition: freedvmodgui.h:79
void setSpectrumGUI(Serializable *spectrumGUI)
static MainWindow * getInstance()
Definition: mainwindow.h:73
void on_showFileDialog_clicked(bool checked)
const QString & getReverseAPIAddress() const
void on_deltaFrequency_changed(qint64 value)
CWKeyer * getCWKeyer()
Definition: freedvmod.h:257
static MsgConfigureFileSourceSeek * create(int seekPercentage)
Definition: freedvmod.h:129
int getCenterFrequency() const
Definition: channelmarker.h:42
static MsgConfigureFreeDVMod * create(const FreeDVModSettings &settings, bool force)
Definition: freedvmod.h:62
void setLowCutoff(int lowCutoff)
void registerTxChannelInstance(const QString &channelName, PluginInstanceGUI *pluginGUI)
Definition: deviceuiset.cpp:88
void on_play_toggled(bool checked)
void updateWithStreamTime()
uint16_t m_reverseAPIDeviceIndex
void push(Message *message, bool emitSignal=true)
Push message onto queue.
static MsgConfigureFileSourceStreamTiming * create()
Definition: freedvmod.h:148
static double dbPower(double magsq, double floor=1e-12)
Definition: db.cpp:22
void enterEvent(QEvent *)
void applyBandwidths(int spanLog2, bool force=false)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
bool blockApplySettings(bool block)
bool deserialize(const QByteArray &data)
QByteArray serialize() const
int m_samplesCount
Definition: freedvmodgui.h:78
void displayBandwidths(int spanLog2)
static int getLowCutoff(FreeDVMode freeDVMode)
void leaveEvent(QEvent *)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
void onMenuDialogCalled(const QPoint &p)
void setReverseAPIChannelIndex(uint16_t channelIndex)
const FreeDVModSettings & getSettings() const
Definition: freedvmod.h:59
void setSpectrumSampleSink(BasebandSampleSink *sampleSink)
Definition: freedvmod.h:212
void audioSelect()
static FreeDVModGUI * create(PluginAPI *pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx)
virtual ~FreeDVModGUI()
void resetContextMenuType()
Definition: rollupwidget.h:50
void addChannelMarker(ChannelMarker *channelMarker)
Add channel marker to spectrum.
Definition: deviceuiset.cpp:72
void setChannelMarker(Serializable *channelMarker)
void on_tone_toggled(bool checked)
bool m_gaugeInputElseModem
Volume gauge shows speech input level else modem level.
void handleSourceMessages()
static int getHiCutoff(FreeDVMode freeDVMode)
int m_spectrumRate
Definition: freedvmodgui.h:69
virtual bool handleMessage(const Message &message)
void on_mic_toggled(bool checked)
ContextMenuType m_contextMenuType
Definition: rollupwidget.h:33
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
void resetToDefaults()
bool m_doApplySettings
Definition: freedvmodgui.h:68
#define SDR_TX_SCALEF
Definition: dsptypes.h:39
quint32 m_recordLength
Definition: freedvmodgui.h:76
void on_audioMute_toggled(bool checked)
double getMagSq() const
Definition: freedvmod.h:253
QByteArray serialize() const
void setSourceOrSinkStream(bool sourceOrSinkStream)
Definition: channelmarker.h:75
static DSPEngine * instance()
Definition: dspengine.cpp:51
void onWidgetRolled(QWidget *widget, bool rollDown)
void setCWKeyerGUI(Serializable *cwKeyerGUI)
void setTitleColor(const QColor &c)
void updateWithStreamData()
void setHighlighted(bool highlighted)
FreeDVModGUI(PluginAPI *pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget *parent=0)
FreeDVModSettings m_settings
Definition: freedvmodgui.h:67
void addRollupWidget(QWidget *widget)
Add rollup widget to channel window.
Definition: deviceuiset.cpp:77
virtual void setMessageQueueToGUI(MessageQueue *queue)
const QString & getTitle() const
Definition: channelmarker.h:38
DeviceUISet * m_deviceUISet
Definition: freedvmodgui.h:65
static bool match(const Message *message)
Definition: message.cpp:45
FreeDVModInputAF m_modAFInput
void displaySettings()
SpectrumVis * m_spectrumVis
Definition: freedvmodgui.h:71
void on_playLoop_toggled(bool checked)
void on_toneFrequency_valueChanged(int value)
void configureFileName()
int m_recordSampleRate
Definition: freedvmodgui.h:77
QString m_fileName
Definition: freedvmodgui.h:75
void setReverseAPIAddress(const QString &address)
bool deserialize(const QByteArray &data)
virtual qint64 getCenterFrequency() const
void on_freeDVMode_currentIndexChanged(int index)
void setColor(const QColor &color)
virtual void destroy()
QString getName() const
FreeDVMod * m_freeDVMod
Definition: freedvmodgui.h:72
Ui::FreeDVModGUI * ui
Definition: freedvmodgui.h:63
static MsgConfigureChannelizer * create(int sampleRate, int centerFrequency)
Definition: freedvmod.h:85
void setVisible(bool visible)
virtual void setCenterFrequency(qint64 centerFrequency)
static const QString m_channelIdURI
Definition: freedvmod.h:259
void setBandwidth(int bandwidth)
void applySettings(bool force=false)
const QColor & getColor() const
Definition: channelmarker.h:64
void channelMarkerUpdate()
void setTitle(const QString &title)
bool m_enableNavTime
Definition: freedvmodgui.h:80
ChannelMarker m_channelMarker
Definition: freedvmodgui.h:66
static MsgConfigureFileSourceName * create(const QString &fileName)
Definition: freedvmod.h:108
virtual MessageQueue * getInputMessageQueue()
Definition: freedvmodgui.h:56
void setCenterFrequency(int centerFrequency)
void setSidebands(sidebands_t sidebands)
void on_gaugeInput_toggled(bool checked)
uint16_t m_reverseAPIChannelIndex
uint32_t getModemSampleRate() const
Definition: freedvmod.h:252
PluginAPI * m_pluginAPI
Definition: freedvmodgui.h:64
void on_navTimeSlider_valueChanged(int value)
void widgetRolled(QWidget *widget, bool rollDown)
void on_spanLog2_valueChanged(int value)
void setUseReverseAPI(bool useReverseAPI)
void channelMarkerChangedByCursor()
void setName(const QString &name)
const CWKeyerSettings & getSettings() const
Definition: cwkeyer.h:60
void on_volume_valueChanged(int value)
void on_morseKeyer_toggled(bool checked)