From 696e7324a4f4d1fb5f96b11b73916da8bfe5605c Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 01:10:51 +0100 Subject: [PATCH] SoapySDR support: device arg GUI --- devices/soapysdr/devicesoapysdrparams.h | 2 + devices/soapysdr/devicesoapysdrshared.cpp | 2 + devices/soapysdr/devicesoapysdrshared.h | 21 ++++ .../soapysdroutput/soapysdroutput.cpp | 106 +++++++++++++++++- .../soapysdroutput/soapysdroutput.h | 2 + .../soapysdroutput/soapysdroutputgui.cpp | 54 ++++++++- .../soapysdroutput/soapysdroutputgui.h | 5 +- .../soapysdroutput/soapysdroutputsettings.cpp | 3 + .../soapysdroutput/soapysdroutputsettings.h | 1 + .../soapysdrinput/soapysdrinput.cpp | 102 ++++++++++++++++- .../soapysdrinput/soapysdrinput.h | 2 + .../soapysdrinput/soapysdrinputgui.cpp | 54 ++++++++- .../soapysdrinput/soapysdrinputgui.h | 5 +- .../soapysdrinput/soapysdrinputsettings.cpp | 3 + .../soapysdrinput/soapysdrinputsettings.h | 1 + 15 files changed, 345 insertions(+), 18 deletions(-) diff --git a/devices/soapysdr/devicesoapysdrparams.h b/devices/soapysdr/devicesoapysdrparams.h index 2489b8f85..74886c147 100644 --- a/devices/soapysdr/devicesoapysdrparams.h +++ b/devices/soapysdr/devicesoapysdrparams.h @@ -68,6 +68,8 @@ public: DeviceSoapySDRParams(SoapySDR::Device *device); ~DeviceSoapySDRParams(); + const SoapySDR::ArgInfoList& getDeviceArgs() const { return m_deviceSettingsArgs; } + const ChannelSettings* getRxChannelSettings(uint32_t index) { if (index < m_nbRx) { diff --git a/devices/soapysdr/devicesoapysdrshared.cpp b/devices/soapysdr/devicesoapysdrshared.cpp index e7ef10f70..a5f04466c 100644 --- a/devices/soapysdr/devicesoapysdrshared.cpp +++ b/devices/soapysdr/devicesoapysdrshared.cpp @@ -17,6 +17,7 @@ #include "devicesoapysdrshared.h" MESSAGE_CLASS_DEFINITION(DeviceSoapySDRShared::MsgReportBuddyChange, Message) +MESSAGE_CLASS_DEFINITION(DeviceSoapySDRShared::MsgReportDeviceArgsChange, Message) const float DeviceSoapySDRShared::m_sampleFifoLengthInSeconds = 0.25; const int DeviceSoapySDRShared::m_sampleFifoMinSize = 75000; // 300 kS/s knee @@ -24,6 +25,7 @@ const int DeviceSoapySDRShared::m_sampleFifoMinSize32 = 150000; // Fixed for DeviceSoapySDRShared::DeviceSoapySDRShared() : m_device(0), + m_deviceParams(0), m_channel(-1), m_source(0), m_sink(0) diff --git a/devices/soapysdr/devicesoapysdrshared.h b/devices/soapysdr/devicesoapysdrshared.h index 85adc878a..d219b70ac 100644 --- a/devices/soapysdr/devicesoapysdrshared.h +++ b/devices/soapysdr/devicesoapysdrshared.h @@ -17,6 +17,9 @@ #ifndef DEVICES_SOAPYSDR_DEVICESOAPYSDRSHARED_H_ #define DEVICES_SOAPYSDR_DEVICESOAPYSDRSHARED_H_ +#include +#include + #include #include "util/message.h" @@ -79,6 +82,24 @@ public: { } }; + class MsgReportDeviceArgsChange : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const QMap& getDeviceArgSettings() const { return m_deviceArgSettings; } + + static MsgReportDeviceArgsChange* create(const QMap& deviceArgSettings) { + return new MsgReportDeviceArgsChange(deviceArgSettings); + } + + private: + QMap m_deviceArgSettings; + + MsgReportDeviceArgsChange(const QMap& deviceArgSettings) : + m_deviceArgSettings(deviceArgSettings) + { } + }; + DeviceSoapySDRShared(); ~DeviceSoapySDRShared(); diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index eb34bd45e..bda2be9e1 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -39,6 +39,7 @@ SoapySDROutput::SoapySDROutput(DeviceSinkAPI *deviceAPI) : openDevice(); initGainSettings(m_settings); initStreamArgSettings(m_settings); + initDeviceArgSettings(m_settings); } SoapySDROutput::~SoapySDROutput() @@ -238,6 +239,11 @@ const std::vector& SoapySDROutput::getIndivid return channelSettings->m_gainSettings; } +const SoapySDR::ArgInfoList& SoapySDROutput::getDeviceArgInfoList() +{ + return m_deviceShared.m_deviceParams->getDeviceArgs(); +} + void SoapySDROutput::initGainSettings(SoapySDROutputSettings& settings) { const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getTxChannelSettings(m_deviceShared.m_channel); @@ -276,6 +282,24 @@ void SoapySDROutput::initStreamArgSettings(SoapySDROutputSettings& settings) } } +void SoapySDROutput::initDeviceArgSettings(SoapySDROutputSettings& settings) +{ + settings.m_deviceArgSettings.clear(); + + for (const auto &it : m_deviceShared.m_deviceParams->getDeviceArgs()) + { + if (it.type == SoapySDR::ArgInfo::BOOL) { + settings.m_deviceArgSettings[QString(it.key.c_str())] = QVariant(it.value == "true"); + } else if (it.type == SoapySDR::ArgInfo::INT) { + settings.m_deviceArgSettings[QString(it.key.c_str())] = QVariant(atoi(it.value.c_str())); + } else if (it.type == SoapySDR::ArgInfo::FLOAT) { + settings.m_deviceArgSettings[QString(it.key.c_str())] = QVariant(atof(it.value.c_str())); + } else if (it.type == SoapySDR::ArgInfo::STRING) { + settings.m_deviceArgSettings[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); @@ -723,6 +747,33 @@ bool SoapySDROutput::handleMessage(const Message& message) return true; } + else if (DeviceSoapySDRShared::MsgReportDeviceArgsChange::match(message)) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange& report = (DeviceSoapySDRShared::MsgReportDeviceArgsChange&) message; + QMap deviceArgSettings = report.getDeviceArgSettings(); + + for (const auto &oname : m_settings.m_deviceArgSettings.keys()) + { + auto nvalue = deviceArgSettings.find(oname); + + if (nvalue != deviceArgSettings.end() && (m_settings.m_deviceArgSettings[oname] != *nvalue)) + { + m_settings.m_deviceArgSettings[oname] = *nvalue; + qDebug("SoapySDROutput::handleMessage: MsgReportDeviceArgsChange: device argument %s set to %s", + oname.toStdString().c_str(), nvalue->toString().toStdString().c_str()); + } + } + + // propagate settings to GUI if any + if (getMessageQueueToGUI()) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange *reportToGUI = DeviceSoapySDRShared::MsgReportDeviceArgsChange::create( + m_settings.m_deviceArgSettings); + getMessageQueueToGUI()->push(reportToGUI); + } + + return true; + } else { return false; @@ -735,6 +786,7 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool bool forwardChangeToBuddies = false; bool globalGainChanged = false; bool individualGainsChanged = false; + bool deviceArgsChanged = false; SoapySDR::Device *dev = m_deviceShared.m_device; SoapySDROutputThread *outputThread = findThread(); @@ -1012,13 +1064,12 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool try { dev->writeSetting(SOAPY_SDR_TX, requestedChannel, oname.toStdString(), nvalue->toString().toStdString()); - qDebug("SoapySDRInput::applySettings: stream argument %s set to %s", + qDebug("SoapySDROutput::applySettings: stream argument %s set to %s", oname.toStdString().c_str(), nvalue->toString().toStdString().c_str()); - individualGainsChanged = true; } catch (const std::exception &ex) { - qCritical("SoapySDRInput::applySettings: cannot set stream argument %s to %s: %s", + qCritical("SoapySDROutput::applySettings: cannot set stream argument %s to %s: %s", oname.toStdString().c_str(), nvalue->toString().toStdString().c_str(), ex.what()); } } @@ -1027,6 +1078,32 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool } } + for (const auto &oname : m_settings.m_deviceArgSettings.keys()) + { + auto nvalue = settings.m_deviceArgSettings.find(oname); + + if (nvalue != settings.m_deviceArgSettings.end() && ((m_settings.m_deviceArgSettings[oname] != *nvalue) || force)) + { + if (dev != 0) + { + try + { + dev->writeSetting(oname.toStdString(), nvalue->toString().toStdString()); + qDebug("SoapySDROutput::applySettings: device argument %s set to %s", + oname.toStdString().c_str(), nvalue->toString().toStdString().c_str()); + } + catch (const std::exception &ex) + { + qCritical("SoapySDRInput::applySettings: cannot set device argument %s to %s: %s", + oname.toStdString().c_str(), nvalue->toString().toStdString().c_str(), ex.what()); + } + } + + m_settings.m_deviceArgSettings[oname] = *nvalue; + deviceArgsChanged = true; + } + } + if (forwardChangeOwnDSP) { int sampleRate = settings.m_devSampleRate/(1<& sourceBuddies = m_deviceAPI->getSourceBuddies(); const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); @@ -1063,6 +1140,27 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool } } + if (deviceArgsChanged) + { + // send to buddies + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + + for (const auto &itSource : sourceBuddies) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange *report = DeviceSoapySDRShared::MsgReportDeviceArgsChange::create( + settings.m_deviceArgSettings); + itSource->getSampleSourceInputMessageQueue()->push(report); + } + + for (const auto &itSink : sinkBuddies) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange *report = DeviceSoapySDRShared::MsgReportDeviceArgsChange::create( + settings.m_deviceArgSettings); + itSink->getSampleSinkInputMessageQueue()->push(report); + } + } + m_settings = settings; if (globalGainChanged || individualGainsChanged) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.h b/plugins/samplesink/soapysdroutput/soapysdroutput.h index 1801b93f1..cb7a0973d 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.h @@ -134,8 +134,10 @@ public: const std::vector& getTunableElements(); const std::vector& getIndividualGainsRanges(); const SoapySDR::ArgInfoList& getStreamArgInfoList(); + const SoapySDR::ArgInfoList& getDeviceArgInfoList(); void initGainSettings(SoapySDROutputSettings& settings); void initStreamArgSettings(SoapySDROutputSettings& settings); + void initDeviceArgSettings(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 3a85e278a..3d997a8f3 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp @@ -69,9 +69,11 @@ SoapySDROutputGui::SoapySDROutputGui(DeviceUISet *deviceUISet, QWidget* parent) createTunableElementsControl(m_sampleSink->getTunableElements()); createGlobalGainControl(); createIndividualGainsControl(m_sampleSink->getIndividualGainsRanges()); - createStreamArgumentsControl(m_sampleSink->getStreamArgInfoList()); + createArgumentsControl(m_sampleSink->getDeviceArgInfoList(), true); + createArgumentsControl(m_sampleSink->getStreamArgInfoList(), false); m_sampleSink->initGainSettings(m_settings); m_sampleSink->initStreamArgSettings(m_settings); + m_sampleSink->initDeviceArgSettings(m_settings); if (m_sampleRateGUI) { connect(m_sampleRateGUI, SIGNAL(valueChanged(double)), this, SLOT(sampleRateChanged(double))); @@ -307,7 +309,7 @@ void SoapySDROutputGui::createCorrectionsControl() } } -void SoapySDROutputGui::createStreamArgumentsControl(const SoapySDR::ArgInfoList& argInfoList) +void SoapySDROutputGui::createArgumentsControl(const SoapySDR::ArgInfoList& argInfoList, bool deviceArguments) { if (argInfoList.size() == 0) { // return early if list is empty return; @@ -356,7 +358,10 @@ void SoapySDROutputGui::createStreamArgumentsControl(const SoapySDR::ArgInfoList for (int i = 0; optionIt != it->options.end(); ++optionIt, i++) { QString name(optionNameIt == it->optionNames.end() ? optionIt->c_str() : optionNameIt->c_str()); - ++optionNameIt; + + if (optionNameIt != it->optionNames.end()) { + ++optionNameIt; + } if (valueType == ArgInfoGUI::ArgInfoValueInt) { argGUI->addIntValue(name, atoi(optionIt->c_str())); @@ -382,8 +387,18 @@ void SoapySDROutputGui::createStreamArgumentsControl(const SoapySDR::ArgInfoList layout->addWidget(argGUI); DynamicArgSettingGUI *gui = new DynamicArgSettingGUI(argGUI, QString(it->key.c_str())); - m_streamArgsGUIs.push_back(gui); - connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(streamArgChanged(QString, QVariant))); + + // This could be made more elegant but let's make it more simple + if (deviceArguments) + { + m_deviceArgsGUIs.push_back(gui); + connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(deviceArgChanged(QString, QVariant))); + } + else + { + m_streamArgsGUIs.push_back(gui); + connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(streamArgChanged(QString, QVariant))); + } } } @@ -465,6 +480,14 @@ bool SoapySDROutputGui::handleMessage(const Message& message) return true; } + else if (DeviceSoapySDRShared::MsgReportDeviceArgsChange::match(message)) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange& notif = (DeviceSoapySDRShared::MsgReportDeviceArgsChange&) message; + m_settings.m_deviceArgSettings = notif.getDeviceArgSettings(); + displayDeviceArgsSettings(); + + return true; + } else if (SoapySDROutput::MsgStartStop::match(message)) { SoapySDROutput::MsgStartStop& notif = (SoapySDROutput::MsgStartStop&) message; @@ -599,6 +622,12 @@ void SoapySDROutputGui::streamArgChanged(QString itemName, QVariant value) sendSettings(); } +void SoapySDROutputGui::deviceArgChanged(QString itemName, QVariant value) +{ + m_settings.m_deviceArgSettings[itemName] = value; + sendSettings(); +} + void SoapySDROutputGui::on_centerFrequency_changed(quint64 value) { m_settings.m_centerFrequency = value * 1000; @@ -676,6 +705,7 @@ void SoapySDROutputGui::displaySettings() displayIndividualGainsControlSettings(); displayCorrectionsSettings(); displayStreamArgsSettings(); + displayDeviceArgsSettings(); blockApplySettings(false); } @@ -745,6 +775,20 @@ void SoapySDROutputGui::displayStreamArgsSettings() } } +void SoapySDROutputGui::displayDeviceArgsSettings() +{ + for (const auto &it : m_deviceArgsGUIs) + { + QMap::iterator elIt = m_settings.m_deviceArgSettings.find(it->getName()); + + if (elIt != m_settings.m_deviceArgSettings.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 be2ed1916..655c25df2 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputgui.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutputgui.h @@ -70,7 +70,7 @@ private: void createGlobalGainControl(); void createIndividualGainsControl(const std::vector& individualGainsList); void createCorrectionsControl(); - void createStreamArgumentsControl(const SoapySDR::ArgInfoList& argInfoList); + void createArgumentsControl(const SoapySDR::ArgInfoList& argInfoList, bool deviceArguments); Ui::SoapySDROutputGui* ui; @@ -98,6 +98,7 @@ private: QCheckBox *m_autoDCCorrection; QCheckBox *m_autoIQCorrection; std::vector m_streamArgsGUIs; + std::vector m_deviceArgsGUIs; void blockApplySettings(bool block) { m_doApplySettings = !block; } void displaySettings(); @@ -105,6 +106,7 @@ private: void displayIndividualGainsControlSettings(); void displayCorrectionsSettings(); void displayStreamArgsSettings(); + void displayDeviceArgsSettings(); void sendSettings(); void updateSampleRateAndFrequency(); void updateFrequencyLimits(); @@ -127,6 +129,7 @@ private slots: void iqCorrectionModuleChanged(double value); void iqCorrectionArgumentChanged(double value); void streamArgChanged(QString itemName, QVariant value); + void deviceArgChanged(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 1db9702c4..5e95ddb8b 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputsettings.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputsettings.cpp @@ -66,6 +66,7 @@ QByteArray SoapySDROutputSettings::serialize() const s.writeDouble(19, m_iqCorrection.real()); s.writeDouble(20, m_iqCorrection.imag()); s.writeBlob(21, serializeArgumentMap(m_streamArgSettings)); + s.writeBlob(22, serializeArgumentMap(m_deviceArgSettings)); return s.final(); } @@ -108,6 +109,8 @@ bool SoapySDROutputSettings::deserialize(const QByteArray& data) m_iqCorrection = std::complex{realval, imagval}; d.readBlob(21, &blob); deserializeArgumentMap(blob, m_streamArgSettings); + d.readBlob(22, &blob); + deserializeArgumentMap(blob, m_deviceArgSettings); return true; } diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputsettings.h b/plugins/samplesink/soapysdroutput/soapysdroutputsettings.h index 992bba988..110b38910 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputsettings.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutputsettings.h @@ -39,6 +39,7 @@ struct SoapySDROutputSettings { std::complex m_dcCorrection; std::complex m_iqCorrection; QMap m_streamArgSettings; + QMap m_deviceArgSettings; SoapySDROutputSettings(); void resetToDefaults(); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 4fabed3d7..3b31b221b 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -43,6 +43,7 @@ SoapySDRInput::SoapySDRInput(DeviceSourceAPI *deviceAPI) : openDevice(); initGainSettings(m_settings); initStreamArgSettings(m_settings); + initDeviceArgSettings(m_settings); m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID())); m_deviceAPI->addSink(m_fileSink); @@ -276,6 +277,11 @@ const SoapySDR::ArgInfoList& SoapySDRInput::getStreamArgInfoList() return channelSettings->m_streamSettingsArgs; } +const SoapySDR::ArgInfoList& SoapySDRInput::getDeviceArgInfoList() +{ + return m_deviceShared.m_deviceParams->getDeviceArgs(); +} + void SoapySDRInput::initGainSettings(SoapySDRInputSettings& settings) { const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(m_deviceShared.m_channel); @@ -308,6 +314,24 @@ void SoapySDRInput::initStreamArgSettings(SoapySDRInputSettings& settings) } } +void SoapySDRInput::initDeviceArgSettings(SoapySDRInputSettings& settings) +{ + settings.m_deviceArgSettings.clear(); + + for (const auto &it : m_deviceShared.m_deviceParams->getDeviceArgs()) + { + if (it.type == SoapySDR::ArgInfo::BOOL) { + settings.m_deviceArgSettings[QString(it.key.c_str())] = QVariant(it.value == "true"); + } else if (it.type == SoapySDR::ArgInfo::INT) { + settings.m_deviceArgSettings[QString(it.key.c_str())] = QVariant(atoi(it.value.c_str())); + } else if (it.type == SoapySDR::ArgInfo::FLOAT) { + settings.m_deviceArgSettings[QString(it.key.c_str())] = QVariant(atof(it.value.c_str())); + } else if (it.type == SoapySDR::ArgInfo::STRING) { + settings.m_deviceArgSettings[QString(it.key.c_str())] = QVariant(it.value.c_str()); + } + } +} + bool SoapySDRInput::hasDCAutoCorrection() { const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(m_deviceShared.m_channel); @@ -777,6 +801,33 @@ bool SoapySDRInput::handleMessage(const Message& message __attribute__((unused)) return true; } + else if (DeviceSoapySDRShared::MsgReportDeviceArgsChange::match(message)) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange& report = (DeviceSoapySDRShared::MsgReportDeviceArgsChange&) message; + QMap deviceArgSettings = report.getDeviceArgSettings(); + + for (const auto &oname : m_settings.m_deviceArgSettings.keys()) + { + auto nvalue = deviceArgSettings.find(oname); + + if (nvalue != deviceArgSettings.end() && (m_settings.m_deviceArgSettings[oname] != *nvalue)) + { + m_settings.m_deviceArgSettings[oname] = *nvalue; + qDebug("SoapySDRInput::handleMessage: MsgReportDeviceArgsChange: device argument %s set to %s", + oname.toStdString().c_str(), nvalue->toString().toStdString().c_str()); + } + } + + // propagate settings to GUI if any + if (getMessageQueueToGUI()) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange *reportToGUI = DeviceSoapySDRShared::MsgReportDeviceArgsChange::create( + m_settings.m_deviceArgSettings); + getMessageQueueToGUI()->push(reportToGUI); + } + + return true; + } else { return false; @@ -789,6 +840,7 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo bool forwardChangeToBuddies = false; bool globalGainChanged = false; bool individualGainsChanged = false; + bool deviceArgsChanged = false; SoapySDR::Device *dev = m_deviceShared.m_device; SoapySDRInputThread *inputThread = findThread(); @@ -1060,7 +1112,6 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo dev->writeSetting(SOAPY_SDR_RX, requestedChannel, oname.toStdString(), nvalue->toString().toStdString()); qDebug("SoapySDRInput::applySettings: stream argument %s set to %s", oname.toStdString().c_str(), nvalue->toString().toStdString().c_str()); - individualGainsChanged = true; } catch (const std::exception &ex) { @@ -1073,6 +1124,32 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo } } + for (const auto &oname : m_settings.m_deviceArgSettings.keys()) + { + auto nvalue = settings.m_deviceArgSettings.find(oname); + + if (nvalue != settings.m_deviceArgSettings.end() && ((m_settings.m_deviceArgSettings[oname] != *nvalue) || force)) + { + if (dev != 0) + { + try + { + dev->writeSetting(oname.toStdString(), nvalue->toString().toStdString()); + qDebug("SoapySDRInput::applySettings: device argument %s set to %s", + oname.toStdString().c_str(), nvalue->toString().toStdString().c_str()); + } + catch (const std::exception &ex) + { + qCritical("SoapySDRInput::applySettings: cannot set device argument %s to %s: %s", + oname.toStdString().c_str(), nvalue->toString().toStdString().c_str(), ex.what()); + } + } + + m_settings.m_deviceArgSettings[oname] = *nvalue; + deviceArgsChanged = true; + } + } + if (forwardChangeOwnDSP) { int sampleRate = settings.m_devSampleRate/(1<& sourceBuddies = m_deviceAPI->getSourceBuddies(); const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); @@ -1110,6 +1187,27 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo } } + if (deviceArgsChanged) + { + // send to buddies + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + + for (const auto &itSource : sourceBuddies) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange *report = DeviceSoapySDRShared::MsgReportDeviceArgsChange::create( + settings.m_deviceArgSettings); + itSource->getSampleSourceInputMessageQueue()->push(report); + } + + for (const auto &itSink : sinkBuddies) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange *report = DeviceSoapySDRShared::MsgReportDeviceArgsChange::create( + settings.m_deviceArgSettings); + itSink->getSampleSinkInputMessageQueue()->push(report); + } + } + m_settings = settings; if (globalGainChanged || individualGainsChanged) diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.h b/plugins/samplesource/soapysdrinput/soapysdrinput.h index e5d4002b9..00501f39b 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.h @@ -156,8 +156,10 @@ public: const std::vector& getTunableElements(); const std::vector& getIndividualGainsRanges(); const SoapySDR::ArgInfoList& getStreamArgInfoList(); + const SoapySDR::ArgInfoList& getDeviceArgInfoList(); void initGainSettings(SoapySDRInputSettings& settings); void initStreamArgSettings(SoapySDRInputSettings& settings); + void initDeviceArgSettings(SoapySDRInputSettings& settings); bool hasDCAutoCorrection(); bool hasDCCorrectionValue(); bool hasIQAutoCorrection() { return false; } // not in SoapySDR interface diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp index cff84df2d..b8382d0c1 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -70,9 +70,11 @@ SoapySDRInputGui::SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) : createTunableElementsControl(m_sampleSource->getTunableElements()); createGlobalGainControl(); createIndividualGainsControl(m_sampleSource->getIndividualGainsRanges()); - createStreamArgumentsControl(m_sampleSource->getStreamArgInfoList()); + createArgumentsControl(m_sampleSource->getDeviceArgInfoList(), true); + createArgumentsControl(m_sampleSource->getStreamArgInfoList(), false); m_sampleSource->initGainSettings(m_settings); m_sampleSource->initStreamArgSettings(m_settings); + m_sampleSource->initDeviceArgSettings(m_settings); if (m_sampleRateGUI) { connect(m_sampleRateGUI, SIGNAL(valueChanged(double)), this, SLOT(sampleRateChanged(double))); @@ -310,7 +312,7 @@ void SoapySDRInputGui::createCorrectionsControl() } } -void SoapySDRInputGui::createStreamArgumentsControl(const SoapySDR::ArgInfoList& argInfoList) +void SoapySDRInputGui::createArgumentsControl(const SoapySDR::ArgInfoList& argInfoList, bool deviceArguments) { if (argInfoList.size() == 0) { // return early if list is empty return; @@ -359,7 +361,10 @@ void SoapySDRInputGui::createStreamArgumentsControl(const SoapySDR::ArgInfoList& for (int i = 0; optionIt != it->options.end(); ++optionIt, i++) { QString name(optionNameIt == it->optionNames.end() ? optionIt->c_str() : optionNameIt->c_str()); - ++optionNameIt; + + if (optionNameIt != it->optionNames.end()) { + ++optionNameIt; + } if (valueType == ArgInfoGUI::ArgInfoValueInt) { argGUI->addIntValue(name, atoi(optionIt->c_str())); @@ -385,8 +390,18 @@ void SoapySDRInputGui::createStreamArgumentsControl(const SoapySDR::ArgInfoList& layout->addWidget(argGUI); DynamicArgSettingGUI *gui = new DynamicArgSettingGUI(argGUI, QString(it->key.c_str())); - m_streamArgsGUIs.push_back(gui); - connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(streamArgChanged(QString, QVariant))); + + // This could be made more elegant but let's make it more simple + if (deviceArguments) + { + m_deviceArgsGUIs.push_back(gui); + connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(deviceArgChanged(QString, QVariant))); + } + else + { + m_streamArgsGUIs.push_back(gui); + connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(streamArgChanged(QString, QVariant))); + } } } @@ -467,6 +482,14 @@ bool SoapySDRInputGui::handleMessage(const Message& message) return true; } + else if (DeviceSoapySDRShared::MsgReportDeviceArgsChange::match(message)) + { + DeviceSoapySDRShared::MsgReportDeviceArgsChange& notif = (DeviceSoapySDRShared::MsgReportDeviceArgsChange&) message; + m_settings.m_deviceArgSettings = notif.getDeviceArgSettings(); + displayDeviceArgsSettings(); + + return true; + } else if (SoapySDRInput::MsgStartStop::match(message)) { SoapySDRInput::MsgStartStop& notif = (SoapySDRInput::MsgStartStop&) message; @@ -602,6 +625,12 @@ void SoapySDRInputGui::streamArgChanged(QString itemName, QVariant value) sendSettings(); } +void SoapySDRInputGui::deviceArgChanged(QString itemName, QVariant value) +{ + m_settings.m_deviceArgSettings[itemName] = value; + sendSettings(); +} + void SoapySDRInputGui::on_centerFrequency_changed(quint64 value) { m_settings.m_centerFrequency = value * 1000; @@ -722,6 +751,7 @@ void SoapySDRInputGui::displaySettings() displayIndividualGainsControlSettings(); displayCorrectionsSettings(); displayStreamArgsSettings(); + displayDeviceArgsSettings(); blockApplySettings(false); } @@ -791,6 +821,20 @@ void SoapySDRInputGui::displayStreamArgsSettings() } } +void SoapySDRInputGui::displayDeviceArgsSettings() +{ + for (const auto &it : m_deviceArgsGUIs) + { + QMap::iterator elIt = m_settings.m_deviceArgSettings.find(it->getName()); + + if (elIt != m_settings.m_deviceArgSettings.end()) + { + it->setValue(*elIt); + *elIt = it->getValue(); + } + } +} + void SoapySDRInputGui::sendSettings() { if (!m_updateTimer.isActive()) { diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.h b/plugins/samplesource/soapysdrinput/soapysdrinputgui.h index 262cd9e8b..e71340818 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.h @@ -68,7 +68,7 @@ private: void createGlobalGainControl(); void createIndividualGainsControl(const std::vector& individualGainsList); void createCorrectionsControl(); - void createStreamArgumentsControl(const SoapySDR::ArgInfoList& argInfoList); + void createArgumentsControl(const SoapySDR::ArgInfoList& argInfoList, bool deviceArguments); Ui::SoapySDRInputGui* ui; @@ -96,12 +96,14 @@ private: QCheckBox *m_autoDCCorrection; QCheckBox *m_autoIQCorrection; std::vector m_streamArgsGUIs; + std::vector m_deviceArgsGUIs; void displaySettings(); void displayTunableElementsControlSettings(); void displayIndividualGainsControlSettings(); void displayCorrectionsSettings(); void displayStreamArgsSettings(); + void displayDeviceArgsSettings(); void sendSettings(); void updateSampleRateAndFrequency(); void updateFrequencyLimits(); @@ -124,6 +126,7 @@ private slots: void iqCorrectionModuleChanged(double value); void iqCorrectionArgumentChanged(double value); void streamArgChanged(QString itemName, QVariant value); + void deviceArgChanged(QString itemName, QVariant value); void on_centerFrequency_changed(quint64 value); void on_LOppm_valueChanged(int value); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp index 6728a2cde..72500dfec 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp @@ -72,6 +72,7 @@ QByteArray SoapySDRInputSettings::serialize() const s.writeDouble(19, m_iqCorrection.real()); s.writeDouble(20, m_iqCorrection.imag()); s.writeBlob(21, serializeArgumentMap(m_streamArgSettings)); + s.writeBlob(22, serializeArgumentMap(m_deviceArgSettings)); return s.final(); } @@ -119,6 +120,8 @@ bool SoapySDRInputSettings::deserialize(const QByteArray& data) m_iqCorrection = std::complex{realval, imagval}; d.readBlob(21, &blob); deserializeArgumentMap(blob, m_streamArgSettings); + d.readBlob(22, &blob); + deserializeArgumentMap(blob, m_deviceArgSettings); return true; } diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputsettings.h b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.h index 1cc7e47be..82bf66f25 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputsettings.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.h @@ -50,6 +50,7 @@ struct SoapySDRInputSettings { std::complex m_dcCorrection; std::complex m_iqCorrection; QMap m_streamArgSettings; + QMap m_deviceArgSettings; SoapySDRInputSettings(); void resetToDefaults();