mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	SoapySDR support: output: stream ArgInfo GUI
This commit is contained in:
		
							parent
							
								
									1005d1d4e5
								
							
						
					
					
						commit
						f436479bd7
					
				| @ -250,6 +250,31 @@ void SoapySDROutput::initGainSettings(SoapySDROutputSettings& settings) | |||||||
|     updateGains(m_deviceShared.m_device, m_deviceShared.m_channel, 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() | bool SoapySDROutput::hasDCAutoCorrection() | ||||||
| { | { | ||||||
|     const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getTxChannelSettings(m_deviceShared.m_channel); |     const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getTxChannelSettings(m_deviceShared.m_channel); | ||||||
|  | |||||||
| @ -133,7 +133,9 @@ public: | |||||||
|     const SoapySDR::RangeList& getBandwidthRanges(); |     const SoapySDR::RangeList& getBandwidthRanges(); | ||||||
|     const std::vector<DeviceSoapySDRParams::FrequencySetting>& getTunableElements(); |     const std::vector<DeviceSoapySDRParams::FrequencySetting>& getTunableElements(); | ||||||
|     const std::vector<DeviceSoapySDRParams::GainSetting>& getIndividualGainsRanges(); |     const std::vector<DeviceSoapySDRParams::GainSetting>& getIndividualGainsRanges(); | ||||||
|  |     const SoapySDR::ArgInfoList& getStreamArgInfoList(); | ||||||
|     void initGainSettings(SoapySDROutputSettings& settings); |     void initGainSettings(SoapySDROutputSettings& settings); | ||||||
|  |     void initStreamArgSettings(SoapySDROutputSettings& settings); | ||||||
|     bool hasDCAutoCorrection(); |     bool hasDCAutoCorrection(); | ||||||
|     bool hasDCCorrectionValue(); |     bool hasDCCorrectionValue(); | ||||||
|     bool hasIQAutoCorrection() { return false; } // not in SoapySDR interface
 |     bool hasIQAutoCorrection() { return false; } // not in SoapySDR interface
 | ||||||
|  | |||||||
| @ -30,6 +30,8 @@ | |||||||
| #include "soapygui/dynamicitemsettinggui.h" | #include "soapygui/dynamicitemsettinggui.h" | ||||||
| #include "soapygui/intervalslidergui.h" | #include "soapygui/intervalslidergui.h" | ||||||
| #include "soapygui/complexfactorgui.h" | #include "soapygui/complexfactorgui.h" | ||||||
|  | #include "soapygui/arginfogui.h" | ||||||
|  | #include "soapygui/dynamicargsettinggui.h" | ||||||
| 
 | 
 | ||||||
| #include "soapysdroutputgui.h" | #include "soapysdroutputgui.h" | ||||||
| 
 | 
 | ||||||
| @ -67,7 +69,9 @@ SoapySDROutputGui::SoapySDROutputGui(DeviceUISet *deviceUISet, QWidget* parent) | |||||||
|     createTunableElementsControl(m_sampleSink->getTunableElements()); |     createTunableElementsControl(m_sampleSink->getTunableElements()); | ||||||
|     createGlobalGainControl(); |     createGlobalGainControl(); | ||||||
|     createIndividualGainsControl(m_sampleSink->getIndividualGainsRanges()); |     createIndividualGainsControl(m_sampleSink->getIndividualGainsRanges()); | ||||||
|  |     createStreamArgumentsControl(m_sampleSink->getStreamArgInfoList()); | ||||||
|     m_sampleSink->initGainSettings(m_settings); |     m_sampleSink->initGainSettings(m_settings); | ||||||
|  |     m_sampleSink->initStreamArgSettings(m_settings); | ||||||
| 
 | 
 | ||||||
|     if (m_sampleRateGUI) { |     if (m_sampleRateGUI) { | ||||||
|         connect(m_sampleRateGUI, SIGNAL(valueChanged(double)), this, SLOT(sampleRateChanged(double))); |         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<SoapySDR::ArgInfo>::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<std::string>::const_iterator optionIt = it->options.begin(); | ||||||
|  |             std::vector<std::string>::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) | void SoapySDROutputGui::setName(const QString& name) | ||||||
| { | { | ||||||
|     setObjectName(name); |     setObjectName(name); | ||||||
| @ -509,6 +593,12 @@ void SoapySDROutputGui::iqCorrectionArgumentChanged(double value) | |||||||
|     sendSettings(); |     sendSettings(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void SoapySDROutputGui::streamArgChanged(QString itemName, QVariant value) | ||||||
|  | { | ||||||
|  |     m_settings.m_streamArgSettings[itemName] = value; | ||||||
|  |     sendSettings(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void SoapySDROutputGui::on_centerFrequency_changed(quint64 value) | void SoapySDROutputGui::on_centerFrequency_changed(quint64 value) | ||||||
| { | { | ||||||
|     m_settings.m_centerFrequency = value * 1000; |     m_settings.m_centerFrequency = value * 1000; | ||||||
| @ -585,6 +675,7 @@ void SoapySDROutputGui::displaySettings() | |||||||
|     displayTunableElementsControlSettings(); |     displayTunableElementsControlSettings(); | ||||||
|     displayIndividualGainsControlSettings(); |     displayIndividualGainsControlSettings(); | ||||||
|     displayCorrectionsSettings(); |     displayCorrectionsSettings(); | ||||||
|  |     displayStreamArgsSettings(); | ||||||
| 
 | 
 | ||||||
|     blockApplySettings(false); |     blockApplySettings(false); | ||||||
| } | } | ||||||
| @ -640,6 +731,20 @@ void SoapySDROutputGui::displayCorrectionsSettings() | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void SoapySDROutputGui::displayStreamArgsSettings() | ||||||
|  | { | ||||||
|  |     for (const auto &it : m_streamArgsGUIs) | ||||||
|  |     { | ||||||
|  |         QMap<QString, QVariant>::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() | void SoapySDROutputGui::sendSettings() | ||||||
| { | { | ||||||
|     if (!m_updateTimer.isActive()) { |     if (!m_updateTimer.isActive()) { | ||||||
|  | |||||||
| @ -31,6 +31,7 @@ class DeviceUISet; | |||||||
| class ItemSettingGUI; | class ItemSettingGUI; | ||||||
| class StringRangeGUI; | class StringRangeGUI; | ||||||
| class DynamicItemSettingGUI; | class DynamicItemSettingGUI; | ||||||
|  | class DynamicArgSettingGUI; | ||||||
| class IntervalSliderGUI; | class IntervalSliderGUI; | ||||||
| class QCheckBox; | class QCheckBox; | ||||||
| class ComplexFactorGUI; | class ComplexFactorGUI; | ||||||
| @ -69,6 +70,7 @@ private: | |||||||
|     void createGlobalGainControl(); |     void createGlobalGainControl(); | ||||||
|     void createIndividualGainsControl(const std::vector<DeviceSoapySDRParams::GainSetting>& individualGainsList); |     void createIndividualGainsControl(const std::vector<DeviceSoapySDRParams::GainSetting>& individualGainsList); | ||||||
|     void createCorrectionsControl(); |     void createCorrectionsControl(); | ||||||
|  |     void createStreamArgumentsControl(const SoapySDR::ArgInfoList& argInfoList); | ||||||
| 
 | 
 | ||||||
|     Ui::SoapySDROutputGui* ui; |     Ui::SoapySDROutputGui* ui; | ||||||
| 
 | 
 | ||||||
| @ -95,12 +97,14 @@ private: | |||||||
|     ComplexFactorGUI *m_iqCorrectionGUI; |     ComplexFactorGUI *m_iqCorrectionGUI; | ||||||
|     QCheckBox *m_autoDCCorrection; |     QCheckBox *m_autoDCCorrection; | ||||||
|     QCheckBox *m_autoIQCorrection; |     QCheckBox *m_autoIQCorrection; | ||||||
|  |     std::vector<DynamicArgSettingGUI*> m_streamArgsGUIs; | ||||||
| 
 | 
 | ||||||
|     void blockApplySettings(bool block) { m_doApplySettings = !block; } |     void blockApplySettings(bool block) { m_doApplySettings = !block; } | ||||||
|     void displaySettings(); |     void displaySettings(); | ||||||
|     void displayTunableElementsControlSettings(); |     void displayTunableElementsControlSettings(); | ||||||
|     void displayIndividualGainsControlSettings(); |     void displayIndividualGainsControlSettings(); | ||||||
|     void displayCorrectionsSettings(); |     void displayCorrectionsSettings(); | ||||||
|  |     void displayStreamArgsSettings(); | ||||||
|     void sendSettings(); |     void sendSettings(); | ||||||
|     void updateSampleRateAndFrequency(); |     void updateSampleRateAndFrequency(); | ||||||
|     void updateFrequencyLimits(); |     void updateFrequencyLimits(); | ||||||
| @ -122,6 +126,7 @@ private slots: | |||||||
|     void dcCorrectionArgumentChanged(double value); |     void dcCorrectionArgumentChanged(double value); | ||||||
|     void iqCorrectionModuleChanged(double value); |     void iqCorrectionModuleChanged(double value); | ||||||
|     void iqCorrectionArgumentChanged(double value); |     void iqCorrectionArgumentChanged(double value); | ||||||
|  |     void streamArgChanged(QString itemName, QVariant value); | ||||||
| 
 | 
 | ||||||
|     void on_centerFrequency_changed(quint64 value); |     void on_centerFrequency_changed(quint64 value); | ||||||
|     void on_LOppm_valueChanged(int value); |     void on_LOppm_valueChanged(int value); | ||||||
|  | |||||||
| @ -65,6 +65,7 @@ QByteArray SoapySDROutputSettings::serialize() const | |||||||
|     s.writeDouble(18, m_dcCorrection.imag()); |     s.writeDouble(18, m_dcCorrection.imag()); | ||||||
|     s.writeDouble(19, m_iqCorrection.real()); |     s.writeDouble(19, m_iqCorrection.real()); | ||||||
|     s.writeDouble(20, m_iqCorrection.imag()); |     s.writeDouble(20, m_iqCorrection.imag()); | ||||||
|  |     s.writeBlob(21, serializeArgumentMap(m_streamArgSettings)); | ||||||
| 
 | 
 | ||||||
|     return s.final(); |     return s.final(); | ||||||
| } | } | ||||||
| @ -105,6 +106,8 @@ bool SoapySDROutputSettings::deserialize(const QByteArray& data) | |||||||
|         d.readDouble(19, &realval, 0); |         d.readDouble(19, &realval, 0); | ||||||
|         d.readDouble(20, &imagval, 0); |         d.readDouble(20, &imagval, 0); | ||||||
|         m_iqCorrection = std::complex<double>{realval, imagval}; |         m_iqCorrection = std::complex<double>{realval, imagval}; | ||||||
|  |         d.readBlob(21, &blob); | ||||||
|  |         deserializeArgumentMap(blob, m_streamArgSettings); | ||||||
| 
 | 
 | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| @ -131,3 +134,21 @@ void SoapySDROutputSettings::deserializeNamedElementMap(const QByteArray& data, | |||||||
|     (*stream) >> map; |     (*stream) >> map; | ||||||
|     delete stream; |     delete stream; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | QByteArray SoapySDROutputSettings::serializeArgumentMap(const QMap<QString, QVariant>& map) const | ||||||
|  | { | ||||||
|  |     QByteArray data; | ||||||
|  |     QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly); | ||||||
|  |     (*stream) << map; | ||||||
|  |     delete stream; | ||||||
|  | 
 | ||||||
|  |     return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SoapySDROutputSettings::deserializeArgumentMap(const QByteArray& data, QMap<QString, QVariant>& map) | ||||||
|  | { | ||||||
|  |     QDataStream *stream = new QDataStream(data); | ||||||
|  |     (*stream) >> map; | ||||||
|  |     delete stream; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ | |||||||
| #define PLUGINS_SAMPLESINK_SOAPYSDROUTPUT_SOAPYSDROUTPUTSETTINGS_H_ | #define PLUGINS_SAMPLESINK_SOAPYSDROUTPUT_SOAPYSDROUTPUTSETTINGS_H_ | ||||||
| 
 | 
 | ||||||
| #include <QtGlobal> | #include <QtGlobal> | ||||||
|  | #include <QVariant> | ||||||
| #include <QMap> | #include <QMap> | ||||||
| 
 | 
 | ||||||
| struct SoapySDROutputSettings { | struct SoapySDROutputSettings { | ||||||
| @ -37,6 +38,7 @@ struct SoapySDROutputSettings { | |||||||
|     bool m_autoIQCorrection; |     bool m_autoIQCorrection; | ||||||
|     std::complex<double> m_dcCorrection; |     std::complex<double> m_dcCorrection; | ||||||
|     std::complex<double> m_iqCorrection; |     std::complex<double> m_iqCorrection; | ||||||
|  |     QMap<QString, QVariant> m_streamArgSettings; | ||||||
| 
 | 
 | ||||||
|     SoapySDROutputSettings(); |     SoapySDROutputSettings(); | ||||||
|     void resetToDefaults(); |     void resetToDefaults(); | ||||||
| @ -46,6 +48,9 @@ struct SoapySDROutputSettings { | |||||||
| private: | private: | ||||||
|     QByteArray serializeNamedElementMap(const QMap<QString, double>& map) const; |     QByteArray serializeNamedElementMap(const QMap<QString, double>& map) const; | ||||||
|     void deserializeNamedElementMap(const QByteArray& data, QMap<QString, double>& map); |     void deserializeNamedElementMap(const QByteArray& data, QMap<QString, double>& map); | ||||||
|  |     QByteArray serializeArgumentMap(const QMap<QString, QVariant>& map) const; | ||||||
|  |     void deserializeArgumentMap(const QByteArray& data, QMap<QString, QVariant>& map); | ||||||
|  | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif /* PLUGINS_SAMPLESINK_SOAPYSDROUTPUT_SOAPYSDROUTPUTSETTINGS_H_ */ | #endif /* PLUGINS_SAMPLESINK_SOAPYSDROUTPUT_SOAPYSDROUTPUTSETTINGS_H_ */ | ||||||
|  | |||||||
| @ -156,7 +156,7 @@ QByteArray SoapySDRInputSettings::serializeArgumentMap(const QMap<QString, QVari | |||||||
|     return data; |     return data; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void deserializeArgumentMap(const QByteArray& data, QMap<QString, QVariant>& map) | void SoapySDRInputSettings::deserializeArgumentMap(const QByteArray& data, QMap<QString, QVariant>& map) | ||||||
| { | { | ||||||
|     QDataStream *stream = new QDataStream(data); |     QDataStream *stream = new QDataStream(data); | ||||||
|     (*stream) >> map; |     (*stream) >> map; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user