From f436479bd710be0900de698874404e5a10d0032e Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 11 Nov 2018 09:31:27 +0100 Subject: [PATCH] SoapySDR support: output: stream ArgInfo GUI --- .../soapysdroutput/soapysdroutput.cpp | 25 +++++ .../soapysdroutput/soapysdroutput.h | 2 + .../soapysdroutput/soapysdroutputgui.cpp | 105 ++++++++++++++++++ .../soapysdroutput/soapysdroutputgui.h | 5 + .../soapysdroutput/soapysdroutputsettings.cpp | 21 ++++ .../soapysdroutput/soapysdroutputsettings.h | 5 + .../soapysdrinput/soapysdrinputsettings.cpp | 2 +- 7 files changed, 164 insertions(+), 1 deletion(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index 698da7065..761a9f125 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -250,6 +250,31 @@ void SoapySDROutput::initGainSettings(SoapySDROutputSettings& settings) updateGains(m_deviceShared.m_device, m_deviceShared.m_channel, settings); } +const SoapySDR::ArgInfoList& SoapySDROutput::getStreamArgInfoList() +{ + const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getTxChannelSettings(m_deviceShared.m_channel); + return channelSettings->m_streamSettingsArgs; +} + +void SoapySDROutput::initStreamArgSettings(SoapySDROutputSettings& settings) +{ + const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getTxChannelSettings(m_deviceShared.m_channel); + settings.m_streamArgSettings.clear(); + + for (const auto &it : channelSettings->m_streamSettingsArgs) + { + if (it.type == SoapySDR::ArgInfo::BOOL) { + settings.m_streamArgSettings[QString(it.key.c_str())] = QVariant(it.value == "true"); + } else if (it.type == SoapySDR::ArgInfo::INT) { + settings.m_streamArgSettings[QString(it.key.c_str())] = QVariant(atoi(it.value.c_str())); + } else if (it.type == SoapySDR::ArgInfo::FLOAT) { + settings.m_streamArgSettings[QString(it.key.c_str())] = QVariant(atof(it.value.c_str())); + } else if (it.type == SoapySDR::ArgInfo::STRING) { + settings.m_streamArgSettings[QString(it.key.c_str())] = QVariant(it.value.c_str()); + } + } +} + bool SoapySDROutput::hasDCAutoCorrection() { const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getTxChannelSettings(m_deviceShared.m_channel); diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.h b/plugins/samplesink/soapysdroutput/soapysdroutput.h index 5fb9cc3f2..1801b93f1 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.h @@ -133,7 +133,9 @@ public: const SoapySDR::RangeList& getBandwidthRanges(); const std::vector& getTunableElements(); const std::vector& getIndividualGainsRanges(); + const SoapySDR::ArgInfoList& getStreamArgInfoList(); void initGainSettings(SoapySDROutputSettings& settings); + void initStreamArgSettings(SoapySDROutputSettings& settings); bool hasDCAutoCorrection(); bool hasDCCorrectionValue(); bool hasIQAutoCorrection() { return false; } // not in SoapySDR interface diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp index 7dc84b694..ad370cbbc 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp @@ -30,6 +30,8 @@ #include "soapygui/dynamicitemsettinggui.h" #include "soapygui/intervalslidergui.h" #include "soapygui/complexfactorgui.h" +#include "soapygui/arginfogui.h" +#include "soapygui/dynamicargsettinggui.h" #include "soapysdroutputgui.h" @@ -67,7 +69,9 @@ SoapySDROutputGui::SoapySDROutputGui(DeviceUISet *deviceUISet, QWidget* parent) createTunableElementsControl(m_sampleSink->getTunableElements()); createGlobalGainControl(); createIndividualGainsControl(m_sampleSink->getIndividualGainsRanges()); + createStreamArgumentsControl(m_sampleSink->getStreamArgInfoList()); m_sampleSink->initGainSettings(m_settings); + m_sampleSink->initStreamArgSettings(m_settings); if (m_sampleRateGUI) { connect(m_sampleRateGUI, SIGNAL(valueChanged(double)), this, SLOT(sampleRateChanged(double))); @@ -303,6 +307,86 @@ void SoapySDROutputGui::createCorrectionsControl() } } +void SoapySDROutputGui::createStreamArgumentsControl(const SoapySDR::ArgInfoList& argInfoList) +{ + if (argInfoList.size() == 0) { // return early if list is empty + return; + } + + QVBoxLayout *layout = (QVBoxLayout *) ui->scrollAreaWidgetContents->layout(); + + QFrame *line = new QFrame(this); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + layout->addWidget(line); + + std::vector::const_iterator it = argInfoList.begin(); + + for (; it != argInfoList.end(); ++it) + { + ArgInfoGUI::ArgInfoValueType valueType; + ArgInfoGUI *argGUI; + + if (it->type == SoapySDR::ArgInfo::BOOL) { + valueType = ArgInfoGUI::ArgInfoValueBool; + } else if (it->type == SoapySDR::ArgInfo::INT) { + valueType = ArgInfoGUI::ArgInfoValueInt; + } else if (it->type == SoapySDR::ArgInfo::FLOAT) { + valueType = ArgInfoGUI::ArgInfoValueFloat; + } else if (it->type == SoapySDR::ArgInfo::STRING) { + valueType = ArgInfoGUI::ArgInfoValueString; + } else { + continue; + } + + if (valueType == ArgInfoGUI::ArgInfoValueBool) + { + argGUI = new ArgInfoGUI(ArgInfoGUI::ArgInfoBinary, ArgInfoGUI::ArgInfoValueBool, this); + } + else if (it->options.size() == 0) + { + argGUI = new ArgInfoGUI(ArgInfoGUI::ArgInfoContinuous, valueType, this); + } + else + { + argGUI = new ArgInfoGUI(ArgInfoGUI::ArgInfoDiscrete, valueType, this); + std::vector::const_iterator optionIt = it->options.begin(); + std::vector::const_iterator optionNameIt = it->optionNames.begin(); + + for (int i = 0; optionIt != it->options.end(); ++optionIt, i++) + { + QString name(optionNameIt == it->optionNames.end() ? optionIt->c_str() : optionNameIt->c_str()); + ++optionNameIt; + + if (valueType == ArgInfoGUI::ArgInfoValueInt) { + argGUI->addIntValue(name, atoi(optionIt->c_str())); + } else if (valueType == ArgInfoGUI::ArgInfoValueFloat) { + argGUI->addFloatValue(name, atof(optionIt->c_str())); + } else if (valueType == ArgInfoGUI::ArgInfoValueString) { + argGUI->addStringValue(name, QString(optionIt->c_str())); + } + } + } + + if ((it->range.minimum() != 0) || (it->range.maximum() != 0)) { + argGUI->setRange(it->range.minimum(), it->range.maximum()); + } + + argGUI->setLabel(QString(it->name.size() == 0 ? it->key.c_str() : it->name.c_str())); + argGUI->setUnits(QString(it->units.c_str())); + + if (it->description.size() != 0) { + argGUI->setToolTip(QString(it->description.c_str())); + } + + layout->addWidget(argGUI); + + DynamicArgSettingGUI *gui = new DynamicArgSettingGUI(argGUI, QString(it->key.c_str())); + m_streamArgsGUIs.push_back(gui); + connect(gui, SIGNAL(valueChanged(QString, value)), this, SLOT(streamArgChanged(QString, QVariant))); + } +} + void SoapySDROutputGui::setName(const QString& name) { setObjectName(name); @@ -509,6 +593,12 @@ void SoapySDROutputGui::iqCorrectionArgumentChanged(double value) sendSettings(); } +void SoapySDROutputGui::streamArgChanged(QString itemName, QVariant value) +{ + m_settings.m_streamArgSettings[itemName] = value; + sendSettings(); +} + void SoapySDROutputGui::on_centerFrequency_changed(quint64 value) { m_settings.m_centerFrequency = value * 1000; @@ -585,6 +675,7 @@ void SoapySDROutputGui::displaySettings() displayTunableElementsControlSettings(); displayIndividualGainsControlSettings(); displayCorrectionsSettings(); + displayStreamArgsSettings(); blockApplySettings(false); } @@ -640,6 +731,20 @@ void SoapySDROutputGui::displayCorrectionsSettings() } } +void SoapySDROutputGui::displayStreamArgsSettings() +{ + for (const auto &it : m_streamArgsGUIs) + { + QMap::iterator elIt = m_settings.m_streamArgSettings.find(it->getName()); + + if (elIt != m_settings.m_streamArgSettings.end()) + { + it->setValue(*elIt); + *elIt = it->getValue(); + } + } +} + void SoapySDROutputGui::sendSettings() { if (!m_updateTimer.isActive()) { diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputgui.h b/plugins/samplesink/soapysdroutput/soapysdroutputgui.h index 1ac196323..be2ed1916 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputgui.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutputgui.h @@ -31,6 +31,7 @@ class DeviceUISet; class ItemSettingGUI; class StringRangeGUI; class DynamicItemSettingGUI; +class DynamicArgSettingGUI; class IntervalSliderGUI; class QCheckBox; class ComplexFactorGUI; @@ -69,6 +70,7 @@ private: void createGlobalGainControl(); void createIndividualGainsControl(const std::vector& individualGainsList); void createCorrectionsControl(); + void createStreamArgumentsControl(const SoapySDR::ArgInfoList& argInfoList); Ui::SoapySDROutputGui* ui; @@ -95,12 +97,14 @@ private: ComplexFactorGUI *m_iqCorrectionGUI; QCheckBox *m_autoDCCorrection; QCheckBox *m_autoIQCorrection; + std::vector m_streamArgsGUIs; void blockApplySettings(bool block) { m_doApplySettings = !block; } void displaySettings(); void displayTunableElementsControlSettings(); void displayIndividualGainsControlSettings(); void displayCorrectionsSettings(); + void displayStreamArgsSettings(); void sendSettings(); void updateSampleRateAndFrequency(); void updateFrequencyLimits(); @@ -122,6 +126,7 @@ private slots: void dcCorrectionArgumentChanged(double value); void iqCorrectionModuleChanged(double value); void iqCorrectionArgumentChanged(double value); + void streamArgChanged(QString itemName, QVariant value); void on_centerFrequency_changed(quint64 value); void on_LOppm_valueChanged(int value); diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputsettings.cpp b/plugins/samplesink/soapysdroutput/soapysdroutputsettings.cpp index 9abc87b96..1db9702c4 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputsettings.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputsettings.cpp @@ -65,6 +65,7 @@ QByteArray SoapySDROutputSettings::serialize() const s.writeDouble(18, m_dcCorrection.imag()); s.writeDouble(19, m_iqCorrection.real()); s.writeDouble(20, m_iqCorrection.imag()); + s.writeBlob(21, serializeArgumentMap(m_streamArgSettings)); return s.final(); } @@ -105,6 +106,8 @@ bool SoapySDROutputSettings::deserialize(const QByteArray& data) d.readDouble(19, &realval, 0); d.readDouble(20, &imagval, 0); m_iqCorrection = std::complex{realval, imagval}; + d.readBlob(21, &blob); + deserializeArgumentMap(blob, m_streamArgSettings); return true; } @@ -131,3 +134,21 @@ void SoapySDROutputSettings::deserializeNamedElementMap(const QByteArray& data, (*stream) >> map; delete stream; } + +QByteArray SoapySDROutputSettings::serializeArgumentMap(const QMap& map) const +{ + QByteArray data; + QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly); + (*stream) << map; + delete stream; + + return data; +} + +void SoapySDROutputSettings::deserializeArgumentMap(const QByteArray& data, QMap& map) +{ + QDataStream *stream = new QDataStream(data); + (*stream) >> map; + delete stream; +} + diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputsettings.h b/plugins/samplesink/soapysdroutput/soapysdroutputsettings.h index d0cf8f448..992bba988 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputsettings.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutputsettings.h @@ -18,6 +18,7 @@ #define PLUGINS_SAMPLESINK_SOAPYSDROUTPUT_SOAPYSDROUTPUTSETTINGS_H_ #include +#include #include struct SoapySDROutputSettings { @@ -37,6 +38,7 @@ struct SoapySDROutputSettings { bool m_autoIQCorrection; std::complex m_dcCorrection; std::complex m_iqCorrection; + QMap m_streamArgSettings; SoapySDROutputSettings(); void resetToDefaults(); @@ -46,6 +48,9 @@ struct SoapySDROutputSettings { private: QByteArray serializeNamedElementMap(const QMap& map) const; void deserializeNamedElementMap(const QByteArray& data, QMap& map); + QByteArray serializeArgumentMap(const QMap& map) const; + void deserializeArgumentMap(const QByteArray& data, QMap& map); + }; #endif /* PLUGINS_SAMPLESINK_SOAPYSDROUTPUT_SOAPYSDROUTPUTSETTINGS_H_ */ diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp index fc793dccc..6728a2cde 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp @@ -156,7 +156,7 @@ QByteArray SoapySDRInputSettings::serializeArgumentMap(const QMap& map) +void SoapySDRInputSettings::deserializeArgumentMap(const QByteArray& data, QMap& map) { QDataStream *stream = new QDataStream(data); (*stream) >> map;