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.
soapysdroutputgui.cpp
Go to the documentation of this file.
1 // Copyright (C) 2018 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 <QMessageBox>
19 #include <QCheckBox>
20 
21 #include "dsp/dspengine.h"
22 #include "dsp/dspcommands.h"
23 #include "device/deviceapi.h"
24 #include "device/deviceuiset.h"
25 #include "util/simpleserializer.h"
26 #include "ui_soapysdroutputgui.h"
27 #include "gui/glspectrum.h"
28 #include "gui/crightclickenabler.h"
36 #include "soapygui/arginfogui.h"
38 
39 #include "soapysdroutputgui.h"
40 
41 SoapySDROutputGui::SoapySDROutputGui(DeviceUISet *deviceUISet, QWidget* parent) :
42  QWidget(parent),
43  ui(new Ui::SoapySDROutputGui),
44  m_deviceUISet(deviceUISet),
45  m_forceSettings(true),
46  m_doApplySettings(true),
47  m_sampleSink(0),
48  m_sampleRate(0),
49  m_lastEngineState(DeviceAPI::StNotStarted),
50  m_antennas(0),
51  m_sampleRateGUI(0),
52  m_bandwidthGUI(0),
53  m_gainSliderGUI(0),
54  m_autoGain(0),
55  m_dcCorrectionGUI(0),
56  m_iqCorrectionGUI(0),
57  m_autoDCCorrection(0),
58  m_autoIQCorrection(0)
59 {
61  ui->setupUi(this);
62 
63  ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
64  uint64_t f_min, f_max;
65  m_sampleSink->getFrequencyRange(f_min, f_max);
66  ui->centerFrequency->setValueRange(7, f_min/1000, f_max/1000);
67 
81 
82  if (m_sampleRateGUI) {
83  connect(m_sampleRateGUI, SIGNAL(valueChanged(double)), this, SLOT(sampleRateChanged(double)));
84  }
85  if (m_bandwidthGUI) {
86  connect(m_bandwidthGUI, SIGNAL(valueChanged(double)), this, SLOT(bandwidthChanged(double)));
87  }
88 
89  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
90  connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
91  m_statusTimer.start(500);
92 
93  CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
94  connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
95 
97 
98  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
100 
101  sendSettings();
102 }
103 
105 {
106  delete ui;
107 }
108 
110 {
111  delete this;
112 }
113 
115  ItemSettingGUI **settingGUI,
116  const SoapySDR::RangeList& rangeList,
117  const QString& text,
118  const QString& unit)
119 {
120  if (rangeList.size() == 0) { // return early if the range list is empty
121  return;
122  }
123 
124  bool rangeDiscrete = true; // discretes values
125  bool rangeInterval = true; // intervals
126 
127  for (const auto &it : rangeList)
128  {
129  if (it.minimum() != it.maximum()) {
130  rangeDiscrete = false;
131  } else {
132  rangeInterval = false;
133  }
134  }
135 
136  if (rangeDiscrete)
137  {
138  DiscreteRangeGUI *rangeGUI = new DiscreteRangeGUI(this);
139  rangeGUI->setLabel(text);
140  rangeGUI->setUnits(QString("k%1").arg(unit));
141 
142  for (const auto &it : rangeList) {
143  rangeGUI->addItem(QString("%1").arg(QString::number(it.minimum()/1000.0, 'f', 0)), it.minimum());
144  }
145 
146  *settingGUI = rangeGUI;
147  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
148  layout->addWidget(rangeGUI);
149  }
150  else if (rangeInterval)
151  {
152  IntervalRangeGUI *rangeGUI = new IntervalRangeGUI(this);
153  rangeGUI->setLabel(text);
154  rangeGUI->setUnits(unit);
155 
156  for (const auto &it : rangeList) {
157  rangeGUI->addInterval(it.minimum(), it.maximum());
158  }
159 
160  rangeGUI->reset();
161 
162  *settingGUI = rangeGUI;
163  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
164  layout->addWidget(rangeGUI);
165  }
166 }
167 
168 void SoapySDROutputGui::createAntennasControl(const std::vector<std::string>& antennaList)
169 {
170  if (antennaList.size() == 0) { // return early if the antenna list is empty
171  return;
172  }
173 
174  m_antennas = new StringRangeGUI(this);
175  m_antennas->setLabel(QString("RF out"));
176  m_antennas->setUnits(QString("Port"));
177 
178  for (const auto &it : antennaList) {
179  m_antennas->addItem(QString(it.c_str()), it);
180  }
181 
182  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
183  layout->addWidget(m_antennas);
184 
185  connect(m_antennas, SIGNAL(valueChanged()), this, SLOT(antennasChanged()));
186 }
187 
188 void SoapySDROutputGui::createTunableElementsControl(const std::vector<DeviceSoapySDRParams::FrequencySetting>& tunableElementsList)
189 {
190  if (tunableElementsList.size() <= 1) { // This list is created for other elements than the main one (RF) which is always at index 0
191  return;
192  }
193 
194  std::vector<DeviceSoapySDRParams::FrequencySetting>::const_iterator it = tunableElementsList.begin() + 1;
195 
196  for (int i = 0; it != tunableElementsList.end(); ++it, i++)
197  {
198  if (it->m_ranges.size() == 0) { // skip empty ranges lists
199  continue;
200  }
201 
202  ItemSettingGUI *rangeGUI;
204  &rangeGUI,
205  it->m_ranges,
206  QString("%1 freq").arg(it->m_name.c_str()),
207  QString((it->m_name == "CORR") ? "ppm" : "Hz"));
208  DynamicItemSettingGUI *gui = new DynamicItemSettingGUI(rangeGUI, QString(it->m_name.c_str()));
209  m_tunableElementsGUIs.push_back(gui);
210  connect(m_tunableElementsGUIs.back(), SIGNAL(valueChanged(QString, double)), this, SLOT(tunableElementChanged(QString, double)));
211  }
212 }
213 
215 {
217  int min, max;
218  m_sampleSink->getGlobalGainRange(min, max);
219  m_gainSliderGUI->setInterval(min, max);
220  m_gainSliderGUI->setLabel(QString("Global gain"));
221  m_gainSliderGUI->setUnits(QString(""));
222 
223  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
224 
225  QFrame *line = new QFrame(this);
226  line->setFrameShape(QFrame::HLine);
227  line->setFrameShadow(QFrame::Sunken);
228  layout->addWidget(line);
229 
231  {
232  m_autoGain = new QCheckBox(this);
233  m_autoGain->setText(QString("AGC"));
234  m_autoGain->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}");
235  layout->addWidget(m_autoGain);
236 
237  connect(m_autoGain, SIGNAL(toggled(bool)), this, SLOT(autoGainChanged(bool)));
238  }
239 
240  layout->addWidget(m_gainSliderGUI);
241 
242  connect(m_gainSliderGUI, SIGNAL(valueChanged(double)), this, SLOT(globalGainChanged(double)));
243 }
244 
245 void SoapySDROutputGui::createIndividualGainsControl(const std::vector<DeviceSoapySDRParams::GainSetting>& individualGainsList)
246 {
247  if (individualGainsList.size() == 0) { // Leave early if list of individual gains is empty
248  return;
249  }
250 
251  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
252  std::vector<DeviceSoapySDRParams::GainSetting>::const_iterator it = individualGainsList.begin();
253 
254  for (int i = 0; it != individualGainsList.end(); ++it, i++)
255  {
256  IntervalSliderGUI *gainGUI = new IntervalSliderGUI(this);
257  gainGUI->setInterval(it->m_range.minimum(), it->m_range.maximum());
258  gainGUI->setLabel(QString("%1 gain").arg(it->m_name.c_str()));
259  gainGUI->setUnits(QString(""));
260  DynamicItemSettingGUI *gui = new DynamicItemSettingGUI(gainGUI, QString(it->m_name.c_str()));
261  layout->addWidget(gainGUI);
262  m_individualGainsGUIs.push_back(gui);
263  connect(m_individualGainsGUIs.back(), SIGNAL(valueChanged(QString, double)), this, SLOT(individualGainChanged(QString, double)));
264  }
265 }
266 
268 {
269  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
270 
271  if (m_sampleSink->hasDCCorrectionValue()) // complex GUI
272  {
274  m_dcCorrectionGUI->setLabel(QString("DC"));
276  layout->addWidget(m_dcCorrectionGUI);
277 
278  connect(m_dcCorrectionGUI, SIGNAL(moduleChanged(double)), this, SLOT(dcCorrectionModuleChanged(double)));
279  connect(m_dcCorrectionGUI, SIGNAL(argumentChanged(double)), this, SLOT(dcCorrectionArgumentChanged(double)));
280 
282  connect(m_dcCorrectionGUI, SIGNAL(automaticChanged(bool)), this, SLOT(autoDCCorrectionChanged(bool)));
283  }
284  }
285  else if (m_sampleSink->hasDCAutoCorrection()) // simple checkbox
286  {
287  m_autoDCCorrection = new QCheckBox(this);
288  m_autoDCCorrection->setText(QString("Auto DC corr"));
289  m_autoDCCorrection->setToolTip(QString("Automatic hardware DC offset correction"));
290  m_autoDCCorrection->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}");
291  layout->addWidget(m_autoDCCorrection);
292 
293  connect(m_autoDCCorrection, SIGNAL(toggled(bool)), this, SLOT(autoDCCorrectionChanged(bool)));
294  }
295 
296  if (m_sampleSink->hasIQCorrectionValue()) // complex GUI
297  {
299  m_iqCorrectionGUI->setLabel(QString("IQ"));
301  layout->addWidget(m_iqCorrectionGUI);
302 
303  connect(m_iqCorrectionGUI, SIGNAL(moduleChanged(double)), this, SLOT(iqCorrectionModuleChanged(double)));
304  connect(m_iqCorrectionGUI, SIGNAL(argumentChanged(double)), this, SLOT(iqCorrectionArgumentChanged(double)));
305 
307  connect(m_iqCorrectionGUI, SIGNAL(automaticChanged(bool)), this, SLOT(autoIQCorrectionChanged(bool)));
308  }
309  }
310  else if (m_sampleSink->hasIQAutoCorrection()) // simple checkbox
311  {
312  m_autoIQCorrection = new QCheckBox(this);
313  m_autoIQCorrection->setText(QString("Auto IQ corr"));
314  m_autoIQCorrection->setToolTip(QString("Automatic hardware IQ imbalance correction"));
315  m_autoIQCorrection->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}");
316  layout->addWidget(m_autoIQCorrection);
317 
318  connect(m_autoIQCorrection, SIGNAL(toggled(bool)), this, SLOT(autoIQCorrectionChanged(bool)));
319  }
320 }
321 
322 void SoapySDROutputGui::createArgumentsControl(const SoapySDR::ArgInfoList& argInfoList, bool deviceArguments)
323 {
324  if (argInfoList.size() == 0) { // return early if list is empty
325  return;
326  }
327 
328  QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout();
329 
330  QFrame *line = new QFrame(this);
331  line->setFrameShape(QFrame::HLine);
332  line->setFrameShadow(QFrame::Sunken);
333  layout->addWidget(line);
334 
335  std::vector<SoapySDR::ArgInfo>::const_iterator it = argInfoList.begin();
336 
337  for (; it != argInfoList.end(); ++it)
338  {
340  ArgInfoGUI *argGUI;
341 
342  if (it->type == SoapySDR::ArgInfo::BOOL) {
343  valueType = ArgInfoGUI::ArgInfoValueBool;
344  } else if (it->type == SoapySDR::ArgInfo::INT) {
345  valueType = ArgInfoGUI::ArgInfoValueInt;
346  } else if (it->type == SoapySDR::ArgInfo::FLOAT) {
347  valueType = ArgInfoGUI::ArgInfoValueFloat;
348  } else if (it->type == SoapySDR::ArgInfo::STRING) {
349  valueType = ArgInfoGUI::ArgInfoValueString;
350  } else {
351  continue;
352  }
353 
354  if (valueType == ArgInfoGUI::ArgInfoValueBool)
355  {
357  }
358  else if (it->options.size() == 0)
359  {
360  argGUI = new ArgInfoGUI(ArgInfoGUI::ArgInfoContinuous, valueType, this);
361  }
362  else
363  {
364  argGUI = new ArgInfoGUI(ArgInfoGUI::ArgInfoDiscrete, valueType, this);
365  std::vector<std::string>::const_iterator optionIt = it->options.begin();
366  std::vector<std::string>::const_iterator optionNameIt = it->optionNames.begin();
367 
368  for (int i = 0; optionIt != it->options.end(); ++optionIt, i++)
369  {
370  QString name(optionNameIt == it->optionNames.end() ? optionIt->c_str() : optionNameIt->c_str());
371 
372  if (optionNameIt != it->optionNames.end()) {
373  ++optionNameIt;
374  }
375 
376  if (valueType == ArgInfoGUI::ArgInfoValueInt) {
377  argGUI->addIntValue(name, atoi(optionIt->c_str()));
378  } else if (valueType == ArgInfoGUI::ArgInfoValueFloat) {
379  argGUI->addFloatValue(name, atof(optionIt->c_str()));
380  } else if (valueType == ArgInfoGUI::ArgInfoValueString) {
381  argGUI->addStringValue(name, QString(optionIt->c_str()));
382  }
383  }
384  }
385 
386  if ((it->range.minimum() != 0) || (it->range.maximum() != 0)) {
387  argGUI->setRange(it->range.minimum(), it->range.maximum());
388  }
389 
390  argGUI->setLabel(QString(it->name.size() == 0 ? it->key.c_str() : it->name.c_str()));
391  argGUI->setUnits(QString(it->units.c_str()));
392 
393  if (it->description.size() != 0) {
394  argGUI->setToolTip(QString(it->description.c_str()));
395  }
396 
397  layout->addWidget(argGUI);
398 
399  DynamicArgSettingGUI *gui = new DynamicArgSettingGUI(argGUI, QString(it->key.c_str()));
400 
401  // This could be made more elegant but let's make it more simple
402  if (deviceArguments)
403  {
404  m_deviceArgsGUIs.push_back(gui);
405  connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(deviceArgChanged(QString, QVariant)));
406  }
407  else
408  {
409  m_streamArgsGUIs.push_back(gui);
410  connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(streamArgChanged(QString, QVariant)));
411  }
412  }
413 }
414 
415 void SoapySDROutputGui::setName(const QString& name)
416 {
417  setObjectName(name);
418 }
419 
421 {
422  return objectName();
423 }
424 
426 {
428  displaySettings();
429  sendSettings();
430 }
431 
433 {
435 }
436 
437 void SoapySDROutputGui::setCenterFrequency(qint64 centerFrequency)
438 {
439  m_settings.m_centerFrequency = centerFrequency;
440  displaySettings();
441  sendSettings();
442 }
443 
445 {
446  return m_settings.serialize();
447 }
448 
449 bool SoapySDROutputGui::deserialize(const QByteArray& data)
450 {
451  if(m_settings.deserialize(data))
452  {
453  displaySettings();
454  m_forceSettings = true;
455  sendSettings();
456  return true;
457  }
458  else
459  {
460  resetToDefaults();
461  return false;
462  }
463 }
464 
465 
467 {
469  {
471  m_settings = cfg.getSettings();
472  blockApplySettings(true);
473  displaySettings();
474  blockApplySettings(false);
475 
476  return true;
477  }
479  {
481  const SoapySDROutputSettings& gainSettings = report.getSettings();
482 
483  if (report.getGlobalGain()) {
484  m_settings.m_globalGain = gainSettings.m_globalGain;
485  }
486  if (report.getIndividualGains()) {
488  }
489 
490  blockApplySettings(true);
491  displaySettings();
492  blockApplySettings(false);
493 
494  return true;
495  }
497  {
501 
502  return true;
503  }
504  else if (SoapySDROutput::MsgStartStop::match(message))
505  {
507  blockApplySettings(true);
508  ui->startStop->setChecked(notif.getStartStop());
509  blockApplySettings(false);
510 
511  return true;
512  }
513  else
514  {
515  return false;
516  }
517 }
518 
520 {
521  Message* message;
522 
523  while ((message = m_inputMessageQueue.pop()) != 0)
524  {
525  qDebug("SoapySDROutputGui::handleInputMessages: message: %s", message->getIdentifier());
526 
527  if (DSPSignalNotification::match(*message))
528  {
529  DSPSignalNotification* notif = (DSPSignalNotification*) message;
530  m_sampleRate = notif->getSampleRate();
532  qDebug("SoapySDROutputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
534 
535  delete message;
536  }
537  else
538  {
539  if (handleMessage(*message))
540  {
541  delete message;
542  }
543  }
544  }
545 }
546 
548 {
549  m_settings.m_devSampleRate = round(sampleRate);
550  sendSettings();
551 }
552 
554 {
555  const std::string& antennaStr = m_antennas->getCurrentValue();
556  m_settings.m_antenna = QString(antennaStr.c_str());
557  sendSettings();
558 }
559 
561 {
562  m_settings.m_bandwidth = round(bandwidth);
563  sendSettings();
564 }
565 
566 void SoapySDROutputGui::tunableElementChanged(QString name, double value)
567 {
568  m_settings.m_tunableElements[name] = value;
569  sendSettings();
570 }
571 
573 {
574  m_settings.m_globalGain = round(gain);
575  sendSettings();
576 }
577 
579 {
580  m_settings.m_autoGain = set;
581  sendSettings();
582 }
583 
584 void SoapySDROutputGui::individualGainChanged(QString name, double value)
585 {
586  m_settings.m_individualGains[name] = value;
587  sendSettings();
588 }
589 
591 {
593  sendSettings();
594 }
595 
597 {
599  sendSettings();
600 }
601 
603 {
604  std::complex<double> dcCorrection = std::polar<double>(value, arg(m_settings.m_dcCorrection));
605  m_settings.m_dcCorrection = dcCorrection;
606  sendSettings();
607 }
608 
610 {
611  double angleInRadians = (value / 180.0) * M_PI;
612  std::complex<double> dcCorrection = std::polar<double>(abs(m_settings.m_dcCorrection), angleInRadians);
613  m_settings.m_dcCorrection = dcCorrection;
614  sendSettings();
615 }
616 
618 {
619  std::complex<double> iqCorrection = std::polar<double>(value, arg(m_settings.m_iqCorrection));
620  m_settings.m_iqCorrection = iqCorrection;
621  sendSettings();
622 }
623 
625 {
626  double angleInRadians = (value / 180.0) * M_PI;
627  std::complex<double> iqCorrection = std::polar<double>(abs(m_settings.m_iqCorrection), angleInRadians);
628  m_settings.m_iqCorrection = iqCorrection;
629  sendSettings();
630 }
631 
632 void SoapySDROutputGui::streamArgChanged(QString itemName, QVariant value)
633 {
634  m_settings.m_streamArgSettings[itemName] = value;
635  sendSettings();
636 }
637 
638 void SoapySDROutputGui::deviceArgChanged(QString itemName, QVariant value)
639 {
640  m_settings.m_deviceArgSettings[itemName] = value;
641  sendSettings();
642 }
643 
645 {
646  m_settings.m_centerFrequency = value * 1000;
647  sendSettings();
648 }
649 
651 {
652  if ((index <0) || (index > 6))
653  return;
654  m_settings.m_log2Interp = index;
655  sendSettings();
656 }
657 
659 {
660  m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive();
661  m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency();
662  qDebug("SoapySDROutputGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off");
664  setCenterFrequencySetting(ui->centerFrequency->getValueNew());
665  sendSettings();
666 }
667 
669 {
670  ui->LOppmText->setText(QString("%1").arg(QString::number(value/10.0, 'f', 1)));
671  m_settings.m_LOppmTenths = value;
672  sendSettings();
673 }
674 
676 {
677  if (m_doApplySettings)
678  {
681  }
682 }
683 
685 {
686  blockApplySettings(true);
687 
688  ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
689 
690  if (m_antennas) {
691  m_antennas->setValue(m_settings.m_antenna.toStdString());
692  }
693  if (m_sampleRateGUI)
694  {
697  }
698  if (m_bandwidthGUI)
699  {
702  }
703  if (m_gainSliderGUI)
704  {
707  }
708  if (m_autoGain) {
709  m_autoGain->setChecked(m_settings.m_autoGain);
710  }
711 
712  ui->interp->setCurrentIndex(m_settings.m_log2Interp);
713 
714  ui->LOppm->setValue(m_settings.m_LOppmTenths);
715  ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1)));
716 
722 
723  blockApplySettings(false);
724 }
725 
727 {
728  for (const auto &it : m_tunableElementsGUIs)
729  {
730  QMap<QString, double>::const_iterator elIt = m_settings.m_tunableElements.find(it->getName());
731 
732  if (elIt != m_settings.m_tunableElements.end()) {
733  it->setValue(*elIt);
734  }
735  }
736 }
737 
739 {
740  for (const auto &it : m_individualGainsGUIs)
741  {
742  QMap<QString, double>::iterator elIt = m_settings.m_individualGains.find(it->getName());
743 
744  if (elIt != m_settings.m_individualGains.end())
745  {
746  it->setValue(*elIt);
747  *elIt = it->getValue();
748  }
749  }
750 }
751 
753 {
754  if (m_dcCorrectionGUI)
755  {
759  }
760 
761  if (m_iqCorrectionGUI)
762  {
766  }
767 
768  if (m_autoDCCorrection) {
770  }
771 
772  if (m_autoIQCorrection) {
774  }
775 }
776 
778 {
779  for (const auto &it : m_streamArgsGUIs)
780  {
781  QMap<QString, QVariant>::iterator elIt = m_settings.m_streamArgSettings.find(it->getName());
782 
783  if (elIt != m_settings.m_streamArgSettings.end())
784  {
785  it->setValue(elIt.value());
786  *elIt = it->getValue();
787  }
788  }
789 }
790 
792 {
793  for (const auto &it : m_deviceArgsGUIs)
794  {
795  QMap<QString, QVariant>::iterator elIt = m_settings.m_deviceArgSettings.find(it->getName());
796 
797  if (elIt != m_settings.m_deviceArgSettings.end())
798  {
799  it->setValue(elIt.value());
800  *elIt = it->getValue();
801  }
802  }
803 }
804 
806 {
807  if (!m_updateTimer.isActive()) {
808  m_updateTimer.start(100);
809  }
810 }
811 
813 {
816  ui->deviceRateText->setText(tr("%1k").arg(QString::number(m_sampleRate / 1000.0f, 'g', 5)));
817 }
818 
820 {
821  // values in kHz
822  uint64_t f_min, f_max;
823  qint64 deltaFrequency = m_settings.m_transverterMode ? m_settings.m_transverterDeltaFrequency/1000 : 0;
824  m_sampleSink->getFrequencyRange(f_min, f_max);
825  qint64 minLimit = f_min/1000 + deltaFrequency;
826  qint64 maxLimit = f_max/1000 + deltaFrequency;
827 
828  minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit;
829  maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit;
830 
831  qDebug("SoapySDRInputGui::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit);
832 
833  ui->centerFrequency->setValueRange(7, minLimit, maxLimit);
834 }
835 
837 {
838  int64_t centerFrequency = kHzValue*1000;
839 
840  m_settings.m_centerFrequency = centerFrequency < 0 ? 0 : (uint64_t) centerFrequency;
841  ui->centerFrequency->setToolTip(QString("Main center frequency in kHz (LO: %1 kHz)").arg(centerFrequency/1000));
842 }
843 
845 {
846  if (m_doApplySettings)
847  {
848  qDebug() << "SoapySDROutputGui::updateHardware";
851  m_forceSettings = false;
852  m_updateTimer.stop();
853  }
854 }
855 
857 {
858  int state = m_deviceUISet->m_deviceAPI->state();
859 
860  if(m_lastEngineState != state)
861  {
862  switch(state)
863  {
865  ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
866  break;
867  case DeviceAPI::StIdle:
868  ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
869  break;
871  ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
872  break;
873  case DeviceAPI::StError:
874  ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
875  QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
876  break;
877  default:
878  break;
879  }
880 
881  m_lastEngineState = state;
882  }
883 }
884 
886 {
887  BasicDeviceSettingsDialog dialog(this);
892 
893  dialog.move(p);
894  dialog.exec();
895 
900 
901  sendSettings();
902 }
void setCenterFrequencySetting(uint64_t kHzValue)
MessageQueue m_inputMessageQueue
void streamArgChanged(QString itemName, QVariant value)
std::vector< DynamicArgSettingGUI * > m_deviceArgsGUIs
void autoDCCorrectionChanged(bool set)
Message * pop()
Pop message from queue.
const QString & getReverseAPIAddress() const
static MsgConfigureSoapySDROutput * create(const SoapySDROutputSettings &settings, bool force)
void sampleRateChanged(double sampleRate)
QString getName() const
QMap< QString, double > m_tunableElements
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
Definition: glspectrum.cpp:211
const std::string & getCurrentValue()
void setUnits(const QString &units)
Definition: arginfogui.cpp:95
void setValue(const std::string &value)
SoapySDROutput * m_sampleSink
std::vector< DynamicItemSettingGUI * > m_tunableElementsGUIs
virtual qint64 getCenterFrequency() const
void setLabel(const QString &text)
void setUseReverseAPI(bool useReverseAPI)
virtual void setValue(double value)=0
virtual void setMessageQueueToGUI(MessageQueue *queue)
void setUnits(const QString &units)
void individualGainChanged(QString name, double value)
std::vector< DynamicItemSettingGUI * > m_individualGainsGUIs
void initStreamArgSettings(SoapySDROutputSettings &settings)
DeviceUISet * m_deviceUISet
void bandwidthChanged(double bandwidth)
bool hasIQAutoCorrection()
void displayTunableElementsControlSettings()
const QMap< QString, QVariant > & getDeviceArgSettings() const
bool hasIQCorrectionValue()
void getGlobalGainRange(int &min, int &max)
SoapySDROutputSettings m_settings
const SoapySDR::RangeList & getBandwidthRanges()
void setRange(double min, double max)
Definition: arginfogui.cpp:72
void autoIQCorrectionChanged(bool set)
Fixed< IntType, IntBits > abs(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2313
void createIndividualGainsControl(const std::vector< DeviceSoapySDRParams::GainSetting > &individualGainsList)
void initDeviceArgSettings(SoapySDROutputSettings &settings)
virtual bool deserialize(const QByteArray &data)
#define M_PI
Definition: rdsdemod.cpp:27
QString errorMessage()
Last error message from the device engine.
Definition: deviceapi.cpp:290
const std::vector< DeviceSoapySDRParams::FrequencySetting > & getTunableElements()
bool hasDCAutoCorrection()
DeviceSampleSink * getSampleSink()
Return pointer to the device sample sink (single Tx) or nullptr.
Definition: deviceapi.cpp:222
__int64 int64_t
Definition: rtptypes_win.h:47
Ui::SoapySDROutputGui * ui
void dcCorrectionModuleChanged(double value)
const SoapySDR::RangeList & getRateRanges()
QCheckBox * m_autoGain
void createTunableElementsControl(const std::vector< DeviceSoapySDRParams::FrequencySetting > &tunableElementsList)
QMap< QString, QVariant > m_streamArgSettings
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
void openDeviceSettingsDialog(const QPoint &p)
GLSpectrum * getSpectrum()
Direct spectrum getter.
Definition: deviceuiset.h:57
engine is before initialization
Definition: deviceapi.h:53
const SoapySDROutputSettings & getSettings() const
qint64 getCenterFrequency() const
Definition: dspcommands.h:329
EngineState state() const
Return the state of the device engine corresponding to the stream type.
Definition: deviceapi.cpp:277
virtual bool handleMessage(const Message &message)
void setArgument(double value)
void createRangesControl(ItemSettingGUI **settingGUI, const SoapySDR::RangeList &rangeList, const QString &text, const QString &unit)
StringRangeGUI * m_antennas
void setAutomatic(bool automatic)
DeviceAPI * m_deviceAPI
Definition: deviceuiset.h:48
void globalGainChanged(double gain)
engine is idle
Definition: deviceapi.h:54
MessageQueue * getInputMessageQueue()
void setLabel(const QString &text)
void displayIndividualGainsControlSettings()
void setInterval(double minimum, double maximum)
void setLabel(const QString &text)
void setAutomaticEnable(bool enable)
QMap< QString, double > m_individualGains
void addItem(const QString &itemStr, double itemValue)
void iqCorrectionModuleChanged(double value)
ItemSettingGUI * m_sampleRateGUI
const SoapySDR::ArgInfoList & getDeviceArgInfoList()
int32_t i
Definition: decimators.h:244
void getFrequencyRange(uint64_t &min, uint64_t &max)
static bool match(const Message *message)
Definition: message.cpp:45
void setLabel(const QString &text)
void initGainSettings(SoapySDROutputSettings &settings)
std::complex< double > m_iqCorrection
virtual double getCurrentValue()
void addItem(const QString &itemStr, const std::string &itemValue)
quint64 m_deviceCenterFrequency
Center frequency in device.
const SoapySDROutputSettings & getSettings() const
void on_centerFrequency_changed(quint64 value)
int BOOL
Definition: fcdhid.h:37
virtual double getCurrentValue()=0
const std::vector< DeviceSoapySDRParams::GainSetting > & getIndividualGainsRanges()
QCheckBox * m_autoDCCorrection
void on_startStop_toggled(bool checked)
void addIntValue(const QString &text, int value)
Definition: arginfogui.cpp:155
void setUnits(const QString &units)
virtual void setCenterFrequency(qint64 centerFrequency)
void blockApplySettings(bool block)
const std::vector< std::string > & getAntennas()
void dcCorrectionArgumentChanged(double value)
void setUnits(const QString &units)
void addInterval(double minimum, double maximum)
virtual QByteArray serialize() const
void addFloatValue(const QString &text, double value)
Definition: arginfogui.cpp:186
void autoGainChanged(bool set)
void setModule(double value)
std::complex< double > m_dcCorrection
void on_LOppm_valueChanged(int value)
int getSampleRate() const
Definition: dspcommands.h:328
void setToolTip(const QString &text)
Definition: arginfogui.cpp:84
SoapySDROutputGui(DeviceUISet *deviceUISet, QWidget *parent=0)
std::vector< DynamicArgSettingGUI * > m_streamArgsGUIs
void setCenterFrequency(qint64 frequency)
Definition: glspectrum.cpp:175
virtual const char * getIdentifier() const
Definition: message.cpp:35
void setReverseAPIAddress(const QString &address)
void initTunableElementsSettings(SoapySDROutputSettings &settings)
ComplexFactorGUI * m_iqCorrectionGUI
void setReverseAPIDeviceIndex(uint16_t deviceIndex)
void setName(const QString &name)
void setLabel(const QString &text)
const SoapySDR::ArgInfoList & getStreamArgInfoList()
static MsgStartStop * create(bool startStop)
void on_interp_currentIndexChanged(int index)
ItemSettingGUI * m_bandwidthGUI
void setUnits(const QString &units)
engine is running
Definition: deviceapi.h:56
QCheckBox * m_autoIQCorrection
void tunableElementChanged(QString name, double value)
IntervalSliderGUI * m_gainSliderGUI
virtual void destroy()
ComplexFactorGUI * m_dcCorrectionGUI
bool deserialize(const QByteArray &data)
void createArgumentsControl(const SoapySDR::ArgInfoList &argInfoList, bool deviceArguments)
bool hasDCCorrectionValue()
void createAntennasControl(const std::vector< std::string > &antennaList)
virtual void setValue(double value)
void deviceArgChanged(QString itemName, QVariant value)
QMap< QString, QVariant > m_deviceArgSettings
void setLabel(const QString &text)
Definition: arginfogui.cpp:79
engine is in error
Definition: deviceapi.h:57
T max(const T &x, const T &y)
Definition: framework.h:446
void addStringValue(const QString &text, const QString &value)
Definition: arginfogui.cpp:219
void iqCorrectionArgumentChanged(double value)
T min(const T &x, const T &y)
Definition: framework.h:440
unsigned __int64 uint64_t
Definition: rtptypes_win.h:48