From 8a72372b285dc989e4ced529913a6f30758681de Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 10 Nov 2018 07:17:55 +0100 Subject: [PATCH 001/102] SoapySDR support: fixed display settings --- .../soapysdroutput/soapysdroutput.cpp | 5 +++-- .../soapysdroutput/soapysdroutputgui.cpp | 22 +++++++++++++------ .../soapysdrinput/soapysdrinput.cpp | 5 +++-- .../soapysdrinput/soapysdrinputgui.cpp | 22 +++++++++++++------ 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index d3642adc4..698da7065 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -846,7 +846,7 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool { auto nvalue = settings.m_tunableElements.find(oname); - if (nvalue != settings.m_tunableElements.end() && (m_settings.m_tunableElements[oname] != *nvalue)) + if (nvalue != settings.m_tunableElements.end() && ((m_settings.m_tunableElements[oname] != *nvalue) || force)) { if (dev != 0) { @@ -1034,7 +1034,8 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool << " m_log2Interp: " << m_settings.m_log2Interp << " m_devSampleRate: " << m_settings.m_devSampleRate << " m_bandwidth: " << m_settings.m_bandwidth - << " m_globalGain: " << m_settings.m_globalGain; + << " m_globalGain: " << m_settings.m_globalGain + << " force: " << force; return true; } diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp index dbee2b4d4..7dc84b694 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp @@ -426,7 +426,7 @@ void SoapySDROutputGui::handleInputMessages() void SoapySDROutputGui::sampleRateChanged(double sampleRate) { - m_settings.m_devSampleRate = sampleRate; + m_settings.m_devSampleRate = round(sampleRate); sendSettings(); } @@ -439,7 +439,7 @@ void SoapySDROutputGui::antennasChanged() void SoapySDROutputGui::bandwidthChanged(double bandwidth) { - m_settings.m_bandwidth = bandwidth; + m_settings.m_bandwidth = round(bandwidth); sendSettings(); } @@ -558,14 +558,20 @@ void SoapySDROutputGui::displaySettings() if (m_antennas) { m_antennas->setValue(m_settings.m_antenna.toStdString()); } - if (m_sampleRateGUI) { + if (m_sampleRateGUI) + { m_sampleRateGUI->setValue(m_settings.m_devSampleRate); + m_settings.m_devSampleRate = m_sampleRateGUI->getCurrentValue(); } - if (m_bandwidthGUI) { + if (m_bandwidthGUI) + { m_bandwidthGUI->setValue(m_settings.m_bandwidth); + m_settings.m_bandwidth = m_bandwidthGUI->getCurrentValue(); } - if (m_gainSliderGUI) { + if (m_gainSliderGUI) + { m_gainSliderGUI->setValue(m_settings.m_globalGain); + m_settings.m_globalGain = m_gainSliderGUI->getCurrentValue(); } if (m_autoGain) { m_autoGain->setChecked(m_settings.m_autoGain); @@ -599,10 +605,12 @@ void SoapySDROutputGui::displayIndividualGainsControlSettings() { for (const auto &it : m_individualGainsGUIs) { - QMap::const_iterator elIt = m_settings.m_individualGains.find(it->getName()); + QMap::iterator elIt = m_settings.m_individualGains.find(it->getName()); - if (elIt != m_settings.m_individualGains.end()) { + if (elIt != m_settings.m_individualGains.end()) + { it->setValue(*elIt); + *elIt = it->getValue(); } } } diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 198c9d822..9357854b9 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -892,7 +892,7 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo { auto nvalue = settings.m_tunableElements.find(oname); - if (nvalue != settings.m_tunableElements.end() && (m_settings.m_tunableElements[oname] != *nvalue)) + if (nvalue != settings.m_tunableElements.end() && ((m_settings.m_tunableElements[oname] != *nvalue) ||force)) { if (dev != 0) { @@ -1085,7 +1085,8 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo << " m_softIQCorrection: " << m_settings.m_softIQCorrection << " m_antenna: " << m_settings.m_antenna << " m_bandwidth: " << m_settings.m_bandwidth - << " m_globalGain: " << m_settings.m_globalGain; + << " m_globalGain: " << m_settings.m_globalGain + << " force: " << force; return true; } diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp index b8c387d76..da4a0dfb4 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -436,13 +436,13 @@ void SoapySDRInputGui::antennasChanged() void SoapySDRInputGui::sampleRateChanged(double sampleRate) { - m_settings.m_devSampleRate = sampleRate; + m_settings.m_devSampleRate = round(sampleRate); sendSettings(); } void SoapySDRInputGui::bandwidthChanged(double bandwidth) { - m_settings.m_bandwidth = bandwidth; + m_settings.m_bandwidth = round(bandwidth); sendSettings(); } @@ -600,14 +600,20 @@ void SoapySDRInputGui::displaySettings() qDebug("SoapySDRInputGui::displaySettings: m_antenna: %s", m_settings.m_antenna.toStdString().c_str()); m_antennas->setValue(m_settings.m_antenna.toStdString()); } - if (m_sampleRateGUI) { + if (m_sampleRateGUI) + { m_sampleRateGUI->setValue(m_settings.m_devSampleRate); + m_settings.m_devSampleRate = m_sampleRateGUI->getCurrentValue(); } - if (m_bandwidthGUI) { + if (m_bandwidthGUI) + { m_bandwidthGUI->setValue(m_settings.m_bandwidth); + m_settings.m_bandwidth = m_bandwidthGUI->getCurrentValue(); } - if (m_gainSliderGUI) { + if (m_gainSliderGUI) + { m_gainSliderGUI->setValue(m_settings.m_globalGain); + m_settings.m_globalGain = m_gainSliderGUI->getCurrentValue(); } if (m_autoGain) { m_autoGain->setChecked(m_settings.m_autoGain); @@ -645,10 +651,12 @@ void SoapySDRInputGui::displayIndividualGainsControlSettings() { for (const auto &it : m_individualGainsGUIs) { - QMap::const_iterator elIt = m_settings.m_individualGains.find(it->getName()); + QMap::iterator elIt = m_settings.m_individualGains.find(it->getName()); - if (elIt != m_settings.m_individualGains.end()) { + if (elIt != m_settings.m_individualGains.end()) + { it->setValue(*elIt); + *elIt = it->getValue(); } } } From 3c9d1a363739182200568fcb7f50bede4231ccfa Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 10 Nov 2018 19:52:27 +0100 Subject: [PATCH 002/102] SoapySDR support: GUI for ArgInfo types --- sdrgui/CMakeLists.txt | 3 + sdrgui/soapygui/arginfogui.cpp | 374 +++++++++++++++++++++++++++++++++ sdrgui/soapygui/arginfogui.h | 101 +++++++++ sdrgui/soapygui/arginfogui.ui | 76 +++++++ 4 files changed, 554 insertions(+) create mode 100644 sdrgui/soapygui/arginfogui.cpp create mode 100644 sdrgui/soapygui/arginfogui.h create mode 100644 sdrgui/soapygui/arginfogui.ui diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index f401299f2..6a5470142 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -61,6 +61,7 @@ set(sdrgui_SOURCES soapygui/dynamicitemsettinggui.cpp soapygui/intervalslidergui.cpp soapygui/complexfactorgui.cpp + soapygui/arginfogui.cpp webapi/webapiadaptergui.cpp ) @@ -126,6 +127,7 @@ set(sdrgui_HEADERS soapygui/dynamicitemsettinggui.h soapygui/intervalslidergui.h soapygui/complexfactorgui.h + soapygui/arginfogui.h webapi/webapiadaptergui.h ) @@ -159,6 +161,7 @@ set(sdrgui_FORMS soapygui/intervalrangegui.ui soapygui/intervalslidergui.ui soapygui/complexfactorgui.ui + soapygui/arginfogui.ui ) set(sdrgui_RESOURCES diff --git a/sdrgui/soapygui/arginfogui.cpp b/sdrgui/soapygui/arginfogui.cpp new file mode 100644 index 000000000..802fa0ce5 --- /dev/null +++ b/sdrgui/soapygui/arginfogui.cpp @@ -0,0 +1,374 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "ui_arginfogui.h" +#include "arginfogui.h" + +ArgInfoGUI::ArgInfoGUI(ArgInfoType type, ArgInfoValueType valueType, QWidget *parent) : + QWidget(parent), + ui(new Ui::ArgInfoGUI), + m_type(type), + m_valueType(valueType), + m_boolValue(false), + m_intValue(0), + m_floatValue(0.0), + m_hasRange(false), + m_minValue(0.0), + m_maxValue(0.0) +{ + ui->setupUi(this); + QHBoxLayout *layout = ui->argLayout; + + if (m_type != ArgInfoBinary) { + layout->removeWidget(ui->argCheck); + } + if (m_type != ArgInfoContinuous) { + layout->removeWidget(ui->argEdit); + } + if (m_type != ArgInfoDiscrete) { + layout->removeWidget(ui->argCombo); + } +} + +ArgInfoGUI::~ArgInfoGUI() +{ + delete ui; +} + +void ArgInfoGUI::setRange(double min, double max) +{ + m_hasRange = true; + m_minValue = min; + m_maxValue = max; +} + +void ArgInfoGUI::setLabel(const QString& text) +{ + ui->argLabel->setText(text); +} + +void ArgInfoGUI::setUnits(const QString& units) +{ + ui->argUnits->setText(units); +} + +void ArgInfoGUI::setBoolValue(bool value) +{ + if (m_valueType == ArgInfoValueBool) + { + m_boolValue = value; + updateUIFromBool(); + } + else if (m_valueType == ArgInfoValueInt) + { + m_intValue = setIntegerValue(value ? 1 : 0); + updateUIFromInt(); + } + else if (m_valueType == ArgInfoValueFloat) + { + m_floatValue = setDoubleValue(value ? 1.0 : 0.0); + updateUIFromFloat(); + } + else if (m_valueType == ArgInfoValueString) + { + m_stringValue = QString(value ? "true" : "false"); + updateUIFromString(); + } +} + +void ArgInfoGUI::addBoolValue(const QString& text, bool value) +{ + if (m_type == ArgInfoDiscrete) { + ui->argCombo->addItem(text, QVariant(value)); + } +} + +void ArgInfoGUI::setIntValue(int value) +{ + if (m_valueType == ArgInfoValueBool) + { + m_boolValue = (value != 0); + updateUIFromBool(); + } + else if (m_valueType == ArgInfoValueInt) + { + m_intValue = setIntegerValue(value); + updateUIFromInt(); + } + else if (m_valueType == ArgInfoValueFloat) + { + m_floatValue = setDoubleValue(value); + updateUIFromFloat(); + } + else if (m_valueType == ArgInfoValueString) + { + m_stringValue = QString("%1").arg(value); + updateUIFromString(); + } +} + +void ArgInfoGUI::addIntValue(const QString& text, int value) +{ + if (m_type == ArgInfoDiscrete) { + ui->argCombo->addItem(text, QVariant(setIntegerValue(value))); + } +} + +void ArgInfoGUI::setFloatValue(double value) +{ + if (m_valueType == ArgInfoValueBool) + { + m_boolValue = (value != 0.0); + updateUIFromBool(); + } + else if (m_valueType == ArgInfoValueInt) + { + m_intValue = setIntegerValue(value); + updateUIFromInt(); + } + else if (m_valueType == ArgInfoValueFloat) + { + m_floatValue = setDoubleValue(value); + updateUIFromFloat(); + } + else if (m_valueType == ArgInfoValueString) + { + m_stringValue = QString("%1").arg(value); + updateUIFromString(); + } +} + +void ArgInfoGUI::addFloatValue(const QString& text, double value) +{ + if (m_type == ArgInfoDiscrete) { + ui->argCombo->addItem(text, QVariant(setDoubleValue(value))); + } +} + +void ArgInfoGUI::setStringValue(const QString& value) +{ + if (m_valueType == ArgInfoValueBool) + { + m_boolValue = (value == "true"); + updateUIFromBool(); + } + else if (m_valueType == ArgInfoValueInt) + { + int intValue = atoi(value.toStdString().c_str()); + m_intValue = setIntegerValue(intValue); + updateUIFromInt(); + } + else if (m_valueType == ArgInfoValueFloat) + { + double doubleValue = atof(value.toStdString().c_str()); + m_floatValue = setDoubleValue(doubleValue); + updateUIFromFloat(); + } + else if (m_valueType == ArgInfoValueString) + { + m_stringValue = value; + updateUIFromString(); + } +} + +void ArgInfoGUI::addStringValue(const QString& text, const QString& value) +{ + if (m_type == ArgInfoDiscrete) { + ui->argCombo->addItem(text, QVariant(value)); + } +} + +int ArgInfoGUI::setIntegerValue(int value) +{ + if (m_hasRange) { + return value < round(m_minValue) ? round(m_minValue) : value > round(m_maxValue) ? round(m_maxValue) : value; + } else { + return value; + } +} + +double ArgInfoGUI::setDoubleValue(double value) +{ + if (m_hasRange) { + return value < m_minValue ? m_minValue : value > m_maxValue ? m_maxValue : value; + } else { + return value; + } +} + +void ArgInfoGUI::updateUIFromBool() +{ + if (m_type == ArgInfoBinary) + { + ui->argCheck->blockSignals(true); + ui->argCheck->setChecked(m_boolValue); + ui->argCheck->blockSignals(false); + } + else if (m_type == ArgInfoContinuous) + { + ui->argEdit->blockSignals(true); + ui->argEdit->setText(QString(m_boolValue ? "true" : "false")); + ui->argEdit->blockSignals(false); + } + else if (m_type == ArgInfoDiscrete) + { + if (ui->argCombo->count() > 1) + { + ui->argCombo->blockSignals(true); + ui->argCombo->setCurrentIndex(m_boolValue ? 0 : 1); + ui->argCombo->blockSignals(false); + } + } +} + +void ArgInfoGUI::updateUIFromInt() +{ + if (m_type == ArgInfoBinary) + { + ui->argCheck->blockSignals(true); + ui->argCheck->setChecked(m_intValue == 0 ? false : true); + ui->argCheck->blockSignals(false); + } + else if (m_type == ArgInfoContinuous) + { + ui->argEdit->blockSignals(true); + ui->argEdit->setText(QString("%1").arg(m_intValue)); + ui->argEdit->blockSignals(false); + } + else if (m_type == ArgInfoDiscrete) + { + for (int i = 0; i < ui->argCombo->count(); i++) + { + if (ui->argCombo->itemData(i).type() == QVariant::Int) + { + bool ok = false; + QVariant v = ui->argCombo->itemData(i); + + if (m_intValue >= v.toInt(&ok) && ok) + { + ui->argCombo->blockSignals(true); + ui->argCombo->setCurrentIndex(i); + ui->argCombo->blockSignals(false); + break; + } + } + } + } +} + +void ArgInfoGUI::updateUIFromFloat() +{ + if (m_type == ArgInfoBinary) + { + ui->argCheck->blockSignals(true); + ui->argCheck->setChecked(m_floatValue == 0.0 ? false : true); + ui->argCheck->blockSignals(false); + } + else if (m_type == ArgInfoContinuous) + { + ui->argEdit->blockSignals(true); + ui->argEdit->setText(QString("%1").arg(m_floatValue)); + ui->argEdit->blockSignals(false); + } + else if (m_type == ArgInfoDiscrete) + { + for (int i = 0; i < ui->argCombo->count(); i++) + { + if (ui->argCombo->itemData(i).type() == QVariant::Double) + { + bool ok = false; + QVariant v = ui->argCombo->itemData(i); + + if (m_floatValue >= v.toDouble(&ok) && ok) + { + ui->argCombo->blockSignals(true); + ui->argCombo->setCurrentIndex(i); + ui->argCombo->blockSignals(false); + break; + } + } + } + } +} + +void ArgInfoGUI::updateUIFromString() +{ + if (m_type == ArgInfoBinary) + { + ui->argCheck->blockSignals(true); + ui->argCheck->setChecked(m_stringValue == "true" ? true : false); + ui->argCheck->blockSignals(false); + } + else if (m_type == ArgInfoContinuous) + { + ui->argEdit->blockSignals(true); + ui->argEdit->setText(m_stringValue); + ui->argEdit->blockSignals(false); + } +} + +void ArgInfoGUI::on_argCheck_toggled(bool checked) +{ + setBoolValue(checked); + emit valueChanged(); +} + +void ArgInfoGUI::on_argEdit_editingFinished() +{ + setStringValue(ui->argEdit->text()); + emit valueChanged(); +} + +#ifdef _MSC_VER +void ArgInfoGUI::on_argCombo_currentIndexChanged(int index) +#else +void ArgInfoGUI::on_argCombo_currentIndexChanged(int index __attribute__((unused))) +#endif +{ + QVariant v = ui->argCombo->currentData(); + bool ok = false; + + if (v.type() == QVariant::Bool) + { + setBoolValue(v.toBool()); + emit valueChanged(); + } + else if (v.type() == QVariant::Int) + { + setIntValue(v.toInt(&ok)); + + if (ok) { + emit valueChanged(); + } + } + else if (v.type() == QVariant::Double) + { + setFloatValue(v.toDouble(&ok)); + + if (ok) { + emit valueChanged(); + } + } + else if (v.type() ==QVariant::String) + { + setStringValue(v.toString()); + emit valueChanged(); + } +} + diff --git a/sdrgui/soapygui/arginfogui.h b/sdrgui/soapygui/arginfogui.h new file mode 100644 index 000000000..b93777863 --- /dev/null +++ b/sdrgui/soapygui/arginfogui.h @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_SOAPYGUI_ARGINFOGUI_H_ +#define SDRGUI_SOAPYGUI_ARGINFOGUI_H_ + +#include +#include + +#include "export.h" + +namespace Ui { + class ArgInfoGUI; +} + +class SDRGUI_API ArgInfoGUI : public QWidget +{ + Q_OBJECT +public: + enum ArgInfoType + { + ArgInfoBinary, + ArgInfoContinuous, + ArgInfoDiscrete + }; + + enum ArgInfoValueType + { + ArgInfoValueBool, + ArgInfoValueInt, + ArgInfoValueFloat, + ArgInfoValueString + }; + + explicit ArgInfoGUI(ArgInfoType type, ArgInfoValueType valueType, QWidget *parent = 0); + ~ArgInfoGUI(); + + void setLabel(const QString& text); + void setUnits(const QString& units); + + ArgInfoType getType() const { return m_type; } + void setRange(double min, double max); + + bool getBoolValue() const { return m_boolValue; } + void setBoolValue(bool value); + void addBoolValue(const QString& text, bool value); + + int getIntValue() const { return m_intValue; } + void setIntValue(int value); + void addIntValue(const QString& text, int value); + + double getFloatValue() const { return m_floatValue; } + void setFloatValue(double value); + void addFloatValue(const QString& text, double value); + + const QString& getStringValue() const { return m_stringValue; } + void setStringValue(const QString& value); + void addStringValue(const QString& text, const QString& value); + +signals: + void valueChanged(); + +private slots: + void on_argCheck_toggled(bool checked); + void on_argEdit_editingFinished(); + void on_argCombo_currentIndexChanged(int index); + +private: + int setIntegerValue(int value); + double setDoubleValue(double value); + void updateUIFromBool(); + void updateUIFromInt(); + void updateUIFromFloat(); + void updateUIFromString(); + + Ui::ArgInfoGUI* ui; + ArgInfoType m_type; + ArgInfoValueType m_valueType; + bool m_boolValue; + int m_intValue; + double m_floatValue; + QString m_stringValue; + bool m_hasRange; + double m_minValue; + double m_maxValue; +}; + +#endif /* SDRGUI_SOAPYGUI_ARGINFOGUI_H_ */ diff --git a/sdrgui/soapygui/arginfogui.ui b/sdrgui/soapygui/arginfogui.ui new file mode 100644 index 000000000..bac0a3f0f --- /dev/null +++ b/sdrgui/soapygui/arginfogui.ui @@ -0,0 +1,76 @@ + + + ArgInfoGUI + + + + 0 + 0 + 384 + 30 + + + + + 0 + 0 + + + + + 0 + 30 + + + + Form + + + + + 0 + 0 + 379 + 29 + + + + + + + + 80 + 0 + + + + Label + + + + + + + + + + + + + + + + + + + + Unit + + + + + + + + + From 1005d1d4e531b59707ab76d37fca4a19bd10ea09 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 11 Nov 2018 02:30:10 +0100 Subject: [PATCH 003/102] SoapySDR support: input: stream ArgInfo GUI --- .../soapysdrinput/soapysdrinput.cpp | 25 +++++ .../soapysdrinput/soapysdrinput.h | 2 + .../soapysdrinput/soapysdrinputgui.cpp | 105 ++++++++++++++++++ .../soapysdrinput/soapysdrinputgui.h | 5 + .../soapysdrinput/soapysdrinputsettings.cpp | 21 ++++ .../soapysdrinput/soapysdrinputsettings.h | 4 + sdrgui/CMakeLists.txt | 2 + sdrgui/soapygui/arginfogui.cpp | 34 +++++- sdrgui/soapygui/arginfogui.h | 2 + sdrgui/soapygui/arginfogui.ui | 18 ++- sdrgui/soapygui/dynamicargsettinggui.cpp | 88 +++++++++++++++ sdrgui/soapygui/dynamicargsettinggui.h | 52 +++++++++ 12 files changed, 353 insertions(+), 5 deletions(-) create mode 100644 sdrgui/soapygui/dynamicargsettinggui.cpp create mode 100644 sdrgui/soapygui/dynamicargsettinggui.h diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 9357854b9..711489128 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -269,6 +269,12 @@ const std::vector& SoapySDRInput::getIndividu return channelSettings->m_gainSettings; } +const SoapySDR::ArgInfoList& SoapySDRInput::getStreamArgInfoList() +{ + const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(m_deviceShared.m_channel); + return channelSettings->m_streamSettingsArgs; +} + void SoapySDRInput::initGainSettings(SoapySDRInputSettings& settings) { const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(m_deviceShared.m_channel); @@ -282,6 +288,25 @@ void SoapySDRInput::initGainSettings(SoapySDRInputSettings& settings) updateGains(m_deviceShared.m_device, m_deviceShared.m_channel, settings); } +void SoapySDRInput::initStreamArgSettings(SoapySDRInputSettings& settings) +{ + const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(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 SoapySDRInput::hasDCAutoCorrection() { const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(m_deviceShared.m_channel); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.h b/plugins/samplesource/soapysdrinput/soapysdrinput.h index d18c5194e..e5d4002b9 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.h @@ -155,7 +155,9 @@ public: int getAntennaIndex(const std::string& antenna); const std::vector& getTunableElements(); const std::vector& getIndividualGainsRanges(); + const SoapySDR::ArgInfoList& getStreamArgInfoList(); void initGainSettings(SoapySDRInputSettings& settings); + void initStreamArgSettings(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 da4a0dfb4..49a7f010d 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -29,6 +29,8 @@ #include "soapygui/dynamicitemsettinggui.h" #include "soapygui/intervalslidergui.h" #include "soapygui/complexfactorgui.h" +#include "soapygui/arginfogui.h" +#include "soapygui/dynamicargsettinggui.h" #include "ui_soapysdrinputgui.h" #include "soapysdrinputgui.h" @@ -68,7 +70,9 @@ SoapySDRInputGui::SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) : createTunableElementsControl(m_sampleSource->getTunableElements()); createGlobalGainControl(); createIndividualGainsControl(m_sampleSource->getIndividualGainsRanges()); + createStreamArgumentsControl(m_sampleSource->getStreamArgInfoList()); m_sampleSource->initGainSettings(m_settings); + m_sampleSource->initStreamArgSettings(m_settings); if (m_sampleRateGUI) { connect(m_sampleRateGUI, SIGNAL(valueChanged(double)), this, SLOT(sampleRateChanged(double))); @@ -306,6 +310,86 @@ void SoapySDRInputGui::createCorrectionsControl() } } +void SoapySDRInputGui::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 SoapySDRInputGui::setName(const QString& name) { setObjectName(name); @@ -512,6 +596,12 @@ void SoapySDRInputGui::iqCorrectionArgumentChanged(double value) sendSettings(); } +void SoapySDRInputGui::streamArgChanged(QString itemName, QVariant value) +{ + m_settings.m_streamArgSettings[itemName] = value; + sendSettings(); +} + void SoapySDRInputGui::on_centerFrequency_changed(quint64 value) { m_settings.m_centerFrequency = value * 1000; @@ -631,6 +721,7 @@ void SoapySDRInputGui::displaySettings() displayTunableElementsControlSettings(); displayIndividualGainsControlSettings(); displayCorrectionsSettings(); + displayStreamArgsSettings(); blockApplySettings(false); } @@ -686,6 +777,20 @@ void SoapySDRInputGui::displayCorrectionsSettings() } } +void SoapySDRInputGui::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 SoapySDRInputGui::sendSettings() { if (!m_updateTimer.isActive()) { diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.h b/plugins/samplesource/soapysdrinput/soapysdrinputgui.h index 7f65de91a..262cd9e8b 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.h @@ -29,6 +29,7 @@ class DeviceUISet; class ItemSettingGUI; class StringRangeGUI; class DynamicItemSettingGUI; +class DynamicArgSettingGUI; class IntervalSliderGUI; class QCheckBox; class ComplexFactorGUI; @@ -67,6 +68,7 @@ private: void createGlobalGainControl(); void createIndividualGainsControl(const std::vector& individualGainsList); void createCorrectionsControl(); + void createStreamArgumentsControl(const SoapySDR::ArgInfoList& argInfoList); Ui::SoapySDRInputGui* ui; @@ -93,11 +95,13 @@ private: ComplexFactorGUI *m_iqCorrectionGUI; QCheckBox *m_autoDCCorrection; QCheckBox *m_autoIQCorrection; + std::vector m_streamArgsGUIs; void displaySettings(); void displayTunableElementsControlSettings(); void displayIndividualGainsControlSettings(); void displayCorrectionsSettings(); + void displayStreamArgsSettings(); void sendSettings(); void updateSampleRateAndFrequency(); void updateFrequencyLimits(); @@ -119,6 +123,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/samplesource/soapysdrinput/soapysdrinputsettings.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp index 7cceae2c4..fc793dccc 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.cpp @@ -71,6 +71,7 @@ QByteArray SoapySDRInputSettings::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(); } @@ -116,6 +117,8 @@ bool SoapySDRInputSettings::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; } @@ -142,3 +145,21 @@ void SoapySDRInputSettings::deserializeNamedElementMap(const QByteArray& data, Q (*stream) >> map; delete stream; } + +QByteArray SoapySDRInputSettings::serializeArgumentMap(const QMap& map) const +{ + QByteArray data; + QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly); + (*stream) << map; + delete stream; + + return data; +} + +void deserializeArgumentMap(const QByteArray& data, QMap& map) +{ + QDataStream *stream = new QDataStream(data); + (*stream) >> map; + delete stream; +} + diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputsettings.h b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.h index 4bbb2db47..1cc7e47be 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputsettings.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinputsettings.h @@ -19,6 +19,7 @@ #include #include +#include #include struct SoapySDRInputSettings { @@ -48,6 +49,7 @@ struct SoapySDRInputSettings { bool m_autoIQCorrection; std::complex m_dcCorrection; std::complex m_iqCorrection; + QMap m_streamArgSettings; SoapySDRInputSettings(); void resetToDefaults(); @@ -57,6 +59,8 @@ struct SoapySDRInputSettings { 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_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUTSETTINGS_H_ */ diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index 6a5470142..9b2de21ab 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -59,6 +59,7 @@ set(sdrgui_SOURCES soapygui/itemsettinggui.cpp soapygui/stringrangegui.cpp soapygui/dynamicitemsettinggui.cpp + soapygui/dynamicargsettinggui.cpp soapygui/intervalslidergui.cpp soapygui/complexfactorgui.cpp soapygui/arginfogui.cpp @@ -125,6 +126,7 @@ set(sdrgui_HEADERS soapygui/itemsettinggui.h soapygui/stringrangegui.h soapygui/dynamicitemsettinggui.h + soapygui/dynamicargsettinggui.h soapygui/intervalslidergui.h soapygui/complexfactorgui.h soapygui/arginfogui.h diff --git a/sdrgui/soapygui/arginfogui.cpp b/sdrgui/soapygui/arginfogui.cpp index 802fa0ce5..d914df185 100644 --- a/sdrgui/soapygui/arginfogui.cpp +++ b/sdrgui/soapygui/arginfogui.cpp @@ -35,14 +35,31 @@ ArgInfoGUI::ArgInfoGUI(ArgInfoType type, ArgInfoValueType valueType, QWidget *pa ui->setupUi(this); QHBoxLayout *layout = ui->argLayout; - if (m_type != ArgInfoBinary) { + if (m_type != ArgInfoBinary) + { layout->removeWidget(ui->argCheck); + delete ui->argCheck; } - if (m_type != ArgInfoContinuous) { + + if (m_type != ArgInfoContinuous) + { layout->removeWidget(ui->argEdit); + delete ui->argEdit; } - if (m_type != ArgInfoDiscrete) { + + if (m_type != ArgInfoDiscrete) + { layout->removeWidget(ui->argCombo); + delete ui->argCombo; + } + + if ((m_valueType == ArgInfoValueInt) || (m_valueType == ArgInfoValueFloat)) + { + if (m_type == ArgInfoContinuous) { + ui->argEdit->setAlignment(Qt::AlignRight); + } else if (m_type == ArgInfoDiscrete) { + ui->argCombo->setLayoutDirection(Qt::RightToLeft); + } } } @@ -63,6 +80,17 @@ void ArgInfoGUI::setLabel(const QString& text) ui->argLabel->setText(text); } +void ArgInfoGUI::setToolTip(const QString& text) +{ + if (m_type == ArgInfoBinary) { + ui->argCheck->setToolTip(text); + } else if (m_type == ArgInfoContinuous) { + ui->argEdit->setToolTip(text); + } else if (m_type == ArgInfoDiscrete) { + ui->argCombo->setToolTip(text); + } +} + void ArgInfoGUI::setUnits(const QString& units) { ui->argUnits->setText(units); diff --git a/sdrgui/soapygui/arginfogui.h b/sdrgui/soapygui/arginfogui.h index b93777863..dda89ee92 100644 --- a/sdrgui/soapygui/arginfogui.h +++ b/sdrgui/soapygui/arginfogui.h @@ -49,9 +49,11 @@ public: ~ArgInfoGUI(); void setLabel(const QString& text); + void setToolTip(const QString& text); void setUnits(const QString& units); ArgInfoType getType() const { return m_type; } + ArgInfoValueType getValueType() const { return m_valueType; } void setRange(double min, double max); bool getBoolValue() const { return m_boolValue; } diff --git a/sdrgui/soapygui/arginfogui.ui b/sdrgui/soapygui/arginfogui.ui index bac0a3f0f..62fd6dd1f 100644 --- a/sdrgui/soapygui/arginfogui.ui +++ b/sdrgui/soapygui/arginfogui.ui @@ -56,10 +56,24 @@ - + + + + 120 + 16777215 + + + - + + + + 120 + 16777215 + + + diff --git a/sdrgui/soapygui/dynamicargsettinggui.cpp b/sdrgui/soapygui/dynamicargsettinggui.cpp new file mode 100644 index 000000000..1ede62c8f --- /dev/null +++ b/sdrgui/soapygui/dynamicargsettinggui.cpp @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "dynamicargsettinggui.h" + +DynamicArgSettingGUI::DynamicArgSettingGUI(ArgInfoGUI *argSettingGUI, const QString& name, QObject *parent) : + QObject(parent), + m_argSettingGUI(argSettingGUI), + m_name(name) +{ + connect(m_argSettingGUI, SIGNAL(valueChanged()), this, SLOT(processValueChanged())); +} + +DynamicArgSettingGUI::~DynamicArgSettingGUI() +{ + disconnect(m_argSettingGUI, SIGNAL(valueChanged()), this, SLOT(processValueChanged())); +} + +void DynamicArgSettingGUI::processValueChanged() +{ + if (m_argSettingGUI->getValueType() == ArgInfoGUI::ArgInfoValueBool) { + emit valueChanged(m_name, QVariant(m_argSettingGUI->getBoolValue())); + } else if (m_argSettingGUI->getValueType() == ArgInfoGUI::ArgInfoValueInt) { + emit valueChanged(m_name, QVariant(m_argSettingGUI->getIntValue())); + } else if (m_argSettingGUI->getValueType() == ArgInfoGUI::ArgInfoValueFloat) { + emit valueChanged(m_name, QVariant(m_argSettingGUI->getFloatValue())); + } else if (m_argSettingGUI->getValueType() == ArgInfoGUI::ArgInfoValueString) { + emit valueChanged(m_name, QVariant(m_argSettingGUI->getStringValue())); + } +} + +QVariant DynamicArgSettingGUI::getValue() const +{ + if (m_argSettingGUI->getValueType() == ArgInfoGUI::ArgInfoValueBool) { + return QVariant(m_argSettingGUI->getBoolValue()); + } else if (m_argSettingGUI->getValueType() == ArgInfoGUI::ArgInfoValueInt) { + return QVariant(m_argSettingGUI->getIntValue()); + } else if (m_argSettingGUI->getValueType() == ArgInfoGUI::ArgInfoValueFloat) { + return QVariant(m_argSettingGUI->getFloatValue()); + } else if (m_argSettingGUI->getValueType() == ArgInfoGUI::ArgInfoValueString) { + return QVariant(m_argSettingGUI->getStringValue()); + } else { + return QVariant(false); + } +} + +void DynamicArgSettingGUI::setValue(const QVariant& value) +{ + bool ok = false; + + if (value.type() == QVariant::Bool) + { + m_argSettingGUI->setBoolValue(value.toBool()); + } + else if (value.type() == QVariant::Int) + { + int newValue = value.toInt(&ok); + + if (ok) { + m_argSettingGUI->setIntValue(newValue); + } + } + else if (value.type() == QVariant::Double) + { + double newValue = value.toDouble(&ok); + + if (ok) { + m_argSettingGUI->setFloatValue(newValue); + } + } + else if (value.type() == QVariant::String) + { + m_argSettingGUI->setStringValue(value.toString()); + } +} diff --git a/sdrgui/soapygui/dynamicargsettinggui.h b/sdrgui/soapygui/dynamicargsettinggui.h new file mode 100644 index 000000000..3d7f47e48 --- /dev/null +++ b/sdrgui/soapygui/dynamicargsettinggui.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_SOAPYGUI_DYNAMICARGSETTINGGUI_H_ +#define SDRGUI_SOAPYGUI_DYNAMICARGSETTINGGUI_H_ + +#include +#include +#include + +#include "export.h" +#include "arginfogui.h" + +class SDRGUI_API DynamicArgSettingGUI : public QObject +{ + Q_OBJECT +public: + DynamicArgSettingGUI(ArgInfoGUI *argSettingGUI, const QString& name, QObject *parent = 0); + ~DynamicArgSettingGUI(); + + const QString& getName() const { return m_name; } + QVariant getValue() const; + void setValue(const QVariant& value); + +signals: + void valueChanged(QString itemName, QVariant value); + +private slots: + void processValueChanged(); + +private: + ArgInfoGUI *m_argSettingGUI; + QString m_name; +}; + + + + +#endif /* SDRGUI_SOAPYGUI_DYNAMICARGSETTINGGUI_H_ */ From f436479bd710be0900de698874404e5a10d0032e Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 11 Nov 2018 09:31:27 +0100 Subject: [PATCH 004/102] 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; From ad8026c6a2aa80e11771345f51985f818554431f Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 11 Nov 2018 09:57:28 +0100 Subject: [PATCH 005/102] SoapySDR support: fixed IntervalRangeGUI::getCurrentValue --- sdrgui/soapygui/intervalrangegui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdrgui/soapygui/intervalrangegui.cpp b/sdrgui/soapygui/intervalrangegui.cpp index ca1db22f2..b72f2f459 100644 --- a/sdrgui/soapygui/intervalrangegui.cpp +++ b/sdrgui/soapygui/intervalrangegui.cpp @@ -80,7 +80,7 @@ void IntervalRangeGUI::reset() double IntervalRangeGUI::getCurrentValue() { - return ui->value->getValue(); + return ui->value->getValueNew(); } void IntervalRangeGUI::setValue(double value) From c382913fb4923da8f3fc4af7b06845f125c893ac Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 11 Nov 2018 19:44:48 +0100 Subject: [PATCH 006/102] SoapySDR support: stream ArgInfo SoapySDR interface --- .../soapysdroutput/soapysdroutput.cpp | 27 +++++++++++++++++++ .../soapysdroutput/soapysdroutputgui.cpp | 2 +- .../soapysdrinput/soapysdrinput.cpp | 27 +++++++++++++++++++ .../soapysdrinput/soapysdrinputgui.cpp | 2 +- 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index 761a9f125..eb34bd45e 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -38,6 +38,7 @@ SoapySDROutput::SoapySDROutput(DeviceSinkAPI *deviceAPI) : { openDevice(); initGainSettings(m_settings); + initStreamArgSettings(m_settings); } SoapySDROutput::~SoapySDROutput() @@ -1000,6 +1001,32 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool } } + for (const auto &oname : m_settings.m_streamArgSettings.keys()) + { + auto nvalue = settings.m_streamArgSettings.find(oname); + + if (nvalue != settings.m_streamArgSettings.end() && ((m_settings.m_streamArgSettings[oname] != *nvalue) || force)) + { + if (dev != 0) + { + try + { + dev->writeSetting(SOAPY_SDR_TX, 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) + { + qCritical("SoapySDRInput::applySettings: cannot set stream argument %s to %s: %s", + oname.toStdString().c_str(), nvalue->toString().toStdString().c_str(), ex.what()); + } + } + + m_settings.m_streamArgSettings[oname] = *nvalue; + } + } + if (forwardChangeOwnDSP) { int sampleRate = settings.m_devSampleRate/(1<key.c_str())); m_streamArgsGUIs.push_back(gui); - connect(gui, SIGNAL(valueChanged(QString, value)), this, SLOT(streamArgChanged(QString, QVariant))); + connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(streamArgChanged(QString, QVariant))); } } diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 711489128..4fabed3d7 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -42,6 +42,7 @@ SoapySDRInput::SoapySDRInput(DeviceSourceAPI *deviceAPI) : { openDevice(); initGainSettings(m_settings); + initStreamArgSettings(m_settings); m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID())); m_deviceAPI->addSink(m_fileSink); @@ -1046,6 +1047,32 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo } } + for (const auto &oname : m_settings.m_streamArgSettings.keys()) + { + auto nvalue = settings.m_streamArgSettings.find(oname); + + if (nvalue != settings.m_streamArgSettings.end() && ((m_settings.m_streamArgSettings[oname] != *nvalue) || force)) + { + if (dev != 0) + { + try + { + 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) + { + qCritical("SoapySDRInput::applySettings: cannot set stream argument %s to %s: %s", + oname.toStdString().c_str(), nvalue->toString().toStdString().c_str(), ex.what()); + } + } + + m_settings.m_streamArgSettings[oname] = *nvalue; + } + } + if (forwardChangeOwnDSP) { int sampleRate = settings.m_devSampleRate/(1<key.c_str())); m_streamArgsGUIs.push_back(gui); - connect(gui, SIGNAL(valueChanged(QString, value)), this, SLOT(streamArgChanged(QString, QVariant))); + connect(gui, SIGNAL(valueChanged(QString, QVariant)), this, SLOT(streamArgChanged(QString, QVariant))); } } From 696e7324a4f4d1fb5f96b11b73916da8bfe5605c Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 01:10:51 +0100 Subject: [PATCH 007/102] 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(); From 6708a6b700cf0babdb5ce68212322b023c5b09f7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 14:04:16 +0100 Subject: [PATCH 008/102] Windows: MSVC2017: changes in sdrbase (1) --- qrtplib/rtptimeutilities.h | 2 +- sdrbase/channel/channelsinkapi.h | 36 +++++------ sdrbase/channel/channelsourceapi.h | 31 ++++++---- sdrbase/commands/command.cpp | 28 ++++----- sdrbase/commands/command.h | 10 ++-- sdrbase/dsp/basebandsamplesource.h | 2 +- sdrbase/dsp/devicesamplesink.h | 49 +++++++++++---- sdrbase/dsp/devicesamplesource.h | 49 +++++++++++---- sdrbase/dsp/freqlockcomplex.cpp | 1 + sdrbase/dsp/hbfiltertraits.h | 32 ++++++++++ sdrbase/dsp/nullsink.cpp | 3 +- sdrbase/dsp/phaselock.h | 2 +- sdrbase/dsp/phaselockcomplex.cpp | 1 + sdrbase/dsp/projector.cpp | 1 + sdrbase/plugin/plugininterface.h | 95 ++++++++++++++++++++++-------- sdrbase/sdrbase.pro | 3 + sdrgui/gui/commandoutputdialog.cpp | 14 ++--- 17 files changed, 244 insertions(+), 115 deletions(-) diff --git a/qrtplib/rtptimeutilities.h b/qrtplib/rtptimeutilities.h index d474ff2fc..7252bb7ba 100644 --- a/qrtplib/rtptimeutilities.h +++ b/qrtplib/rtptimeutilities.h @@ -143,7 +143,7 @@ public: bool IsZero() const { - return m_t == 0; + return m_t == 0.0; } private: #ifdef RTP_HAVE_QUERYPERFORMANCECOUNTER diff --git a/sdrbase/channel/channelsinkapi.h b/sdrbase/channel/channelsinkapi.h index ecfa13bf3..ebebe1adf 100644 --- a/sdrbase/channel/channelsinkapi.h +++ b/sdrbase/channel/channelsinkapi.h @@ -46,41 +46,33 @@ public: virtual QByteArray serialize() const = 0; virtual bool deserialize(const QByteArray& data) = 0; -#ifdef _MSC_VER virtual int webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) response; + errorMessage = "Not implemented"; return 501; + } virtual int webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) force; + (void) channelSettingsKeys; + (void) response; + errorMessage = "Not implemented"; return 501; + } virtual int webapiReportGet( SWGSDRangel::SWGChannelReport& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } -#else - virtual int webapiSettingsGet( - SWGSDRangel::SWGChannelSettings& response __attribute__((unused)), - QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } - - virtual int webapiSettingsPutPatch( - bool force __attribute__((unused)), - const QStringList& channelSettingsKeys __attribute__((unused)), - SWGSDRangel::SWGChannelSettings& response __attribute__((unused)), - QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } - - virtual int webapiReportGet( - SWGSDRangel::SWGChannelReport& response __attribute__((unused)), - QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } -#endif + { + (void) response; + errorMessage = "Not implemented"; return 501; + } int getIndexInDeviceSet() const { return m_indexInDeviceSet; } void setIndexInDeviceSet(int indexInDeviceSet) { m_indexInDeviceSet = indexInDeviceSet; } diff --git a/sdrbase/channel/channelsourceapi.h b/sdrbase/channel/channelsourceapi.h index 44466bd33..48d02c108 100644 --- a/sdrbase/channel/channelsourceapi.h +++ b/sdrbase/channel/channelsourceapi.h @@ -38,29 +38,40 @@ public: virtual void getIdentifier(QString& id) = 0; virtual void getTitle(QString& title) = 0; - virtual void setName(const QString& name) { m_name = name; }; - virtual QString getName() const { return m_name; }; + virtual void setName(const QString& name) { m_name = name; } + virtual QString getName() const { return m_name; } virtual qint64 getCenterFrequency() const = 0; virtual QByteArray serialize() const = 0; virtual bool deserialize(const QByteArray& data) = 0; virtual int webapiSettingsGet( - SWGSDRangel::SWGChannelSettings& response __attribute__((unused)), + SWGSDRangel::SWGChannelSettings& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) response; + errorMessage = "Not implemented"; return 501; + } virtual int webapiSettingsPutPatch( - bool force __attribute__((unused)), - const QStringList& channelSettingsKeys __attribute__((unused)), - SWGSDRangel::SWGChannelSettings& response __attribute__((unused)), + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) force; + (void) channelSettingsKeys; + (void) response; + errorMessage = "Not implemented"; return 501; + } virtual int webapiReportGet( - SWGSDRangel::SWGChannelReport& response __attribute__((unused)), + SWGSDRangel::SWGChannelReport& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) response; + errorMessage = "Not implemented"; return 501; + } int getIndexInDeviceSet() const { return m_indexInDeviceSet; } void setIndexInDeviceSet(int indexInDeviceSet) { m_indexInDeviceSet = indexInDeviceSet; } diff --git a/sdrbase/commands/command.cpp b/sdrbase/commands/command.cpp index 4e82037b0..097bb42da 100644 --- a/sdrbase/commands/command.cpp +++ b/sdrbase/commands/command.cpp @@ -21,7 +21,7 @@ #include Command::Command() : - m_currentProcess(0), + m_currentProcess(nullptr), m_currentProcessState(QProcess::NotRunning), m_isInError(false), m_currentProcessError(QProcess::UnknownError), @@ -30,10 +30,8 @@ Command::Command() : m_currentProcessExitStatus(QProcess::NormalExit), m_currentProcessPid(0) { - m_currentProcessStartTimeStamp.tv_sec = 0; - m_currentProcessStartTimeStamp.tv_usec = 0; - m_currentProcessFinishTimeStamp.tv_sec = 0; - m_currentProcessFinishTimeStamp.tv_usec = 0; + m_currentProcessStartTimeStamp = 0; + m_currentProcessFinishTimeStamp = 0; resetToDefaults(); } @@ -48,7 +46,7 @@ Command::Command(const Command& command) : m_keyModifiers(command.m_keyModifiers), m_associateKey(command.m_associateKey), m_release(command.m_release), - m_currentProcess(0), + m_currentProcess(nullptr), m_currentProcessState(QProcess::NotRunning), m_isInError(false), m_currentProcessError(QProcess::UnknownError), @@ -57,10 +55,8 @@ Command::Command(const Command& command) : m_currentProcessExitStatus(QProcess::NormalExit), m_currentProcessPid(0) { - m_currentProcessStartTimeStamp.tv_sec = 0; - m_currentProcessStartTimeStamp.tv_usec = 0; - m_currentProcessFinishTimeStamp.tv_sec = 0; - m_currentProcessFinishTimeStamp.tv_usec = 0; + m_currentProcessStartTimeStamp = 0; + m_currentProcessFinishTimeStamp = 0; } Command::~Command() @@ -85,7 +81,7 @@ void Command::resetToDefaults() m_command = ""; m_argString = ""; m_key = static_cast(0); - m_keyModifiers = Qt::NoModifier, + m_keyModifiers = Qt::NoModifier; m_associateKey = false; m_release = false; } @@ -202,7 +198,7 @@ void Command::run(const QString& apiAddress, int apiPort, int deviceSetIndex) connect(m_currentProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState))); m_currentProcess->setProcessChannelMode(QProcess::MergedChannels); - gettimeofday(&m_currentProcessStartTimeStamp, 0); + m_currentProcessStartTimeStamp = clock(); m_currentProcess->start(m_currentProcessCommandLine); } @@ -258,7 +254,7 @@ void Command::processStateChanged(QProcess::ProcessState newState) void Command::processError(QProcess::ProcessError error) { //qDebug("Command::processError: %d state: %d", error, m_currentProcessState); - gettimeofday(&m_currentProcessFinishTimeStamp, 0); + m_currentProcessFinishTimeStamp = clock(); m_currentProcessError = error; m_isInError = true; @@ -275,14 +271,14 @@ void Command::processError(QProcess::ProcessError error) disconnect(m_currentProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState))); m_currentProcess->deleteLater(); // make sure other threads can still access it until all events have been processed - m_currentProcess = 0; // for this thread it can assume it was deleted + m_currentProcess = nullptr; // for this thread it can assume it was deleted } } void Command::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { //qDebug("Command::processFinished: (%d) %d", exitCode, exitStatus); - gettimeofday(&m_currentProcessFinishTimeStamp, 0); + m_currentProcessFinishTimeStamp = clock(); m_currentProcessExitCode = exitCode; m_currentProcessExitStatus = exitStatus; m_hasExited = true; @@ -297,5 +293,5 @@ void Command::processFinished(int exitCode, QProcess::ExitStatus exitStatus) disconnect(m_currentProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState))); m_currentProcess->deleteLater(); // make sure other threads can still access it until all events have been processed - m_currentProcess = 0; // for this thread it can assume it was deleted + m_currentProcess = nullptr; // for this thread it can assume it was deleted } diff --git a/sdrbase/commands/command.h b/sdrbase/commands/command.h index 8103b1791..b61442ad1 100644 --- a/sdrbase/commands/command.h +++ b/sdrbase/commands/command.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "export.h" @@ -63,8 +63,8 @@ public: bool getLastProcessError(QProcess::ProcessError& error) const; bool getLastProcessExit(int& exitCode, QProcess::ExitStatus& exitStatus) const; const QString& getLastProcessLog() const; - struct timeval getLastProcessStartTimestamp() const { return m_currentProcessStartTimeStamp; } - struct timeval getLastProcessFinishTimestamp() const { return m_currentProcessFinishTimeStamp; } + clock_t getLastProcessStartTimestamp() const { return m_currentProcessStartTimeStamp; } + clock_t getLastProcessFinishTimestamp() const { return m_currentProcessFinishTimeStamp; } const QString& getLastProcessCommandLine() const { return m_currentProcessCommandLine; } qint64 getLastProcessPid() const { return m_currentProcessPid; } @@ -107,8 +107,8 @@ private: int m_currentProcessExitCode; QProcess::ExitStatus m_currentProcessExitStatus; QString m_log; - struct timeval m_currentProcessStartTimeStamp; - struct timeval m_currentProcessFinishTimeStamp; + clock_t m_currentProcessStartTimeStamp; + clock_t m_currentProcessFinishTimeStamp; QString m_currentProcessCommandLine; qint64 m_currentProcessPid; diff --git a/sdrbase/dsp/basebandsamplesource.h b/sdrbase/dsp/basebandsamplesource.h index f9f2a66a9..e323fd230 100644 --- a/sdrbase/dsp/basebandsamplesource.h +++ b/sdrbase/dsp/basebandsamplesource.h @@ -35,7 +35,7 @@ public: virtual void start() = 0; virtual void stop() = 0; virtual void pull(Sample& sample) = 0; - virtual void pullAudio(int nbSamples __attribute__((unused))) {} + virtual void pullAudio(int nbSamples) { (void) nbSamples; } /** direct feeding of sample source FIFO */ void feed(SampleSourceFifo* sampleFifo, int nbSamples) diff --git a/sdrbase/dsp/devicesamplesink.h b/sdrbase/dsp/devicesamplesink.h index 5666f5e8c..8ecb74d20 100644 --- a/sdrbase/dsp/devicesamplesink.h +++ b/sdrbase/dsp/devicesamplesink.h @@ -54,31 +54,54 @@ public: virtual bool handleMessage(const Message& message) = 0; virtual int webapiSettingsGet( - SWGSDRangel::SWGDeviceSettings& response __attribute__((unused)), + SWGSDRangel::SWGDeviceSettings& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) response; + errorMessage = "Not implemented"; + return 501; + } virtual int webapiSettingsPutPatch( - bool force __attribute__((unused)), //!< true to force settings = put - const QStringList& deviceSettingsKeys __attribute__((unused)), - SWGSDRangel::SWGDeviceSettings& response __attribute__((unused)), + bool force, //!< true to force settings = put + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) force; + (void) deviceSettingsKeys; + (void) response; + errorMessage = "Not implemented"; + return 501; + } virtual int webapiRunGet( - SWGSDRangel::SWGDeviceState& response __attribute__((unused)), + SWGSDRangel::SWGDeviceState& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) response; + errorMessage = "Not implemented"; + return 501; + } - virtual int webapiRun(bool run __attribute__((unused)), - SWGSDRangel::SWGDeviceState& response __attribute__((unused)), + virtual int webapiRun(bool run, + SWGSDRangel::SWGDeviceState& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) run; + (void) response; + errorMessage = "Not implemented"; + return 501; + } virtual int webapiReportGet( - SWGSDRangel::SWGDeviceReport& response __attribute__((unused)), + SWGSDRangel::SWGDeviceReport& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) response; + errorMessage = "Not implemented"; + return 501; + } MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual void setMessageQueueToGUI(MessageQueue *queue) = 0; // pure virtual so that child classes must have to deal with this diff --git a/sdrbase/dsp/devicesamplesource.h b/sdrbase/dsp/devicesamplesource.h index 60c541d8a..c07d2426b 100644 --- a/sdrbase/dsp/devicesamplesource.h +++ b/sdrbase/dsp/devicesamplesource.h @@ -61,31 +61,54 @@ public: virtual bool handleMessage(const Message& message) = 0; virtual int webapiSettingsGet( - SWGSDRangel::SWGDeviceSettings& response __attribute__((unused)), + SWGSDRangel::SWGDeviceSettings& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) response; + errorMessage = "Not implemented"; + return 501; + } virtual int webapiSettingsPutPatch( - bool force __attribute__((unused)), //!< true to force settings = put - const QStringList& deviceSettingsKeys __attribute__((unused)), - SWGSDRangel::SWGDeviceSettings& response __attribute__((unused)), + bool force, //!< true to force settings = put + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) force; + (void) deviceSettingsKeys; + (void) response; + errorMessage = "Not implemented"; + return 501; + } virtual int webapiRunGet( - SWGSDRangel::SWGDeviceState& response __attribute__((unused)), + SWGSDRangel::SWGDeviceState& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) response; + errorMessage = "Not implemented"; + return 501; + } - virtual int webapiRun(bool run __attribute__((unused)), - SWGSDRangel::SWGDeviceState& response __attribute__((unused)), + virtual int webapiRun(bool run, + SWGSDRangel::SWGDeviceState& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) run; + (void) response; + errorMessage = "Not implemented"; + return 501; + } virtual int webapiReportGet( - SWGSDRangel::SWGDeviceReport& response __attribute__((unused)), + SWGSDRangel::SWGDeviceReport& response, QString& errorMessage) - { errorMessage = "Not implemented"; return 501; } + { + (void) response; + errorMessage = "Not implemented"; + return 501; + } MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual void setMessageQueueToGUI(MessageQueue *queue) = 0; // pure virtual so that child classes must have to deal with this diff --git a/sdrbase/dsp/freqlockcomplex.cpp b/sdrbase/dsp/freqlockcomplex.cpp index 2e8b9676f..8a7e787d0 100644 --- a/sdrbase/dsp/freqlockcomplex.cpp +++ b/sdrbase/dsp/freqlockcomplex.cpp @@ -21,6 +21,7 @@ /////////////////////////////////////////////////////////////////////////////////// #include "freqlockcomplex.h" +#define _USE_MATH_DEFINES #include FreqLockComplex::FreqLockComplex() : diff --git a/sdrbase/dsp/hbfiltertraits.h b/sdrbase/dsp/hbfiltertraits.h index 9232c9a73..066d34b93 100644 --- a/sdrbase/dsp/hbfiltertraits.h +++ b/sdrbase/dsp/hbfiltertraits.h @@ -38,7 +38,11 @@ struct SDRBASE_API HBFIRFilterTraits<16> static const int32_t hbOrder = 16; static const int32_t hbShift = 12; static const int16_t hbMod[16+6]; +#ifdef _MSC_VER + __declspec(align(16)) static const int32_t hbCoeffs[4]; +#else static const int32_t hbCoeffs[4] __attribute__ ((aligned (16))); +#endif static const double hbCoeffsF[4]; }; @@ -48,7 +52,11 @@ struct SDRBASE_API HBFIRFilterTraits<32> static const int32_t hbOrder = 32; static const int32_t hbShift = 12; static const int16_t hbMod[32+6]; +#ifdef _MSC_VER + __declspec(align(32)) static const int32_t hbCoeffs[8]; +#else static const int32_t hbCoeffs[8] __attribute__ ((aligned (32))); +#endif static const double hbCoeffsF[8]; }; @@ -58,7 +66,11 @@ struct SDRBASE_API HBFIRFilterTraits<48> static const int32_t hbOrder = 48; static const int32_t hbShift = 12; static const int16_t hbMod[48+6]; +#ifdef _MSC_VER + __declspec(align(16)) static const int32_t hbCoeffs[12]; +#else static const int32_t hbCoeffs[12] __attribute__ ((aligned (16))); +#endif static const double hbCoeffsF[12]; }; @@ -68,7 +80,11 @@ struct SDRBASE_API HBFIRFilterTraits<64> static const int32_t hbOrder = 64; static const int32_t hbShift = 12; static const int16_t hbMod[64+6]; +#ifdef _MSC_VER + __declspec(align(32)) static const int32_t hbCoeffs[16]; +#else static const int32_t hbCoeffs[16] __attribute__ ((aligned (32))); +#endif static const float hbCoeffsF[16]; }; @@ -78,7 +94,11 @@ struct SDRBASE_API HBFIRFilterTraits<80> static const int32_t hbOrder = 80; static const int32_t hbShift = 14; static const int16_t hbMod[80+6]; +#ifdef _MSC_VER + __declspec(align(16)) static const int32_t hbCoeffs[20]; +#else static const int32_t hbCoeffs[20] __attribute__ ((aligned (16))); +#endif static const double hbCoeffsF[20]; }; @@ -88,7 +108,11 @@ struct SDRBASE_API HBFIRFilterTraits<96> static const int32_t hbOrder = 96; static const int32_t hbShift = 16; static const int16_t hbMod[96+6]; +#ifdef _MSC_VER + __declspec(align(32)) static const int32_t hbCoeffs[24]; +#else static const int32_t hbCoeffs[24] __attribute__ ((aligned (32))); +#endif static const double hbCoeffsF[24]; }; @@ -98,7 +122,11 @@ struct SDRBASE_API HBFIRFilterTraits<112> static const int32_t hbOrder = 112; static const int32_t hbShift = 18; static const int16_t hbMod[112+6]; +#ifdef _MSC_VER + __declspec(align(16)) static const int32_t hbCoeffs[28]; +#else static const int32_t hbCoeffs[28] __attribute__ ((aligned (16))); +#endif static const double hbCoeffsF[28]; }; @@ -108,7 +136,11 @@ struct SDRBASE_API HBFIRFilterTraits<128> static const int32_t hbOrder = 128; static const int32_t hbShift = 20; static const int16_t hbMod[128+6]; +#ifdef _MSC_VER + __declspec(align(16)) static const int32_t hbCoeffs[32]; +#else static const int32_t hbCoeffs[32] __attribute__ ((aligned (16))); +#endif static const double hbCoeffsF[32]; }; diff --git a/sdrbase/dsp/nullsink.cpp b/sdrbase/dsp/nullsink.cpp index 592735116..5f1b7a3fa 100644 --- a/sdrbase/dsp/nullsink.cpp +++ b/sdrbase/dsp/nullsink.cpp @@ -11,8 +11,9 @@ NullSink::~NullSink() { } -bool NullSink::init(const Message& message __attribute__((unused))) +bool NullSink::init(const Message& message) { + (void) message return false; } diff --git a/sdrbase/dsp/phaselock.h b/sdrbase/dsp/phaselock.h index ab1b2af03..b6984b67f 100644 --- a/sdrbase/dsp/phaselock.h +++ b/sdrbase/dsp/phaselock.h @@ -95,7 +95,7 @@ protected: * Callback method to produce multiple outputs from the current phase value in m_phase * and/or the sin and cos values in m_psin and m_pcos */ - virtual void processPhase(Real *samples_out __attribute__((unused))) const {}; + virtual void processPhase(Real *samples_out) const { (void) samples_out; } private: Real m_minfreq, m_maxfreq; diff --git a/sdrbase/dsp/phaselockcomplex.cpp b/sdrbase/dsp/phaselockcomplex.cpp index 0c8d604f3..5aa35c534 100644 --- a/sdrbase/dsp/phaselockcomplex.cpp +++ b/sdrbase/dsp/phaselockcomplex.cpp @@ -21,6 +21,7 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#define _USE_MATH_DEFINES #include #include "phaselockcomplex.h" diff --git a/sdrbase/dsp/projector.cpp b/sdrbase/dsp/projector.cpp index 887be37c0..e557e410d 100644 --- a/sdrbase/dsp/projector.cpp +++ b/sdrbase/dsp/projector.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#define _USE_MATH_DEFINES #include #include "projector.h" diff --git a/sdrbase/plugin/plugininterface.h b/sdrbase/plugin/plugininterface.h index 64d73793d..fca56083b 100644 --- a/sdrbase/plugin/plugininterface.h +++ b/sdrbase/plugin/plugininterface.h @@ -73,7 +73,7 @@ public: }; typedef QList SamplingDevices; - virtual ~PluginInterface() { }; + virtual ~PluginInterface() { } virtual const PluginDescriptor& getPluginDescriptor() const = 0; virtual void initPlugin(PluginAPI* pluginAPI) = 0; @@ -81,44 +81,76 @@ public: // channel Rx plugins virtual PluginInstanceGUI* createRxChannelGUI( - DeviceUISet *deviceUISet __attribute__((unused)), - BasebandSampleSink *rxChannel __attribute__((unused))) - { return 0; } + DeviceUISet *deviceUISet, + BasebandSampleSink *rxChannel) + { + (void) deviceUISet; + (void) rxChannel; + return nullptr; + } virtual BasebandSampleSink* createRxChannelBS( - DeviceSourceAPI *deviceAPI __attribute__((unused)) ) - { return 0; } + DeviceSourceAPI *deviceAPI) + { + (void) deviceAPI; + return nullptr; + } virtual ChannelSinkAPI* createRxChannelCS( - DeviceSourceAPI *deviceAPI __attribute__((unused)) ) - { return 0; } + DeviceSourceAPI *deviceAPI) + { + (void) deviceAPI; + return nullptr; + } // channel Tx plugins virtual PluginInstanceGUI* createTxChannelGUI( - DeviceUISet *deviceUISet __attribute__((unused)), - BasebandSampleSource *txChannel __attribute__((unused))) - { return 0; } + DeviceUISet *deviceUISet, + BasebandSampleSource *txChannel) + { + (void) deviceUISet; + (void) txChannel; + return nullptr; + } virtual BasebandSampleSource* createTxChannelBS( - DeviceSinkAPI *deviceAPI __attribute__((unused)) ) - { return 0; } + DeviceSinkAPI *deviceAPI) + { + (void) deviceAPI; + return nullptr; + } virtual ChannelSourceAPI* createTxChannelCS( - DeviceSinkAPI *deviceAPI __attribute__((unused)) ) - { return 0; } + DeviceSinkAPI *deviceAPI) + { + (void) deviceAPI; + return nullptr; + } // device source plugins only virtual SamplingDevices enumSampleSources() { return SamplingDevices(); } virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI( - const QString& sourceId __attribute__((unused)), - QWidget **widget __attribute__((unused)), - DeviceUISet *deviceUISet __attribute__((unused))) - { return 0; } + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet) + { + (void) sourceId; + (void) widget; + (void) deviceUISet; + return nullptr; + } - virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId __attribute__((unused)), DeviceSourceAPI *deviceAPI __attribute__((unused))) { return 0; } // creates the input "core" + virtual DeviceSampleSource* createSampleSourcePluginInstanceInput( // creates the input "core" + const QString& sourceId, + DeviceSourceAPI *deviceAPI) + { + (void) sourceId; + (void) deviceAPI; + return nullptr; + } virtual void deleteSampleSourcePluginInstanceGUI(PluginInstanceGUI *ui); virtual void deleteSampleSourcePluginInstanceInput(DeviceSampleSource *source); @@ -127,12 +159,25 @@ public: virtual SamplingDevices enumSampleSinks() { return SamplingDevices(); } virtual PluginInstanceGUI* createSampleSinkPluginInstanceGUI( - const QString& sinkId __attribute__((unused)), - QWidget **widget __attribute__((unused)), - DeviceUISet *deviceUISet __attribute__((unused))) - { return 0; } + const QString& sinkId, + QWidget **widget, + DeviceUISet *deviceUISet) + { + (void) sinkId; + (void) widget; + (void) deviceUISet; + return nullptr; + } + + virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput( // creates the output "core" + const QString& sinkId, + DeviceSinkAPI *deviceAPI) + { + (void) sinkId; + (void) deviceAPI; + return nullptr; + } - virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput(const QString& sinkId __attribute__((unused)), DeviceSinkAPI *deviceAPI __attribute__((unused))) { return 0; } // creates the output "core" virtual void deleteSampleSinkPluginInstanceGUI(PluginInstanceGUI *ui); virtual void deleteSampleSinkPluginInstanceOutput(DeviceSampleSink *sink); }; diff --git a/sdrbase/sdrbase.pro b/sdrbase/sdrbase.pro index 37b0f4e91..8b706087b 100644 --- a/sdrbase/sdrbase.pro +++ b/sdrbase/sdrbase.pro @@ -30,10 +30,13 @@ QMAKE_CXXFLAGS += -std=c++11 CONFIG(Release):build_subdir = release CONFIG(Debug):build_subdir = debug +CONFIG(MSVC):DEFINES += sdrbase_EXPORTS + CONFIG(ANDROID):INCLUDEPATH += /opt/softs/boost_1_60_0 CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\boost_1_66_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW32):INCLUDEPATH += "C:\softs\serialDV" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\serialDV" diff --git a/sdrgui/gui/commandoutputdialog.cpp b/sdrgui/gui/commandoutputdialog.cpp index f1c85457c..01bd3e2e7 100644 --- a/sdrgui/gui/commandoutputdialog.cpp +++ b/sdrgui/gui/commandoutputdialog.cpp @@ -39,24 +39,24 @@ void CommandOutputDialog::refresh() ui->commandText->setText(m_command.getLastProcessCommandLine()); ui->processPid->setText(QString("%1").arg(m_command.getLastProcessPid())); - if (m_command.getLastProcessStartTimestamp().tv_sec == 0) { + if (m_command.getLastProcessStartTimestamp() == 0) { ui->startTime->setText(("...")); } else { - struct timeval tv = m_command.getLastProcessStartTimestamp(); - QDateTime dt = QDateTime::fromMSecsSinceEpoch(tv.tv_sec * 1000LL + tv.tv_usec / 1000LL); + clock_t tv = m_command.getLastProcessStartTimestamp(); + QDateTime dt = QDateTime::fromMSecsSinceEpoch((tv * 1000LL) / CLOCKS_PER_SEC); QString dateStr = dt.toString("yyyy-MM-dd HH:mm:ss.zzz"); ui->startTime->setText(dateStr); } - if (m_command.getLastProcessFinishTimestamp().tv_sec == 0) { + if (m_command.getLastProcessFinishTimestamp() == 0) { ui->endTime->setText(("...")); } else { - struct timeval tv = m_command.getLastProcessFinishTimestamp(); - QDateTime dt = QDateTime::fromMSecsSinceEpoch(tv.tv_sec * 1000LL + tv.tv_usec / 1000LL); + clock_t tv = m_command.getLastProcessFinishTimestamp(); + QDateTime dt = QDateTime::fromMSecsSinceEpoch((tv * 1000LL) / CLOCKS_PER_SEC); QString dateStr = dt.toString("yyyy-MM-dd HH:mm:ss.zzz"); ui->endTime->setText(dateStr); } @@ -64,7 +64,7 @@ void CommandOutputDialog::refresh() ui->runningState->setChecked(m_command.getLastProcessState() == QProcess::Running); QProcess::ProcessError processError; - if (m_command.getLastProcessStartTimestamp().tv_sec == 0) // not started + if (m_command.getLastProcessStartTimestamp() == 0) // not started { ui->errorText->setText("..."); ui->exitCode->setText("-"); From 127178f44c7b84334b3aa7837af7f2269c5631c5 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 15:05:14 +0100 Subject: [PATCH 009/102] Windows: MSVC2017: changes in sdrbase (1): fixed with std::chrono --- sdrbase/commands/command.cpp | 30 +++++++++++++++++++++--------- sdrbase/commands/command.h | 10 ++++++---- sdrbase/dsp/nullsink.cpp | 2 +- sdrgui/gui/commandoutputdialog.cpp | 12 +++++------- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/sdrbase/commands/command.cpp b/sdrbase/commands/command.cpp index 097bb42da..d1d52c2d9 100644 --- a/sdrbase/commands/command.cpp +++ b/sdrbase/commands/command.cpp @@ -14,12 +14,14 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "command.h" -#include "util/simpleserializer.h" +#include #include #include +#include "command.h" +#include "util/simpleserializer.h" + Command::Command() : m_currentProcess(nullptr), m_currentProcessState(QProcess::NotRunning), @@ -30,8 +32,8 @@ Command::Command() : m_currentProcessExitStatus(QProcess::NormalExit), m_currentProcessPid(0) { - m_currentProcessStartTimeStamp = 0; - m_currentProcessFinishTimeStamp = 0; + m_currentProcessStartTimeStampms = 0; + m_currentProcessFinishTimeStampms = 0; resetToDefaults(); } @@ -55,8 +57,8 @@ Command::Command(const Command& command) : m_currentProcessExitStatus(QProcess::NormalExit), m_currentProcessPid(0) { - m_currentProcessStartTimeStamp = 0; - m_currentProcessFinishTimeStamp = 0; + m_currentProcessStartTimeStampms = 0; + m_currentProcessFinishTimeStampms = 0; } Command::~Command() @@ -198,7 +200,7 @@ void Command::run(const QString& apiAddress, int apiPort, int deviceSetIndex) connect(m_currentProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState))); m_currentProcess->setProcessChannelMode(QProcess::MergedChannels); - m_currentProcessStartTimeStamp = clock(); + m_currentProcessStartTimeStampms = nowms(); m_currentProcess->start(m_currentProcessCommandLine); } @@ -254,7 +256,7 @@ void Command::processStateChanged(QProcess::ProcessState newState) void Command::processError(QProcess::ProcessError error) { //qDebug("Command::processError: %d state: %d", error, m_currentProcessState); - m_currentProcessFinishTimeStamp = clock(); + m_currentProcessFinishTimeStampms = nowms(); m_currentProcessError = error; m_isInError = true; @@ -278,7 +280,7 @@ void Command::processError(QProcess::ProcessError error) void Command::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { //qDebug("Command::processFinished: (%d) %d", exitCode, exitStatus); - m_currentProcessFinishTimeStamp = clock(); + m_currentProcessFinishTimeStampms = nowms(); m_currentProcessExitCode = exitCode; m_currentProcessExitStatus = exitStatus; m_hasExited = true; @@ -295,3 +297,13 @@ void Command::processFinished(int exitCode, QProcess::ExitStatus exitStatus) m_currentProcess->deleteLater(); // make sure other threads can still access it until all events have been processed m_currentProcess = nullptr; // for this thread it can assume it was deleted } + +uint64_t Command::nowms() +{ + auto now = std::chrono::system_clock::now(); + auto now_ms = std::chrono::time_point_cast(now); + auto epoch = now_ms.time_since_epoch(); + auto value = std::chrono::duration_cast(epoch); + + return value.count(); +} \ No newline at end of file diff --git a/sdrbase/commands/command.h b/sdrbase/commands/command.h index b61442ad1..92e628ead 100644 --- a/sdrbase/commands/command.h +++ b/sdrbase/commands/command.h @@ -63,8 +63,8 @@ public: bool getLastProcessError(QProcess::ProcessError& error) const; bool getLastProcessExit(int& exitCode, QProcess::ExitStatus& exitStatus) const; const QString& getLastProcessLog() const; - clock_t getLastProcessStartTimestamp() const { return m_currentProcessStartTimeStamp; } - clock_t getLastProcessFinishTimestamp() const { return m_currentProcessFinishTimeStamp; } + uint64_t getLastProcessStartTimestampms() const { return m_currentProcessStartTimeStampms; } + uint64_t getLastProcessFinishTimestampms() const { return m_currentProcessFinishTimeStampms; } const QString& getLastProcessCommandLine() const { return m_currentProcessCommandLine; } qint64 getLastProcessPid() const { return m_currentProcessPid; } @@ -91,6 +91,8 @@ public: } private: + uint64_t nowms(); //!< Get now time in milliseconds + QString m_group; QString m_description; QString m_command; @@ -107,8 +109,8 @@ private: int m_currentProcessExitCode; QProcess::ExitStatus m_currentProcessExitStatus; QString m_log; - clock_t m_currentProcessStartTimeStamp; - clock_t m_currentProcessFinishTimeStamp; + uint64_t m_currentProcessStartTimeStampms; + uint64_t m_currentProcessFinishTimeStampms; QString m_currentProcessCommandLine; qint64 m_currentProcessPid; diff --git a/sdrbase/dsp/nullsink.cpp b/sdrbase/dsp/nullsink.cpp index 5f1b7a3fa..b244dc15e 100644 --- a/sdrbase/dsp/nullsink.cpp +++ b/sdrbase/dsp/nullsink.cpp @@ -13,7 +13,7 @@ NullSink::~NullSink() bool NullSink::init(const Message& message) { - (void) message + (void) message; return false; } diff --git a/sdrgui/gui/commandoutputdialog.cpp b/sdrgui/gui/commandoutputdialog.cpp index 01bd3e2e7..0c9d2adf9 100644 --- a/sdrgui/gui/commandoutputdialog.cpp +++ b/sdrgui/gui/commandoutputdialog.cpp @@ -39,24 +39,22 @@ void CommandOutputDialog::refresh() ui->commandText->setText(m_command.getLastProcessCommandLine()); ui->processPid->setText(QString("%1").arg(m_command.getLastProcessPid())); - if (m_command.getLastProcessStartTimestamp() == 0) { + if (m_command.getLastProcessStartTimestampms() == 0) { ui->startTime->setText(("...")); } else { - clock_t tv = m_command.getLastProcessStartTimestamp(); - QDateTime dt = QDateTime::fromMSecsSinceEpoch((tv * 1000LL) / CLOCKS_PER_SEC); + QDateTime dt = QDateTime::fromMSecsSinceEpoch(m_command.getLastProcessStartTimestampms()); QString dateStr = dt.toString("yyyy-MM-dd HH:mm:ss.zzz"); ui->startTime->setText(dateStr); } - if (m_command.getLastProcessFinishTimestamp() == 0) { + if (m_command.getLastProcessFinishTimestampms() == 0) { ui->endTime->setText(("...")); } else { - clock_t tv = m_command.getLastProcessFinishTimestamp(); - QDateTime dt = QDateTime::fromMSecsSinceEpoch((tv * 1000LL) / CLOCKS_PER_SEC); + QDateTime dt = QDateTime::fromMSecsSinceEpoch(m_command.getLastProcessFinishTimestampms()); QString dateStr = dt.toString("yyyy-MM-dd HH:mm:ss.zzz"); ui->endTime->setText(dateStr); } @@ -64,7 +62,7 @@ void CommandOutputDialog::refresh() ui->runningState->setChecked(m_command.getLastProcessState() == QProcess::Running); QProcess::ProcessError processError; - if (m_command.getLastProcessStartTimestamp() == 0) // not started + if (m_command.getLastProcessStartTimestampms() == 0) // not started { ui->errorText->setText("..."); ui->exitCode->setText("-"); From cdacf51bfb61a2372b4efcf53a5b40bedac068b5 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 15:48:41 +0100 Subject: [PATCH 010/102] Windows: MSVC2017: fixed some attribute unused cases --- devices/hackrf/devicehackrf.h | 6 +----- sdrgui/soapygui/arginfogui.cpp | 5 +---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/devices/hackrf/devicehackrf.h b/devices/hackrf/devicehackrf.h index 291e617b6..51ee822c2 100644 --- a/devices/hackrf/devicehackrf.h +++ b/devices/hackrf/devicehackrf.h @@ -30,11 +30,7 @@ public: protected: DeviceHackRF(); DeviceHackRF(const DeviceHackRF&) {} -#ifdef _MSC_VER - DeviceHackRF& operator=(const DeviceHackRF& other) { return *this; } -#else - DeviceHackRF& operator=(const DeviceHackRF& other __attribute__((unused))) { return *this; } -#endif + DeviceHackRF& operator=(const DeviceHackRF& other) { (void) other; return *this; } ~DeviceHackRF(); private: static hackrf_device *open_hackrf_from_sequence(int sequence); diff --git a/sdrgui/soapygui/arginfogui.cpp b/sdrgui/soapygui/arginfogui.cpp index d914df185..ae3705771 100644 --- a/sdrgui/soapygui/arginfogui.cpp +++ b/sdrgui/soapygui/arginfogui.cpp @@ -363,12 +363,9 @@ void ArgInfoGUI::on_argEdit_editingFinished() emit valueChanged(); } -#ifdef _MSC_VER void ArgInfoGUI::on_argCombo_currentIndexChanged(int index) -#else -void ArgInfoGUI::on_argCombo_currentIndexChanged(int index __attribute__((unused))) -#endif { + (void) index; QVariant v = ui->argCombo->currentData(); bool ok = false; From f97728c4e95ca0a04aaaf7bbf31b88bd61000b65 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 16:05:18 +0100 Subject: [PATCH 011/102] Windows: MSVC2017: changes in qrtplib --- qrtplib/rtpconfig.h | 4 ++++ qrtplib/rtprandom.cpp | 8 ++++++++ qrtplib/rtpsession.cpp | 4 ++-- qrtplib/rtpsessionparams.cpp | 6 ++++-- qrtplib/rtptimeutilities.h | 2 ++ 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/qrtplib/rtpconfig.h b/qrtplib/rtpconfig.h index faf4e6e2f..c69114266 100644 --- a/qrtplib/rtpconfig.h +++ b/qrtplib/rtpconfig.h @@ -84,7 +84,11 @@ // No SRTP support +#ifdef _MSC_VER +#define RTP_HAVE_QUERYPERFORMANCECOUNTER +#else #define RTP_HAVE_CLOCK_GETTIME +#endif #define RTP_HAVE_POLL diff --git a/qrtplib/rtprandom.cpp b/qrtplib/rtprandom.cpp index 5fbb5562f..e5764714c 100644 --- a/qrtplib/rtprandom.cpp +++ b/qrtplib/rtprandom.cpp @@ -40,7 +40,11 @@ #include "rtprandomrand48.h" #include +#ifdef _MSC_VER +#include "Windows.h" +#else #include +#endif #include @@ -50,7 +54,11 @@ namespace qrtplib uint32_t RTPRandom::PickSeed() { uint32_t x; +#ifdef _MSC_VER + x = GetCurrentProcessId(); +#else x = (uint32_t) getpid(); +#endif QDateTime currentDateTime = QDateTime::currentDateTime(); x += currentDateTime.toTime_t(); #if defined(WIN32) diff --git a/qrtplib/rtpsession.cpp b/qrtplib/rtpsession.cpp index a9d42a8d2..1740409d0 100644 --- a/qrtplib/rtpsession.cpp +++ b/qrtplib/rtpsession.cpp @@ -49,7 +49,6 @@ #endif // RTP_SUPPORT_SENDAPP #include "rtpinternalutils.h" -#include #include #include @@ -1143,8 +1142,9 @@ int RTPSession::ProcessPolledData() return 0; } -int RTPSession::CreateCNAME(uint8_t *buffer, std::size_t *bufferlength, bool resolve __attribute__((unused))) +int RTPSession::CreateCNAME(uint8_t *buffer, std::size_t *bufferlength, bool resolve) { + (void) resolve; buffer[*bufferlength - 1] = 0; std::size_t offset = strlen((const char *) buffer); diff --git a/qrtplib/rtpsessionparams.cpp b/qrtplib/rtpsessionparams.cpp index 40b611899..916c49852 100644 --- a/qrtplib/rtpsessionparams.cpp +++ b/qrtplib/rtpsessionparams.cpp @@ -67,13 +67,15 @@ RTPSessionParams::RTPSessionParams() : predefinedssrc = 0; } -int RTPSessionParams::SetUsePollThread(bool usethread __attribute__((unused))) +int RTPSessionParams::SetUsePollThread(bool usethread) { + (void) usethread; return ERR_RTP_NOTHREADSUPPORT; } -int RTPSessionParams::SetNeedThreadSafety(bool __attribute__((unused))) +int RTPSessionParams::SetNeedThreadSafety(bool x) { + (void) x; return ERR_RTP_NOTHREADSUPPORT; } diff --git a/qrtplib/rtptimeutilities.h b/qrtplib/rtptimeutilities.h index 7252bb7ba..526141777 100644 --- a/qrtplib/rtptimeutilities.h +++ b/qrtplib/rtptimeutilities.h @@ -44,6 +44,8 @@ #include #include #include +#else +#include "Windows.h" #endif // RTP_HAVE_QUERYPERFORMANCECOUNTER #include "export.h" From 70a4db39c0d984c650da534caa3127a9e37a9396 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 16:58:20 +0100 Subject: [PATCH 012/102] Windows: MSVC2017: changes in sdrbase (2) --- sdrbase/audio/audionetsink.cpp | 1 - sdrbase/dsp/fftfilt.cpp | 1 - sdrbase/dsp/filerecord.cpp | 5 +- sdrbase/dsp/filtermbe.h | 8 +- sdrbase/dsp/nullsink.cpp | 8 +- sdrbase/dsp/threadedbasebandsamplesink.cpp | 3 +- sdrbase/sdrbase.pro | 4 +- sdrbase/util/uid.cpp | 4 +- sdrbase/webapi/webapiadapterinterface.h | 248 ++++++++++++++------- 9 files changed, 186 insertions(+), 96 deletions(-) diff --git a/sdrbase/audio/audionetsink.cpp b/sdrbase/audio/audionetsink.cpp index 70c7dac0f..4da761a5e 100644 --- a/sdrbase/audio/audionetsink.cpp +++ b/sdrbase/audio/audionetsink.cpp @@ -18,7 +18,6 @@ #include "audionetsink.h" #include "util/rtpsink.h" -#include #include const int AudioNetSink::m_udpBlockSize = 512; diff --git a/sdrbase/dsp/fftfilt.cpp b/sdrbase/dsp/fftfilt.cpp index 8b7a6698f..e05029b3c 100644 --- a/sdrbase/dsp/fftfilt.cpp +++ b/sdrbase/dsp/fftfilt.cpp @@ -37,7 +37,6 @@ #include #include -#include #include #include diff --git a/sdrbase/dsp/filerecord.cpp b/sdrbase/dsp/filerecord.cpp index 5a483e7d9..5e7e3a6bd 100644 --- a/sdrbase/dsp/filerecord.cpp +++ b/sdrbase/dsp/filerecord.cpp @@ -68,8 +68,9 @@ void FileRecord::genUniqueFileName(uint deviceUID) setFileName(QString("rec%1_%2.sdriq").arg(deviceUID).arg(QDateTime::currentDateTimeUtc().toString("yyyy-MM-ddTHH_mm_ss_zzz"))); } -void FileRecord::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused))) +void FileRecord::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) { + (void) positiveOnly; // if no recording is active, send the samples to /dev/null if(!m_recordOn) return; @@ -173,4 +174,4 @@ void FileRecord::writeHeader(std::ofstream& sampleFile, Header& header) crc32.process_bytes(&header, 28); header.crc32 = crc32.checksum(); sampleFile.write((const char *) &header, sizeof(Header)); -} \ No newline at end of file +} diff --git a/sdrbase/dsp/filtermbe.h b/sdrbase/dsp/filtermbe.h index 2b4cc3dc1..1406fa32f 100644 --- a/sdrbase/dsp/filtermbe.h +++ b/sdrbase/dsp/filtermbe.h @@ -76,8 +76,12 @@ private: IIRFilter m_filterLP; IIRFilter m_filterHP; bool m_useHP; - static const float m_lpa[3], m_lpb[3]; // low pass coefficients - static const float m_hpa[3], m_hpb[3]; // band pass coefficients + // low pass coefficients + static const float m_lpa[3]; + static const float m_lpb[3]; + // band pass coefficients + static const float m_hpa[3]; + static const float m_hpb[3]; }; diff --git a/sdrbase/dsp/nullsink.cpp b/sdrbase/dsp/nullsink.cpp index b244dc15e..1c372a6b1 100644 --- a/sdrbase/dsp/nullsink.cpp +++ b/sdrbase/dsp/nullsink.cpp @@ -17,8 +17,11 @@ bool NullSink::init(const Message& message) return false; } -void NullSink::feed(const SampleVector::const_iterator& begin __attribute__((unused)), const SampleVector::const_iterator& end __attribute__((unused)), bool positiveOnly __attribute__((unused))) +void NullSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) { + (void) begin; + (void) end; + (void) positiveOnly; } void NullSink::start() @@ -29,7 +32,8 @@ void NullSink::stop() { } -bool NullSink::handleMessage(const Message& message __attribute__((unused))) +bool NullSink::handleMessage(const Message& message) { + (void) message; return false; } diff --git a/sdrbase/dsp/threadedbasebandsamplesink.cpp b/sdrbase/dsp/threadedbasebandsamplesink.cpp index e646cd7cc..cce47ec6a 100644 --- a/sdrbase/dsp/threadedbasebandsamplesink.cpp +++ b/sdrbase/dsp/threadedbasebandsamplesink.cpp @@ -111,8 +111,9 @@ void ThreadedBasebandSampleSink::stop() m_thread->wait(); } -void ThreadedBasebandSampleSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly __attribute__((unused))) +void ThreadedBasebandSampleSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly) { + (void) positiveOnly; //m_sampleSink->feed(begin, end, positiveOnly); //m_sampleFifo.write(begin, end); m_threadedBasebandSampleSinkFifo->writeToFifo(begin, end); diff --git a/sdrbase/sdrbase.pro b/sdrbase/sdrbase.pro index 8b706087b..1dd573aeb 100644 --- a/sdrbase/sdrbase.pro +++ b/sdrbase/sdrbase.pro @@ -224,7 +224,9 @@ HEADERS += audio/audiodevicemanager.h\ webapi/webapiserver.h\ mainparser.h -!macx:LIBS += -L../serialdv/$${build_subdir} -lserialdv +MINGW32 || MINGW64 { + LIBS += -L../serialdv/$${build_subdir} -lserialdv +} LIBS += -L../httpserver/$${build_subdir} -lhttpserver LIBS += -L../qrtplib/$${build_subdir} -lqrtplib LIBS += -L../swagger/$${build_subdir} -lswagger diff --git a/sdrbase/util/uid.cpp b/sdrbase/util/uid.cpp index 386f16586..ed19086ba 100644 --- a/sdrbase/util/uid.cpp +++ b/sdrbase/util/uid.cpp @@ -23,7 +23,7 @@ #include #include -#ifdef _WIN32_ +#if (defined _WIN32_) || (defined _MSC_VER) #include #else #include @@ -67,7 +67,7 @@ uint32_t UidCalculator::getNewInstanceId() uint64_t UidCalculator::getCurrentMiroseconds() { -#ifdef _WIN32_ +#if (defined _WIN32_) || (defined _MSC_VER) LARGE_INTEGER tickPerSecond; LARGE_INTEGER tick; // a point in time diff --git a/sdrbase/webapi/webapiadapterinterface.h b/sdrbase/webapi/webapiadapterinterface.h index 7f0434734..df03cd554 100644 --- a/sdrbase/webapi/webapiadapterinterface.h +++ b/sdrbase/webapi/webapiadapterinterface.h @@ -64,9 +64,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceSummary( - SWGSDRangel::SWGInstanceSummaryResponse& response __attribute__((unused)), + SWGSDRangel::SWGInstanceSummaryResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -77,9 +78,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceDelete( - SWGSDRangel::SWGSuccessResponse& response __attribute__((unused)), + SWGSDRangel::SWGSuccessResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -90,10 +92,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceDevices( - bool tx __attribute__((unused)), - SWGSDRangel::SWGInstanceDevicesResponse& response __attribute__((unused)), + bool tx, + SWGSDRangel::SWGInstanceDevicesResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) tx; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -104,10 +108,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceChannels( - bool tx __attribute__((unused)), - SWGSDRangel::SWGInstanceChannelsResponse& response __attribute__((unused)), + bool tx, + SWGSDRangel::SWGInstanceChannelsResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) tx; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -118,9 +124,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceLoggingGet( - SWGSDRangel::SWGLoggingInfo& response __attribute__((unused)), + SWGSDRangel::SWGLoggingInfo& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -131,10 +138,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceLoggingPut( - SWGSDRangel::SWGLoggingInfo& query __attribute__((unused)), - SWGSDRangel::SWGLoggingInfo& response __attribute__((unused)), + SWGSDRangel::SWGLoggingInfo& query, + SWGSDRangel::SWGLoggingInfo& response, SWGSDRangel::SWGErrorResponse& error) { + (void) query; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -145,9 +154,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceAudioGet( - SWGSDRangel::SWGAudioDevices& response __attribute__((unused)), + SWGSDRangel::SWGAudioDevices& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -158,10 +168,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceAudioInputPatch( - SWGSDRangel::SWGAudioInputDevice& response __attribute__((unused)), - const QStringList& audioInputKeys __attribute__((unused)), + SWGSDRangel::SWGAudioInputDevice& response, + const QStringList& audioInputKeys, SWGSDRangel::SWGErrorResponse& error) { + (void) response; + (void) audioInputKeys; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -172,10 +184,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceAudioOutputPatch( - SWGSDRangel::SWGAudioOutputDevice& response __attribute__((unused)), - const QStringList& audioOutputKeys __attribute__((unused)), + SWGSDRangel::SWGAudioOutputDevice& response, + const QStringList& audioOutputKeys, SWGSDRangel::SWGErrorResponse& error) { + (void) response; + (void) audioOutputKeys; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -186,9 +200,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceAudioInputDelete( - SWGSDRangel::SWGAudioInputDevice& response __attribute__((unused)), + SWGSDRangel::SWGAudioInputDevice& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -199,9 +214,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceAudioOutputDelete( - SWGSDRangel::SWGAudioOutputDevice& response __attribute__((unused)), + SWGSDRangel::SWGAudioOutputDevice& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -212,9 +228,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceAudioInputCleanupPatch( - SWGSDRangel::SWGSuccessResponse& response __attribute__((unused)), + SWGSDRangel::SWGSuccessResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -225,9 +242,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceAudioOutputCleanupPatch( - SWGSDRangel::SWGSuccessResponse& response __attribute__((unused)), + SWGSDRangel::SWGSuccessResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -238,9 +256,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceLocationGet( - SWGSDRangel::SWGLocationInformation& response __attribute__((unused)), + SWGSDRangel::SWGLocationInformation& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -251,9 +270,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceLocationPut( - SWGSDRangel::SWGLocationInformation& response __attribute__((unused)), + SWGSDRangel::SWGLocationInformation& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -264,9 +284,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceDVSerialGet( - SWGSDRangel::SWGDVSeralDevices& response __attribute__((unused)), + SWGSDRangel::SWGDVSeralDevices& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -277,10 +298,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceDVSerialPatch( - bool dvserial __attribute__((unused)), - SWGSDRangel::SWGDVSeralDevices& response __attribute__((unused)), + bool dvserial, + SWGSDRangel::SWGDVSeralDevices& response, SWGSDRangel::SWGErrorResponse& error) { + (void) dvserial; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -291,9 +314,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instancePresetsGet( - SWGSDRangel::SWGPresets& response __attribute__((unused)), + SWGSDRangel::SWGPresets& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -304,10 +328,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instancePresetPatch( - SWGSDRangel::SWGPresetTransfer& query __attribute__((unused)), - SWGSDRangel::SWGPresetIdentifier& response __attribute__((unused)), + SWGSDRangel::SWGPresetTransfer& query, + SWGSDRangel::SWGPresetIdentifier& response, SWGSDRangel::SWGErrorResponse& error) { + (void) query; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -318,10 +344,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instancePresetPut( - SWGSDRangel::SWGPresetTransfer& query __attribute__((unused)), - SWGSDRangel::SWGPresetIdentifier& response __attribute__((unused)), + SWGSDRangel::SWGPresetTransfer& query, + SWGSDRangel::SWGPresetIdentifier& response, SWGSDRangel::SWGErrorResponse& error) { + (void) query; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -332,10 +360,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instancePresetPost( - SWGSDRangel::SWGPresetTransfer& query __attribute__((unused)), - SWGSDRangel::SWGPresetIdentifier& response __attribute__((unused)), + SWGSDRangel::SWGPresetTransfer& query, + SWGSDRangel::SWGPresetIdentifier& response, SWGSDRangel::SWGErrorResponse& error) { + (void) query; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -346,9 +376,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instancePresetDelete( - SWGSDRangel::SWGPresetIdentifier& response __attribute__((unused)), + SWGSDRangel::SWGPresetIdentifier& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -359,10 +390,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instancePresetFilePut( - SWGSDRangel::SWGPresetImport& query __attribute__((unused)), - SWGSDRangel::SWGPresetIdentifier& response __attribute__((unused)), + SWGSDRangel::SWGPresetImport& query, + SWGSDRangel::SWGPresetIdentifier& response, SWGSDRangel::SWGErrorResponse& error) { + (void) query; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -373,10 +406,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instancePresetFilePost( - SWGSDRangel::SWGPresetExport& query __attribute__((unused)), - SWGSDRangel::SWGPresetIdentifier& response __attribute__((unused)), + SWGSDRangel::SWGPresetExport& query, + SWGSDRangel::SWGPresetIdentifier& response, SWGSDRangel::SWGErrorResponse& error) { + (void) query; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -387,9 +422,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceDeviceSetsGet( - SWGSDRangel::SWGDeviceSetList& response __attribute__((unused)), + SWGSDRangel::SWGDeviceSetList& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -400,10 +436,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceDeviceSetPost( - bool tx __attribute__((unused)), - SWGSDRangel::SWGSuccessResponse& response __attribute__((unused)), + bool tx, + SWGSDRangel::SWGSuccessResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) tx; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -414,9 +452,10 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int instanceDeviceSetDelete( - SWGSDRangel::SWGSuccessResponse& response __attribute__((unused)), + SWGSDRangel::SWGSuccessResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -427,10 +466,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetGet( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGDeviceSet& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGDeviceSet& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -441,10 +482,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetFocusPatch( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGSuccessResponse& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGSuccessResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -455,11 +498,14 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetDevicePut( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGDeviceListItem& query __attribute__((unused)), - SWGSDRangel::SWGDeviceListItem& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGDeviceListItem& query, + SWGSDRangel::SWGDeviceListItem& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) query; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -470,10 +516,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetDeviceSettingsGet( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGDeviceSettings& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGDeviceSettings& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -484,12 +532,16 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetDeviceSettingsPutPatch( - int deviceSetIndex __attribute__((unused)), - bool force __attribute__((unused)), //!< true to force settings = put else patch - const QStringList& channelSettingsKeys __attribute__((unused)), - SWGSDRangel::SWGDeviceSettings& response __attribute__((unused)), + int deviceSetIndex, + bool force, //!< true to force settings = put else patch + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) force; + (void) channelSettingsKeys; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -500,10 +552,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetDeviceRunGet( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGDeviceState& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGDeviceState& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -514,10 +568,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetDeviceRunPost( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGDeviceState& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGDeviceState& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -528,11 +584,13 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetDeviceRunDelete( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGDeviceState& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGDeviceState& response, SWGSDRangel::SWGErrorResponse& error) { - error.init(); + (void) deviceSetIndex; + (void) response; + error.init(); *error.getMessage() = QString("Function not implemented"); return 501; } @@ -542,10 +600,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetDeviceReportGet( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGDeviceReport& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGDeviceReport& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -556,10 +616,12 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetChannelsReportGet( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGChannelsDetail& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGChannelsDetail& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -570,12 +632,15 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetChannelPost( - int deviceSetIndex __attribute__((unused)), - SWGSDRangel::SWGChannelSettings& query __attribute__((unused)), - SWGSDRangel::SWGSuccessResponse& response __attribute__((unused)), + int deviceSetIndex, + SWGSDRangel::SWGChannelSettings& query, + SWGSDRangel::SWGSuccessResponse& response, SWGSDRangel::SWGErrorResponse& error) { - error.init(); + (void) deviceSetIndex; + (void) query; + (void) response; + error.init(); *error.getMessage() = QString("Function not implemented"); return 501; } @@ -585,11 +650,15 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetChannelDelete( - int deviceSetIndex __attribute__((unused)), - int channelIndex __attribute__((unused)), - SWGSDRangel::SWGSuccessResponse& response __attribute__((unused)), - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + int deviceSetIndex, + int channelIndex, + SWGSDRangel::SWGSuccessResponse& response, + SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) channelIndex; + (void) response; + (void) error; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; @@ -600,12 +669,15 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetChannelSettingsGet( - int deviceSetIndex __attribute__((unused)), - int channelIndex __attribute__((unused)), - SWGSDRangel::SWGChannelSettings& response __attribute__((unused)), + int deviceSetIndex, + int channelIndex, + SWGSDRangel::SWGChannelSettings& response, SWGSDRangel::SWGErrorResponse& error) { - error.init(); + (void) deviceSetIndex; + (void) channelIndex; + (void) response; + error.init(); *error.getMessage() = QString("Function not implemented"); return 501; } @@ -615,14 +687,19 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetChannelSettingsPutPatch( - int deviceSetIndex __attribute__((unused)), - int channelIndex __attribute__((unused)), - bool force __attribute__((unused)), - const QStringList& channelSettingsKeys __attribute__((unused)), - SWGSDRangel::SWGChannelSettings& response __attribute__((unused)), + int deviceSetIndex, + int channelIndex, + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, SWGSDRangel::SWGErrorResponse& error) { - error.init(); + (void) deviceSetIndex; + (void) channelIndex; + (void) force; + (void) channelSettingsKeys; + (void) response; + error.init(); *error.getMessage() = QString("Function not implemented"); return 501; } @@ -633,11 +710,14 @@ public: * returns the Http status code (default 501: not implemented) */ virtual int devicesetChannelReportGet( - int deviceSetIndex __attribute__((unused)), - int channelIndex __attribute__((unused)), - SWGSDRangel::SWGChannelReport& response __attribute__((unused)), + int deviceSetIndex, + int channelIndex, + SWGSDRangel::SWGChannelReport& response, SWGSDRangel::SWGErrorResponse& error) { + (void) deviceSetIndex; + (void) channelIndex; + (void) response; error.init(); *error.getMessage() = QString("Function not implemented"); return 501; From 64169bc168b22bd1086d9e1868c82d9cc161d178 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 17:22:19 +0100 Subject: [PATCH 013/102] Windows: MSVC2017: changes in sdrbase (3) serialdv --- exports/export.h | 12 ++++++++++++ sdrbase/dsp/dvserialengine.cpp | 6 ++++-- sdrbase/dsp/dvserialworker.cpp | 5 +++-- sdrbase/sdrbase.pro | 5 +++-- serialdv/serialdv.pro | 4 ++++ 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/exports/export.h b/exports/export.h index 10b79fea5..cda4f61f8 100644 --- a/exports/export.h +++ b/exports/export.h @@ -102,6 +102,18 @@ # define QRTPLIB_API #endif +/* the 'SERIALDV_API' controls the import/export of 'serialdv' symbols + */ +#if !defined(sdrangel_STATIC) +# ifdef serialdv_EXPORTS +# define SERIALDV_API __SDR_EXPORT +# else +# define SERIALDV_API __SDR_IMPORT +# endif +#else +# define SERIALDV_API +#endif + /* the 'SWG_API' controls the import/export of 'swagger' symbols */ #if !defined(sdrangel_STATIC) diff --git a/sdrbase/dsp/dvserialengine.cpp b/sdrbase/dsp/dvserialengine.cpp index ddb4370b9..5aba10314 100644 --- a/sdrbase/dsp/dvserialengine.cpp +++ b/sdrbase/dsp/dvserialengine.cpp @@ -16,14 +16,16 @@ /////////////////////////////////////////////////////////////////////////////////// #include -#include #include #include #include -#include #include #include +#ifndef _MSC_VER +#include +#include #include +#endif #ifndef __WINDOWS__ #include diff --git a/sdrbase/dsp/dvserialworker.cpp b/sdrbase/dsp/dvserialworker.cpp index e72f0f5db..cc5f04b56 100644 --- a/sdrbase/dsp/dvserialworker.cpp +++ b/sdrbase/dsp/dvserialworker.cpp @@ -15,7 +15,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include +#include +#include #include "dsp/dvserialworker.h" #include "audio/audiofifo.h" @@ -60,7 +61,7 @@ void DVSerialWorker::process() while (m_running) { - sleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); } qDebug("DVSerialWorker::process: stopped"); diff --git a/sdrbase/sdrbase.pro b/sdrbase/sdrbase.pro index 1dd573aeb..2cb0d17e4 100644 --- a/sdrbase/sdrbase.pro +++ b/sdrbase/sdrbase.pro @@ -40,10 +40,11 @@ CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW32):INCLUDEPATH += "C:\softs\serialDV" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\serialDV" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\serialDV" CONFIG(macx):INCLUDEPATH += "../../../boost_1_64_0" -MINGW32 || MINGW64 { +MINGW32 || MINGW64 || MSVC { HEADERS += \ dsp/dvserialengine.h \ dsp/dvserialworker.h @@ -224,7 +225,7 @@ HEADERS += audio/audiodevicemanager.h\ webapi/webapiserver.h\ mainparser.h -MINGW32 || MINGW64 { +MINGW32 || MINGW64 || MSVC { LIBS += -L../serialdv/$${build_subdir} -lserialdv } LIBS += -L../httpserver/$${build_subdir} -lhttpserver diff --git a/serialdv/serialdv.pro b/serialdv/serialdv.pro index e1b141383..48b7a38c9 100644 --- a/serialdv/serialdv.pro +++ b/serialdv/serialdv.pro @@ -9,10 +9,14 @@ QT += core TEMPLATE = lib TARGET = serialdv +CONFIG(MSVC):DEFINES += serialdv_EXPORTS + CONFIG(MINGW32):LIBSERIALDVSRC = "C:\softs\serialDV" CONFIG(MINGW64):LIBSERIALDVSRC = "C:\softs\serialDV" +CONFIG(MSVC):LIBSERIALDVSRC = "C:\softs\serialDV" INCLUDEPATH += $$LIBSERIALDVSRC +INCLUDEPATH += ../exports DEFINES += __WINDOWS__=1 From fd50eeb8106f97fc9420c8a3495f3c360c5c065e Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 17:50:52 +0100 Subject: [PATCH 014/102] Windows: MSVC2017: changes in sdrbase (4) qrtplib (2) --- qrtplib/rtperrors.h | 3 ++- sdrbase/dsp/dspcommands.cpp | 1 - sdrbase/dsp/dspcommands.h | 21 --------------------- 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/qrtplib/rtperrors.h b/qrtplib/rtperrors.h index ec12c7955..fba59d681 100644 --- a/qrtplib/rtperrors.h +++ b/qrtplib/rtperrors.h @@ -38,6 +38,7 @@ #define RTPERRORS_H +#include "export.h" #include "rtpconfig.h" #include @@ -45,7 +46,7 @@ namespace qrtplib { /** Returns a string describing the error code \c errcode. */ -std::string RTPGetErrorString(int errcode); +QRTPLIB_API std::string RTPGetErrorString(int errcode); } // end namespace diff --git a/sdrbase/dsp/dspcommands.cpp b/sdrbase/dsp/dspcommands.cpp index 71ab79ca2..a6cc3765a 100644 --- a/sdrbase/dsp/dspcommands.cpp +++ b/sdrbase/dsp/dspcommands.cpp @@ -40,7 +40,6 @@ MESSAGE_CLASS_DEFINITION(DSPRemoveThreadedBasebandSampleSink, Message) MESSAGE_CLASS_DEFINITION(DSPRemoveThreadedBasebandSampleSource, Message) MESSAGE_CLASS_DEFINITION(DSPAddAudioSink, Message) MESSAGE_CLASS_DEFINITION(DSPRemoveAudioSink, Message) -//MESSAGE_CLASS_DEFINITION(DSPConfigureSpectrumVis, Message) MESSAGE_CLASS_DEFINITION(DSPConfigureCorrection, Message) MESSAGE_CLASS_DEFINITION(DSPEngineReport, Message) MESSAGE_CLASS_DEFINITION(DSPConfigureScopeVis, Message) diff --git a/sdrbase/dsp/dspcommands.h b/sdrbase/dsp/dspcommands.h index ca1a5343b..3d66541e3 100644 --- a/sdrbase/dsp/dspcommands.h +++ b/sdrbase/dsp/dspcommands.h @@ -256,27 +256,6 @@ private: AudioFifo* m_audioFifo; }; -class SDRBASE_API DSPConfigureSpectrumVis : public Message { - MESSAGE_CLASS_DECLARATION - -public: - DSPConfigureSpectrumVis(int fftSize, int overlapPercent, FFTWindow::Function window) : - Message(), - m_fftSize(fftSize), - m_overlapPercent(overlapPercent), - m_window(window) - { } - - int getFFTSize() const { return m_fftSize; } - int getOverlapPercent() const { return m_overlapPercent; } - FFTWindow::Function getWindow() const { return m_window; } - -private: - int m_fftSize; - int m_overlapPercent; - FFTWindow::Function m_window; -}; - class SDRBASE_API DSPConfigureCorrection : public Message { MESSAGE_CLASS_DECLARATION From d910675587f222f19bdd958bdb0f7c889c5befe1 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 12 Nov 2018 18:36:27 +0100 Subject: [PATCH 015/102] Windows: MSVC2017: changes in sdrgui and sdrbase (5) --- sdrbase/dsp/projector.h | 3 +- sdrgui/dsp/scopevis.cpp | 3 +- sdrgui/dsp/scopevisxy.cpp | 13 +++-- sdrgui/dsp/spectrumscopecombovis.cpp | 3 +- sdrgui/gui/audiodialog.cpp | 12 +++-- sdrgui/gui/clickablelabel.cpp | 10 +++- sdrgui/gui/clickablelabel.h | 5 +- sdrgui/gui/crightclickenabler.h | 4 +- sdrgui/gui/cwkeyergui.cpp | 3 +- sdrgui/gui/editcommanddialog.cpp | 6 ++- sdrgui/gui/glscopegui.cpp | 75 ++++++++++++++++++---------- sdrgui/gui/glspectrumgui.cpp | 3 +- sdrgui/gui/loggingdialog.cpp | 3 +- sdrgui/gui/tickedslider.cpp | 4 +- sdrgui/gui/tvscreen.cpp | 3 +- sdrgui/mainwindow.cpp | 14 ++++-- sdrgui/sdrgui.pro | 3 ++ sdrgui/webapi/webapiadaptergui.cpp | 50 ++++++++++++------- 18 files changed, 146 insertions(+), 71 deletions(-) diff --git a/sdrbase/dsp/projector.h b/sdrbase/dsp/projector.h index 3e2f65602..093b878fb 100644 --- a/sdrbase/dsp/projector.h +++ b/sdrbase/dsp/projector.h @@ -15,9 +15,10 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include "export.h" #include "dsptypes.h" -class Projector +class SDRBASE_API Projector { public: enum ProjectionType diff --git a/sdrgui/dsp/scopevis.cpp b/sdrgui/dsp/scopevis.cpp index 170214162..872d34f05 100644 --- a/sdrgui/dsp/scopevis.cpp +++ b/sdrgui/dsp/scopevis.cpp @@ -216,8 +216,9 @@ void ScopeVis::setMemoryIndex(uint32_t memoryIndex) getInputMessageQueue()->push(cmd); } -void ScopeVis::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused))) +void ScopeVis::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly) { + (void) positiveOnly; if (m_freeRun) { m_triggerPoint = cbegin; } diff --git a/sdrgui/dsp/scopevisxy.cpp b/sdrgui/dsp/scopevisxy.cpp index 2677d4690..e754e75a6 100644 --- a/sdrgui/dsp/scopevisxy.cpp +++ b/sdrgui/dsp/scopevisxy.cpp @@ -15,9 +15,11 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include +#include + #include "scopevisxy.h" #include "gui/tvscreen.h" -#include ScopeVisXY::ScopeVisXY(TVScreen *tvScreen) : m_tvScreen(tvScreen), @@ -47,9 +49,9 @@ void ScopeVisXY::setPixelsPerFrame(int pixelsPerFrame) m_tvScreen->setAlphaReset(); } -void ScopeVisXY::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, - bool positiveOnly __attribute__((unused))) +void ScopeVisXY::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly) { + (void) positiveOnly; SampleVector::const_iterator begin(cbegin); while (begin < end) @@ -83,7 +85,7 @@ void ScopeVisXY::feed(const SampleVector::const_iterator& cbegin, const SampleVe m_tvScreen->renderImage(0); m_tvScreen->update(); - usleep(5000); + std::this_thread::sleep_for(std::chrono::microseconds(5000)); m_tvScreen->resetImage(m_alphaReset); drawGraticule(); m_pixelCount = 0; @@ -99,8 +101,9 @@ void ScopeVisXY::stop() { } -bool ScopeVisXY::handleMessage(const Message& message __attribute__((unused))) +bool ScopeVisXY::handleMessage(const Message& message) { + (void) message; return false; } diff --git a/sdrgui/dsp/spectrumscopecombovis.cpp b/sdrgui/dsp/spectrumscopecombovis.cpp index 970ef82ca..627be45a5 100644 --- a/sdrgui/dsp/spectrumscopecombovis.cpp +++ b/sdrgui/dsp/spectrumscopecombovis.cpp @@ -14,8 +14,9 @@ SpectrumScopeComboVis::~SpectrumScopeComboVis() { } -void SpectrumScopeComboVis::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused))) +void SpectrumScopeComboVis::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) { + (void) positiveOnly; m_scopeVis->feed(begin, end, false); SampleVector::const_iterator triggerPoint = m_scopeVis->getTriggerPoint(); m_spectrumVis->feedTriggered(triggerPoint, end, positiveOnly); diff --git a/sdrgui/gui/audiodialog.cpp b/sdrgui/gui/audiodialog.cpp index fe491f7e6..3f9759a29 100644 --- a/sdrgui/gui/audiodialog.cpp +++ b/sdrgui/gui/audiodialog.cpp @@ -159,14 +159,16 @@ void AudioDialogX::on_inputVolume_valueChanged(int value) ui->inputVolumeText->setText(QString("%1").arg(volume, 0, 'f', 2)); } -void AudioDialogX::on_inputReset_clicked(bool checked __attribute__((unused))) +void AudioDialogX::on_inputReset_clicked(bool checked) { + (void) checked; m_inputDeviceInfo.resetToDefaults(); updateInputDisplay(); } -void AudioDialogX::on_inputCleanup_clicked(bool checked __attribute__((unused))) +void AudioDialogX::on_inputCleanup_clicked(bool checked) { + (void) checked; m_audioDeviceManager->inputInfosCleanup(); } @@ -196,14 +198,16 @@ void AudioDialogX::on_outputUDPPort_editingFinished() ui->outputUDPPort->setText(tr("%1").arg(m_outputDeviceInfo.udpPort)); } -void AudioDialogX::on_outputReset_clicked(bool checked __attribute__((unused))) +void AudioDialogX::on_outputReset_clicked(bool checked) { + (void) checked; m_outputDeviceInfo.resetToDefaults(); updateOutputDisplay(); } -void AudioDialogX::on_outputCleanup_clicked(bool checked __attribute__((unused))) +void AudioDialogX::on_outputCleanup_clicked(bool checked) { + (void) checked; m_audioDeviceManager->outputInfosCleanup(); } diff --git a/sdrgui/gui/clickablelabel.cpp b/sdrgui/gui/clickablelabel.cpp index 2a735f39c..7a225db95 100644 --- a/sdrgui/gui/clickablelabel.cpp +++ b/sdrgui/gui/clickablelabel.cpp @@ -17,9 +17,16 @@ #include "gui/clickablelabel.h" +ClickableLabel::ClickableLabel() + : QLabel(nullptr) +{ + setText(""); +} + ClickableLabel::ClickableLabel(QWidget* parent) : QLabel(parent) { + setText(""); } ClickableLabel::ClickableLabel(const QString& text, QWidget* parent) @@ -32,8 +39,9 @@ ClickableLabel::~ClickableLabel() { } -void ClickableLabel::mousePressEvent(QMouseEvent* event __attribute__((unused))) +void ClickableLabel::mousePressEvent(QMouseEvent* event) { + (void) event; emit clicked(); } diff --git a/sdrgui/gui/clickablelabel.h b/sdrgui/gui/clickablelabel.h index 1c8bae13a..be395a5d4 100644 --- a/sdrgui/gui/clickablelabel.h +++ b/sdrgui/gui/clickablelabel.h @@ -27,8 +27,9 @@ class SDRGUI_API ClickableLabel : public QLabel { Q_OBJECT public: - explicit ClickableLabel( QWidget* parent=0 ); - explicit ClickableLabel( const QString& text="", QWidget* parent=0 ); + explicit ClickableLabel(); + explicit ClickableLabel(QWidget* parent); + explicit ClickableLabel(const QString& text, QWidget* parent=nullptr); ~ClickableLabel(); signals: void clicked(); diff --git a/sdrgui/gui/crightclickenabler.h b/sdrgui/gui/crightclickenabler.h index bfa05dfb4..6ce92f2d5 100644 --- a/sdrgui/gui/crightclickenabler.h +++ b/sdrgui/gui/crightclickenabler.h @@ -30,7 +30,9 @@ signals: void rightClick(); protected: - inline bool eventFilter(QObject *watched __attribute__((unused)), QEvent *event) override { + inline bool eventFilter(QObject *watched, QEvent *event) override + { + (void) watched; if (event->type() == QEvent::MouseButtonPress) { auto mouseEvent = (QMouseEvent*)event; diff --git a/sdrgui/gui/cwkeyergui.cpp b/sdrgui/gui/cwkeyergui.cpp index 009f6b4ef..72abccc90 100644 --- a/sdrgui/gui/cwkeyergui.cpp +++ b/sdrgui/gui/cwkeyergui.cpp @@ -93,8 +93,9 @@ bool CWKeyerGUI::deserialize(const QByteArray& data) // === SLOTS ================================================================== -void CWKeyerGUI::on_cwTextClear_clicked(bool checked __attribute__((unused))) +void CWKeyerGUI::on_cwTextClear_clicked(bool checked) { + (void) checked; ui->cwTextEdit->clear(); m_cwKeyer->setText(""); } diff --git a/sdrgui/gui/editcommanddialog.cpp b/sdrgui/gui/editcommanddialog.cpp index d2f5d7bec..43fa14437 100644 --- a/sdrgui/gui/editcommanddialog.cpp +++ b/sdrgui/gui/editcommanddialog.cpp @@ -122,8 +122,9 @@ void EditCommandDialog::setRelease(bool release) ui->keyRelease->setChecked(release); } -void EditCommandDialog::on_showFileDialog_clicked(bool checked __attribute__((unused))) +void EditCommandDialog::on_showFileDialog_clicked(bool checked) { + (void) checked; QString commandFileName = ui->command->text(); QFileInfo commandFileInfo(commandFileName); QString commandFolderName = commandFileInfo.baseName(); @@ -224,8 +225,9 @@ void EditCommandDialog::setKeyAssociate() } } -void EditCommandDialog::commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release __attribute__((unused))) +void EditCommandDialog::commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release) { + (void) release; // qDebug("EditCommandDialog::commandKeyPressed: key: %x", m_key); // qDebug("EditCommandDialog::commandKeyPressed: has modifiers: %x", QFlags::Int(keyModifiers)); m_key = key; diff --git a/sdrgui/gui/glscopegui.cpp b/sdrgui/gui/glscopegui.cpp index 2ffca3cdb..29b58e7fd 100644 --- a/sdrgui/gui/glscopegui.cpp +++ b/sdrgui/gui/glscopegui.cpp @@ -616,15 +616,17 @@ void GLScopeGUI::on_trace_valueChanged(int value) m_scopeVis->focusOnTrace(value); } -void GLScopeGUI::on_traceAdd_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_traceAdd_clicked(bool checked) { + (void) checked; ScopeVis::TraceData traceData; fillTraceData(traceData); addTrace(traceData); } -void GLScopeGUI::on_traceDel_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_traceDel_clicked(bool checked) { + (void) checked; if (ui->trace->value() > 0) // not the X trace { ui->trace->setMaximum(ui->trace->maximum() - 1); @@ -644,8 +646,9 @@ void GLScopeGUI::on_traceDel_clicked(bool checked __attribute__((unused))) } } -void GLScopeGUI::on_traceUp_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_traceUp_clicked(bool checked) { + (void) checked; if (ui->trace->maximum() > 0) // more than one trace { int newTraceIndex = (ui->trace->value() + 1) % (ui->trace->maximum()+1); @@ -658,8 +661,9 @@ void GLScopeGUI::on_traceUp_clicked(bool checked __attribute__((unused))) } } -void GLScopeGUI::on_traceDown_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_traceDown_clicked(bool checked) { + (void) checked; if (ui->trace->value() > 0) // not the X (lowest) trace { int newTraceIndex = (ui->trace->value() - 1) % (ui->trace->maximum()+1); @@ -691,15 +695,17 @@ void GLScopeGUI::on_trig_valueChanged(int value) m_scopeVis->focusOnTrigger(value); } -void GLScopeGUI::on_trigAdd_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_trigAdd_clicked(bool checked) { + (void) checked; ScopeVis::TriggerData triggerData; fillTriggerData(triggerData); addTrigger(triggerData); } -void GLScopeGUI::on_trigDel_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_trigDel_clicked(bool checked) { + (void) checked; if (ui->trig->value() > 0) { m_scopeVis->removeTrigger(ui->trig->value()); @@ -707,8 +713,9 @@ void GLScopeGUI::on_trigDel_clicked(bool checked __attribute__((unused))) } } -void GLScopeGUI::on_trigUp_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_trigUp_clicked(bool checked) { + (void) checked; if (ui->trig->maximum() > 0) // more than one trigger { int newTriggerIndex = (ui->trig->value() + 1) % (ui->trig->maximum()+1); @@ -721,8 +728,9 @@ void GLScopeGUI::on_trigUp_clicked(bool checked __attribute__((unused))) } } -void GLScopeGUI::on_trigDown_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_trigDown_clicked(bool checked) { + (void) checked; if (ui->trig->value() > 0) // not the 0 (lowest) trigger { int newTriggerIndex = (ui->trig->value() - 1) % (ui->trig->maximum()+1); @@ -735,45 +743,52 @@ void GLScopeGUI::on_trigDown_clicked(bool checked __attribute__((unused))) } } -void GLScopeGUI::on_traceMode_currentIndexChanged(int index __attribute__((unused))) +void GLScopeGUI::on_traceMode_currentIndexChanged(int index) { + (void) index; setAmpScaleDisplay(); setAmpOfsDisplay(); changeCurrentTrace(); } -void GLScopeGUI::on_amp_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_amp_valueChanged(int value) { + (void) value; setAmpScaleDisplay(); changeCurrentTrace(); } -void GLScopeGUI::on_ofsCoarse_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_ofsCoarse_valueChanged(int value) { + (void) value; setAmpOfsDisplay(); changeCurrentTrace(); } -void GLScopeGUI::on_ofsFine_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_ofsFine_valueChanged(int value) { + (void) value; setAmpOfsDisplay(); changeCurrentTrace(); } -void GLScopeGUI::on_traceDelayCoarse_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_traceDelayCoarse_valueChanged(int value) { + (void) value; setTraceDelayDisplay(); changeCurrentTrace(); } -void GLScopeGUI::on_traceDelayFine_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_traceDelayFine_valueChanged(int value) { + (void) value; setTraceDelayDisplay(); changeCurrentTrace(); } -void GLScopeGUI::on_traceView_toggled(bool checked __attribute__((unused))) +void GLScopeGUI::on_traceView_toggled(bool checked) { + (void) checked; changeCurrentTrace(); } @@ -791,8 +806,9 @@ void GLScopeGUI::on_traceColor_clicked() } } -void GLScopeGUI::on_memorySave_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_memorySave_clicked(bool checked) { + (void) checked; QString fileName = QFileDialog::getSaveFileName(this, tr("Open trace memory file"), ".", tr("Trace memory files (*.trcm)"), 0, QFileDialog::DontUseNativeDialog); @@ -821,8 +837,9 @@ void GLScopeGUI::on_memorySave_clicked(bool checked __attribute__((unused))) } } -void GLScopeGUI::on_memoryLoad_clicked(bool checked __attribute__((unused))) +void GLScopeGUI::on_memoryLoad_clicked(bool checked) { + (void) checked; qDebug("GLScopeGUI::on_memoryLoad_clicked"); QString fileName = QFileDialog::getOpenFileName(this, @@ -857,14 +874,16 @@ void GLScopeGUI::on_mem_valueChanged(int value) m_scopeVis->setMemoryIndex(value); } -void GLScopeGUI::on_trigMode_currentIndexChanged(int index __attribute__((unused))) +void GLScopeGUI::on_trigMode_currentIndexChanged(int index) { + (void) index; setTrigLevelDisplay(); changeCurrentTrigger(); } -void GLScopeGUI::on_trigCount_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_trigCount_valueChanged(int value) { + (void) value; setTrigCountDisplay(); changeCurrentTrigger(); } @@ -905,32 +924,37 @@ void GLScopeGUI::on_trigHoldoff_valueChanged(int value) changeCurrentTrigger(); } -void GLScopeGUI::on_trigLevelCoarse_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_trigLevelCoarse_valueChanged(int value) { + (void) value; setTrigLevelDisplay(); changeCurrentTrigger(); } -void GLScopeGUI::on_trigLevelFine_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_trigLevelFine_valueChanged(int value) { + (void) value; setTrigLevelDisplay(); changeCurrentTrigger(); } -void GLScopeGUI::on_trigDelayCoarse_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_trigDelayCoarse_valueChanged(int value) { + (void) value; setTrigDelayDisplay(); changeCurrentTrigger(); } -void GLScopeGUI::on_trigDelayFine_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_trigDelayFine_valueChanged(int value) { + (void) value; setTrigDelayDisplay(); changeCurrentTrigger(); } -void GLScopeGUI::on_trigPre_valueChanged(int value __attribute__((unused))) +void GLScopeGUI::on_trigPre_valueChanged(int value) { + (void) value; setTrigPreDisplay(); m_scopeVis->configure(m_traceLenMult*ScopeVis::m_traceChunkSize, m_timeBase, @@ -1436,8 +1460,9 @@ void GLScopeGUI::applySettings() { } -bool GLScopeGUI::handleMessage(Message* message __attribute__((unused))) +bool GLScopeGUI::handleMessage(Message* message) { + (void) message; return false; } diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp index 8e266039d..808325521 100644 --- a/sdrgui/gui/glspectrumgui.cpp +++ b/sdrgui/gui/glspectrumgui.cpp @@ -451,8 +451,9 @@ void GLSpectrumGUI::on_traceIntensity_valueChanged(int index) } } -void GLSpectrumGUI::on_clearSpectrum_clicked(bool checked __attribute__((unused))) +void GLSpectrumGUI::on_clearSpectrum_clicked(bool checked) { + (void) checked; if(m_glSpectrum != 0) { m_glSpectrum->clearSpectrumHistogram(); } diff --git a/sdrgui/gui/loggingdialog.cpp b/sdrgui/gui/loggingdialog.cpp index 8ee5648ba..814e751fb 100644 --- a/sdrgui/gui/loggingdialog.cpp +++ b/sdrgui/gui/loggingdialog.cpp @@ -47,8 +47,9 @@ void LoggingDialog::accept() QDialog::accept(); } -void LoggingDialog::on_showFileDialog_clicked(bool checked __attribute__((unused))) +void LoggingDialog::on_showFileDialog_clicked(bool checked) { + (void) checked; QString fileName = QFileDialog::getSaveFileName(this, tr("Save log file"), ".", tr("Log Files (*.log)"), 0, QFileDialog::DontUseNativeDialog); diff --git a/sdrgui/gui/tickedslider.cpp b/sdrgui/gui/tickedslider.cpp index 113ebf10b..c57064f1e 100644 --- a/sdrgui/gui/tickedslider.cpp +++ b/sdrgui/gui/tickedslider.cpp @@ -28,9 +28,9 @@ TickedSlider::TickedSlider(QWidget* parent) : m_tickColor(Qt::white) { } -void TickedSlider::paintEvent(QPaintEvent *ev __attribute__((unused))) +void TickedSlider::paintEvent(QPaintEvent *ev) { - + (void) ev; QStylePainter p(this); QStyleOptionSlider opt; initStyleOption(&opt); diff --git a/sdrgui/gui/tvscreen.cpp b/sdrgui/gui/tvscreen.cpp index 005126971..422f2a9f6 100644 --- a/sdrgui/gui/tvscreen.cpp +++ b/sdrgui/gui/tvscreen.cpp @@ -180,8 +180,9 @@ void TVScreen::paintGL() m_objMutex.unlock(); } -void TVScreen::mousePressEvent(QMouseEvent* event __attribute__((unused))) +void TVScreen::mousePressEvent(QMouseEvent* event) { + (void) event; } void TVScreen::tick() diff --git a/sdrgui/mainwindow.cpp b/sdrgui/mainwindow.cpp index 3884bf2d2..38fbeb05b 100644 --- a/sdrgui/mainwindow.cpp +++ b/sdrgui/mainwindow.cpp @@ -1404,13 +1404,17 @@ void MainWindow::on_presetDelete_clicked() } } -void MainWindow::on_presetTree_currentItemChanged(QTreeWidgetItem *current __attribute__((unused)), QTreeWidgetItem *previous __attribute__((unused))) +void MainWindow::on_presetTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { + (void) current; + (void) previous; updatePresetControls(); } -void MainWindow::on_presetTree_itemActivated(QTreeWidgetItem *item __attribute__((unused)), int column __attribute__((unused))) +void MainWindow::on_presetTree_itemActivated(QTreeWidgetItem *item, int column) { + (void) item; + (void) column; on_presetLoad_clicked(); } @@ -1644,8 +1648,9 @@ void MainWindow::sampleSinkChanged() } } -void MainWindow::channelAddClicked(bool checked __attribute__((unused))) +void MainWindow::channelAddClicked(bool checked) { + (void) checked; // Do it in the currently selected source tab int currentSourceTabIndex = ui->tabInputsSelect->currentIndex(); @@ -1778,8 +1783,9 @@ void MainWindow::setLoggingOptions() } } -void MainWindow::focusHasChanged(QWidget *oldWidget __attribute__((unused)), QWidget *newWidget) +void MainWindow::focusHasChanged(QWidget *oldWidget, QWidget *newWidget) { + (void) oldWidget; // this is the hard way: // if (ui->commandKeyboardConnect->isChecked() && (newWidget != this)) { // setFocus(); diff --git a/sdrgui/sdrgui.pro b/sdrgui/sdrgui.pro index 3e93fa6e0..a10c0e74d 100644 --- a/sdrgui/sdrgui.pro +++ b/sdrgui/sdrgui.pro @@ -30,10 +30,13 @@ QMAKE_CXXFLAGS += -std=c++11 CONFIG(Release):build_subdir = release CONFIG(Debug):build_subdir = debug +CONFIG(MSVC):DEFINES += sdrgui_EXPORTS + CONFIG(ANDROID):INCLUDEPATH += /opt/softs/boost_1_60_0 CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\boost_1_66_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(macx):INCLUDEPATH += "../../../boost_1_64_0" diff --git a/sdrgui/webapi/webapiadaptergui.cpp b/sdrgui/webapi/webapiadaptergui.cpp index 6cedfc190..ecc6e0d6a 100644 --- a/sdrgui/webapi/webapiadaptergui.cpp +++ b/sdrgui/webapi/webapiadaptergui.cpp @@ -20,8 +20,6 @@ #include #include -#include - #include "mainwindow.h" #include "ui_mainwindow.h" #include "loggerwithfile.h" @@ -73,8 +71,9 @@ WebAPIAdapterGUI::~WebAPIAdapterGUI() int WebAPIAdapterGUI::instanceSummary( SWGSDRangel::SWGInstanceSummaryResponse& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; response.init(); *response.getAppname() = qApp->applicationName(); *response.getVersion() = qApp->applicationVersion(); @@ -105,9 +104,10 @@ int WebAPIAdapterGUI::instanceSummary( } int WebAPIAdapterGUI::instanceDelete( - SWGSDRangel::SWGSuccessResponse& response __attribute__((unused)), + SWGSDRangel::SWGSuccessResponse& response, SWGSDRangel::SWGErrorResponse& error) { + (void) response; *error.getMessage() = QString("Not supported in GUI instance"); return 400; } @@ -115,8 +115,9 @@ int WebAPIAdapterGUI::instanceDelete( int WebAPIAdapterGUI::instanceDevices( bool tx, SWGSDRangel::SWGInstanceDevicesResponse& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; response.init(); int nbSamplingDevices = tx ? DeviceEnumerator::instance()->getNbTxSamplingDevices() : DeviceEnumerator::instance()->getNbRxSamplingDevices(); response.setDevicecount(nbSamplingDevices); @@ -143,8 +144,9 @@ int WebAPIAdapterGUI::instanceDevices( int WebAPIAdapterGUI::instanceChannels( bool tx, SWGSDRangel::SWGInstanceChannelsResponse& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; response.init(); PluginAPI::ChannelRegistrations *channelRegistrations = tx ? m_mainWindow.m_pluginManager->getTxChannelRegistrations() : m_mainWindow.m_pluginManager->getRxChannelRegistrations(); int nbChannelDevices = channelRegistrations->size(); @@ -170,8 +172,9 @@ int WebAPIAdapterGUI::instanceChannels( int WebAPIAdapterGUI::instanceLoggingGet( SWGSDRangel::SWGLoggingInfo& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; response.init(); response.setDumpToFile(m_mainWindow.m_logger->getUseFileLogger() ? 1 : 0); @@ -188,8 +191,9 @@ int WebAPIAdapterGUI::instanceLoggingGet( int WebAPIAdapterGUI::instanceLoggingPut( SWGSDRangel::SWGLoggingInfo& query, SWGSDRangel::SWGLoggingInfo& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; // response input is the query actually bool dumpToFile = (query.getDumpToFile() != 0); QString* consoleLevel = query.getConsoleLevel(); @@ -225,8 +229,9 @@ int WebAPIAdapterGUI::instanceLoggingPut( int WebAPIAdapterGUI::instanceAudioGet( SWGSDRangel::SWGAudioDevices& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; const QList& audioInputDevices = m_mainWindow.m_dspEngine->getAudioDeviceManager()->getInputDevices(); const QList& audioOutputDevices = m_mainWindow.m_dspEngine->getAudioDeviceManager()->getOutputDevices(); int nbInputDevices = audioInputDevices.size(); @@ -454,8 +459,9 @@ int WebAPIAdapterGUI::instanceAudioOutputDelete( int WebAPIAdapterGUI::instanceAudioInputCleanupPatch( SWGSDRangel::SWGSuccessResponse& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; m_mainWindow.m_dspEngine->getAudioDeviceManager()->inputInfosCleanup(); response.init(); @@ -466,8 +472,9 @@ int WebAPIAdapterGUI::instanceAudioInputCleanupPatch( int WebAPIAdapterGUI::instanceAudioOutputCleanupPatch( SWGSDRangel::SWGSuccessResponse& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; m_mainWindow.m_dspEngine->getAudioDeviceManager()->outputInfosCleanup(); response.init(); @@ -478,8 +485,9 @@ int WebAPIAdapterGUI::instanceAudioOutputCleanupPatch( int WebAPIAdapterGUI::instanceLocationGet( SWGSDRangel::SWGLocationInformation& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; response.init(); response.setLatitude(m_mainWindow.m_settings.getLatitude()); response.setLongitude(m_mainWindow.m_settings.getLongitude()); @@ -489,8 +497,9 @@ int WebAPIAdapterGUI::instanceLocationGet( int WebAPIAdapterGUI::instanceLocationPut( SWGSDRangel::SWGLocationInformation& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; float latitude = response.getLatitude(); float longitude = response.getLongitude(); @@ -508,8 +517,9 @@ int WebAPIAdapterGUI::instanceLocationPut( int WebAPIAdapterGUI::instanceDVSerialGet( SWGSDRangel::SWGDVSeralDevices& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; response.init(); std::vector deviceNames; @@ -533,8 +543,9 @@ int WebAPIAdapterGUI::instanceDVSerialGet( int WebAPIAdapterGUI::instanceDVSerialPatch( bool dvserial, SWGSDRangel::SWGDVSeralDevices& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; m_mainWindow.m_dspEngine->setDVSerialSupport(dvserial); m_mainWindow.ui->action_DV_Serial->setChecked(dvserial); response.init(); @@ -566,8 +577,9 @@ int WebAPIAdapterGUI::instanceDVSerialPatch( int WebAPIAdapterGUI::instancePresetsGet( SWGSDRangel::SWGPresets& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; int nbPresets = m_mainWindow.m_settings.getPresetCount(); int nbGroups = 0; int nbPresetsThisGroup = 0; @@ -816,8 +828,9 @@ int WebAPIAdapterGUI::instancePresetDelete( int WebAPIAdapterGUI::instanceDeviceSetsGet( SWGSDRangel::SWGDeviceSetList& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; getDeviceSetList(&response); return 200; } @@ -825,8 +838,9 @@ int WebAPIAdapterGUI::instanceDeviceSetsGet( int WebAPIAdapterGUI::instanceDeviceSetPost( bool tx, SWGSDRangel::SWGSuccessResponse& response, - SWGSDRangel::SWGErrorResponse& error __attribute__((unused))) + SWGSDRangel::SWGErrorResponse& error) { + (void) error; MainWindow::MsgAddDeviceSet *msg = MainWindow::MsgAddDeviceSet::create(tx); m_mainWindow.m_inputMessageQueue.push(msg); From dc2f25a00b4da00189ca7df1250ff05fdba1727f Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 00:45:03 +0100 Subject: [PATCH 016/102] Windows: MSVC2017: fixed more attribute unused cases (1) --- devices/soapysdr/devicesoapysdr.h | 2 +- plugins/channelrx/chanalyzer/chanalyzer.cpp | 3 +- plugins/channelrx/chanalyzer/chanalyzer.h | 2 +- .../channelrx/chanalyzer/chanalyzergui.cpp | 10 ++-- plugins/channelrx/daemonsink/daemonsink.cpp | 15 ++++-- .../channelrx/daemonsink/daemonsinkgui.cpp | 10 ++-- plugins/channelrx/demodam/amdemod.cpp | 12 +++-- plugins/channelrx/demodam/amdemodgui.cpp | 7 ++- plugins/channelrx/demodatv/atvdemod.cpp | 3 +- plugins/channelrx/demodatv/atvdemod.h | 2 +- plugins/channelrx/demodatv/atvdemodgui.cpp | 28 +++++++---- plugins/channelrx/demodbfm/bfmdemod.cpp | 12 +++-- plugins/channelrx/demodbfm/bfmdemodgui.cpp | 16 +++++-- plugins/channelrx/demodbfm/rdsdemod.cpp | 3 +- plugins/channelrx/demodbfm/rdsparser.cpp | 32 +++++++++---- plugins/channelrx/demoddatv/datvdemod.cpp | 3 +- plugins/channelrx/demoddatv/datvdemod.h | 2 +- plugins/channelrx/demoddatv/datvdemodgui.cpp | 46 +++++++++++++------ .../channelrx/demoddatv/datvideostream.cpp | 8 +++- plugins/channelrx/demoddatv/leansdr/dvb.h | 2 + .../channelrx/demoddatv/leansdr/framework.h | 3 +- plugins/channelrx/demoddatv/leansdr/generic.h | 3 +- plugins/channelrx/demoddatv/leansdr/sdr.h | 6 ++- plugins/channelrx/demoddsd/dsddemod.cpp | 12 +++-- plugins/channelrx/demoddsd/dsddemodgui.cpp | 4 +- plugins/channelrx/demodlora/lorademod.cpp | 3 +- plugins/channelrx/demodlora/lorademodgui.cpp | 10 ++-- plugins/channelrx/demodnfm/nfmdemod.cpp | 12 +++-- plugins/channelrx/demodnfm/nfmdemodgui.cpp | 4 +- plugins/channelrx/demodssb/ssbdemod.cpp | 12 +++-- plugins/channelrx/demodssb/ssbdemodgui.cpp | 13 ++++-- plugins/channelrx/demodwfm/wfmdemod.cpp | 12 +++-- plugins/channelrx/demodwfm/wfmdemodgui.cpp | 7 ++- plugins/channelrx/udpsink/udpsink.cpp | 9 ++-- plugins/channelrx/udpsink/udpsinkgui.cpp | 9 ++-- .../channeltx/daemonsource/daemonsource.cpp | 18 +++++--- .../daemonsource/daemonsourcegui.cpp | 16 +++++-- plugins/channeltx/modam/ammod.cpp | 9 ++-- plugins/channeltx/modam/ammodgui.cpp | 10 ++-- plugins/channeltx/modatv/atvmod.cpp | 12 +++-- plugins/channeltx/modatv/atvmodgui.cpp | 19 +++++--- plugins/channeltx/modnfm/nfmmod.cpp | 9 ++-- plugins/channeltx/modnfm/nfmmodgui.cpp | 7 ++- plugins/channeltx/modssb/ssbmod.cpp | 9 ++-- plugins/channeltx/modssb/ssbmodgui.cpp | 14 ++++-- sdrgui/soapygui/stringrangegui.cpp | 3 +- 46 files changed, 317 insertions(+), 146 deletions(-) diff --git a/devices/soapysdr/devicesoapysdr.h b/devices/soapysdr/devicesoapysdr.h index c8be84557..d26e87a4f 100644 --- a/devices/soapysdr/devicesoapysdr.h +++ b/devices/soapysdr/devicesoapysdr.h @@ -38,7 +38,7 @@ public: protected: DeviceSoapySDR(); DeviceSoapySDR(const DeviceSoapySDR&) {} - DeviceSoapySDR& operator=(const DeviceSoapySDR& other __attribute__((unused))) { return *this; } + DeviceSoapySDR& operator=(const DeviceSoapySDR& other) { (void) other; return *this; } ~DeviceSoapySDR(); private: diff --git a/plugins/channelrx/chanalyzer/chanalyzer.cpp b/plugins/channelrx/chanalyzer/chanalyzer.cpp index 3299e5ab5..2b6038084 100644 --- a/plugins/channelrx/chanalyzer/chanalyzer.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzer.cpp @@ -89,8 +89,9 @@ void ChannelAnalyzer::configure(MessageQueue* messageQueue, messageQueue->push(cmd); } -void ChannelAnalyzer::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused))) +void ChannelAnalyzer::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) { + (void) positiveOnly; fftfilt::cmplx *sideband = 0; Complex ci; diff --git a/plugins/channelrx/chanalyzer/chanalyzer.h b/plugins/channelrx/chanalyzer/chanalyzer.h index 6a56ab486..54be55fd2 100644 --- a/plugins/channelrx/chanalyzer/chanalyzer.h +++ b/plugins/channelrx/chanalyzer/chanalyzer.h @@ -205,7 +205,7 @@ public: virtual qint64 getCenterFrequency() const { return m_settings.m_frequency; } virtual QByteArray serialize() const { return QByteArray(); } - virtual bool deserialize(const QByteArray& data __attribute__((unused))) { return false; } + virtual bool deserialize(const QByteArray& data) { (void) data; return false; } static const QString m_channelIdURI; static const QString m_channelId; diff --git a/plugins/channelrx/chanalyzer/chanalyzergui.cpp b/plugins/channelrx/chanalyzer/chanalyzergui.cpp index 4a21d237b..d394b076e 100644 --- a/plugins/channelrx/chanalyzer/chanalyzergui.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzergui.cpp @@ -312,16 +312,18 @@ void ChannelAnalyzerGUI::on_rrcRolloff_valueChanged(int value) applySettings(); } -void ChannelAnalyzerGUI::on_BW_valueChanged(int value __attribute__((unused))) +void ChannelAnalyzerGUI::on_BW_valueChanged(int value) { + (void) value; setFiltersUIBoundaries(); m_settings.m_bandwidth = ui->BW->value() * 100; m_settings.m_lowCutoff = ui->lowCut->value() * 100; applySettings(); } -void ChannelAnalyzerGUI::on_lowCut_valueChanged(int value __attribute__((unused))) +void ChannelAnalyzerGUI::on_lowCut_valueChanged(int value) { + (void) value; setFiltersUIBoundaries(); m_settings.m_bandwidth = ui->BW->value() * 100; m_settings.m_lowCutoff = ui->lowCut->value() * 100; @@ -351,8 +353,10 @@ void ChannelAnalyzerGUI::on_ssb_toggled(bool checked) applySettings(); } -void ChannelAnalyzerGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void ChannelAnalyzerGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void ChannelAnalyzerGUI::onMenuDialogCalled(const QPoint& p) diff --git a/plugins/channelrx/daemonsink/daemonsink.cpp b/plugins/channelrx/daemonsink/daemonsink.cpp index ac5dfd02e..80313d68d 100644 --- a/plugins/channelrx/daemonsink/daemonsink.cpp +++ b/plugins/channelrx/daemonsink/daemonsink.cpp @@ -97,8 +97,9 @@ void DaemonSink::setNbBlocksFEC(int nbBlocksFEC) m_nbBlocksFEC = nbBlocksFEC; } -void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) +void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) { + (void) firstOfBurst; SampleVector::const_iterator it = begin; while (it != end) @@ -238,8 +239,9 @@ void DaemonSink::stop() m_running = false; } -bool DaemonSink::handleMessage(const Message& cmd __attribute__((unused))) +bool DaemonSink::handleMessage(const Message& cmd) { + (void) cmd; if (DownChannelizer::MsgChannelizerNotification::match(cmd)) { DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; @@ -293,8 +295,9 @@ QByteArray DaemonSink::serialize() const return m_settings.serialize(); } -bool DaemonSink::deserialize(const QByteArray& data __attribute__((unused))) +bool DaemonSink::deserialize(const QByteArray& data) { + (void) data; if (m_settings.deserialize(data)) { MsgConfigureDaemonSink *msg = MsgConfigureDaemonSink::create(m_settings, true); @@ -341,8 +344,9 @@ void DaemonSink::applySettings(const DaemonSinkSettings& settings, bool force) int DaemonSink::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setDaemonSinkSettings(new SWGSDRangel::SWGDaemonSinkSettings()); response.getDaemonSinkSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -353,8 +357,9 @@ int DaemonSink::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; DaemonSinkSettings settings = m_settings; if (channelSettingsKeys.contains("nbFECBlocks")) diff --git a/plugins/channelrx/daemonsink/daemonsinkgui.cpp b/plugins/channelrx/daemonsink/daemonsinkgui.cpp index 83338b822..a77bc9a64 100644 --- a/plugins/channelrx/daemonsink/daemonsinkgui.cpp +++ b/plugins/channelrx/daemonsink/daemonsinkgui.cpp @@ -48,8 +48,9 @@ qint64 DaemonSinkGUI::getCenterFrequency() const { return 0; } -void DaemonSinkGUI::setCenterFrequency(qint64 centerFrequency __attribute__((unused))) +void DaemonSinkGUI::setCenterFrequency(qint64 centerFrequency) { + (void) centerFrequency; } void DaemonSinkGUI::resetToDefaults() @@ -207,8 +208,10 @@ void DaemonSinkGUI::handleSourceMessages() } } -void DaemonSinkGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void DaemonSinkGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void DaemonSinkGUI::onMenuDialogCalled(const QPoint &p) @@ -249,8 +252,9 @@ void DaemonSinkGUI::on_dataPort_returnPressed() applySettings(); } -void DaemonSinkGUI::on_dataApplyButton_clicked(bool checked __attribute__((unused))) +void DaemonSinkGUI::on_dataApplyButton_clicked(bool checked) { + (void) checked; m_settings.m_dataAddress = ui->dataAddress->text(); bool dataOk; diff --git a/plugins/channelrx/demodam/amdemod.cpp b/plugins/channelrx/demodam/amdemod.cpp index 29a01559f..f0f48d562 100644 --- a/plugins/channelrx/demodam/amdemod.cpp +++ b/plugins/channelrx/demodam/amdemod.cpp @@ -98,8 +98,9 @@ AMDemod::~AMDemod() delete SSBFilter; } -void AMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) +void AMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) { + (void) firstOfBurst; Complex ci; if (!m_running) { @@ -502,8 +503,9 @@ bool AMDemod::deserialize(const QByteArray& data) int AMDemod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAmDemodSettings(new SWGSDRangel::SWGAMDemodSettings()); response.getAmDemodSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -514,8 +516,9 @@ int AMDemod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; AMDemodSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -584,8 +587,9 @@ int AMDemod::webapiSettingsPutPatch( int AMDemod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAmDemodReport(new SWGSDRangel::SWGAMDemodReport()); response.getAmDemodReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channelrx/demodam/amdemodgui.cpp b/plugins/channelrx/demodam/amdemodgui.cpp index c1a8184d2..2bc57c488 100644 --- a/plugins/channelrx/demodam/amdemodgui.cpp +++ b/plugins/channelrx/demodam/amdemodgui.cpp @@ -92,8 +92,9 @@ bool AMDemodGUI::deserialize(const QByteArray& data) } } -bool AMDemodGUI::handleMessage(const Message& message __attribute__((unused))) +bool AMDemodGUI::handleMessage(const Message& message) { + (void) message; if (AMDemod::MsgConfigureAMDemod::match(message)) { qDebug("AMDemodGUI::handleMessage: AMDemod::MsgConfigureAMDemod"); @@ -192,8 +193,10 @@ void AMDemodGUI::on_audioMute_toggled(bool checked) applySettings(); } -void AMDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void AMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; /* if((widget == ui->spectrumContainer) && (m_nfmDemod != NULL)) m_nfmDemod->setSpectrum(m_threadedSampleSink->getMessageQueue(), rollDown); diff --git a/plugins/channelrx/demodatv/atvdemod.cpp b/plugins/channelrx/demodatv/atvdemod.cpp index 68e8feed5..778de4045 100644 --- a/plugins/channelrx/demodatv/atvdemod.cpp +++ b/plugins/channelrx/demodatv/atvdemod.cpp @@ -164,8 +164,9 @@ void ATVDemod::configureRF( objMessageQueue->push(msgCmd); } -void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) +void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) { + (void) firstOfBurst; float fltI; float fltQ; Complex ci; diff --git a/plugins/channelrx/demodatv/atvdemod.h b/plugins/channelrx/demodatv/atvdemod.h index dda259740..d4a5d4a7e 100644 --- a/plugins/channelrx/demodatv/atvdemod.h +++ b/plugins/channelrx/demodatv/atvdemod.h @@ -229,7 +229,7 @@ public: virtual qint64 getCenterFrequency() const { return m_rfRunning.m_intFrequencyOffset; } virtual QByteArray serialize() const { return QByteArray(); } - virtual bool deserialize(const QByteArray& data __attribute__((unused))) { return false; } + virtual bool deserialize(const QByteArray& data) { (void) data; return false; } void setTVScreen(TVScreen *objScreen); //!< set by the GUI int getSampleRate(); diff --git a/plugins/channelrx/demodatv/atvdemodgui.cpp b/plugins/channelrx/demodatv/atvdemodgui.cpp index 4fadfd9b6..a73f05724 100644 --- a/plugins/channelrx/demodatv/atvdemodgui.cpp +++ b/plugins/channelrx/demodatv/atvdemodgui.cpp @@ -263,8 +263,10 @@ void ATVDemodGUI::handleSourceMessages() } } -void ATVDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void ATVDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* objParent) : @@ -534,32 +536,37 @@ void ATVDemodGUI::on_halfImage_clicked() applySettings(); } -void ATVDemodGUI::on_nbLines_currentIndexChanged(int index __attribute__((unused))) +void ATVDemodGUI::on_nbLines_currentIndexChanged(int index) { + (void) index; lineTimeUpdate(); topTimeUpdate(); applySettings(); } -void ATVDemodGUI::on_fps_currentIndexChanged(int index __attribute__((unused))) +void ATVDemodGUI::on_fps_currentIndexChanged(int index) { + (void) index; lineTimeUpdate(); topTimeUpdate(); applySettings(); } -void ATVDemodGUI::on_standard_currentIndexChanged(int index __attribute__((unused))) +void ATVDemodGUI::on_standard_currentIndexChanged(int index) { + (void) index; applySettings(); } -void ATVDemodGUI::on_reset_clicked(bool checked __attribute__((unused))) +void ATVDemodGUI::on_reset_clicked(bool checked) { + (void) checked; resetToDefaults(); } -void ATVDemodGUI::on_modulation_currentIndexChanged(int index __attribute__((unused))) +void ATVDemodGUI::on_modulation_currentIndexChanged(int index) { + (void) index; setRFFiltersSlidersRange(m_atvDemod->getEffectiveSampleRate()); setChannelMarkerBandwidth(); applyRFSettings(); @@ -579,15 +586,17 @@ void ATVDemodGUI::on_rfOppBW_valueChanged(int value) applyRFSettings(); } -void ATVDemodGUI::on_rfFiltering_toggled(bool checked __attribute__((unused))) +void ATVDemodGUI::on_rfFiltering_toggled(bool checked) { + (void) checked; setRFFiltersSlidersRange(m_atvDemod->getEffectiveSampleRate()); setChannelMarkerBandwidth(); applyRFSettings(); } -void ATVDemodGUI::on_decimatorEnable_toggled(bool checked __attribute__((unused))) +void ATVDemodGUI::on_decimatorEnable_toggled(bool checked) { + (void) checked; setChannelMarkerBandwidth(); applyRFSettings(); } @@ -610,8 +619,9 @@ void ATVDemodGUI::on_fmDeviation_valueChanged(int value) applyRFSettings(); } -void ATVDemodGUI::on_screenTabWidget_currentChanged(int index __attribute__((unused))) +void ATVDemodGUI::on_screenTabWidget_currentChanged(int index) { + (void) index; applySettings(); } diff --git a/plugins/channelrx/demodbfm/bfmdemod.cpp b/plugins/channelrx/demodbfm/bfmdemod.cpp index 1d056771d..1ac07377e 100644 --- a/plugins/channelrx/demodbfm/bfmdemod.cpp +++ b/plugins/channelrx/demodbfm/bfmdemod.cpp @@ -113,8 +113,9 @@ BFMDemod::~BFMDemod() delete m_rfFilter; } -void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) +void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) { + (void) firstOfBurst; Complex ci, cs, cr; fftfilt::cmplx *rf; int rf_out; @@ -538,8 +539,9 @@ bool BFMDemod::deserialize(const QByteArray& data) int BFMDemod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setBfmDemodSettings(new SWGSDRangel::SWGBFMDemodSettings()); response.getBfmDemodSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -550,8 +552,9 @@ int BFMDemod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; BFMDemodSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -618,8 +621,9 @@ int BFMDemod::webapiSettingsPutPatch( int BFMDemod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setBfmDemodReport(new SWGSDRangel::SWGBFMDemodReport()); response.getBfmDemodReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channelrx/demodbfm/bfmdemodgui.cpp b/plugins/channelrx/demodbfm/bfmdemodgui.cpp index 2e0f4c42a..a2fded696 100644 --- a/plugins/channelrx/demodbfm/bfmdemodgui.cpp +++ b/plugins/channelrx/demodbfm/bfmdemodgui.cpp @@ -225,8 +225,9 @@ void BFMDemodGUI::on_rds_clicked() applySettings(); } -void BFMDemodGUI::on_clearData_clicked(bool checked __attribute__((unused))) +void BFMDemodGUI::on_clearData_clicked(bool checked) { + (void) checked; if (ui->rds->isChecked()) { m_bfmDemod->getRDSParser().clearAllFields(); @@ -288,26 +289,31 @@ void BFMDemodGUI::on_g14ProgServiceNames_currentIndexChanged(int _index) } } -void BFMDemodGUI::on_g00AltFrequenciesBox_activated(int index __attribute__((unused))) +void BFMDemodGUI::on_g00AltFrequenciesBox_activated(int index) { + (void) index; qint64 f = (qint64) ((ui->g00AltFrequenciesBox->currentText()).toDouble() * 1e6); changeFrequency(f); } -void BFMDemodGUI::on_g14MappedFrequencies_activated(int index __attribute__((unused))) +void BFMDemodGUI::on_g14MappedFrequencies_activated(int index) { + (void) index; qint64 f = (qint64) ((ui->g14MappedFrequencies->currentText()).toDouble() * 1e6); changeFrequency(f); } -void BFMDemodGUI::on_g14AltFrequencies_activated(int index __attribute__((unused))) +void BFMDemodGUI::on_g14AltFrequencies_activated(int index) { + (void) index; qint64 f = (qint64) ((ui->g14AltFrequencies->currentText()).toDouble() * 1e6); changeFrequency(f); } -void BFMDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void BFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void BFMDemodGUI::onMenuDialogCalled(const QPoint &p) diff --git a/plugins/channelrx/demodbfm/rdsdemod.cpp b/plugins/channelrx/demodbfm/rdsdemod.cpp index c38cccdf8..bdce3ef0e 100644 --- a/plugins/channelrx/demodbfm/rdsdemod.cpp +++ b/plugins/channelrx/demodbfm/rdsdemod.cpp @@ -66,8 +66,9 @@ RDSDemod::~RDSDemod() //delete m_socket; } -void RDSDemod::setSampleRate(int srate __attribute__((unused))) /// FIXME: fix rate for now +void RDSDemod::setSampleRate(int srate) /// FIXME: fix rate for now { + (void) srate; } bool RDSDemod::process(Real demod, bool& bit) diff --git a/plugins/channelrx/demodbfm/rdsparser.cpp b/plugins/channelrx/demodbfm/rdsparser.cpp index eaa95c98e..089aa2399 100644 --- a/plugins/channelrx/demodbfm/rdsparser.cpp +++ b/plugins/channelrx/demodbfm/rdsparser.cpp @@ -828,19 +828,25 @@ void RDSParser::decode_type4(unsigned int *group, bool B) //send_message(5,time); } -void RDSParser::decode_type5(unsigned int *group __attribute__((unused)), bool B __attribute__((unused))) { +void RDSParser::decode_type5(unsigned int *group, bool B) { + (void) group; + (void) B; qDebug() << "RDSParser::decode_type5: type5 not implemented yet"; m_g5_updated = true; m_g5_count++; } -void RDSParser::decode_type6(unsigned int *group __attribute__((unused)), bool B __attribute__((unused))) { +void RDSParser::decode_type6(unsigned int *group, bool B) { + (void) group; + (void) B; qDebug() << "RDSParser::decode_type6: type 6 not implemented yet"; m_g6_updated = true; m_g6_count++; } -void RDSParser::decode_type7(unsigned int *group __attribute__((unused)), bool B __attribute__((unused))) { +void RDSParser::decode_type7(unsigned int *group, bool B) { + (void) group; + (void) B; qDebug() << "RDSParser::decode_type7: type 7 not implemented yet"; m_g7_updated = true; m_g7_count++; @@ -971,29 +977,37 @@ void RDSParser::decode_type9(unsigned int *group, bool B){ m_g9_count++; } -void RDSParser::decode_type10(unsigned int *group __attribute__((unused)), bool B __attribute__((unused))) +void RDSParser::decode_type10(unsigned int *group, bool B) { + (void) group; + (void) B; qDebug() << "RDSParser::decode_type10: type 10 not implemented yet"; m_g10_updated = true; m_g10_count++; } -void RDSParser::decode_type11(unsigned int *group __attribute__((unused)), bool B __attribute__((unused))) +void RDSParser::decode_type11(unsigned int *group, bool B) { + (void) group; + (void) B; qDebug() << "RDSParser::decode_type11: type 11 not implemented yet"; m_g11_updated = true; m_g11_count++; } -void RDSParser::decode_type12(unsigned int *group __attribute__((unused)), bool B __attribute__((unused))) +void RDSParser::decode_type12(unsigned int *group, bool B) { + (void) group; + (void) B; qDebug() << "RDSParser::decode_type12: type 12 not implemented yet"; m_g12_updated = true; m_g12_count++; } -void RDSParser::decode_type13(unsigned int *group __attribute__((unused)), bool B __attribute__((unused))) +void RDSParser::decode_type13(unsigned int *group, bool B) { + (void) group; + (void) B; qDebug() << "RDSParser::decode_type13: type 13 not implemented yet"; m_g13_updated = true; m_g13_count++; @@ -1180,8 +1194,10 @@ void RDSParser::decode_type14(unsigned int *group, bool B) }*/ } -void RDSParser::decode_type15(unsigned int *group __attribute__((unused)), bool B __attribute__((unused))) +void RDSParser::decode_type15(unsigned int *group, bool B) { + (void) group; + (void) B; qDebug() << "RDSParser::decode_type5: type 15 not implemented yet"; m_g15_updated = true; m_g15_count++; diff --git a/plugins/channelrx/demoddatv/datvdemod.cpp b/plugins/channelrx/demoddatv/datvdemod.cpp index 2023e5c3f..7d22cd8f6 100644 --- a/plugins/channelrx/demoddatv/datvdemod.cpp +++ b/plugins/channelrx/demoddatv/datvdemod.cpp @@ -764,8 +764,9 @@ void DATVDemod::InitDATVFramework() m_blnDVBInitialized=true; } -void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) +void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) { + (void) firstOfBurst; float fltI; float fltQ; leansdr::cf32 objIQ; diff --git a/plugins/channelrx/demoddatv/datvdemod.h b/plugins/channelrx/demoddatv/datvdemod.h index a5af83546..8bccb0ca9 100644 --- a/plugins/channelrx/demoddatv/datvdemod.h +++ b/plugins/channelrx/demoddatv/datvdemod.h @@ -185,7 +185,7 @@ public: virtual qint64 getCenterFrequency() const { return m_objRunning.intCenterFrequency; } virtual QByteArray serialize() const { return QByteArray(); } - virtual bool deserialize(const QByteArray& data __attribute__((unused))) { return false; } + virtual bool deserialize(const QByteArray& data) { (void) data; return false; } void configure( MessageQueue* objMessageQueue, diff --git a/plugins/channelrx/demoddatv/datvdemodgui.cpp b/plugins/channelrx/demoddatv/datvdemodgui.cpp index 21c22892e..090a407db 100644 --- a/plugins/channelrx/demoddatv/datvdemodgui.cpp +++ b/plugins/channelrx/demoddatv/datvdemodgui.cpp @@ -219,8 +219,9 @@ bool DATVDemodGUI::deserialize(const QByteArray& arrData) } } -bool DATVDemodGUI::handleMessage(const Message& objMessage __attribute__((unused))) +bool DATVDemodGUI::handleMessage(const Message& objMessage) { + (void) objMessage; return false; } @@ -241,8 +242,10 @@ void DATVDemodGUI::channelMarkerHighlightedByCursor() } -void DATVDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void DATVDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void DATVDemodGUI::onMenuDoubleClicked() @@ -526,13 +529,15 @@ void DATVDemodGUI::tick() return; } -void DATVDemodGUI::on_cmbStandard_currentIndexChanged(const QString &arg1 __attribute__((unused))) +void DATVDemodGUI::on_cmbStandard_currentIndexChanged(const QString &arg1) { + (void) arg1; applySettings(); } -void DATVDemodGUI::on_cmbModulation_currentIndexChanged(const QString &arg1 __attribute__((unused))) +void DATVDemodGUI::on_cmbModulation_currentIndexChanged(const QString &arg1) { + (void) arg1; QString strModulation; QString strFEC; @@ -583,8 +588,9 @@ void DATVDemodGUI::on_cmbModulation_currentIndexChanged(const QString &arg1 __at } -void DATVDemodGUI::on_cmbFEC_currentIndexChanged(const QString &arg1 __attribute__((unused))) +void DATVDemodGUI::on_cmbFEC_currentIndexChanged(const QString &arg1) { + (void) arg1; QString strFEC; strFEC = ui->cmbFEC->currentText(); @@ -647,13 +653,15 @@ void DATVDemodGUI::on_pushButton_2_clicked() resetToDefaults(); } -void DATVDemodGUI::on_spiSymbolRate_valueChanged(int arg1 __attribute__((unused))) +void DATVDemodGUI::on_spiSymbolRate_valueChanged(int arg1) { + (void) arg1; applySettings(); } -void DATVDemodGUI::on_spiNotchFilters_valueChanged(int arg1 __attribute__((unused))) +void DATVDemodGUI::on_spiNotchFilters_valueChanged(int arg1) { + (void) arg1; applySettings(); } @@ -680,8 +688,9 @@ void DATVDemodGUI::on_pushButton_4_clicked() } -void DATVDemodGUI::on_mouseEvent(QMouseEvent* obj __attribute__((unused))) +void DATVDemodGUI::on_mouseEvent(QMouseEvent* obj) { + (void) obj; } QString DATVDemodGUI::formatBytes(qint64 intBytes) @@ -703,8 +712,9 @@ QString DATVDemodGUI::formatBytes(qint64 intBytes) } -void DATVDemodGUI::on_StreamDataAvailable(int *intPackets __attribute__((unused)), int *intBytes, int *intPercent, qint64 *intTotalReceived) +void DATVDemodGUI::on_StreamDataAvailable(int *intPackets, int *intBytes, int *intPercent, qint64 *intTotalReceived) { + (void) intPackets; ui->lblStatus->setText(QString("Data: %1B").arg(formatBytes(*intTotalReceived))); m_intLastDecodedData = *intTotalReceived; @@ -721,18 +731,21 @@ void DATVDemodGUI::on_StreamDataAvailable(int *intPackets __attribute__((unused) } -void DATVDemodGUI::on_spiBandwidth_valueChanged(int arg1 __attribute__((unused))) +void DATVDemodGUI::on_spiBandwidth_valueChanged(int arg1) { + (void) arg1; applySettings(); } -void DATVDemodGUI::on_deltaFrequency_changed(qint64 value __attribute__((unused))) +void DATVDemodGUI::on_deltaFrequency_changed(qint64 value) { + (void) value; applySettings(); } -void DATVDemodGUI::on_rfBandwidth_changed(qint64 value __attribute__((unused))) +void DATVDemodGUI::on_rfBandwidth_changed(qint64 value) { + (void) value; applySettings(); } @@ -789,19 +802,22 @@ void DATVDemodGUI::displayRRCParameters(bool blnVisible) ui->label_6->setVisible(blnVisible); } -void DATVDemodGUI::on_cmbFilter_currentIndexChanged(int index __attribute__((unused))) +void DATVDemodGUI::on_cmbFilter_currentIndexChanged(int index) { + (void) index; displayRRCParameters((ui->cmbFilter->currentIndex()==2)); applySettings(); } -void DATVDemodGUI::on_spiRollOff_valueChanged(int arg1 __attribute__((unused))) +void DATVDemodGUI::on_spiRollOff_valueChanged(int arg1) { + (void) arg1; applySettings(); } -void DATVDemodGUI::on_spiExcursion_valueChanged(int arg1 __attribute__((unused))) +void DATVDemodGUI::on_spiExcursion_valueChanged(int arg1) { + (void) arg1; applySettings(); } diff --git a/plugins/channelrx/demoddatv/datvideostream.cpp b/plugins/channelrx/demoddatv/datvideostream.cpp index 53016cb76..fc89f6d1c 100644 --- a/plugins/channelrx/demoddatv/datvideostream.cpp +++ b/plugins/channelrx/demoddatv/datvideostream.cpp @@ -224,12 +224,16 @@ qint64 DATVideostream::readData(char *data, qint64 len) return (qint64)intEffectiveLen; } -qint64 DATVideostream::writeData(const char *data __attribute__((unused)), qint64 len __attribute__((unused))) +qint64 DATVideostream::writeData(const char *data, qint64 len) { + (void) data; + (void) len; return 0; } -qint64 DATVideostream::readLineData(char *data __attribute__((unused)), qint64 maxSize __attribute__((unused))) +qint64 DATVideostream::readLineData(char *data, qint64 maxSize) { + (void) data; + (void) maxSize; return 0; } diff --git a/plugins/channelrx/demoddatv/leansdr/dvb.h b/plugins/channelrx/demoddatv/leansdr/dvb.h index da4e44fb8..3bd9a624a 100644 --- a/plugins/channelrx/demoddatv/leansdr/dvb.h +++ b/plugins/channelrx/demoddatv/leansdr/dvb.h @@ -404,7 +404,9 @@ private: for (int im_pos = 0; im_pos <= 1; ++im_pos) { int re_neg = !re_pos; +#if 0 int im_neg __attribute__((unused)) = !im_pos; +#endif int I, Q; switch (sync_id) { diff --git a/plugins/channelrx/demoddatv/leansdr/framework.h b/plugins/channelrx/demoddatv/leansdr/framework.h index e705b2db6..f6abfd1e3 100644 --- a/plugins/channelrx/demoddatv/leansdr/framework.h +++ b/plugins/channelrx/demoddatv/leansdr/framework.h @@ -46,8 +46,9 @@ struct pipebuf_common return 0; } - virtual void dump(std::size_t *total_bufs __attribute__((unused))) + virtual void dump(std::size_t *total_bufs) { + (void) total_bufs; } pipebuf_common(const char *_name) : diff --git a/plugins/channelrx/demoddatv/leansdr/generic.h b/plugins/channelrx/demoddatv/leansdr/generic.h index 47577328e..206b15473 100644 --- a/plugins/channelrx/demoddatv/leansdr/generic.h +++ b/plugins/channelrx/demoddatv/leansdr/generic.h @@ -329,9 +329,10 @@ private: template struct serializer: runnable { - serializer(scheduler *sch __attribute__((unused)), pipebuf &_in, pipebuf &_out) : + serializer(scheduler *sch, pipebuf &_in, pipebuf &_out) : nin(max((size_t) 1, sizeof(Tin) / sizeof(Tout))), nout(max((size_t) 1, sizeof(Tout) / sizeof(Tin))), in(_in), out(_out, nout) { + (void) sch; if (nin * sizeof(Tin) != nout * sizeof(Tout)) { fail("serializer::serializer", "incompatible sizes"); diff --git a/plugins/channelrx/demoddatv/leansdr/sdr.h b/plugins/channelrx/demoddatv/leansdr/sdr.h index 6d87eb90e..a8da24be9 100644 --- a/plugins/channelrx/demoddatv/leansdr/sdr.h +++ b/plugins/channelrx/demoddatv/leansdr/sdr.h @@ -700,8 +700,9 @@ struct sampler_interface { virtual complex interp(const complex *pin, float mu, float phase) = 0; - virtual void update_freq(float freqw __attribute__((unused))) + virtual void update_freq(float freqw) { + (void) freqw; } // 65536 = 1 Hz virtual int readahead() @@ -725,8 +726,9 @@ struct nearest_sampler: sampler_interface return 0; } - complex interp(const complex *pin, float mu __attribute__((unused)), float phase) + complex interp(const complex *pin, float mu, float phase) { + (void) mu; return pin[0] * trig.expi(-phase); } diff --git a/plugins/channelrx/demoddsd/dsddemod.cpp b/plugins/channelrx/demoddsd/dsddemod.cpp index 04a9169e3..0b63c3c35 100644 --- a/plugins/channelrx/demoddsd/dsddemod.cpp +++ b/plugins/channelrx/demoddsd/dsddemod.cpp @@ -112,8 +112,9 @@ void DSDDemod::configureMyPosition(MessageQueue* messageQueue, float myLatitude, messageQueue->push(cmd); } -void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) +void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) { + (void) firstOfBurst; Complex ci; int samplesPerSymbol = m_dsdDecoder.getSamplesPerSymbol(); @@ -767,8 +768,9 @@ void DSDDemod::formatStatusText() int DSDDemod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setDsdDemodSettings(new SWGSDRangel::SWGDSDDemodSettings()); response.getDsdDemodSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -779,8 +781,9 @@ int DSDDemod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; DSDDemodSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -877,8 +880,9 @@ int DSDDemod::webapiSettingsPutPatch( int DSDDemod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setDsdDemodReport(new SWGSDRangel::SWGDSDDemodReport()); response.getDsdDemodReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channelrx/demoddsd/dsddemodgui.cpp b/plugins/channelrx/demoddsd/dsddemodgui.cpp index 514a3e333..b8dbf0429 100644 --- a/plugins/channelrx/demoddsd/dsddemodgui.cpp +++ b/plugins/channelrx/demoddsd/dsddemodgui.cpp @@ -264,8 +264,10 @@ void DSDDemodGUI::on_symbolPLLLock_toggled(bool checked) applySettings(); } -void DSDDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void DSDDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void DSDDemodGUI::onMenuDialogCalled(const QPoint &p) diff --git a/plugins/channelrx/demodlora/lorademod.cpp b/plugins/channelrx/demodlora/lorademod.cpp index 87d9882b3..831997bdd 100644 --- a/plugins/channelrx/demodlora/lorademod.cpp +++ b/plugins/channelrx/demodlora/lorademod.cpp @@ -251,8 +251,9 @@ int LoRaDemod::detect(Complex c, Complex a) return m_result; } -void LoRaDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool pO __attribute__((unused))) +void LoRaDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool pO) { + (void) pO; int newangle; Complex ci; diff --git a/plugins/channelrx/demodlora/lorademodgui.cpp b/plugins/channelrx/demodlora/lorademodgui.cpp index f70abc72c..ceb5da5b4 100644 --- a/plugins/channelrx/demodlora/lorademodgui.cpp +++ b/plugins/channelrx/demodlora/lorademodgui.cpp @@ -70,8 +70,9 @@ bool LoRaDemodGUI::deserialize(const QByteArray& data) } } -bool LoRaDemodGUI::handleMessage(const Message& message __attribute__((unused))) +bool LoRaDemodGUI::handleMessage(const Message& message) { + (void) message; return false; } @@ -97,12 +98,15 @@ void LoRaDemodGUI::on_BW_valueChanged(int value) applySettings(); } -void LoRaDemodGUI::on_Spread_valueChanged(int value __attribute__((unused))) +void LoRaDemodGUI::on_Spread_valueChanged(int value) { + (void) value; } -void LoRaDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void LoRaDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } LoRaDemodGUI::LoRaDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) : diff --git a/plugins/channelrx/demodnfm/nfmdemod.cpp b/plugins/channelrx/demodnfm/nfmdemod.cpp index 2002d2463..69d75bba4 100644 --- a/plugins/channelrx/demodnfm/nfmdemod.cpp +++ b/plugins/channelrx/demodnfm/nfmdemod.cpp @@ -137,8 +137,9 @@ Real angleDist(Real a, Real b) return dist; } -void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) +void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) { + (void) firstOfBurst; Complex ci; if (!m_running) { @@ -585,8 +586,9 @@ bool NFMDemod::deserialize(const QByteArray& data) int NFMDemod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setNfmDemodSettings(new SWGSDRangel::SWGNFMDemodSettings()); response.getNfmDemodSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -597,8 +599,9 @@ int NFMDemod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; NFMDemodSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -670,8 +673,9 @@ int NFMDemod::webapiSettingsPutPatch( int NFMDemod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setNfmDemodReport(new SWGSDRangel::SWGNFMDemodReport()); response.getNfmDemodReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channelrx/demodnfm/nfmdemodgui.cpp b/plugins/channelrx/demodnfm/nfmdemodgui.cpp index 98c2361d4..e3ac5afc5 100644 --- a/plugins/channelrx/demodnfm/nfmdemodgui.cpp +++ b/plugins/channelrx/demodnfm/nfmdemodgui.cpp @@ -214,8 +214,10 @@ void NFMDemodGUI::on_ctcss_currentIndexChanged(int index) applySettings(); } -void NFMDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void NFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; /* if((widget == ui->spectrumContainer) && (m_nfmDemod != NULL)) m_nfmDemod->setSpectrum(m_threadedSampleSink->getMessageQueue(), rollDown); diff --git a/plugins/channelrx/demodssb/ssbdemod.cpp b/plugins/channelrx/demodssb/ssbdemod.cpp index 0b0aa6b21..311cca888 100644 --- a/plugins/channelrx/demodssb/ssbdemod.cpp +++ b/plugins/channelrx/demodssb/ssbdemod.cpp @@ -144,8 +144,9 @@ void SSBDemod::configure(MessageQueue* messageQueue, messageQueue->push(cmd); } -void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused))) +void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) { + (void) positiveOnly; Complex ci; fftfilt::cmplx *sideband; int n_out; @@ -585,8 +586,9 @@ bool SSBDemod::deserialize(const QByteArray& data) int SSBDemod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSsbDemodSettings(new SWGSDRangel::SWGSSBDemodSettings()); response.getSsbDemodSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -597,8 +599,9 @@ int SSBDemod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; SSBDemodSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -680,8 +683,9 @@ int SSBDemod::webapiSettingsPutPatch( int SSBDemod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSsbDemodReport(new SWGSDRangel::SWGSSBDemodReport()); response.getSsbDemodReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channelrx/demodssb/ssbdemodgui.cpp b/plugins/channelrx/demodssb/ssbdemodgui.cpp index 788b1d946..d6b3e2e85 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.cpp +++ b/plugins/channelrx/demodssb/ssbdemodgui.cpp @@ -156,13 +156,15 @@ void SSBDemodGUI::on_deltaFrequency_changed(qint64 value) applySettings(); } -void SSBDemodGUI::on_BW_valueChanged(int value __attribute__((unused))) +void SSBDemodGUI::on_BW_valueChanged(int value) { + (void) value; applyBandwidths(5 - ui->spanLog2->value()); } -void SSBDemodGUI::on_lowCut_valueChanged(int value __attribute__((unused))) +void SSBDemodGUI::on_lowCut_valueChanged(int value) { + (void) value; applyBandwidths(5 - ui->spanLog2->value()); } @@ -224,8 +226,9 @@ void SSBDemodGUI::on_spanLog2_valueChanged(int value) applyBandwidths(5 - ui->spanLog2->value()); } -void SSBDemodGUI::on_flipSidebands_clicked(bool checked __attribute__((unused))) +void SSBDemodGUI::on_flipSidebands_clicked(bool checked) { + (void) checked; int bwValue = ui->BW->value(); int lcValue = ui->lowCut->value(); ui->BW->setValue(-bwValue); @@ -248,8 +251,10 @@ void SSBDemodGUI::onMenuDialogCalled(const QPoint &p) applySettings(); } -void SSBDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void SSBDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) : diff --git a/plugins/channelrx/demodwfm/wfmdemod.cpp b/plugins/channelrx/demodwfm/wfmdemod.cpp index 3b1d49619..b9dbd0547 100644 --- a/plugins/channelrx/demodwfm/wfmdemod.cpp +++ b/plugins/channelrx/demodwfm/wfmdemod.cpp @@ -87,8 +87,9 @@ WFMDemod::~WFMDemod() delete m_rfFilter; } -void WFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) +void WFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) { + (void) firstOfBurst; Complex ci; fftfilt::cmplx *rf; int rf_out; @@ -382,8 +383,9 @@ bool WFMDemod::deserialize(const QByteArray& data) int WFMDemod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setWfmDemodSettings(new SWGSDRangel::SWGWFMDemodSettings()); response.getWfmDemodSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -394,8 +396,9 @@ int WFMDemod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; WFMDemodSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -453,8 +456,9 @@ int WFMDemod::webapiSettingsPutPatch( int WFMDemod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setWfmDemodReport(new SWGSDRangel::SWGWFMDemodReport()); response.getWfmDemodReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channelrx/demodwfm/wfmdemodgui.cpp b/plugins/channelrx/demodwfm/wfmdemodgui.cpp index 77ec241dd..b6b6cfc85 100644 --- a/plugins/channelrx/demodwfm/wfmdemodgui.cpp +++ b/plugins/channelrx/demodwfm/wfmdemodgui.cpp @@ -75,8 +75,9 @@ bool WFMDemodGUI::deserialize(const QByteArray& data) } } -bool WFMDemodGUI::handleMessage(const Message& message __attribute__((unused))) +bool WFMDemodGUI::handleMessage(const Message& message) { + (void) message; if (WFMDemod::MsgConfigureWFMDemod::match(message)) { qDebug("WFMDemodGUI::handleMessage: WFMDemod::MsgConfigureWFMDemod"); @@ -159,8 +160,10 @@ void WFMDemodGUI::on_audioMute_toggled(bool checked) applySettings(); } -void WFMDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void WFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void WFMDemodGUI::onMenuDialogCalled(const QPoint &p) diff --git a/plugins/channelrx/udpsink/udpsink.cpp b/plugins/channelrx/udpsink/udpsink.cpp index 040c054df..ba828f590 100644 --- a/plugins/channelrx/udpsink/udpsink.cpp +++ b/plugins/channelrx/udpsink/udpsink.cpp @@ -644,8 +644,9 @@ bool UDPSink::deserialize(const QByteArray& data) int UDPSink::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setUdpSinkSettings(new SWGSDRangel::SWGUDPSinkSettings()); response.getUdpSinkSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -656,8 +657,9 @@ int UDPSink::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; UDPSinkSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -746,8 +748,9 @@ int UDPSink::webapiSettingsPutPatch( int UDPSink::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setUdpSinkReport(new SWGSDRangel::SWGUDPSinkReport()); response.getUdpSinkReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channelrx/udpsink/udpsinkgui.cpp b/plugins/channelrx/udpsink/udpsinkgui.cpp index eed9fcb54..c4c8a06bb 100644 --- a/plugins/channelrx/udpsink/udpsinkgui.cpp +++ b/plugins/channelrx/udpsink/udpsinkgui.cpp @@ -472,8 +472,9 @@ void UDPSinkGUI::on_inputUDPAudioPort_editingFinished() ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }"); } -void UDPSinkGUI::on_sampleRate_textEdited(const QString& arg1 __attribute__((unused))) +void UDPSinkGUI::on_sampleRate_textEdited(const QString& arg1) { + (void) arg1; bool ok; Real outputSampleRate = ui->sampleRate->text().toDouble(&ok); @@ -491,8 +492,9 @@ void UDPSinkGUI::on_sampleRate_textEdited(const QString& arg1 __attribute__((unu ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }"); } -void UDPSinkGUI::on_rfBandwidth_textEdited(const QString& arg1 __attribute__((unused))) +void UDPSinkGUI::on_rfBandwidth_textEdited(const QString& arg1) { + (void) arg1; bool ok; Real rfBandwidth = ui->rfBandwidth->text().toDouble(&ok); @@ -512,8 +514,9 @@ void UDPSinkGUI::on_rfBandwidth_textEdited(const QString& arg1 __attribute__((un ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }"); } -void UDPSinkGUI::on_fmDeviation_textEdited(const QString& arg1 __attribute__((unused))) +void UDPSinkGUI::on_fmDeviation_textEdited(const QString& arg1) { + (void) arg1; bool ok; int fmDeviation = ui->fmDeviation->text().toInt(&ok); diff --git a/plugins/channeltx/daemonsource/daemonsource.cpp b/plugins/channeltx/daemonsource/daemonsource.cpp index d23e1e100..bf57d0283 100644 --- a/plugins/channeltx/daemonsource/daemonsource.cpp +++ b/plugins/channeltx/daemonsource/daemonsource.cpp @@ -74,8 +74,9 @@ void DaemonSource::pull(Sample& sample) m_dataReadQueue.readSample(sample, true); // true is scale for Tx } -void DaemonSource::pullAudio(int nbSamples __attribute__((unused))) +void DaemonSource::pullAudio(int nbSamples) { + (void) nbSamples; } void DaemonSource::start() @@ -174,8 +175,9 @@ QByteArray DaemonSource::serialize() const return m_settings.serialize(); } -bool DaemonSource::deserialize(const QByteArray& data __attribute__((unused))) +bool DaemonSource::deserialize(const QByteArray& data) { + (void) data; if (m_settings.deserialize(data)) { MsgConfigureDaemonSource *msg = MsgConfigureDaemonSource::create(m_settings, true); @@ -215,8 +217,9 @@ void DaemonSource::applySettings(const DaemonSourceSettings& settings, bool forc m_settings = settings; } -void DaemonSource::handleDataBlock(SDRDaemonDataBlock* dataBlock __attribute__((unused))) +void DaemonSource::handleDataBlock(SDRDaemonDataBlock* dataBlock) { + (void) dataBlock; if (dataBlock->m_rxControlBlock.m_blockCount < SDRDaemonNbOrginalBlocks) { qWarning("DaemonSource::handleDataBlock: incomplete data block: not processing"); @@ -352,8 +355,9 @@ uint32_t DaemonSource::calculateDataReadQueueSize(int sampleRate) int DaemonSource::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setDaemonSourceSettings(new SWGSDRangel::SWGDaemonSourceSettings()); response.getDaemonSourceSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -364,8 +368,9 @@ int DaemonSource::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; DaemonSourceSettings settings = m_settings; if (channelSettingsKeys.contains("dataAddress")) { @@ -405,8 +410,9 @@ int DaemonSource::webapiSettingsPutPatch( int DaemonSource::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setDaemonSourceReport(new SWGSDRangel::SWGDaemonSourceReport()); response.getDaemonSourceReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channeltx/daemonsource/daemonsourcegui.cpp b/plugins/channeltx/daemonsource/daemonsourcegui.cpp index 10ba93ba5..5a95a4059 100644 --- a/plugins/channeltx/daemonsource/daemonsourcegui.cpp +++ b/plugins/channeltx/daemonsource/daemonsourcegui.cpp @@ -48,8 +48,9 @@ qint64 DaemonSourceGUI::getCenterFrequency() const { return 0; } -void DaemonSourceGUI::setCenterFrequency(qint64 centerFrequency __attribute__((unused))) +void DaemonSourceGUI::setCenterFrequency(qint64 centerFrequency) { + (void) centerFrequency; } void DaemonSourceGUI::resetToDefaults() @@ -152,7 +153,7 @@ bool DaemonSourceGUI::handleMessage(const Message& message) } } -DaemonSourceGUI::DaemonSourceGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx __attribute__((unused)), QWidget* parent) : +DaemonSourceGUI::DaemonSourceGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget* parent) : RollupWidget(parent), ui(new Ui::DaemonSourceGUI), m_pluginAPI(pluginAPI), @@ -166,6 +167,7 @@ DaemonSourceGUI::DaemonSourceGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, m_resetCounts(true), m_tickCount(0) { + (void) channelTx; ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); @@ -262,8 +264,10 @@ void DaemonSourceGUI::handleSourceMessages() } } -void DaemonSourceGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void DaemonSourceGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void DaemonSourceGUI::onMenuDialogCalled(const QPoint &p) @@ -304,8 +308,9 @@ void DaemonSourceGUI::on_dataPort_returnPressed() applySettings(); } -void DaemonSourceGUI::on_dataApplyButton_clicked(bool checked __attribute__((unused))) +void DaemonSourceGUI::on_dataApplyButton_clicked(bool checked) { + (void) checked; m_settings.m_dataAddress = ui->dataAddress->text(); bool dataOk; @@ -319,8 +324,9 @@ void DaemonSourceGUI::on_dataApplyButton_clicked(bool checked __attribute__((unu applySettings(); } -void DaemonSourceGUI::on_eventCountsReset_clicked(bool checked __attribute__((unused))) +void DaemonSourceGUI::on_eventCountsReset_clicked(bool checked) { + (void) checked; m_countUnrecoverable = 0; m_countRecovered = 0; m_time.start(); diff --git a/plugins/channeltx/modam/ammod.cpp b/plugins/channeltx/modam/ammod.cpp index 6fe798e1c..8604b001b 100644 --- a/plugins/channeltx/modam/ammod.cpp +++ b/plugins/channeltx/modam/ammod.cpp @@ -513,8 +513,9 @@ bool AMMod::deserialize(const QByteArray& data) int AMMod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAmModSettings(new SWGSDRangel::SWGAMModSettings()); response.getAmModSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -525,8 +526,9 @@ int AMMod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; AMModSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -623,8 +625,9 @@ int AMMod::webapiSettingsPutPatch( int AMMod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAmModReport(new SWGSDRangel::SWGAMModReport()); response.getAmModReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channeltx/modam/ammodgui.cpp b/plugins/channeltx/modam/ammodgui.cpp index 25270da64..e3decf2bc 100644 --- a/plugins/channeltx/modam/ammodgui.cpp +++ b/plugins/channeltx/modam/ammodgui.cpp @@ -248,8 +248,9 @@ void AMModGUI::on_navTimeSlider_valueChanged(int value) } } -void AMModGUI::on_showFileDialog_clicked(bool checked __attribute__((unused))) +void AMModGUI::on_showFileDialog_clicked(bool checked) { + (void) checked; QString fileName = QFileDialog::getOpenFileName(this, tr("Open raw audio file"), ".", tr("Raw audio Files (*.raw)"), 0, QFileDialog::DontUseNativeDialog); @@ -269,8 +270,10 @@ void AMModGUI::configureFileName() m_amMod->getInputMessageQueue()->push(message); } -void AMModGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void AMModGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void AMModGUI::onMenuDialogCalled(const QPoint &p) @@ -363,8 +366,9 @@ void AMModGUI::blockApplySettings(bool block) m_doApplySettings = !block; } -void AMModGUI::applySettings(bool force __attribute((unused))) +void AMModGUI::applySettings(bool force) { + (void) force; if (m_doApplySettings) { setTitleColor(m_channelMarker.getColor()); diff --git a/plugins/channeltx/modatv/atvmod.cpp b/plugins/channeltx/modatv/atvmod.cpp index 6c98853dd..bce87b3f6 100644 --- a/plugins/channeltx/modatv/atvmod.cpp +++ b/plugins/channeltx/modatv/atvmod.cpp @@ -116,8 +116,9 @@ ATVMod::~ATVMod() delete[] m_DSBFilterBuffer; } -void ATVMod::pullAudio(int nbSamples __attribute__((unused))) +void ATVMod::pullAudio(int nbSamples) { + (void) nbSamples; } void ATVMod::pull(Sample& sample) @@ -1185,8 +1186,9 @@ bool ATVMod::deserialize(const QByteArray& data) int ATVMod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAtvModSettings(new SWGSDRangel::SWGATVModSettings()); response.getAtvModSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -1197,8 +1199,9 @@ int ATVMod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; ATVModSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -1319,8 +1322,9 @@ int ATVMod::webapiSettingsPutPatch( int ATVMod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAtvModReport(new SWGSDRangel::SWGATVModReport()); response.getAtvModReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channeltx/modatv/atvmodgui.cpp b/plugins/channeltx/modatv/atvmodgui.cpp index 1059423a1..be40013e2 100644 --- a/plugins/channeltx/modatv/atvmodgui.cpp +++ b/plugins/channeltx/modatv/atvmodgui.cpp @@ -444,14 +444,16 @@ void ATVModGUI::setChannelMarkerBandwidth() } } -void ATVModGUI::on_nbLines_currentIndexChanged(int index __attribute__((unused))) +void ATVModGUI::on_nbLines_currentIndexChanged(int index) { + (void) index; m_settings.m_nbLines = getNbLines(); applySettings(); } -void ATVModGUI::on_fps_currentIndexChanged(int index __attribute__((unused))) +void ATVModGUI::on_fps_currentIndexChanged(int index) { + (void) index; m_settings.m_fps = getFPS(); applySettings(); } @@ -494,8 +496,9 @@ void ATVModGUI::on_forceDecimator_toggled(bool checked) applySettings(); } -void ATVModGUI::on_imageFileDialog_clicked(bool checked __attribute__((unused))) +void ATVModGUI::on_imageFileDialog_clicked(bool checked) { + (void) checked; QString fileName = QFileDialog::getOpenFileName(this, tr("Open image file"), ".", tr("Image Files (*.png *.jpg *.bmp *.gif *.tiff)"), 0, QFileDialog::DontUseNativeDialog); @@ -507,8 +510,9 @@ void ATVModGUI::on_imageFileDialog_clicked(bool checked __attribute__((unused))) } } -void ATVModGUI::on_videoFileDialog_clicked(bool checked __attribute__((unused))) +void ATVModGUI::on_videoFileDialog_clicked(bool checked) { + (void) checked; QString fileName = QFileDialog::getOpenFileName(this, tr("Open video file"), ".", tr("Video Files (*.avi *.mpg *.mp4 *.mov *.m4v *.mkv *.vob *.wmv)"), 0, QFileDialog::DontUseNativeDialog); @@ -580,8 +584,9 @@ void ATVModGUI::on_overlayTextShow_toggled(bool checked) applySettings(); } -void ATVModGUI::on_overlayText_textEdited(const QString& arg1 __attribute__((unused))) +void ATVModGUI::on_overlayText_textEdited(const QString& arg1) { + (void) arg1; m_settings.m_overlayText = arg1; applySettings(); } @@ -600,8 +605,10 @@ void ATVModGUI::configureVideoFileName() m_atvMod->getInputMessageQueue()->push(message); } -void ATVModGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void ATVModGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void ATVModGUI::onMenuDialogCalled(const QPoint &p) diff --git a/plugins/channeltx/modnfm/nfmmod.cpp b/plugins/channeltx/modnfm/nfmmod.cpp index 894d4ffb5..f51e91276 100644 --- a/plugins/channeltx/modnfm/nfmmod.cpp +++ b/plugins/channeltx/modnfm/nfmmod.cpp @@ -553,8 +553,9 @@ bool NFMMod::deserialize(const QByteArray& data) int NFMMod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setNfmModSettings(new SWGSDRangel::SWGNFMModSettings()); response.getNfmModSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -565,8 +566,9 @@ int NFMMod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; NFMModSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -673,8 +675,9 @@ int NFMMod::webapiSettingsPutPatch( int NFMMod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setNfmModReport(new SWGSDRangel::SWGNFMModReport()); response.getNfmModReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channeltx/modnfm/nfmmodgui.cpp b/plugins/channeltx/modnfm/nfmmodgui.cpp index 6db1738a8..9d7ec0262 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.cpp +++ b/plugins/channeltx/modnfm/nfmmodgui.cpp @@ -252,8 +252,9 @@ void NFMModGUI::on_navTimeSlider_valueChanged(int value) } } -void NFMModGUI::on_showFileDialog_clicked(bool checked __attribute__((unused))) +void NFMModGUI::on_showFileDialog_clicked(bool checked) { + (void) checked; QString fileName = QFileDialog::getOpenFileName(this, tr("Open raw audio file"), ".", tr("Raw audio Files (*.raw)"), 0, QFileDialog::DontUseNativeDialog); @@ -286,8 +287,10 @@ void NFMModGUI::configureFileName() m_nfmMod->getInputMessageQueue()->push(message); } -void NFMModGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void NFMModGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void NFMModGUI::onMenuDialogCalled(const QPoint &p) diff --git a/plugins/channeltx/modssb/ssbmod.cpp b/plugins/channeltx/modssb/ssbmod.cpp index 2efda0df5..b8fcbb357 100644 --- a/plugins/channeltx/modssb/ssbmod.cpp +++ b/plugins/channeltx/modssb/ssbmod.cpp @@ -872,8 +872,9 @@ bool SSBMod::deserialize(const QByteArray& data) int SSBMod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSsbModSettings(new SWGSDRangel::SWGSSBModSettings()); response.getSsbModSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -884,8 +885,9 @@ int SSBMod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; SSBModSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -1018,8 +1020,9 @@ int SSBMod::webapiSettingsPutPatch( int SSBMod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSsbModReport(new SWGSDRangel::SWGSSBModReport()); response.getSsbModReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channeltx/modssb/ssbmodgui.cpp b/plugins/channeltx/modssb/ssbmodgui.cpp index b15818d42..81e88d9b0 100644 --- a/plugins/channeltx/modssb/ssbmodgui.cpp +++ b/plugins/channeltx/modssb/ssbmodgui.cpp @@ -173,8 +173,9 @@ void SSBModGUI::on_deltaFrequency_changed(qint64 value) applySettings(); } -void SSBModGUI::on_flipSidebands_clicked(bool checked __attribute__((unused))) +void SSBModGUI::on_flipSidebands_clicked(bool checked) { + (void) checked; int bwValue = ui->BW->value(); int lcValue = ui->lowCut->value(); ui->BW->setValue(-bwValue); @@ -208,13 +209,15 @@ void SSBModGUI::on_spanLog2_valueChanged(int value) applyBandwidths(5 - value); } -void SSBModGUI::on_BW_valueChanged(int value __attribute__((unused))) +void SSBModGUI::on_BW_valueChanged(int value) { + (void) value; applyBandwidths(5 - ui->spanLog2->value()); } -void SSBModGUI::on_lowCut_valueChanged(int value __attribute__((unused))) +void SSBModGUI::on_lowCut_valueChanged(int value) { + (void) value; applyBandwidths(5 - ui->spanLog2->value()); } @@ -340,6 +343,7 @@ void SSBModGUI::on_navTimeSlider_valueChanged(int value) void SSBModGUI::on_showFileDialog_clicked(bool checked __attribute__((unused))) { + (void) checked; QString fileName = QFileDialog::getOpenFileName(this, tr("Open raw audio file"), ".", tr("Raw audio Files (*.raw)"), 0, QFileDialog::DontUseNativeDialog); @@ -359,8 +363,10 @@ void SSBModGUI::configureFileName() m_ssbMod->getInputMessageQueue()->push(message); } -void SSBModGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void SSBModGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void SSBModGUI::onMenuDialogCalled(const QPoint &p) diff --git a/sdrgui/soapygui/stringrangegui.cpp b/sdrgui/soapygui/stringrangegui.cpp index 677bcd5db..88e8efc2e 100644 --- a/sdrgui/soapygui/stringrangegui.cpp +++ b/sdrgui/soapygui/stringrangegui.cpp @@ -71,8 +71,9 @@ void StringRangeGUI::setValue(const std::string& value) } } -void StringRangeGUI::on_rangeCombo_currentIndexChanged(int index __attribute__((unused))) +void StringRangeGUI::on_rangeCombo_currentIndexChanged(int index) { + (void) index; emit valueChanged(); } From 7574cb23d41194f388ffe80b4d9c0efb1158f991 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 08:51:14 +0100 Subject: [PATCH 017/102] Windows: MSVC2017: fixed more attribute unused cases (2) --- devices/perseus/deviceperseus.h | 2 +- plugins/channeltx/modssb/ssbmodgui.cpp | 2 +- plugins/channeltx/modwfm/wfmmod.cpp | 9 ++++-- plugins/channeltx/modwfm/wfmmodgui.cpp | 7 ++-- plugins/channeltx/udpsource/udpsource.cpp | 9 ++++-- plugins/channeltx/udpsource/udpsourcegui.cpp | 12 ++++--- .../bladerf1output/bladerf1output.cpp | 12 ++++--- .../bladerf2output/bladerf2output.cpp | 15 ++++++--- plugins/samplesink/filesink/filesinkgui.cpp | 3 +- .../samplesink/filesink/filesinkoutput.cpp | 6 ++-- .../samplesink/hackrfoutput/hackrfoutput.cpp | 12 ++++--- .../limesdroutput/limesdroutput.cpp | 15 ++++++--- .../limesdroutput/limesdroutputthread.h | 2 +- .../plutosdroutput/plutosdroutput.cpp | 15 ++++++--- .../plutosdroutput/plutosdroutputgui.cpp | 3 +- .../plutosdroutput/plutosdroutputthread.h | 2 +- .../sdrdaemonsink/sdrdaemonsinkgui.cpp | 9 ++++-- .../sdrdaemonsink/sdrdaemonsinkgui.h | 2 +- .../sdrdaemonsink/sdrdaemonsinkoutput.cpp | 15 ++++++--- .../sdrdaemonsink/sdrdaemonsinkoutput.h | 2 +- .../soapysdroutput/soapysdroutput.cpp | 2 +- plugins/samplesource/airspy/airspyinput.cpp | 15 ++++++--- .../samplesource/airspyhf/airspyhfinput.cpp | 15 ++++++--- .../bladerf1input/bladerf1input.cpp | 12 ++++--- .../bladerf2input/bladerf2input.cpp | 15 ++++++--- plugins/samplesource/fcdpro/fcdprogui.cpp | 5 +-- plugins/samplesource/fcdpro/fcdproinput.cpp | 15 ++++++--- .../samplesource/fcdproplus/fcdproplusgui.cpp | 2 +- .../fcdproplus/fcdproplusinput.cpp | 12 ++++--- .../samplesource/filesource/filesourcegui.cpp | 3 +- .../filesource/filesourceinput.cpp | 15 ++++++--- .../samplesource/hackrfinput/hackrfinput.cpp | 12 ++++--- .../limesdrinput/limesdrinput.cpp | 15 ++++++--- .../limesdrinput/limesdrinputthread.h | 2 +- plugins/samplesource/perseus/perseusinput.cpp | 15 ++++++--- .../samplesource/perseus/perseusthread.cpp | 3 +- .../plutosdrinput/plutosdrinput.cpp | 15 ++++++--- .../plutosdrinput/plutosdrinputgui.cpp | 2 +- .../plutosdrinput/plutosdrinputthread.h | 2 +- plugins/samplesource/rtlsdr/rtlsdrinput.cpp | 15 ++++++--- .../sdrdaemonsource/sdrdaemonsourcegui.cpp | 12 ++++--- .../sdrdaemonsource/sdrdaemonsourceinput.cpp | 18 +++++++---- plugins/samplesource/sdrplay/sdrplayinput.cpp | 15 ++++++--- .../soapysdrinput/soapysdrinput.cpp | 7 ++-- .../samplesource/testsource/testsourcegui.cpp | 6 ++-- .../testsource/testsourceinput.cpp | 12 ++++--- sdrbase/dsp/decimatorsu.h | 4 +-- sdrbase/dsp/dspengine.cpp | 32 ++++++++++++------- 48 files changed, 295 insertions(+), 157 deletions(-) diff --git a/devices/perseus/deviceperseus.h b/devices/perseus/deviceperseus.h index 1ac30fcdb..47d8a38c5 100644 --- a/devices/perseus/deviceperseus.h +++ b/devices/perseus/deviceperseus.h @@ -32,7 +32,7 @@ public: protected: DevicePerseus(); DevicePerseus(const DevicePerseus&) : m_nbDevices(0) {} - DevicePerseus& operator=(const DevicePerseus& other __attribute__((unused))) { return *this; } + DevicePerseus& operator=(const DevicePerseus& other) { (void) other; return *this; } ~DevicePerseus(); private: diff --git a/plugins/channeltx/modssb/ssbmodgui.cpp b/plugins/channeltx/modssb/ssbmodgui.cpp index 81e88d9b0..85d13da29 100644 --- a/plugins/channeltx/modssb/ssbmodgui.cpp +++ b/plugins/channeltx/modssb/ssbmodgui.cpp @@ -341,7 +341,7 @@ void SSBModGUI::on_navTimeSlider_valueChanged(int value) } } -void SSBModGUI::on_showFileDialog_clicked(bool checked __attribute__((unused))) +void SSBModGUI::on_showFileDialog_clicked(bool checked) { (void) checked; QString fileName = QFileDialog::getOpenFileName(this, diff --git a/plugins/channeltx/modwfm/wfmmod.cpp b/plugins/channeltx/modwfm/wfmmod.cpp index 916781f0d..dcf34a040 100644 --- a/plugins/channeltx/modwfm/wfmmod.cpp +++ b/plugins/channeltx/modwfm/wfmmod.cpp @@ -546,8 +546,9 @@ bool WFMMod::deserialize(const QByteArray& data) int WFMMod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setWfmModSettings(new SWGSDRangel::SWGWFMModSettings()); response.getWfmModSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -558,8 +559,9 @@ int WFMMod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; WFMModSettings settings = m_settings; bool channelizerChange = false; @@ -657,8 +659,9 @@ int WFMMod::webapiSettingsPutPatch( int WFMMod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setWfmModReport(new SWGSDRangel::SWGWFMModReport()); response.getWfmModReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channeltx/modwfm/wfmmodgui.cpp b/plugins/channeltx/modwfm/wfmmodgui.cpp index b5cf6d6c2..eeef938ef 100644 --- a/plugins/channeltx/modwfm/wfmmodgui.cpp +++ b/plugins/channeltx/modwfm/wfmmodgui.cpp @@ -254,8 +254,9 @@ void WFMModGUI::on_navTimeSlider_valueChanged(int value) } } -void WFMModGUI::on_showFileDialog_clicked(bool checked __attribute__((unused))) +void WFMModGUI::on_showFileDialog_clicked(bool checked) { + (void) checked; QString fileName = QFileDialog::getOpenFileName(this, tr("Open raw audio file"), ".", tr("Raw audio Files (*.raw)"), 0, QFileDialog::DontUseNativeDialog); @@ -275,8 +276,10 @@ void WFMModGUI::configureFileName() m_wfmMod->getInputMessageQueue()->push(message); } -void WFMModGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused))) +void WFMModGUI::onWidgetRolled(QWidget* widget, bool rollDown) { + (void) widget; + (void) rollDown; } void WFMModGUI::onMenuDialogCalled(const QPoint &p) diff --git a/plugins/channeltx/udpsource/udpsource.cpp b/plugins/channeltx/udpsource/udpsource.cpp index 38b25e946..809919927 100644 --- a/plugins/channeltx/udpsource/udpsource.cpp +++ b/plugins/channeltx/udpsource/udpsource.cpp @@ -599,8 +599,9 @@ bool UDPSource::deserialize(const QByteArray& data) int UDPSource::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setUdpSourceSettings(new SWGSDRangel::SWGUDPSourceSettings()); response.getUdpSourceSettings()->init(); webapiFormatChannelSettings(response, m_settings); @@ -611,8 +612,9 @@ int UDPSource::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; UDPSourceSettings settings = m_settings; bool frequencyOffsetChanged = false; @@ -700,8 +702,9 @@ int UDPSource::webapiSettingsPutPatch( int UDPSource::webapiReportGet( SWGSDRangel::SWGChannelReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setUdpSourceReport(new SWGSDRangel::SWGUDPSourceReport()); response.getUdpSourceReport()->init(); webapiFormatChannelReport(response); diff --git a/plugins/channeltx/udpsource/udpsourcegui.cpp b/plugins/channeltx/udpsource/udpsourcegui.cpp index fefa33893..08ad2942a 100644 --- a/plugins/channeltx/udpsource/udpsourcegui.cpp +++ b/plugins/channeltx/udpsource/udpsourcegui.cpp @@ -316,8 +316,9 @@ void UDPSourceGUI::on_localUDPPort_editingFinished() ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }"); } -void UDPSourceGUI::on_sampleRate_textEdited(const QString& arg1 __attribute__((unused))) +void UDPSourceGUI::on_sampleRate_textEdited(const QString& arg1) { + (void) arg1; bool ok; Real inputSampleRate = ui->sampleRate->text().toDouble(&ok); @@ -332,8 +333,9 @@ void UDPSourceGUI::on_sampleRate_textEdited(const QString& arg1 __attribute__((u ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }"); } -void UDPSourceGUI::on_rfBandwidth_textEdited(const QString& arg1 __attribute__((unused))) +void UDPSourceGUI::on_rfBandwidth_textEdited(const QString& arg1) { + (void) arg1; bool ok; Real rfBandwidth = ui->rfBandwidth->text().toDouble(&ok); @@ -353,8 +355,9 @@ void UDPSourceGUI::on_rfBandwidth_textEdited(const QString& arg1 __attribute__(( ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }"); } -void UDPSourceGUI::on_fmDeviation_textEdited(const QString& arg1 __attribute__((unused))) +void UDPSourceGUI::on_fmDeviation_textEdited(const QString& arg1) { + (void) arg1; bool ok; int fmDeviation = ui->fmDeviation->text().toInt(&ok); @@ -369,8 +372,9 @@ void UDPSourceGUI::on_fmDeviation_textEdited(const QString& arg1 __attribute__(( ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }"); } -void UDPSourceGUI::on_amModPercent_textEdited(const QString& arg1 __attribute__((unused))) +void UDPSourceGUI::on_amModPercent_textEdited(const QString& arg1) { + (void) arg1; bool ok; int amModPercent = ui->amModPercent->text().toInt(&ok); diff --git a/plugins/samplesink/bladerf1output/bladerf1output.cpp b/plugins/samplesink/bladerf1output/bladerf1output.cpp index 75d15f593..17fbecbb0 100644 --- a/plugins/samplesink/bladerf1output/bladerf1output.cpp +++ b/plugins/samplesink/bladerf1output/bladerf1output.cpp @@ -535,8 +535,9 @@ bool Bladerf1Output::applySettings(const BladeRF1OutputSettings& settings, bool int Bladerf1Output::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setBladeRf1OutputSettings(new SWGSDRangel::SWGBladeRF1OutputSettings()); response.getBladeRf1OutputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -560,8 +561,9 @@ int Bladerf1Output::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; BladeRF1OutputSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -607,8 +609,9 @@ int Bladerf1Output::webapiSettingsPutPatch( int Bladerf1Output::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -616,8 +619,9 @@ int Bladerf1Output::webapiRunGet( int Bladerf1Output::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesink/bladerf2output/bladerf2output.cpp b/plugins/samplesink/bladerf2output/bladerf2output.cpp index 8ebec2a37..db0b52f82 100644 --- a/plugins/samplesink/bladerf2output/bladerf2output.cpp +++ b/plugins/samplesink/bladerf2output/bladerf2output.cpp @@ -900,8 +900,9 @@ int BladeRF2Output::getNbChannels() int BladeRF2Output::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setBladeRf2OutputSettings(new SWGSDRangel::SWGBladeRF2OutputSettings()); response.getBladeRf2OutputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -912,8 +913,9 @@ int BladeRF2Output::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; BladeRF2OutputSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -957,8 +959,9 @@ int BladeRF2Output::webapiSettingsPutPatch( return 200; } -int BladeRF2Output::webapiReportGet(SWGSDRangel::SWGDeviceReport& response, QString& errorMessage __attribute__((unused))) +int BladeRF2Output::webapiReportGet(SWGSDRangel::SWGDeviceReport& response, QString& errorMessage) { + (void) errorMessage; response.setBladeRf2OutputReport(new SWGSDRangel::SWGBladeRF2OutputReport()); response.getBladeRf2OutputReport()->init(); webapiFormatDeviceReport(response); @@ -1019,8 +1022,9 @@ void BladeRF2Output::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& resp int BladeRF2Output::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -1028,8 +1032,9 @@ int BladeRF2Output::webapiRunGet( int BladeRF2Output::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesink/filesink/filesinkgui.cpp b/plugins/samplesink/filesink/filesinkgui.cpp index c05d525c0..9e2327276 100644 --- a/plugins/samplesink/filesink/filesinkgui.cpp +++ b/plugins/samplesink/filesink/filesinkgui.cpp @@ -284,8 +284,9 @@ void FileSinkGui::on_startStop_toggled(bool checked) } } -void FileSinkGui::on_showFileDialog_clicked(bool checked __attribute__((unused))) +void FileSinkGui::on_showFileDialog_clicked(bool checked) { + (void) checked; QString fileName = QFileDialog::getSaveFileName(this, tr("Save I/Q record file"), ".", tr("SDR I/Q Files (*.sdriq)"), 0, QFileDialog::DontUseNativeDialog); diff --git a/plugins/samplesink/filesink/filesinkoutput.cpp b/plugins/samplesink/filesink/filesinkoutput.cpp index d73747c1a..602812ec8 100644 --- a/plugins/samplesink/filesink/filesinkoutput.cpp +++ b/plugins/samplesink/filesink/filesinkoutput.cpp @@ -318,8 +318,9 @@ void FileSinkOutput::applySettings(const FileSinkSettings& settings, bool force) int FileSinkOutput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -327,8 +328,9 @@ int FileSinkOutput::webapiRunGet( int FileSinkOutput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesink/hackrfoutput/hackrfoutput.cpp b/plugins/samplesink/hackrfoutput/hackrfoutput.cpp index 3ae7437b1..00f0137cd 100644 --- a/plugins/samplesink/hackrfoutput/hackrfoutput.cpp +++ b/plugins/samplesink/hackrfoutput/hackrfoutput.cpp @@ -463,8 +463,9 @@ bool HackRFOutput::applySettings(const HackRFOutputSettings& settings, bool forc int HackRFOutput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setHackRfOutputSettings(new SWGSDRangel::SWGHackRFOutputSettings()); response.getHackRfOutputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -475,8 +476,9 @@ int HackRFOutput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; HackRFOutputSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -531,8 +533,9 @@ void HackRFOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& re int HackRFOutput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -540,8 +543,9 @@ int HackRFOutput::webapiRunGet( int HackRFOutput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesink/limesdroutput/limesdroutput.cpp b/plugins/samplesink/limesdroutput/limesdroutput.cpp index a166d488c..09c8fd387 100644 --- a/plugins/samplesink/limesdroutput/limesdroutput.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutput.cpp @@ -1102,8 +1102,9 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo int LimeSDROutput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setLimeSdrOutputSettings(new SWGSDRangel::SWGLimeSdrOutputSettings()); response.getLimeSdrOutputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -1114,8 +1115,9 @@ int LimeSDROutput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; LimeSDROutputSettings settings = m_settings; if (deviceSettingsKeys.contains("antennaPath")) { @@ -1179,8 +1181,9 @@ int LimeSDROutput::webapiSettingsPutPatch( int LimeSDROutput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setLimeSdrOutputReport(new SWGSDRangel::SWGLimeSdrOutputReport()); response.getLimeSdrOutputReport()->init(); webapiFormatDeviceReport(response); @@ -1207,8 +1210,9 @@ void LimeSDROutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& r int LimeSDROutput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -1216,8 +1220,9 @@ int LimeSDROutput::webapiRunGet( int LimeSDROutput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesink/limesdroutput/limesdroutputthread.h b/plugins/samplesink/limesdroutput/limesdroutputthread.h index 2761f45d5..ec5c4a5c8 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputthread.h +++ b/plugins/samplesink/limesdroutput/limesdroutputthread.h @@ -39,7 +39,7 @@ public: virtual void startWork(); virtual void stopWork(); - virtual void setDeviceSampleRate(int __attribute__((unused)) sampleRate) {} + virtual void setDeviceSampleRate(int sampleRate) { (void) sampleRate; } virtual bool isRunning() { return m_running; } void setLog2Interpolation(unsigned int log2_ioterp); diff --git a/plugins/samplesink/plutosdroutput/plutosdroutput.cpp b/plugins/samplesink/plutosdroutput/plutosdroutput.cpp index 3c81a79a2..54157a930 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutput.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutput.cpp @@ -549,8 +549,9 @@ float PlutoSDROutput::getTemperature() int PlutoSDROutput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -558,8 +559,9 @@ int PlutoSDROutput::webapiRunGet( int PlutoSDROutput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -575,8 +577,9 @@ int PlutoSDROutput::webapiRun( int PlutoSDROutput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setPlutoSdrOutputSettings(new SWGSDRangel::SWGPlutoSdrOutputSettings()); response.getPlutoSdrOutputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -587,8 +590,9 @@ int PlutoSDROutput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; PlutoSDROutputSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -648,8 +652,9 @@ int PlutoSDROutput::webapiSettingsPutPatch( int PlutoSDROutput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setPlutoSdrOutputReport(new SWGSDRangel::SWGPlutoSdrOutputReport()); response.getPlutoSdrOutputReport()->init(); webapiFormatDeviceReport(response); diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp index 731240c46..4d96665e6 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp @@ -129,8 +129,9 @@ bool PlutoSDROutputGUI::deserialize(const QByteArray& data) } } -bool PlutoSDROutputGUI::handleMessage(const Message& message __attribute__((unused))) +bool PlutoSDROutputGUI::handleMessage(const Message& message) { + (void) message; if (PlutoSDROutput::MsgConfigurePlutoSDR::match(message)) { const PlutoSDROutput::MsgConfigurePlutoSDR& cfg = (PlutoSDROutput::MsgConfigurePlutoSDR&) message; diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputthread.h b/plugins/samplesink/plutosdroutput/plutosdroutputthread.h index 45f80e218..080b093bb 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputthread.h +++ b/plugins/samplesink/plutosdroutput/plutosdroutputthread.h @@ -37,7 +37,7 @@ public: virtual void startWork(); virtual void stopWork(); - virtual void setDeviceSampleRate(int sampleRate __attribute__((unused))) {} + virtual void setDeviceSampleRate(int sampleRate) { (void) sampleRate; } virtual bool isRunning() { return m_running; } void setLog2Interpolation(unsigned int log2_interp); diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp index c2607530f..b7eb7e9ff 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp @@ -391,8 +391,9 @@ void SDRdaemonSinkGui::on_dataPort_returnPressed() sendSettings(); } -void SDRdaemonSinkGui::on_apiApplyButton_clicked(bool checked __attribute__((unused))) +void SDRdaemonSinkGui::on_apiApplyButton_clicked(bool checked) { + (void) checked; m_settings.m_apiAddress = ui->apiAddress->text(); bool apiOk; @@ -410,8 +411,9 @@ void SDRdaemonSinkGui::on_apiApplyButton_clicked(bool checked __attribute__((unu m_networkManager->get(m_networkRequest); } -void SDRdaemonSinkGui::on_dataApplyButton_clicked(bool checked __attribute__((unused))) +void SDRdaemonSinkGui::on_dataApplyButton_clicked(bool checked) { + (void) checked; m_settings.m_dataAddress = ui->dataAddress->text(); bool dataOk; @@ -434,8 +436,9 @@ void SDRdaemonSinkGui::on_startStop_toggled(bool checked) } } -void SDRdaemonSinkGui::on_eventCountsReset_clicked(bool checked __attribute__((unused))) +void SDRdaemonSinkGui::on_eventCountsReset_clicked(bool checked) { + (void) checked; m_countUnrecoverable = 0; m_countRecovered = 0; m_time.start(); diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h index 314be9314..4204dfc16 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h @@ -81,7 +81,7 @@ public: void resetToDefaults(); virtual qint64 getCenterFrequency() const { return m_deviceCenterFrequency; } - virtual void setCenterFrequency(qint64 centerFrequency __attribute__((unused))) {} + virtual void setCenterFrequency(qint64 centerFrequency) { (void) centerFrequency; } QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp index 0403c80c2..2e9c39e0c 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp @@ -306,8 +306,9 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b int SDRdaemonSinkOutput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -315,8 +316,9 @@ int SDRdaemonSinkOutput::webapiRunGet( int SDRdaemonSinkOutput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -332,8 +334,9 @@ int SDRdaemonSinkOutput::webapiRun( int SDRdaemonSinkOutput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSdrDaemonSinkSettings(new SWGSDRangel::SWGSDRdaemonSinkSettings()); response.getSdrDaemonSinkSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -344,8 +347,9 @@ int SDRdaemonSinkOutput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; SDRdaemonSinkSettings settings = m_settings; if (deviceSettingsKeys.contains("sampleRate")) { @@ -391,8 +395,9 @@ int SDRdaemonSinkOutput::webapiSettingsPutPatch( int SDRdaemonSinkOutput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSdrDaemonSinkReport(new SWGSDRangel::SWGSDRdaemonSinkReport()); response.getSdrDaemonSinkReport()->init(); webapiFormatDeviceReport(response); diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.h b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.h index 741c6d1bd..93ce45d5e 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.h +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.h @@ -136,7 +136,7 @@ public: virtual const QString& getDeviceDescription() const; virtual int getSampleRate() const; virtual quint64 getCenterFrequency() const; - virtual void setCenterFrequency(qint64 centerFrequency __attribute__((unused))) {} + virtual void setCenterFrequency(qint64 centerFrequency) { (void) centerFrequency; } std::time_t getStartingTimeStamp() const; virtual bool handleMessage(const Message& message); diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index bda2be9e1..17fb49e20 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -599,7 +599,7 @@ QByteArray SoapySDROutput::serialize() const return m_settings.serialize(); } -bool SoapySDROutput::deserialize(const QByteArray& data __attribute__((unused))) +bool SoapySDROutput::deserialize(const QByteArray& data) { bool success = true; diff --git a/plugins/samplesource/airspy/airspyinput.cpp b/plugins/samplesource/airspy/airspyinput.cpp index 7ec2f68f3..111ea4dcc 100644 --- a/plugins/samplesource/airspy/airspyinput.cpp +++ b/plugins/samplesource/airspy/airspyinput.cpp @@ -594,8 +594,9 @@ struct airspy_device *AirspyInput::open_airspy_from_sequence(int sequence) int AirspyInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -603,8 +604,9 @@ int AirspyInput::webapiRunGet( int AirspyInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -620,8 +622,9 @@ int AirspyInput::webapiRun( int AirspyInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAirspySettings(new SWGSDRangel::SWGAirspySettings()); response.getAirspySettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -632,8 +635,9 @@ int AirspyInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; AirspySettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -702,8 +706,9 @@ int AirspyInput::webapiSettingsPutPatch( int AirspyInput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAirspyReport(new SWGSDRangel::SWGAirspyReport()); response.getAirspyReport()->init(); webapiFormatDeviceReport(response); diff --git a/plugins/samplesource/airspyhf/airspyhfinput.cpp b/plugins/samplesource/airspyhf/airspyhfinput.cpp index 1cadfcc39..25b16b437 100644 --- a/plugins/samplesource/airspyhf/airspyhfinput.cpp +++ b/plugins/samplesource/airspyhf/airspyhfinput.cpp @@ -486,8 +486,9 @@ airspyhf_device_t *AirspyHFInput::open_airspyhf_from_serial(const QString& seria int AirspyHFInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAirspyHfSettings(new SWGSDRangel::SWGAirspyHFSettings()); response.getAirspyHfSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -498,8 +499,9 @@ int AirspyHFInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; AirspyHFSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -570,8 +572,9 @@ void AirspyHFInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respo int AirspyHFInput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setAirspyHfReport(new SWGSDRangel::SWGAirspyHFReport()); response.getAirspyHfReport()->init(); webapiFormatDeviceReport(response); @@ -580,8 +583,9 @@ int AirspyHFInput::webapiReportGet( int AirspyHFInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -589,8 +593,9 @@ int AirspyHFInput::webapiRunGet( int AirspyHFInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesource/bladerf1input/bladerf1input.cpp b/plugins/samplesource/bladerf1input/bladerf1input.cpp index 1791772c9..f21349624 100644 --- a/plugins/samplesource/bladerf1input/bladerf1input.cpp +++ b/plugins/samplesource/bladerf1input/bladerf1input.cpp @@ -609,8 +609,9 @@ bladerf_lna_gain Bladerf1Input::getLnaGain(int lnaGain) int Bladerf1Input::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setBladeRf1InputSettings(new SWGSDRangel::SWGBladeRF1InputSettings()); response.getBladeRf1InputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -644,8 +645,9 @@ int Bladerf1Input::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; BladeRF1InputSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -706,8 +708,9 @@ int Bladerf1Input::webapiSettingsPutPatch( int Bladerf1Input::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -715,8 +718,9 @@ int Bladerf1Input::webapiRunGet( int Bladerf1Input::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesource/bladerf2input/bladerf2input.cpp b/plugins/samplesource/bladerf2input/bladerf2input.cpp index 577c4a323..e2c46c04a 100644 --- a/plugins/samplesource/bladerf2input/bladerf2input.cpp +++ b/plugins/samplesource/bladerf2input/bladerf2input.cpp @@ -967,8 +967,9 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo int BladeRF2Input::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setBladeRf2InputSettings(new SWGSDRangel::SWGBladeRF2InputSettings()); response.getBladeRf2InputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -979,8 +980,9 @@ int BladeRF2Input::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; BladeRF2InputSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -1039,8 +1041,9 @@ int BladeRF2Input::webapiSettingsPutPatch( return 200; } -int BladeRF2Input::webapiReportGet(SWGSDRangel::SWGDeviceReport& response, QString& errorMessage __attribute__((unused))) +int BladeRF2Input::webapiReportGet(SWGSDRangel::SWGDeviceReport& response, QString& errorMessage) { + (void) errorMessage; response.setBladeRf2InputReport(new SWGSDRangel::SWGBladeRF2InputReport()); response.getBladeRf2InputReport()->init(); webapiFormatDeviceReport(response); @@ -1123,8 +1126,9 @@ void BladeRF2Input::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respo int BladeRF2Input::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -1132,8 +1136,9 @@ int BladeRF2Input::webapiRunGet( int BladeRF2Input::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesource/fcdpro/fcdprogui.cpp b/plugins/samplesource/fcdpro/fcdprogui.cpp index 20920db13..6928742b1 100644 --- a/plugins/samplesource/fcdpro/fcdprogui.cpp +++ b/plugins/samplesource/fcdpro/fcdprogui.cpp @@ -209,7 +209,7 @@ bool FCDProGui::deserialize(const QByteArray& data) } } -bool FCDProGui::handleMessage(const Message& message __attribute__((unused))) +bool FCDProGui::handleMessage(const Message& message) { if (FCDProInput::MsgConfigureFCDPro::match(message)) { @@ -434,8 +434,9 @@ void FCDProGui::on_gain6_currentIndexChanged(int index) sendSettings(); } -void FCDProGui::on_setDefaults_clicked(bool checked __attribute__((unused))) +void FCDProGui::on_setDefaults_clicked(bool checked) { + (void) checked; m_settings.m_lnaGainIndex = 8; // +15 dB //m_settings.rfFilterIndex = 0; m_settings.m_mixerGainIndex = 1; // +12 dB diff --git a/plugins/samplesource/fcdpro/fcdproinput.cpp b/plugins/samplesource/fcdpro/fcdproinput.cpp index 5059a79fd..03f1ec662 100644 --- a/plugins/samplesource/fcdpro/fcdproinput.cpp +++ b/plugins/samplesource/fcdpro/fcdproinput.cpp @@ -493,8 +493,9 @@ void FCDProInput::set_center_freq(double freq) } -void FCDProInput::set_bias_t(bool on __attribute__((unused))) +void FCDProInput::set_bias_t(bool on) { + (void) on; //quint8 cmd = on ? 1 : 0; // TODO: use FCD Pro controls @@ -749,8 +750,9 @@ void FCDProInput::set_lo_ppm() int FCDProInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -758,8 +760,9 @@ int FCDProInput::webapiRunGet( int FCDProInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -775,8 +778,9 @@ int FCDProInput::webapiRun( int FCDProInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setFcdProSettings(new SWGSDRangel::SWGFCDProSettings()); response.getFcdProSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -787,8 +791,9 @@ int FCDProInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; FCDProSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { diff --git a/plugins/samplesource/fcdproplus/fcdproplusgui.cpp b/plugins/samplesource/fcdproplus/fcdproplusgui.cpp index 210bb4752..e557f160a 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusgui.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusgui.cpp @@ -127,7 +127,7 @@ bool FCDProPlusGui::deserialize(const QByteArray& data) } } -bool FCDProPlusGui::handleMessage(const Message& message __attribute__((unused))) +bool FCDProPlusGui::handleMessage(const Message& message) { if (FCDProPlusInput::MsgConfigureFCDProPlus::match(message)) { diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp index a15a0819e..be4902914 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp @@ -460,8 +460,9 @@ void FCDProPlusInput::set_lo_ppm() int FCDProPlusInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -469,8 +470,9 @@ int FCDProPlusInput::webapiRunGet( int FCDProPlusInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -486,8 +488,9 @@ int FCDProPlusInput::webapiRun( int FCDProPlusInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setFcdProPlusSettings(new SWGSDRangel::SWGFCDProPlusSettings()); response.getFcdProPlusSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -498,8 +501,9 @@ int FCDProPlusInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; FCDProPlusSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { diff --git a/plugins/samplesource/filesource/filesourcegui.cpp b/plugins/samplesource/filesource/filesourcegui.cpp index f19e500dd..700065a27 100644 --- a/plugins/samplesource/filesource/filesourcegui.cpp +++ b/plugins/samplesource/filesource/filesourcegui.cpp @@ -310,8 +310,9 @@ void FileSourceGui::on_navTimeSlider_valueChanged(int value) } } -void FileSourceGui::on_showFileDialog_clicked(bool checked __attribute__((unused))) +void FileSourceGui::on_showFileDialog_clicked(bool checked) { + (void) checked; QString fileName = QFileDialog::getOpenFileName(this, tr("Open I/Q record file"), ".", tr("SDR I/Q Files (*.sdriq)"), 0, QFileDialog::DontUseNativeDialog); diff --git a/plugins/samplesource/filesource/filesourceinput.cpp b/plugins/samplesource/filesource/filesourceinput.cpp index 74f0b4c26..c68d3bbd1 100644 --- a/plugins/samplesource/filesource/filesourceinput.cpp +++ b/plugins/samplesource/filesource/filesourceinput.cpp @@ -409,8 +409,9 @@ bool FileSourceInput::applySettings(const FileSourceSettings& settings, bool for int FileSourceInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setFileSourceSettings(new SWGSDRangel::SWGFileSourceSettings()); response.getFileSourceSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -421,8 +422,9 @@ int FileSourceInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; FileSourceSettings settings = m_settings; if (deviceSettingsKeys.contains("fileName")) { @@ -450,8 +452,9 @@ int FileSourceInput::webapiSettingsPutPatch( int FileSourceInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -459,8 +462,9 @@ int FileSourceInput::webapiRunGet( int FileSourceInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -476,8 +480,9 @@ int FileSourceInput::webapiRun( int FileSourceInput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setFileSourceReport(new SWGSDRangel::SWGFileSourceReport()); response.getFileSourceReport()->init(); webapiFormatDeviceReport(response); diff --git a/plugins/samplesource/hackrfinput/hackrfinput.cpp b/plugins/samplesource/hackrfinput/hackrfinput.cpp index 744119e0c..2e0dc8dc9 100644 --- a/plugins/samplesource/hackrfinput/hackrfinput.cpp +++ b/plugins/samplesource/hackrfinput/hackrfinput.cpp @@ -528,8 +528,9 @@ bool HackRFInput::applySettings(const HackRFInputSettings& settings, bool force) int HackRFInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setHackRfInputSettings(new SWGSDRangel::SWGHackRFInputSettings()); response.getHackRfInputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -540,8 +541,9 @@ int HackRFInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; HackRFInputSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -628,8 +630,9 @@ void HackRFInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& res int HackRFInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -637,8 +640,9 @@ int HackRFInput::webapiRunGet( int HackRFInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index 45add7cdd..bcd8dee34 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -1280,8 +1280,9 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc int LimeSDRInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setLimeSdrInputSettings(new SWGSDRangel::SWGLimeSdrInputSettings()); response.getLimeSdrInputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -1292,8 +1293,9 @@ int LimeSDRInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; LimeSDRInputSettings settings = m_settings; if (deviceSettingsKeys.contains("antennaPath")) { @@ -1409,8 +1411,9 @@ void LimeSDRInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& re int LimeSDRInput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setLimeSdrInputReport(new SWGSDRangel::SWGLimeSdrInputReport()); response.getLimeSdrInputReport()->init(); webapiFormatDeviceReport(response); @@ -1419,8 +1422,9 @@ int LimeSDRInput::webapiReportGet( int LimeSDRInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -1428,8 +1432,9 @@ int LimeSDRInput::webapiRunGet( int LimeSDRInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); diff --git a/plugins/samplesource/limesdrinput/limesdrinputthread.h b/plugins/samplesource/limesdrinput/limesdrinputthread.h index ddf671047..90b09b611 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputthread.h +++ b/plugins/samplesource/limesdrinput/limesdrinputthread.h @@ -39,7 +39,7 @@ public: virtual void startWork(); virtual void stopWork(); - virtual void setDeviceSampleRate(int sampleRate __attribute__((unused))) {} + virtual void setDeviceSampleRate(int sampleRate) { (void) sampleRate; } virtual bool isRunning() { return m_running; } void setLog2Decimation(unsigned int log2_decim); diff --git a/plugins/samplesource/perseus/perseusinput.cpp b/plugins/samplesource/perseus/perseusinput.cpp index aaf431566..67632131e 100644 --- a/plugins/samplesource/perseus/perseusinput.cpp +++ b/plugins/samplesource/perseus/perseusinput.cpp @@ -402,8 +402,9 @@ bool PerseusInput::applySettings(const PerseusSettings& settings, bool force) int PerseusInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -411,8 +412,9 @@ int PerseusInput::webapiRunGet( int PerseusInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -428,8 +430,9 @@ int PerseusInput::webapiRun( int PerseusInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setPerseusSettings(new SWGSDRangel::SWGPerseusSettings()); response.getPerseusSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -440,8 +443,9 @@ int PerseusInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; PerseusSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -495,8 +499,9 @@ int PerseusInput::webapiSettingsPutPatch( int PerseusInput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setPerseusReport(new SWGSDRangel::SWGPerseusReport()); response.getPerseusReport()->init(); webapiFormatDeviceReport(response); diff --git a/plugins/samplesource/perseus/perseusthread.cpp b/plugins/samplesource/perseus/perseusthread.cpp index ec0441a78..217dd6643 100644 --- a/plugins/samplesource/perseus/perseusthread.cpp +++ b/plugins/samplesource/perseus/perseusthread.cpp @@ -111,8 +111,9 @@ void PerseusThread::callback(const uint8_t* buf, qint32 len) m_sampleFifo->write(m_convertBuffer.begin(), it); } -int PerseusThread::rx_callback(void *buf, int buf_size, void *extra __attribute__((unused))) +int PerseusThread::rx_callback(void *buf, int buf_size, void *extra) { + (void) extra; qint32 nbIAndQ = buf_size / 3; // 3 bytes per I or Q m_this->callback((uint8_t*) buf, nbIAndQ); return 0; diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp index 09c2317fc..c56c35a36 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp @@ -619,8 +619,9 @@ float PlutoSDRInput::getTemperature() int PlutoSDRInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -628,8 +629,9 @@ int PlutoSDRInput::webapiRunGet( int PlutoSDRInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -645,8 +647,9 @@ int PlutoSDRInput::webapiRun( int PlutoSDRInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setPlutoSdrInputSettings(new SWGSDRangel::SWGPlutoSdrInputSettings()); response.getPlutoSdrInputSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -657,8 +660,9 @@ int PlutoSDRInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; PlutoSDRInputSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -737,8 +741,9 @@ int PlutoSDRInput::webapiSettingsPutPatch( int PlutoSDRInput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setPlutoSdrInputReport(new SWGSDRangel::SWGPlutoSdrInputReport()); response.getPlutoSdrInputReport()->init(); webapiFormatDeviceReport(response); diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp index 441413b0d..9121a91a0 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp @@ -130,7 +130,7 @@ bool PlutoSDRInputGui::deserialize(const QByteArray& data) } } -bool PlutoSDRInputGui::handleMessage(const Message& message __attribute__((unused))) +bool PlutoSDRInputGui::handleMessage(const Message& message) { if (PlutoSDRInput::MsgConfigurePlutoSDR::match(message)) { diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputthread.h b/plugins/samplesource/plutosdrinput/plutosdrinputthread.h index 4bd285aee..68d2f9bc8 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputthread.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinputthread.h @@ -37,7 +37,7 @@ public: virtual void startWork(); virtual void stopWork(); - virtual void setDeviceSampleRate(int sampleRate __attribute__((unused))) {} + virtual void setDeviceSampleRate(int sampleRate) { (void) sampleRate; } virtual bool isRunning() { return m_running; } void setLog2Decimation(unsigned int log2_decim); void setFcPos(int fcPos); diff --git a/plugins/samplesource/rtlsdr/rtlsdrinput.cpp b/plugins/samplesource/rtlsdr/rtlsdrinput.cpp index 406f104ba..f78765cca 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrinput.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrinput.cpp @@ -536,8 +536,9 @@ void RTLSDRInput::set_ds_mode(int on) int RTLSDRInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setRtlSdrSettings(new SWGSDRangel::SWGRtlSdrSettings()); response.getRtlSdrSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -548,8 +549,9 @@ int RTLSDRInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; RTLSDRSettings settings = m_settings; if (deviceSettingsKeys.contains("agc")) { @@ -638,8 +640,9 @@ void RTLSDRInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& res int RTLSDRInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -647,8 +650,9 @@ int RTLSDRInput::webapiRunGet( int RTLSDRInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -664,8 +668,9 @@ int RTLSDRInput::webapiRun( int RTLSDRInput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setRtlSdrReport(new SWGSDRangel::SWGRtlSdrReport()); response.getRtlSdrReport()->init(); webapiFormatDeviceReport(response); diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp index 2607ff590..c85e42208 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp @@ -163,8 +163,9 @@ qint64 SDRdaemonSourceGui::getCenterFrequency() const return m_streamCenterFrequency; } -void SDRdaemonSourceGui::setCenterFrequency(qint64 centerFrequency __attribute__((unused))) +void SDRdaemonSourceGui::setCenterFrequency(qint64 centerFrequency) { + (void) centerFrequency; } bool SDRdaemonSourceGui::handleMessage(const Message& message) @@ -308,8 +309,9 @@ void SDRdaemonSourceGui::sendSettings() m_updateTimer.start(100); } -void SDRdaemonSourceGui::on_apiApplyButton_clicked(bool checked __attribute__((unused))) +void SDRdaemonSourceGui::on_apiApplyButton_clicked(bool checked) { + (void) checked; m_settings.m_apiAddress = ui->apiAddress->text(); bool ctlOk; @@ -326,8 +328,9 @@ void SDRdaemonSourceGui::on_apiApplyButton_clicked(bool checked __attribute__((u m_networkManager->get(m_networkRequest); } -void SDRdaemonSourceGui::on_dataApplyButton_clicked(bool checked __attribute__((unused))) +void SDRdaemonSourceGui::on_dataApplyButton_clicked(bool checked) { + (void) checked; m_settings.m_dataAddress = ui->dataAddress->text(); bool dataOk; @@ -427,8 +430,9 @@ void SDRdaemonSourceGui::on_record_toggled(bool checked) m_sampleSource->getInputMessageQueue()->push(message); } -void SDRdaemonSourceGui::on_eventCountsReset_clicked(bool checked __attribute__((unused))) +void SDRdaemonSourceGui::on_eventCountsReset_clicked(bool checked) { + (void) checked; m_countUnrecoverable = 0; m_countRecovered = 0; m_eventsTime.start(); diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp index 2718bed46..fa2899f38 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp @@ -134,8 +134,9 @@ quint64 SDRdaemonSourceInput::getCenterFrequency() const return m_SDRdaemonUDPHandler->getCenterFrequency(); } -void SDRdaemonSourceInput::setCenterFrequency(qint64 centerFrequency __attribute__((unused))) +void SDRdaemonSourceInput::setCenterFrequency(qint64 centerFrequency) { + (void) centerFrequency; } std::time_t SDRdaemonSourceInput::getStartingTimeStamp() const @@ -241,8 +242,9 @@ void SDRdaemonSourceInput::applySettings(const SDRdaemonSourceSettings& settings int SDRdaemonSourceInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -250,8 +252,9 @@ int SDRdaemonSourceInput::webapiRunGet( int SDRdaemonSourceInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -267,8 +270,9 @@ int SDRdaemonSourceInput::webapiRun( int SDRdaemonSourceInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSdrDaemonSourceSettings(new SWGSDRangel::SWGSDRdaemonSourceSettings()); response.getSdrDaemonSourceSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -279,8 +283,9 @@ int SDRdaemonSourceInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; SDRdaemonSourceSettings settings = m_settings; if (deviceSettingsKeys.contains("apiAddress")) { @@ -336,8 +341,9 @@ void SDRdaemonSourceInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSett int SDRdaemonSourceInput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSdrDaemonSourceReport(new SWGSDRangel::SWGSDRdaemonSourceReport()); response.getSdrDaemonSourceReport()->init(); webapiFormatDeviceReport(response); diff --git a/plugins/samplesource/sdrplay/sdrplayinput.cpp b/plugins/samplesource/sdrplay/sdrplayinput.cpp index cc970b956..80ff8815a 100644 --- a/plugins/samplesource/sdrplay/sdrplayinput.cpp +++ b/plugins/samplesource/sdrplay/sdrplayinput.cpp @@ -625,8 +625,9 @@ bool SDRPlayInput::setDeviceCenterFrequency(quint64 freq_hz) int SDRPlayInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -634,8 +635,9 @@ int SDRPlayInput::webapiRunGet( int SDRPlayInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -651,8 +653,9 @@ int SDRPlayInput::webapiRun( int SDRPlayInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSdrPlaySettings(new SWGSDRangel::SWGSDRPlaySettings()); response.getSdrPlaySettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -663,8 +666,9 @@ int SDRPlayInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; SDRPlaySettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { @@ -759,8 +763,9 @@ void SDRPlayInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& re int SDRPlayInput::webapiReportGet( SWGSDRangel::SWGDeviceReport& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setSdrPlayReport(new SWGSDRangel::SWGSDRPlayReport()); response.getSdrPlayReport()->init(); webapiFormatDeviceReport(response); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 3b31b221b..67795876e 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -642,8 +642,9 @@ QByteArray SoapySDRInput::serialize() const return s.final(); } -bool SoapySDRInput::deserialize(const QByteArray& data __attribute__((unused))) +bool SoapySDRInput::deserialize(const QByteArray& data) { + (void) data; return false; } @@ -663,7 +664,7 @@ quint64 SoapySDRInput::getCenterFrequency() const return m_settings.m_centerFrequency; } -void SoapySDRInput::setCenterFrequency(qint64 centerFrequency __attribute__((unused))) +void SoapySDRInput::setCenterFrequency(qint64 centerFrequency) { SoapySDRInputSettings settings = m_settings; settings.m_centerFrequency = centerFrequency; @@ -712,7 +713,7 @@ void SoapySDRInput::updateGains(SoapySDR::Device *dev, int requestedChannel, Soa } } -bool SoapySDRInput::handleMessage(const Message& message __attribute__((unused))) +bool SoapySDRInput::handleMessage(const Message& message) { if (MsgConfigureSoapySDRInput::match(message)) { diff --git a/plugins/samplesource/testsource/testsourcegui.cpp b/plugins/samplesource/testsource/testsourcegui.cpp index e91b49dec..ccffc6a25 100644 --- a/plugins/samplesource/testsource/testsourcegui.cpp +++ b/plugins/samplesource/testsource/testsourcegui.cpp @@ -198,16 +198,18 @@ void TestSourceGui::on_sampleSize_currentIndexChanged(int index) sendSettings(); } -void TestSourceGui::on_amplitudeCoarse_valueChanged(int value __attribute__((unused))) +void TestSourceGui::on_amplitudeCoarse_valueChanged(int value) { + (void) value; updateAmpFineLimit(); displayAmplitude(); m_settings.m_amplitudeBits = ui->amplitudeCoarse->value() * 100 + ui->amplitudeFine->value(); sendSettings(); } -void TestSourceGui::on_amplitudeFine_valueChanged(int value __attribute__((unused))) +void TestSourceGui::on_amplitudeFine_valueChanged(int value) { + (void) value; displayAmplitude(); m_settings.m_amplitudeBits = ui->amplitudeCoarse->value() * 100 + ui->amplitudeFine->value(); sendSettings(); diff --git a/plugins/samplesource/testsource/testsourceinput.cpp b/plugins/samplesource/testsource/testsourceinput.cpp index 3d230b2d6..776a1c540 100644 --- a/plugins/samplesource/testsource/testsourceinput.cpp +++ b/plugins/samplesource/testsource/testsourceinput.cpp @@ -388,8 +388,9 @@ bool TestSourceInput::applySettings(const TestSourceSettings& settings, bool for int TestSourceInput::webapiRunGet( SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); return 200; } @@ -397,8 +398,9 @@ int TestSourceInput::webapiRunGet( int TestSourceInput::webapiRun( bool run, SWGSDRangel::SWGDeviceState& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; m_deviceAPI->getDeviceEngineStateStr(*response.getState()); MsgStartStop *message = MsgStartStop::create(run); m_inputMessageQueue.push(message); @@ -414,8 +416,9 @@ int TestSourceInput::webapiRun( int TestSourceInput::webapiSettingsGet( SWGSDRangel::SWGDeviceSettings& response, - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; response.setTestSourceSettings(new SWGSDRangel::SWGTestSourceSettings()); response.getTestSourceSettings()->init(); webapiFormatDeviceSettings(response, m_settings); @@ -426,8 +429,9 @@ int TestSourceInput::webapiSettingsPutPatch( bool force, const QStringList& deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings& response, // query + response - QString& errorMessage __attribute__((unused))) + QString& errorMessage) { + (void) errorMessage; TestSourceSettings settings = m_settings; if (deviceSettingsKeys.contains("centerFrequency")) { diff --git a/sdrbase/dsp/decimatorsu.h b/sdrbase/dsp/decimatorsu.h index 36f897634..26489c1d5 100644 --- a/sdrbase/dsp/decimatorsu.h +++ b/sdrbase/dsp/decimatorsu.h @@ -387,7 +387,7 @@ void DecimatorsU::decimate4_sup(Sampl } template -void DecimatorsU::decimate8_inf(SampleVector::iterator* it, const T* buf __attribute__((unused)), qint32 len) +void DecimatorsU::decimate8_inf(SampleVector::iterator* it, const T* buf, qint32 len) { StorageType buf2[16], buf4[8], buf8[4]; @@ -463,7 +463,7 @@ void DecimatorsU::decimate8_inf(Sampl } template -void DecimatorsU::decimate8_sup(SampleVector::iterator* it, const T* buf __attribute__((unused)), qint32 len) +void DecimatorsU::decimate8_sup(SampleVector::iterator* it, const T* buf, qint32 len) { StorageType buf2[16], buf4[8], buf8[4]; diff --git a/sdrbase/dsp/dspengine.cpp b/sdrbase/dsp/dspengine.cpp index afa9c4453..623d93f39 100644 --- a/sdrbase/dsp/dspengine.cpp +++ b/sdrbase/dsp/dspengine.cpp @@ -134,8 +134,8 @@ void DSPEngine::setDVSerialSupport(bool support) } } #else -void DSPEngine::setDVSerialSupport(bool support __attribute__((unused))) -{} +void DSPEngine::setDVSerialSupport(bool support) +{ (void) support; } #endif bool DSPEngine::hasDVSerialSupport() @@ -153,8 +153,8 @@ void DSPEngine::getDVSerialNames(std::vector& deviceNames) m_dvSerialEngine.getDevicesNames(deviceNames); } #else -void DSPEngine::getDVSerialNames(std::vector& deviceNames __attribute((unused))) -{} +void DSPEngine::getDVSerialNames(std::vector& deviceNames) +{ (void) deviceNames; } #endif #ifdef DSD_USE_SERIALDV @@ -171,12 +171,20 @@ void DSPEngine::pushMbeFrame( } #else void DSPEngine::pushMbeFrame( - const unsigned char *mbeFrame __attribute((unused)), - int mbeRateIndex __attribute((unused)), - int mbeVolumeIndex __attribute((unused)), - unsigned char channels __attribute((unused)), - bool useHP __attribute((unused)), - int upsampling __attribute((unused)), - AudioFifo *audioFifo __attribute((unused))) -{} + const unsigned char *mbeFrame, + int mbeRateIndex, + int mbeVolumeIndex, + unsigned char channels, + bool useHP, + int upsampling, + AudioFifo *audioFifo) +{ + (void) mbeFrame; + (void) mbeRateIndex; + (void) mbeVolumeIndex; + (void) channels; + (void) useHP; + (void) upsampling; + (void) audioFifo; +} #endif From 222aa9f40d9dc2f22954eff3952564cdfb388060 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 10:51:57 +0100 Subject: [PATCH 018/102] Windows: MSVC2017: adapt decimators.h to handle packing with MSVC --- plugins/samplesource/airspy/airspy.pro | 2 + sdrbase/dsp/decimators.h | 114 ++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/plugins/samplesource/airspy/airspy.pro b/plugins/samplesource/airspy/airspy.pro index 5ba6d7050..600b51672 100644 --- a/plugins/samplesource/airspy/airspy.pro +++ b/plugins/samplesource/airspy/airspy.pro @@ -13,6 +13,8 @@ TARGET = inputairspy CONFIG(MINGW32):LIBAIRSPYSRC = "C:\softs\libairspy" CONFIG(MINGW64):LIBAIRSPYSRC = "C:\softs\libairspy" +CONFIG(MSVC):LIBAIRSPYSRC = "C:\softs\libairspy" + INCLUDEPATH += $$PWD INCLUDEPATH += ../../../exports INCLUDEPATH += ../../../sdrbase diff --git a/sdrbase/dsp/decimators.h b/sdrbase/dsp/decimators.h index ee54b56e9..3979d92f8 100644 --- a/sdrbase/dsp/decimators.h +++ b/sdrbase/dsp/decimators.h @@ -184,6 +184,42 @@ struct decimation_shifts<24, 8> static const uint post64 = 0; }; +#ifdef _MSC_VER +#pragma pack(push,1) +template +struct TripleByteLE +{ + uint8_t b0; + uint8_t b1; + uint8_t b2; + + typedef union { +#pragma pack(push,1) + struct { + int32_t i; + }; +#pragma pack(pop) +#pragma pack(push, 1) + struct { + uint8_t i0; + uint8_t i1; + uint8_t i2; + uint8_t i3; + }; +#pragma pack(pop) + } isample; + + operator T() const { + isample s; + s.i0 = 0; + s.i1 = b0; + s.i2 = b1; + s.i3 = b2; + return s.i; + } +}; +#pragma pack(pop) +#else template struct TripleByteLE { @@ -212,7 +248,44 @@ struct TripleByteLE return s.i; } } __attribute__((__packed__)); +#endif +#ifdef _MSC_VER +#pragma pack(push, 1) +template<> +struct TripleByteLE +{ + uint8_t b0; + uint8_t b1; + uint8_t b2; + + typedef union { +#pragma pack(push, 1) + struct { + qint32 i; + }; +#pragma pack(pop) +#pragma pack(push, 1) + struct { + uint8_t i0; + uint8_t i1; + uint8_t i2; + uint8_t i3; + }; +#pragma pack(pop) + } isample; + + operator qint32() const { + isample s; + s.i0 = 0; + s.i1 = b0; + s.i2 = b1; + s.i3 = b2; + return s.i >> 8; + } +}; +#pragma pack(pop) +#else template<> struct TripleByteLE { @@ -241,7 +314,46 @@ struct TripleByteLE return s.i >> 8; } } __attribute__((__packed__)); +#endif +#ifdef _MSC_VER +#pragma pack(push, 1) +template<> +struct TripleByteLE +{ + uint8_t b0; + uint8_t b1; + uint8_t b2; + + typedef union { +#pragma pack(push, 1) + struct { + qint64 i; + }; +#pragma pack(pop) +#pragma pack(push, 1) + struct { + uint32_t ia; + uint8_t i0; + uint8_t i1; + uint8_t i2; + uint8_t i3; + }; +#pragma pack(pop) + } isample; + + operator qint64() const { + isample s; + s.ia = 0; + s.i0 = 0; + s.i1 = b0; + s.i2 = b1; + s.i3 = b2; + return s.i >> 40; + } +}; +#pragma pack(pop) +#else template<> struct TripleByteLE { @@ -272,7 +384,7 @@ struct TripleByteLE return s.i >> 40; } } __attribute__((__packed__)); - +#endif /** Decimators with integer input and integer output */ template From 734e976e67384f4ba07f3349234c71e3655bd9f9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 10:52:41 +0100 Subject: [PATCH 019/102] Windows: MSVC2017: remove export from templated class IntHalfbandFilterEO --- sdrbase/dsp/inthalfbandfiltereo.h | 53 ++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/sdrbase/dsp/inthalfbandfiltereo.h b/sdrbase/dsp/inthalfbandfiltereo.h index a5cff5344..fb598521e 100644 --- a/sdrbase/dsp/inthalfbandfiltereo.h +++ b/sdrbase/dsp/inthalfbandfiltereo.h @@ -26,12 +26,27 @@ #include #include "dsp/dsptypes.h" #include "dsp/hbfiltertraits.h" -#include "export.h" template -class SDRBASE_API IntHalfbandFilterEO { +class IntHalfbandFilterEO { public: - IntHalfbandFilterEO(); + IntHalfbandFilterEO() + { + m_size = HBFIRFilterTraits::hbOrder/2; + + for (int i = 0; i < 2*m_size; i++) + { + m_even[0][i] = 0; + m_even[1][i] = 0; + m_odd[0][i] = 0; + m_odd[1][i] = 0; + m_samples[i][0] = 0; + m_samples[i][1] = 0; + } + + m_ptr = 0; + m_state = 0; + } // downsample by 2, return center part of original spectrum bool workDecimateCenter(Sample* sample) @@ -912,23 +927,23 @@ protected: } }; -template -IntHalfbandFilterEO::IntHalfbandFilterEO() -{ - m_size = HBFIRFilterTraits::hbOrder/2; +//template +//IntHalfbandFilterEO::IntHalfbandFilterEO() +//{ +// m_size = HBFIRFilterTraits::hbOrder/2; - for (int i = 0; i < 2*m_size; i++) - { - m_even[0][i] = 0; - m_even[1][i] = 0; - m_odd[0][i] = 0; - m_odd[1][i] = 0; - m_samples[i][0] = 0; - m_samples[i][1] = 0; - } +// for (int i = 0; i < 2*m_size; i++) +// { +// m_even[0][i] = 0; +// m_even[1][i] = 0; +// m_odd[0][i] = 0; +// m_odd[1][i] = 0; +// m_samples[i][0] = 0; +// m_samples[i][1] = 0; +// } - m_ptr = 0; - m_state = 0; -} +// m_ptr = 0; +// m_state = 0; +//} #endif /* SDRBASE_DSP_INTHALFBANDFILTEREO_H_ */ From 27152dbb143c819930f2a7d14e9475cb3d236614 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 10:55:10 +0100 Subject: [PATCH 020/102] Windows: MSVC2017: remove export from templated class IntHalfbandFilterEOF --- plugins/samplesource/airspyhf/airspyhf.pro | 2 ++ sdrbase/dsp/inthalfbandfiltereof.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/samplesource/airspyhf/airspyhf.pro b/plugins/samplesource/airspyhf/airspyhf.pro index 6f95b2485..9c611a347 100644 --- a/plugins/samplesource/airspyhf/airspyhf.pro +++ b/plugins/samplesource/airspyhf/airspyhf.pro @@ -13,6 +13,8 @@ TARGET = inputairspyhf CONFIG(MINGW32):LIBAIRSPYHFSRC = "C:\softs\airspyhf" CONFIG(MINGW64):LIBAIRSPYHFSRC = "C:\softs\airspyhf" +CONFIG(MSVC):LIBAIRSPYHFSRC = "C:\softs\airspyhf" + INCLUDEPATH += $$PWD INCLUDEPATH += ../../../exports INCLUDEPATH += ../../../sdrbase diff --git a/sdrbase/dsp/inthalfbandfiltereof.h b/sdrbase/dsp/inthalfbandfiltereof.h index 09f188e0a..f6cf12f75 100644 --- a/sdrbase/dsp/inthalfbandfiltereof.h +++ b/sdrbase/dsp/inthalfbandfiltereof.h @@ -29,7 +29,7 @@ #include "export.h" template -class SDRBASE_API IntHalfbandFilterEOF { +class IntHalfbandFilterEOF { public: IntHalfbandFilterEOF(); From 977a2abd908a5b5744a3b7d293d571cfae81a9dd Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 11:08:34 +0100 Subject: [PATCH 021/102] Windows: MSVC2017: adapt hackrfinput plugin module --- devices/hackrf/devicehackrfshared.h | 2 +- plugins/samplesource/hackrfinput/hackrfinput.pro | 2 ++ plugins/samplesource/hackrfinput/hackrfinputthread.cpp | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/devices/hackrf/devicehackrfshared.h b/devices/hackrf/devicehackrfshared.h index 249c30852..6c392b3c2 100644 --- a/devices/hackrf/devicehackrfshared.h +++ b/devices/hackrf/devicehackrfshared.h @@ -23,7 +23,7 @@ class DEVICES_API DeviceHackRFShared { public: - class MsgConfigureFrequencyDelta : public Message + class DEVICES_API MsgConfigureFrequencyDelta : public Message { MESSAGE_CLASS_DECLARATION diff --git a/plugins/samplesource/hackrfinput/hackrfinput.pro b/plugins/samplesource/hackrfinput/hackrfinput.pro index ea5511dc7..573d81165 100644 --- a/plugins/samplesource/hackrfinput/hackrfinput.pro +++ b/plugins/samplesource/hackrfinput/hackrfinput.pro @@ -19,6 +19,8 @@ QMAKE_CXXFLAGS += -std=c++11 CONFIG(MINGW32):LIBHACKRFSRC = "C:\softs\hackrf\host" CONFIG(MINGW64):LIBHACKRFSRC = "C:\softs\hackrf\host" +CONFIG(MSVC):LIBHACKRFSRC = "C:\softs\hackrf\host" + INCLUDEPATH += $$PWD INCLUDEPATH += ../../../exports INCLUDEPATH += ../../../sdrbase diff --git a/plugins/samplesource/hackrfinput/hackrfinputthread.cpp b/plugins/samplesource/hackrfinput/hackrfinputthread.cpp index c0a9dfc57..af3baa502 100644 --- a/plugins/samplesource/hackrfinput/hackrfinputthread.cpp +++ b/plugins/samplesource/hackrfinput/hackrfinputthread.cpp @@ -18,7 +18,6 @@ #include #include -#include #include #include "dsp/samplesinkfifo.h" From b8d894894e5c03852fadc77363164114a116d4c1 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 11:16:49 +0100 Subject: [PATCH 022/102] Windows: MSVC2017: adapt testsource plugin module --- plugins/samplesource/testsource/testsourcethread.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/samplesource/testsource/testsourcethread.cpp b/plugins/samplesource/testsource/testsourcethread.cpp index 0e972b776..7aa56531c 100644 --- a/plugins/samplesource/testsource/testsourcethread.cpp +++ b/plugins/samplesource/testsource/testsourcethread.cpp @@ -14,6 +14,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#define _USE_MATH_DEFINES +#include #include #include #include "testsourcethread.h" From 1a051b41c64785efb43b7920742e12a781f7ca2a Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 11:17:21 +0100 Subject: [PATCH 023/102] Windows: MSVC2017: remove export from templated class IntHalfbandFilterEO1 --- sdrbase/dsp/inthalfbandfiltereo1.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdrbase/dsp/inthalfbandfiltereo1.h b/sdrbase/dsp/inthalfbandfiltereo1.h index 21bc112de..5062984cf 100644 --- a/sdrbase/dsp/inthalfbandfiltereo1.h +++ b/sdrbase/dsp/inthalfbandfiltereo1.h @@ -27,10 +27,9 @@ #include "dsp/dsptypes.h" #include "dsp/hbfiltertraits.h" //#include "dsp/inthalfbandfiltereo1i.h" -#include "export.h" template -class SDRBASE_API IntHalfbandFilterEO1 { +class IntHalfbandFilterEO1 { public: IntHalfbandFilterEO1(); From 71387eb61a22d2548404a161b95d0e90c0c12908 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 11:20:40 +0100 Subject: [PATCH 024/102] Windows: MSVC2017: adapt hackrfoutput plugin module --- plugins/samplesink/hackrfoutput/hackrfoutput.pro | 2 ++ plugins/samplesink/hackrfoutput/hackrfoutputthread.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/samplesink/hackrfoutput/hackrfoutput.pro b/plugins/samplesink/hackrfoutput/hackrfoutput.pro index 3fe253caf..f8c1f1113 100644 --- a/plugins/samplesink/hackrfoutput/hackrfoutput.pro +++ b/plugins/samplesink/hackrfoutput/hackrfoutput.pro @@ -19,6 +19,8 @@ QMAKE_CXXFLAGS += -std=c++11 CONFIG(MINGW32):LIBHACKRFSRC = "C:\softs\hackrf\host" CONFIG(MINGW64):LIBHACKRFSRC = "C:\softs\hackrf\host" +CONFIG(MSVC):LIBHACKRFSRC = "C:\softs\hackrf\host" + INCLUDEPATH += $$PWD INCLUDEPATH += ../../../exports INCLUDEPATH += ../../../sdrbase diff --git a/plugins/samplesink/hackrfoutput/hackrfoutputthread.cpp b/plugins/samplesink/hackrfoutput/hackrfoutputthread.cpp index 0223c33b8..4ed07ec3f 100644 --- a/plugins/samplesink/hackrfoutput/hackrfoutputthread.cpp +++ b/plugins/samplesink/hackrfoutput/hackrfoutputthread.cpp @@ -18,7 +18,6 @@ #include #include -#include #include "dsp/samplesourcefifo.h" From ad9758f541e4ad7bb4c696776f882d4578097210 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 13:06:19 +0100 Subject: [PATCH 025/102] Windows: MSVC2017: adapt sdrdaemoninput plugin module (1) --- cm256cc/cm256cc.pro | 1 + plugins/samplesource/sdrdaemonsource/sdrdaemonsource.pro | 2 ++ plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp | 1 - .../samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp | 1 - 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cm256cc/cm256cc.pro b/cm256cc/cm256cc.pro index 26a533757..6b7aeceb1 100644 --- a/cm256cc/cm256cc.pro +++ b/cm256cc/cm256cc.pro @@ -11,6 +11,7 @@ TARGET = cm256cc CONFIG(MINGW32):LIBCM256CCSRC = "C:\softs\cm256cc" CONFIG(MINGW64):LIBCM256CCSRC = "C:\softs\cm256cc" +CONFIG(MSVC):LIBCM256CCSRC = "C:\softs\cm256cc" CONFIG(macx):LIBCM256CCSRC = "../../deps/cm256cc" INCLUDEPATH += $$LIBCM256CCSRC diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsource.pro b/plugins/samplesource/sdrdaemonsource/sdrdaemonsource.pro index 4bb075cc3..b80841071 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsource.pro +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsource.pro @@ -13,6 +13,7 @@ TARGET = inputsdrdaemonsource CONFIG(MINGW32):LIBCM256CCSRC = "C:\softs\cm256cc" CONFIG(MINGW64):LIBCM256CCSRC = "C:\softs\cm256cc" +CONFIG(MSVC):LIBCM256CCSRC = "C:\softs\cm256cc" CONFIG(macx):LIBCM256CCSRC = "../../../../deps/cm256cc" INCLUDEPATH += $$PWD @@ -36,6 +37,7 @@ CONFIG(Debug):build_subdir = debug CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\boost_1_66_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(macx):INCLUDEPATH += "../../../boost_1_64_0" SOURCES += sdrdaemonsourcebuffer.cpp\ diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp index fa2899f38..d93f5aef7 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp @@ -16,7 +16,6 @@ #include #include -#include #include #include "SWGDeviceSettings.h" diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp index 399ca525e..c679289f9 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include "dsp/dspcommands.h" #include "dsp/dspengine.h" From ec2bf7a57df392039d536fe4d13a90f0fa065603 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 13:19:54 +0100 Subject: [PATCH 026/102] New time utility class using std::chrono --- sdrbase/CMakeLists.txt | 2 ++ sdrbase/commands/command.cpp | 17 ++++------------- sdrbase/commands/command.h | 2 -- sdrbase/sdrbase.pro | 2 ++ sdrbase/util/timeutil.cpp | 27 +++++++++++++++++++++++++++ sdrbase/util/timeutil.h | 26 ++++++++++++++++++++++++++ 6 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 sdrbase/util/timeutil.cpp create mode 100644 sdrbase/util/timeutil.h diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index 9613b434a..1040d5948 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -81,6 +81,7 @@ set(sdrbase_SOURCES util/simpleserializer.cpp #util/spinlock.cpp util/uid.cpp + util/timeutil.cpp plugin/plugininterface.cpp plugin/pluginapi.cpp @@ -204,6 +205,7 @@ set(sdrbase_HEADERS util/simpleserializer.h #util/spinlock.h util/uid.h + util/timeutil.h webapi/webapiadapterinterface.h webapi/webapirequestmapper.h diff --git a/sdrbase/commands/command.cpp b/sdrbase/commands/command.cpp index d1d52c2d9..e9199b4b9 100644 --- a/sdrbase/commands/command.cpp +++ b/sdrbase/commands/command.cpp @@ -21,6 +21,7 @@ #include "command.h" #include "util/simpleserializer.h" +#include "util/timeutil.h" Command::Command() : m_currentProcess(nullptr), @@ -200,7 +201,7 @@ void Command::run(const QString& apiAddress, int apiPort, int deviceSetIndex) connect(m_currentProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState))); m_currentProcess->setProcessChannelMode(QProcess::MergedChannels); - m_currentProcessStartTimeStampms = nowms(); + m_currentProcessStartTimeStampms = TimeUtil::nowms(); m_currentProcess->start(m_currentProcessCommandLine); } @@ -256,7 +257,7 @@ void Command::processStateChanged(QProcess::ProcessState newState) void Command::processError(QProcess::ProcessError error) { //qDebug("Command::processError: %d state: %d", error, m_currentProcessState); - m_currentProcessFinishTimeStampms = nowms(); + m_currentProcessFinishTimeStampms = TimeUtil::nowms(); m_currentProcessError = error; m_isInError = true; @@ -280,7 +281,7 @@ void Command::processError(QProcess::ProcessError error) void Command::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { //qDebug("Command::processFinished: (%d) %d", exitCode, exitStatus); - m_currentProcessFinishTimeStampms = nowms(); + m_currentProcessFinishTimeStampms = TimeUtil::nowms(); m_currentProcessExitCode = exitCode; m_currentProcessExitStatus = exitStatus; m_hasExited = true; @@ -297,13 +298,3 @@ void Command::processFinished(int exitCode, QProcess::ExitStatus exitStatus) m_currentProcess->deleteLater(); // make sure other threads can still access it until all events have been processed m_currentProcess = nullptr; // for this thread it can assume it was deleted } - -uint64_t Command::nowms() -{ - auto now = std::chrono::system_clock::now(); - auto now_ms = std::chrono::time_point_cast(now); - auto epoch = now_ms.time_since_epoch(); - auto value = std::chrono::duration_cast(epoch); - - return value.count(); -} \ No newline at end of file diff --git a/sdrbase/commands/command.h b/sdrbase/commands/command.h index 92e628ead..baae07f71 100644 --- a/sdrbase/commands/command.h +++ b/sdrbase/commands/command.h @@ -91,8 +91,6 @@ public: } private: - uint64_t nowms(); //!< Get now time in milliseconds - QString m_group; QString m_description; QString m_command; diff --git a/sdrbase/sdrbase.pro b/sdrbase/sdrbase.pro index 2cb0d17e4..eb6eed3f8 100644 --- a/sdrbase/sdrbase.pro +++ b/sdrbase/sdrbase.pro @@ -122,6 +122,7 @@ SOURCES += audio/audiodevicemanager.cpp\ util/samplesourceserializer.cpp\ util/simpleserializer.cpp\ util/uid.cpp\ + util/timeutil.cpp\ plugin/plugininterface.cpp\ plugin/pluginapi.cpp\ plugin/pluginmanager.cpp\ @@ -220,6 +221,7 @@ HEADERS += audio/audiodevicemanager.h\ util/samplesourceserializer.h\ util/simpleserializer.h\ util/uid.h\ + util/timeutil.h\ webapi/webapiadapterinterface.h\ webapi/webapirequestmapper.h\ webapi/webapiserver.h\ diff --git a/sdrbase/util/timeutil.cpp b/sdrbase/util/timeutil.cpp new file mode 100644 index 000000000..ce405bcc8 --- /dev/null +++ b/sdrbase/util/timeutil.cpp @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "timeutil.h" + +uint64_t TimeUtil::nowms() +{ + auto now = std::chrono::system_clock::now(); + auto now_ms = std::chrono::time_point_cast(now); + auto epoch = now_ms.time_since_epoch(); + auto value = std::chrono::duration_cast(epoch); + + return value.count(); +} diff --git a/sdrbase/util/timeutil.h b/sdrbase/util/timeutil.h new file mode 100644 index 000000000..cd983a8d7 --- /dev/null +++ b/sdrbase/util/timeutil.h @@ -0,0 +1,26 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "export.h" + +class SDRBASE_API TimeUtil +{ +public: + static uint64_t nowms(); //!< returns the current epoch in milliseconds +}; From 5167aecb6a243327384c132c7cd3a145b3c4c60c Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 13:45:55 +0100 Subject: [PATCH 027/102] SDRDaemon input: use timestamps in milliseconds directly --- .../sdrdaemonsource/sdrdaemonsourcebuffer.h | 1 + .../sdrdaemonsource/sdrdaemonsourcegui.cpp | 15 +++------ .../sdrdaemonsource/sdrdaemonsourcegui.h | 4 +-- .../sdrdaemonsource/sdrdaemonsourceinput.cpp | 3 +- .../sdrdaemonsource/sdrdaemonsourceinput.h | 33 +++++++------------ .../sdrdaemonsourceudphandler.cpp | 12 +++---- .../sdrdaemonsourceudphandler.h | 6 ++-- 7 files changed, 26 insertions(+), 48 deletions(-) diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcebuffer.h b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcebuffer.h index 405ad38ce..6c660d5e3 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcebuffer.h +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcebuffer.h @@ -45,6 +45,7 @@ public: // samples timestamp uint32_t getTVOutSec() const { return m_tvOut_sec; } uint32_t getTVOutUsec() const { return m_tvOut_usec; } + uint64_t getTVOutMSec() const { return (m_tvOut_sec * 1000LL) + (m_tvOut_usec/ 1000LL); } // stats diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp index c85e42208..4b05bbc0c 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp @@ -71,8 +71,7 @@ SDRdaemonSourceGui::SDRdaemonSourceGui(DeviceUISet *deviceUISet, QWidget* parent m_paletteGreenText.setColor(QPalette::WindowText, Qt::green); m_paletteWhiteText.setColor(QPalette::WindowText, Qt::white); - m_startingTimeStamp.tv_sec = 0; - m_startingTimeStamp.tv_usec = 0; + m_startingTimeStampms = 0; ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); @@ -187,20 +186,17 @@ bool SDRdaemonSourceGui::handleMessage(const Message& message) } else if (SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamData::match(message)) { - m_startingTimeStamp.tv_sec = ((SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamData&)message).get_tv_sec(); - m_startingTimeStamp.tv_usec = ((SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamData&)message).get_tv_usec(); + m_startingTimeStampms = ((SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamData&)message).get_tv_msec(); qDebug() << "SDRdaemonSourceGui::handleMessage: SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamData: " - << " : " << m_startingTimeStamp.tv_sec - << " : " << m_startingTimeStamp.tv_usec; + << " : " << m_startingTimeStampms << " ms"; updateWithStreamTime(); return true; } else if (SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamTiming::match(message)) { - m_startingTimeStamp.tv_sec = ((SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamTiming&)message).get_tv_sec(); - m_startingTimeStamp.tv_usec = ((SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamTiming&)message).get_tv_usec(); + m_startingTimeStampms = ((SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamTiming&)message).get_tv_msec(); m_framesDecodingStatus = ((SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamTiming&)message).getFramesDecodingStatus(); m_allBlocksReceived = ((SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamTiming&)message).allBlocksReceived(); m_bufferLengthInSecs = ((SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamTiming&)message).getBufferLengthInSecs(); @@ -464,8 +460,7 @@ void SDRdaemonSourceGui::updateWithAcquisition() void SDRdaemonSourceGui::updateWithStreamTime() { bool updateEventCounts = false; - quint64 startingTimeStampMsec = ((quint64) m_startingTimeStamp.tv_sec * 1000LL) + ((quint64) m_startingTimeStamp.tv_usec / 1000LL); - QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec); + QDateTime dt = QDateTime::fromMSecsSinceEpoch(m_startingTimeStampms); QString s_date = dt.toString("yyyy-MM-dd HH:mm:ss.zzz"); ui->absTimeText->setText(s_date); diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.h b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.h index 457705f5a..92d6a8147 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.h +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.h @@ -17,8 +17,6 @@ #ifndef INCLUDE_SDRDAEMONSOURCEGUI_H #define INCLUDE_SDRDAEMONSOURCEGUI_H -#include - #include #include #include @@ -72,7 +70,7 @@ private: // int m_sampleRate; // quint64 m_centerFrequency; - struct timeval m_startingTimeStamp; + uint64_t m_startingTimeStampms; int m_framesDecodingStatus; bool m_allBlocksReceived; float m_bufferLengthInSecs; diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp index d93f5aef7..566130e8b 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.cpp @@ -355,8 +355,7 @@ void SDRdaemonSourceInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport response.getSdrDaemonSourceReport()->setSampleRate(m_SDRdaemonUDPHandler->getSampleRate()); response.getSdrDaemonSourceReport()->setBufferRwBalance(m_SDRdaemonUDPHandler->getBufferGauge()); - quint64 startingTimeStampMsec = ((quint64) m_SDRdaemonUDPHandler->getTVSec() * 1000LL) + ((quint64) m_SDRdaemonUDPHandler->getTVuSec() / 1000LL); - QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec); + QDateTime dt = QDateTime::fromMSecsSinceEpoch(m_SDRdaemonUDPHandler->getTVmSec()); response.getSdrDaemonSourceReport()->setDaemonTimestamp(new QString(dt.toString("yyyy-MM-dd HH:mm:ss.zzz"))); response.getSdrDaemonSourceReport()->setMinNbBlocks(m_SDRdaemonUDPHandler->getMinNbBlocks()); diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.h b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.h index 077a2b1ac..3f5c09a29 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.h +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceinput.h @@ -99,26 +99,23 @@ public: public: int getSampleRate() const { return m_sampleRate; } quint64 getCenterFrequency() const { return m_centerFrequency; } - uint32_t get_tv_sec() const { return m_tv_sec; } - uint32_t get_tv_usec() const { return m_tv_usec; } + uint32_t get_tv_msec() const { return m_tv_msec; } - static MsgReportSDRdaemonSourceStreamData* create(int sampleRate, quint64 centerFrequency, uint32_t tv_sec, uint32_t tv_usec) + static MsgReportSDRdaemonSourceStreamData* create(int sampleRate, quint64 centerFrequency, uint64_t tv_msec) { - return new MsgReportSDRdaemonSourceStreamData(sampleRate, centerFrequency, tv_sec, tv_usec); + return new MsgReportSDRdaemonSourceStreamData(sampleRate, centerFrequency, tv_msec); } protected: int m_sampleRate; quint64 m_centerFrequency; - uint32_t m_tv_sec; - uint32_t m_tv_usec; + uint64_t m_tv_msec; - MsgReportSDRdaemonSourceStreamData(int sampleRate, quint64 centerFrequency, uint32_t tv_sec, uint32_t tv_usec) : + MsgReportSDRdaemonSourceStreamData(int sampleRate, quint64 centerFrequency, uint64_t tv_msec) : Message(), m_sampleRate(sampleRate), m_centerFrequency(centerFrequency), - m_tv_sec(tv_sec), - m_tv_usec(tv_usec) + m_tv_msec(tv_msec) { } }; @@ -126,8 +123,7 @@ public: MESSAGE_CLASS_DECLARATION public: - uint32_t get_tv_sec() const { return m_tv_sec; } - uint32_t get_tv_usec() const { return m_tv_usec; } + uint64_t get_tv_msec() const { return m_tv_msec; } int getFramesDecodingStatus() const { return m_framesDecodingStatus; } bool allBlocksReceived() const { return m_allBlocksReceived; } float getBufferLengthInSecs() const { return m_bufferLenSec; } @@ -143,8 +139,7 @@ public: int getSampleBits() const { return m_sampleBits; } int getSampleBytes() const { return m_sampleBytes; } - static MsgReportSDRdaemonSourceStreamTiming* create(uint32_t tv_sec, - uint32_t tv_usec, + static MsgReportSDRdaemonSourceStreamTiming* create(uint64_t tv_msec, float bufferLenSec, int32_t bufferGauge, int framesDecodingStatus, @@ -160,8 +155,7 @@ public: int sampleBits, int sampleBytes) { - return new MsgReportSDRdaemonSourceStreamTiming(tv_sec, - tv_usec, + return new MsgReportSDRdaemonSourceStreamTiming(tv_msec, bufferLenSec, bufferGauge, framesDecodingStatus, @@ -179,8 +173,7 @@ public: } protected: - uint32_t m_tv_sec; - uint32_t m_tv_usec; + uint64_t m_tv_msec; int m_framesDecodingStatus; bool m_allBlocksReceived; float m_bufferLenSec; @@ -196,8 +189,7 @@ public: int m_sampleBits; int m_sampleBytes; - MsgReportSDRdaemonSourceStreamTiming(uint32_t tv_sec, - uint32_t tv_usec, + MsgReportSDRdaemonSourceStreamTiming(uint64_t tv_msec, float bufferLenSec, int32_t bufferGauge, int framesDecodingStatus, @@ -213,8 +205,7 @@ public: int sampleBits, int sampleBytes) : Message(), - m_tv_sec(tv_sec), - m_tv_usec(tv_usec), + m_tv_msec(tv_msec), m_framesDecodingStatus(framesDecodingStatus), m_allBlocksReceived(allBlocksReceived), m_bufferLenSec(bufferLenSec), diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp index c679289f9..d24579eaa 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp @@ -41,8 +41,7 @@ SDRdaemonSourceUDPHandler::SDRdaemonSourceUDPHandler(SampleSinkFifo *sampleFifo, m_sampleFifo(sampleFifo), m_samplerate(0), m_centerFrequency(0), - m_tv_sec(0), - m_tv_usec(0), + m_tv_msec(0), m_outputMessageQueueToGUI(0), m_tickCount(0), m_samplesCount(0), @@ -179,8 +178,7 @@ void SDRdaemonSourceUDPHandler::processData() const SDRDaemonMetaDataFEC& metaData = m_sdrDaemonBuffer.getCurrentMeta(); bool change = false; - m_tv_sec = m_sdrDaemonBuffer.getTVOutSec(); - m_tv_usec = m_sdrDaemonBuffer.getTVOutUsec(); + m_tv_msec = m_sdrDaemonBuffer.getTVOutMSec(); if (m_centerFrequency != metaData.m_centerFrequency) { @@ -206,8 +204,7 @@ void SDRdaemonSourceUDPHandler::processData() SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamData *report = SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamData::create( m_samplerate, m_centerFrequency * 1000, // Frequency in Hz for the GUI - m_tv_sec, - m_tv_usec); + m_tv_msec); m_outputMessageQueueToGUI->push(report); } @@ -343,8 +340,7 @@ void SDRdaemonSourceUDPHandler::tick() } SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamTiming *report = SDRdaemonSourceInput::MsgReportSDRdaemonSourceStreamTiming::create( - m_tv_sec, - m_tv_usec, + m_tv_msec, m_sdrDaemonBuffer.getBufferLengthInSecs(), m_sdrDaemonBuffer.getBufferGauge(), framesDecodingStatus, diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.h b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.h index 6abc6b03f..23b335f24 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.h +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.h @@ -48,8 +48,7 @@ public: int getSampleRate() const { return m_samplerate; } int getCenterFrequency() const { return m_centerFrequency * 1000; } int getBufferGauge() const { return m_sdrDaemonBuffer.getBufferGauge(); } - uint32_t getTVSec() const { return m_tv_sec; } - uint32_t getTVuSec() const { return m_tv_usec; } + uint64_t getTVmSec() const { return m_tv_msec; } int getMinNbBlocks() { return m_sdrDaemonBuffer.getMinNbBlocks(); } int getMaxNbRecovery() { return m_sdrDaemonBuffer.getMaxNbRecovery(); } public slots: @@ -72,8 +71,7 @@ private: SampleSinkFifo *m_sampleFifo; uint32_t m_samplerate; uint32_t m_centerFrequency; - uint32_t m_tv_sec; - uint32_t m_tv_usec; + uint64_t m_tv_msec; MessageQueue *m_outputMessageQueueToGUI; uint32_t m_tickCount; std::size_t m_samplesCount; From be6e9a0bb4a901ba2c864574e08337c7a8c78993 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 14:08:41 +0100 Subject: [PATCH 028/102] Windows: MSVC2017: adapt sdrdaemoninput plugin module (2) --- cm256cc/cm256cc.pro | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cm256cc/cm256cc.pro b/cm256cc/cm256cc.pro index 6b7aeceb1..67c59ca7a 100644 --- a/cm256cc/cm256cc.pro +++ b/cm256cc/cm256cc.pro @@ -9,6 +9,8 @@ QT += core TEMPLATE = lib TARGET = cm256cc +CONFIG(MSVC):DEFINES += cm256cc_EXPORTS + CONFIG(MINGW32):LIBCM256CCSRC = "C:\softs\cm256cc" CONFIG(MINGW64):LIBCM256CCSRC = "C:\softs\cm256cc" CONFIG(MSVC):LIBCM256CCSRC = "C:\softs\cm256cc" @@ -27,4 +29,5 @@ SOURCES = $$LIBCM256CCSRC/gf256.cpp\ $$LIBCM256CCSRC/cm256.cpp HEADERS = $$LIBCM256CCSRC/gf256.h\ -$$LIBCM256CCSRC/cm256.h +$$LIBCM256CCSRC/cm256.h\ +$$LIBCM256CCSRC/export.h From 83069dec63232d22ce168d4d34864af7a6a5e826 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 14:21:36 +0100 Subject: [PATCH 029/102] SDRDaemon output: removed dependency on sys/time.h and unistd.h --- .../samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp | 11 ++++------- .../samplesink/sdrdaemonsink/sdrdaemonsinkthread.cpp | 6 +++--- .../samplesink/sdrdaemonsink/sdrdaemonsinkthread.h | 2 +- plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp | 10 ++++------ sdrbase/util/timeutil.cpp | 10 ++++++++++ sdrbase/util/timeutil.h | 1 + 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp index 2e9c39e0c..7f9c9ab62 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp @@ -14,7 +14,6 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include #include #include #include @@ -420,9 +419,9 @@ void SDRdaemonSinkOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSetti void SDRdaemonSinkOutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response) { - struct timeval tv; + uint64_t ts_usecs; response.getSdrDaemonSinkReport()->setBufferRwBalance(m_sampleSourceFifo.getRWBalance()); - response.getSdrDaemonSinkReport()->setSampleCount(m_sdrDaemonSinkThread ? (int) m_sdrDaemonSinkThread->getSamplesCount(tv) : 0); + response.getSdrDaemonSinkReport()->setSampleCount(m_sdrDaemonSinkThread ? (int) m_sdrDaemonSinkThread->getSamplesCount(ts_usecs) : 0); } void SDRdaemonSinkOutput::tick() @@ -504,8 +503,8 @@ void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject) } uint32_t sampleCountDelta, sampleCount; - struct timeval tv; - sampleCount = m_sdrDaemonSinkThread->getSamplesCount(tv); + uint64_t timestampUs; + sampleCount = m_sdrDaemonSinkThread->getSamplesCount(timestampUs); if (sampleCount < m_lastSampleCount) { sampleCountDelta = (0xFFFFFFFFU - m_lastSampleCount) + sampleCount + 1; @@ -513,8 +512,6 @@ void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject) sampleCountDelta = sampleCount - m_lastSampleCount; } - uint64_t timestampUs = tv.tv_sec*1000000ULL + tv.tv_usec; - // on initial state wait for queue stabilization if ((m_lastRemoteTimestampRateCorrection == 0) && (queueLength >= m_lastQueueLength-1) && (queueLength <= m_lastQueueLength+1)) { diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.cpp b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.cpp index bbe966cb8..a412b7efb 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.cpp +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.cpp @@ -14,7 +14,6 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include #include #include #include @@ -22,6 +21,7 @@ #include #include "dsp/samplesourcefifo.h" +#include "util/timeutil.h" #include "sdrdaemonsinkthread.h" SDRdaemonSinkThread::SDRdaemonSinkThread(SampleSourceFifo* sampleFifo, QObject* parent) : @@ -140,8 +140,8 @@ void SDRdaemonSinkThread::tick() } } -uint32_t SDRdaemonSinkThread::getSamplesCount(struct timeval& tv) const +uint32_t SDRdaemonSinkThread::getSamplesCount(uint64_t& ts_usecs) const { - gettimeofday(&tv, 0); + ts_usecs = TimeUtil::nowus(); return m_samplesCount; } diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.h b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.h index e6a2fd91a..af6f09440 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.h +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.h @@ -55,7 +55,7 @@ public: bool isRunning() const { return m_running; } - uint32_t getSamplesCount(struct timeval& tv) const; + uint32_t getSamplesCount(uint64_t& ts_usecs) const; void setSamplesCount(int samplesCount) { m_samplesCount = samplesCount; } void setChunkCorrection(int chunkCorrection) { m_chunkCorrection = chunkCorrection; } diff --git a/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp b/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp index cd1b6fb0f..14b9ef820 100644 --- a/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp +++ b/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp @@ -16,11 +16,10 @@ #include -#include -#include #include #include +#include "util/timeutil.h" #include "udpsinkfec.h" #include "udpsinkfecworker.h" @@ -118,10 +117,9 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk if (m_txBlockIndex == 0) // Tx block index 0 is a block with only meta data { - struct timeval tv; SDRDaemonMetaDataFEC metaData; - gettimeofday(&tv, 0); + uint64_t ts_usecs = TimeUtil::nowus(); metaData.m_centerFrequency = 0; // frequency not set by stream metaData.m_sampleRate = m_sampleRate; @@ -129,8 +127,8 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk metaData.m_sampleBits = SDR_RX_SAMP_SZ; metaData.m_nbOriginalBlocks = m_nbOriginalBlocks; metaData.m_nbFECBlocks = m_nbBlocksFEC; - metaData.m_tv_sec = tv.tv_sec; - metaData.m_tv_usec = tv.tv_usec; + metaData.m_tv_sec = ts_usecs / 1000000UL; + metaData.m_tv_usec = ts_usecs % 1000000UL; boost::crc_32_type crc32; crc32.process_bytes(&metaData, 20); diff --git a/sdrbase/util/timeutil.cpp b/sdrbase/util/timeutil.cpp index ce405bcc8..a4caa9739 100644 --- a/sdrbase/util/timeutil.cpp +++ b/sdrbase/util/timeutil.cpp @@ -25,3 +25,13 @@ uint64_t TimeUtil::nowms() return value.count(); } + +uint64_t TimeUtil::nowus() +{ + auto now = std::chrono::system_clock::now(); + auto now_ms = std::chrono::time_point_cast(now); + auto epoch = now_ms.time_since_epoch(); + auto value = std::chrono::duration_cast(epoch); + + return value.count(); +} diff --git a/sdrbase/util/timeutil.h b/sdrbase/util/timeutil.h index cd983a8d7..fa2303205 100644 --- a/sdrbase/util/timeutil.h +++ b/sdrbase/util/timeutil.h @@ -23,4 +23,5 @@ class SDRBASE_API TimeUtil { public: static uint64_t nowms(); //!< returns the current epoch in milliseconds + static uint64_t nowus(); //!< returns the current epoch in microseconds }; From 28bf2578fa6212701acf73edc4ef118dd8746dc7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 14:29:27 +0100 Subject: [PATCH 030/102] Windows: MSVC2017: adapt sdrdaemonoutput plugin module --- plugins/samplesink/sdrdaemonsink/sdrdaemonsink.pro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsink.pro b/plugins/samplesink/sdrdaemonsink/sdrdaemonsink.pro index 51a2d307a..b70d7a122 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsink.pro +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsink.pro @@ -13,6 +13,7 @@ TARGET = outputsdrdaemonsink CONFIG(MINGW32):LIBCM256CCSRC = "C:\softs\cm256cc" CONFIG(MINGW64):LIBCM256CCSRC = "C:\softs\cm256cc" +CONFIG(MSVC):LIBCM256CCSRC = "C:\softs\cm256cc" CONFIG(macx):LIBCM256CCSRC = "../../../../deps/cm256cc" INCLUDEPATH += $$PWD @@ -36,6 +37,7 @@ CONFIG(Debug):build_subdir = debug CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\boost_1_66_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(macx):INCLUDEPATH += "../../../boost_1_64_0" SOURCES += sdrdaemonsinkthread.cpp\ From 2fa57d45f50c685a95f5780abd3bb3f62144aa9c Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 14:31:16 +0100 Subject: [PATCH 031/102] Windows: MSVC2017: main libraries and sample source/sinks setup --- sdrangel.windows.pro | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sdrangel.windows.pro b/sdrangel.windows.pro index a27c13f78..fae8ea587 100644 --- a/sdrangel.windows.pro +++ b/sdrangel.windows.pro @@ -28,25 +28,25 @@ SUBDIRS += librtlsdr SUBDIRS += devices SUBDIRS += mbelib SUBDIRS += dsdcc -#SUBDIRS += cm256cc +CONFIG(MSVC):SUBDIRS += cm256cc SUBDIRS += plugins/samplesource/airspy SUBDIRS += plugins/samplesource/airspyhf -SUBDIRS += plugins/samplesource/bladerf1input -SUBDIRS += plugins/samplesource/bladerf2input +CONFIG(!MSVC):SUBDIRS += plugins/samplesource/bladerf1input +CONFIG(!MSVC):SUBDIRS += plugins/samplesource/bladerf2input SUBDIRS += plugins/samplesource/filesource SUBDIRS += plugins/samplesource/hackrfinput -SUBDIRS += plugins/samplesource/limesdrinput +CONFIG(!MSVC):SUBDIRS += plugins/samplesource/limesdrinput CONFIG(!MSVC):SUBDIRS += plugins/samplesource/plutosdrinput -#SUBDIRS += plugins/samplesource/sdrdaemonsource +CONFIG(MSVC):SUBDIRS += plugins/samplesource/sdrdaemonsource SUBDIRS += plugins/samplesource/rtlsdr SUBDIRS += plugins/samplesource/testsource SUBDIRS += plugins/samplesink/filesink -SUBDIRS += plugins/samplesink/bladerf1output -SUBDIRS += plugins/samplesink/bladerf2output +CONFIG(!MSVC):SUBDIRS += plugins/samplesink/bladerf1output +CONFIG(!MSVC):SUBDIRS += plugins/samplesink/bladerf2output SUBDIRS += plugins/samplesink/hackrfoutput -SUBDIRS += plugins/samplesink/limesdroutput +CONFIG(!MSVC):SUBDIRS += plugins/samplesink/limesdroutput CONFIG(!MSVC):SUBDIRS += plugins/samplesink/plutosdroutput -#SUBDIRS += plugins/samplesink/sdrdaemonsink +CONFIG(MSVC):SUBDIRS += plugins/samplesink/sdrdaemonsink SUBDIRS += plugins/channelrx/chanalyzer SUBDIRS += plugins/channelrx/demodam SUBDIRS += plugins/channelrx/demodatv From 1dc466e60440c8dd3edd823fbee8870efa358c0d Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 16:02:26 +0100 Subject: [PATCH 032/102] Windows: MSVC2017: adapt channel analyzer, AM and ATV demods plugin modules --- plugins/channelrx/chanalyzer/chanalyzer.pro | 1 + plugins/channelrx/demodatv/demodatv.pro | 1 + plugins/channelrx/demodbfm/demodbfm.pro | 1 + sdrbase/dsp/downchannelizer.h | 2 +- sdrbase/dsp/interpolator.h | 3 --- sdrgui/gui/tvscreen.h | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/channelrx/chanalyzer/chanalyzer.pro b/plugins/channelrx/chanalyzer/chanalyzer.pro index e2209802a..14377d5b9 100644 --- a/plugins/channelrx/chanalyzer/chanalyzer.pro +++ b/plugins/channelrx/chanalyzer/chanalyzer.pro @@ -25,6 +25,7 @@ INCLUDEPATH += ../../../sdrgui CONFIG(ANDROID):INCLUDEPATH += /opt/softs/boost_1_60_0 CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\boost_1_66_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(macx):INCLUDEPATH += "../../../../../boost_1_64_0" CONFIG(Release):build_subdir = release diff --git a/plugins/channelrx/demodatv/demodatv.pro b/plugins/channelrx/demodatv/demodatv.pro index decef5410..aa5fce3d4 100644 --- a/plugins/channelrx/demodatv/demodatv.pro +++ b/plugins/channelrx/demodatv/demodatv.pro @@ -27,6 +27,7 @@ CONFIG(Debug):build_subdir = debug CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\boost_1_66_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(macx):INCLUDEPATH += "../../../../../boost_1_64_0" SOURCES += atvdemod.cpp\ diff --git a/plugins/channelrx/demodbfm/demodbfm.pro b/plugins/channelrx/demodbfm/demodbfm.pro index 8f7d6bea1..efb129f79 100644 --- a/plugins/channelrx/demodbfm/demodbfm.pro +++ b/plugins/channelrx/demodbfm/demodbfm.pro @@ -26,6 +26,7 @@ INCLUDEPATH += ../../../swagger/sdrangel/code/qt5/client CONFIG(ANDROID):INCLUDEPATH += /opt/softs/boost_1_60_0 CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\boost_1_66_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(macx):INCLUDEPATH += "../../../../../boost_1_64_0" CONFIG(Release):build_subdir = release diff --git a/sdrbase/dsp/downchannelizer.h b/sdrbase/dsp/downchannelizer.h index 3e5059154..d67f3b4de 100644 --- a/sdrbase/dsp/downchannelizer.h +++ b/sdrbase/dsp/downchannelizer.h @@ -32,7 +32,7 @@ class MessageQueue; class SDRBASE_API DownChannelizer : public BasebandSampleSink { Q_OBJECT public: - class MsgChannelizerNotification : public Message { + class SDRBASE_API MsgChannelizerNotification : public Message { MESSAGE_CLASS_DECLARATION public: diff --git a/sdrbase/dsp/interpolator.h b/sdrbase/dsp/interpolator.h index 607b3fe97..07d5171d0 100644 --- a/sdrbase/dsp/interpolator.h +++ b/sdrbase/dsp/interpolator.h @@ -7,9 +7,6 @@ #include "dsp/dsptypes.h" #include "export.h" #include -#ifndef __WINDOWS__ -#include -#endif class SDRBASE_API Interpolator { public: diff --git a/sdrgui/gui/tvscreen.h b/sdrgui/gui/tvscreen.h index 45587ec8e..756636aed 100644 --- a/sdrgui/gui/tvscreen.h +++ b/sdrgui/gui/tvscreen.h @@ -35,7 +35,7 @@ class QPainter; -class TVScreen: public QGLWidget +class SDRGUI_API TVScreen: public QGLWidget { Q_OBJECT From 98a193e5913d764b4515d9d18dd4d715f8063725 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 16:01:33 +0100 Subject: [PATCH 033/102] BFM demod: fixed iterator in RDS parser --- plugins/channelrx/demodbfm/rdsparser.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/plugins/channelrx/demodbfm/rdsparser.cpp b/plugins/channelrx/demodbfm/rdsparser.cpp index 089aa2399..be40ab821 100644 --- a/plugins/channelrx/demodbfm/rdsparser.cpp +++ b/plugins/channelrx/demodbfm/rdsparser.cpp @@ -532,20 +532,16 @@ void RDSParser::decode_type0(unsigned int *group, bool B) if (af_1) { // @TODO: Find proper header or STL on OSX -#ifndef __APPLE__ - std::pair, bool> res = m_g0_alt_freq.insert(af_1/1e3); - m_g0_af_updated = m_g0_af_updated || res.second; -#endif + auto res = m_g0_alt_freq.insert(af_1/1e3); + m_g0_af_updated = m_g0_af_updated || res.second; no_af += 1; } if (af_2) { // @TODO: Find proper header or STL on OSX -#ifndef __APPLE__ - std::pair, bool> res = m_g0_alt_freq.insert(af_2/1e3); + auto res = m_g0_alt_freq.insert(af_2/1e3); m_g0_af_updated = m_g0_af_updated || res.second; -#endif no_af += 2; } From b224e42ef039e49beb0b73846420e997dc6603a5 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 17:29:34 +0100 Subject: [PATCH 034/102] Windows: MSVC2017: adapt more channel plugin modules (1) --- dsdcc/dsdcc.pro | 2 ++ httpserver/httpserver.pro | 2 ++ sdrangel.windows.pro | 10 +++++----- sdrbase/dsp/basebandsamplesink.h | 2 +- sdrbase/dsp/cwkeyer.h | 2 +- sdrbase/dsp/upchannelizer.h | 2 +- sdrgui/gui/crightclickenabler.h | 4 +++- sdrgui/gui/levelmeter.h | 4 ++-- 8 files changed, 17 insertions(+), 11 deletions(-) diff --git a/dsdcc/dsdcc.pro b/dsdcc/dsdcc.pro index 7cb2add66..e89ae3230 100644 --- a/dsdcc/dsdcc.pro +++ b/dsdcc/dsdcc.pro @@ -11,10 +11,12 @@ TARGET = dsdcc CONFIG(MINGW32):LIBDSDCCSRC = "C:\softs\dsdcc" CONFIG(MINGW64):LIBDSDCCSRC = "C:\softs\dsdcc" +CONFIG(MSVC):LIBDSDCCSRC = "C:\softs\dsdcc" CONFIG(macx):LIBDSDCCSRC = "../../deps/dsdcc" CONFIG(MINGW32):LIBMBELIBSRC = "C:\softs\mbelib" CONFIG(MINGW64):LIBMBELIBSRC = "C:\softs\mbelib" +CONFIG(MSVC):LIBMBELIBSRC = "C:\softs\mbelib" CONFIG(macx):LIBMBELIBSRC = "../../deps/mbelib" INCLUDEPATH += $$LIBDSDCCSRC diff --git a/httpserver/httpserver.pro b/httpserver/httpserver.pro index 9dd999c07..a3f82fb0b 100644 --- a/httpserver/httpserver.pro +++ b/httpserver/httpserver.pro @@ -17,6 +17,8 @@ QMAKE_CXXFLAGS += -std=c++11 CONFIG(Release):build_subdir = release CONFIG(Debug):build_subdir = debug +CONFIG(MSVC):DEFINES += httpserver_EXPORTS + # Enable very detailed debug messages when compiling the debug version CONFIG(debug, debug|release) { DEFINES += SUPERVERBOSE diff --git a/sdrangel.windows.pro b/sdrangel.windows.pro index fae8ea587..b3ca705e6 100644 --- a/sdrangel.windows.pro +++ b/sdrangel.windows.pro @@ -15,8 +15,8 @@ SUBDIRS += qrtplib SUBDIRS += swagger SUBDIRS += sdrbase SUBDIRS += sdrgui -SUBDIRS += fcdhid -SUBDIRS += fcdlib +CONFIG(!MSVC):SUBDIRS += fcdhid +CONFIG(!MSVC):SUBDIRS += fcdlib SUBDIRS += libairspy SUBDIRS += libairspyhf #SUBDIRS += libbladerf @@ -27,7 +27,7 @@ CONFIG(!MSVC):SUBDIRS += libperseus SUBDIRS += librtlsdr SUBDIRS += devices SUBDIRS += mbelib -SUBDIRS += dsdcc +CONFIG(!MSVC):SUBDIRS += dsdcc CONFIG(MSVC):SUBDIRS += cm256cc SUBDIRS += plugins/samplesource/airspy SUBDIRS += plugins/samplesource/airspyhf @@ -51,8 +51,8 @@ SUBDIRS += plugins/channelrx/chanalyzer SUBDIRS += plugins/channelrx/demodam SUBDIRS += plugins/channelrx/demodatv SUBDIRS += plugins/channelrx/demodbfm -SUBDIRS += plugins/channelrx/demoddsd -SUBDIRS += plugins/channelrx/demodlora +CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demoddsd +CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demodlora SUBDIRS += plugins/channelrx/demodnfm SUBDIRS += plugins/channelrx/demodssb SUBDIRS += plugins/channelrx/demodwfm diff --git a/sdrbase/dsp/basebandsamplesink.h b/sdrbase/dsp/basebandsamplesink.h index 21e122434..e6a85a0d4 100644 --- a/sdrbase/dsp/basebandsamplesink.h +++ b/sdrbase/dsp/basebandsamplesink.h @@ -30,7 +30,7 @@ class SDRBASE_API BasebandSampleSink : public QObject { Q_OBJECT public: /** Used to notify on which thread the sample sink is now running (with ThreadedSampleSink) */ - class MsgThreadedSink : public Message { + class SDRBASE_API MsgThreadedSink : public Message { MESSAGE_CLASS_DECLARATION public: diff --git a/sdrbase/dsp/cwkeyer.h b/sdrbase/dsp/cwkeyer.h index a1c977a0c..3b2718d6f 100644 --- a/sdrbase/dsp/cwkeyer.h +++ b/sdrbase/dsp/cwkeyer.h @@ -50,7 +50,7 @@ class SDRBASE_API CWKeyer : public QObject { Q_OBJECT public: - class MsgConfigureCWKeyer : public Message { + class SDRBASE_API MsgConfigureCWKeyer : public Message { MESSAGE_CLASS_DECLARATION public: diff --git a/sdrbase/dsp/upchannelizer.h b/sdrbase/dsp/upchannelizer.h index 63698f334..3a99183a0 100644 --- a/sdrbase/dsp/upchannelizer.h +++ b/sdrbase/dsp/upchannelizer.h @@ -36,7 +36,7 @@ class MessageQueue; class SDRBASE_API UpChannelizer : public BasebandSampleSource { Q_OBJECT public: - class MsgChannelizerNotification : public Message { + class SDRBASE_API MsgChannelizerNotification : public Message { MESSAGE_CLASS_DECLARATION public: diff --git a/sdrgui/gui/crightclickenabler.h b/sdrgui/gui/crightclickenabler.h index 6ce92f2d5..f7843b34c 100644 --- a/sdrgui/gui/crightclickenabler.h +++ b/sdrgui/gui/crightclickenabler.h @@ -21,7 +21,9 @@ #include #include -class CRightClickEnabler : public QObject { +#include "export.h" + +class SDRGUI_API CRightClickEnabler : public QObject { Q_OBJECT public: CRightClickEnabler(QAbstractButton *button); diff --git a/sdrgui/gui/levelmeter.h b/sdrgui/gui/levelmeter.h index e4927e68d..348ee4f93 100644 --- a/sdrgui/gui/levelmeter.h +++ b/sdrgui/gui/levelmeter.h @@ -138,7 +138,7 @@ protected: } }; -class LevelMeterVU : public LevelMeter +class SDRGUI_API LevelMeterVU : public LevelMeter { public: LevelMeterVU(QWidget *parent = 0); @@ -148,7 +148,7 @@ protected: virtual void resized(); }; -class LevelMeterSignalDB : public LevelMeter +class SDRGUI_API LevelMeterSignalDB : public LevelMeter { public: typedef enum From 40deb5dc7288d4489628816202402b637094ea3c Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 21:11:17 +0100 Subject: [PATCH 035/102] HackRF: enhance device operations error messages --- devices/hackrf/devicehackrf.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/devices/hackrf/devicehackrf.cpp b/devices/hackrf/devicehackrf.cpp index f07f5fc57..9ab2d7ec6 100644 --- a/devices/hackrf/devicehackrf.cpp +++ b/devices/hackrf/devicehackrf.cpp @@ -15,6 +15,7 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#include #include "devicehackrf.h" DeviceHackRF::DeviceHackRF() @@ -22,7 +23,7 @@ DeviceHackRF::DeviceHackRF() hackrf_error rc = (hackrf_error) hackrf_init(); if (rc != HACKRF_SUCCESS) { - fprintf(stderr, "DeviceHackRF::open_hackrf: failed to initiate HackRF library %s\n", hackrf_error_name(rc)); + qCritical("DeviceHackRF::open_hackrf: failed to initiate HackRF library %s", hackrf_error_name(rc)); } } @@ -59,6 +60,7 @@ hackrf_device *DeviceHackRF::open_hackrf(const char * const serial) } else { + qCritical("DeviceHackRF::open_hackrf: error #%d: %s", (int) rc, hackrf_error_name(rc)); return 0; } } @@ -79,6 +81,7 @@ hackrf_device *DeviceHackRF::open_hackrf_from_sequence(int sequence) } else { + qCritical("DeviceHackRF::open_hackrf_from_sequence: error #%d: %s", (int) rc, hackrf_error_name(rc)); return 0; } } From 89899a48d3751751a7ca76041cdd03428b2b7033 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 13 Nov 2018 23:49:04 +0100 Subject: [PATCH 036/102] SoapySDR support: REST API: created structures --- sdrbase/resources/res.qrc | 1 + sdrbase/resources/webapi/doc/html2/index.html | 331 +++++++++- .../webapi/doc/swagger/include/SoapySDR.yaml | 191 ++++++ .../webapi/doc/swagger/include/Structs.yaml | 37 +- .../resources/webapi/doc/swagger/swagger.yaml | 10 +- .../api/swagger/include/SoapySDR.yaml | 191 ++++++ .../sdrangel/api/swagger/include/Structs.yaml | 37 +- swagger/sdrangel/api/swagger/swagger.yaml | 10 +- swagger/sdrangel/code/html2/index.html | 331 +++++++++- .../code/qt5/client/SWGAMDemodReport.cpp | 2 +- .../code/qt5/client/SWGAMDemodReport.h | 2 +- .../code/qt5/client/SWGAMDemodSettings.cpp | 2 +- .../code/qt5/client/SWGAMDemodSettings.h | 2 +- .../code/qt5/client/SWGAMModReport.cpp | 2 +- .../sdrangel/code/qt5/client/SWGAMModReport.h | 2 +- .../code/qt5/client/SWGAMModSettings.cpp | 2 +- .../code/qt5/client/SWGAMModSettings.h | 2 +- .../code/qt5/client/SWGATVModReport.cpp | 2 +- .../code/qt5/client/SWGATVModReport.h | 2 +- .../code/qt5/client/SWGATVModSettings.cpp | 2 +- .../code/qt5/client/SWGATVModSettings.h | 2 +- .../code/qt5/client/SWGAirspyHFReport.cpp | 2 +- .../code/qt5/client/SWGAirspyHFReport.h | 2 +- .../code/qt5/client/SWGAirspyHFSettings.cpp | 2 +- .../code/qt5/client/SWGAirspyHFSettings.h | 2 +- .../code/qt5/client/SWGAirspyReport.cpp | 2 +- .../code/qt5/client/SWGAirspyReport.h | 2 +- .../code/qt5/client/SWGAirspySettings.cpp | 2 +- .../code/qt5/client/SWGAirspySettings.h | 2 +- .../sdrangel/code/qt5/client/SWGArgInfo.cpp | 154 +++++ swagger/sdrangel/code/qt5/client/SWGArgInfo.h | 71 +++ .../code/qt5/client/SWGAudioDevices.cpp | 2 +- .../code/qt5/client/SWGAudioDevices.h | 2 +- .../code/qt5/client/SWGAudioInputDevice.cpp | 2 +- .../code/qt5/client/SWGAudioInputDevice.h | 2 +- .../code/qt5/client/SWGAudioOutputDevice.cpp | 2 +- .../code/qt5/client/SWGAudioOutputDevice.h | 2 +- .../code/qt5/client/SWGBFMDemodReport.cpp | 2 +- .../code/qt5/client/SWGBFMDemodReport.h | 2 +- .../code/qt5/client/SWGBFMDemodSettings.cpp | 2 +- .../code/qt5/client/SWGBFMDemodSettings.h | 2 +- .../sdrangel/code/qt5/client/SWGBandwidth.cpp | 2 +- .../sdrangel/code/qt5/client/SWGBandwidth.h | 2 +- .../qt5/client/SWGBladeRF1InputSettings.cpp | 2 +- .../qt5/client/SWGBladeRF1InputSettings.h | 2 +- .../qt5/client/SWGBladeRF1OutputSettings.cpp | 2 +- .../qt5/client/SWGBladeRF1OutputSettings.h | 2 +- .../qt5/client/SWGBladeRF2InputReport.cpp | 2 +- .../code/qt5/client/SWGBladeRF2InputReport.h | 2 +- .../qt5/client/SWGBladeRF2InputSettings.cpp | 2 +- .../qt5/client/SWGBladeRF2InputSettings.h | 2 +- .../qt5/client/SWGBladeRF2OutputReport.cpp | 2 +- .../code/qt5/client/SWGBladeRF2OutputReport.h | 2 +- .../qt5/client/SWGBladeRF2OutputSettings.cpp | 2 +- .../qt5/client/SWGBladeRF2OutputSettings.h | 2 +- .../code/qt5/client/SWGCWKeyerSettings.cpp | 2 +- .../code/qt5/client/SWGCWKeyerSettings.h | 2 +- .../sdrangel/code/qt5/client/SWGChannel.cpp | 2 +- swagger/sdrangel/code/qt5/client/SWGChannel.h | 2 +- .../code/qt5/client/SWGChannelListItem.cpp | 2 +- .../code/qt5/client/SWGChannelListItem.h | 2 +- .../code/qt5/client/SWGChannelReport.cpp | 2 +- .../code/qt5/client/SWGChannelReport.h | 2 +- .../code/qt5/client/SWGChannelSettings.cpp | 2 +- .../code/qt5/client/SWGChannelSettings.h | 2 +- .../code/qt5/client/SWGChannelsDetail.cpp | 2 +- .../code/qt5/client/SWGChannelsDetail.h | 2 +- .../sdrangel/code/qt5/client/SWGComplex.cpp | 127 ++++ swagger/sdrangel/code/qt5/client/SWGComplex.h | 64 ++ .../code/qt5/client/SWGDSDDemodReport.cpp | 2 +- .../code/qt5/client/SWGDSDDemodReport.h | 2 +- .../code/qt5/client/SWGDSDDemodSettings.cpp | 2 +- .../code/qt5/client/SWGDSDDemodSettings.h | 2 +- .../code/qt5/client/SWGDVSeralDevices.cpp | 2 +- .../code/qt5/client/SWGDVSeralDevices.h | 2 +- .../code/qt5/client/SWGDVSerialDevice.cpp | 2 +- .../code/qt5/client/SWGDVSerialDevice.h | 2 +- .../code/qt5/client/SWGDaemonSinkSettings.cpp | 2 +- .../code/qt5/client/SWGDaemonSinkSettings.h | 2 +- .../code/qt5/client/SWGDaemonSourceReport.cpp | 2 +- .../code/qt5/client/SWGDaemonSourceReport.h | 2 +- .../qt5/client/SWGDaemonSourceSettings.cpp | 2 +- .../code/qt5/client/SWGDaemonSourceSettings.h | 2 +- .../code/qt5/client/SWGDeviceListItem.cpp | 2 +- .../code/qt5/client/SWGDeviceListItem.h | 2 +- .../code/qt5/client/SWGDeviceReport.cpp | 48 +- .../code/qt5/client/SWGDeviceReport.h | 15 +- .../sdrangel/code/qt5/client/SWGDeviceSet.cpp | 2 +- .../sdrangel/code/qt5/client/SWGDeviceSet.h | 2 +- .../code/qt5/client/SWGDeviceSetApi.cpp | 2 +- .../code/qt5/client/SWGDeviceSetApi.h | 2 +- .../code/qt5/client/SWGDeviceSetList.cpp | 2 +- .../code/qt5/client/SWGDeviceSetList.h | 2 +- .../code/qt5/client/SWGDeviceSettings.cpp | 48 +- .../code/qt5/client/SWGDeviceSettings.h | 16 +- .../code/qt5/client/SWGDeviceState.cpp | 2 +- .../sdrangel/code/qt5/client/SWGDeviceState.h | 2 +- .../code/qt5/client/SWGErrorResponse.cpp | 2 +- .../code/qt5/client/SWGErrorResponse.h | 2 +- .../code/qt5/client/SWGFCDProPlusSettings.cpp | 2 +- .../code/qt5/client/SWGFCDProPlusSettings.h | 2 +- .../code/qt5/client/SWGFCDProSettings.cpp | 2 +- .../code/qt5/client/SWGFCDProSettings.h | 2 +- .../code/qt5/client/SWGFileSourceReport.cpp | 2 +- .../code/qt5/client/SWGFileSourceReport.h | 2 +- .../code/qt5/client/SWGFileSourceSettings.cpp | 2 +- .../code/qt5/client/SWGFileSourceSettings.h | 2 +- .../sdrangel/code/qt5/client/SWGFrequency.cpp | 2 +- .../sdrangel/code/qt5/client/SWGFrequency.h | 2 +- .../code/qt5/client/SWGFrequencyBand.cpp | 2 +- .../code/qt5/client/SWGFrequencyBand.h | 2 +- .../code/qt5/client/SWGFrequencyRange.cpp | 2 +- .../code/qt5/client/SWGFrequencyRange.h | 2 +- swagger/sdrangel/code/qt5/client/SWGGain.cpp | 2 +- swagger/sdrangel/code/qt5/client/SWGGain.h | 2 +- .../qt5/client/SWGHackRFInputSettings.cpp | 2 +- .../code/qt5/client/SWGHackRFInputSettings.h | 2 +- .../qt5/client/SWGHackRFOutputSettings.cpp | 2 +- .../code/qt5/client/SWGHackRFOutputSettings.h | 2 +- .../sdrangel/code/qt5/client/SWGHelpers.cpp | 2 +- swagger/sdrangel/code/qt5/client/SWGHelpers.h | 2 +- .../code/qt5/client/SWGHttpRequest.cpp | 2 +- .../sdrangel/code/qt5/client/SWGHttpRequest.h | 2 +- .../code/qt5/client/SWGInstanceApi.cpp | 2 +- .../sdrangel/code/qt5/client/SWGInstanceApi.h | 2 +- .../client/SWGInstanceChannelsResponse.cpp | 2 +- .../qt5/client/SWGInstanceChannelsResponse.h | 2 +- .../qt5/client/SWGInstanceDevicesResponse.cpp | 2 +- .../qt5/client/SWGInstanceDevicesResponse.h | 2 +- .../qt5/client/SWGInstanceSummaryResponse.cpp | 2 +- .../qt5/client/SWGInstanceSummaryResponse.h | 2 +- .../code/qt5/client/SWGLimeSdrInputReport.cpp | 2 +- .../code/qt5/client/SWGLimeSdrInputReport.h | 2 +- .../qt5/client/SWGLimeSdrInputSettings.cpp | 2 +- .../code/qt5/client/SWGLimeSdrInputSettings.h | 2 +- .../qt5/client/SWGLimeSdrOutputReport.cpp | 2 +- .../code/qt5/client/SWGLimeSdrOutputReport.h | 2 +- .../qt5/client/SWGLimeSdrOutputSettings.cpp | 2 +- .../qt5/client/SWGLimeSdrOutputSettings.h | 2 +- .../qt5/client/SWGLocationInformation.cpp | 2 +- .../code/qt5/client/SWGLocationInformation.h | 2 +- .../code/qt5/client/SWGLoggingInfo.cpp | 2 +- .../sdrangel/code/qt5/client/SWGLoggingInfo.h | 2 +- .../code/qt5/client/SWGModelFactory.h | 34 +- .../code/qt5/client/SWGNFMDemodReport.cpp | 2 +- .../code/qt5/client/SWGNFMDemodReport.h | 2 +- .../code/qt5/client/SWGNFMDemodSettings.cpp | 2 +- .../code/qt5/client/SWGNFMDemodSettings.h | 2 +- .../code/qt5/client/SWGNFMModReport.cpp | 2 +- .../code/qt5/client/SWGNFMModReport.h | 2 +- .../code/qt5/client/SWGNFMModSettings.cpp | 2 +- .../code/qt5/client/SWGNFMModSettings.h | 2 +- .../sdrangel/code/qt5/client/SWGNamedEnum.cpp | 2 +- .../sdrangel/code/qt5/client/SWGNamedEnum.h | 2 +- swagger/sdrangel/code/qt5/client/SWGObject.h | 2 +- .../code/qt5/client/SWGPerseusReport.cpp | 2 +- .../code/qt5/client/SWGPerseusReport.h | 2 +- .../code/qt5/client/SWGPerseusSettings.cpp | 2 +- .../code/qt5/client/SWGPerseusSettings.h | 2 +- .../qt5/client/SWGPlutoSdrInputReport.cpp | 2 +- .../code/qt5/client/SWGPlutoSdrInputReport.h | 2 +- .../qt5/client/SWGPlutoSdrInputSettings.cpp | 2 +- .../qt5/client/SWGPlutoSdrInputSettings.h | 2 +- .../qt5/client/SWGPlutoSdrOutputReport.cpp | 2 +- .../code/qt5/client/SWGPlutoSdrOutputReport.h | 2 +- .../qt5/client/SWGPlutoSdrOutputSettings.cpp | 2 +- .../qt5/client/SWGPlutoSdrOutputSettings.h | 2 +- .../code/qt5/client/SWGPresetExport.cpp | 2 +- .../code/qt5/client/SWGPresetExport.h | 2 +- .../code/qt5/client/SWGPresetGroup.cpp | 2 +- .../sdrangel/code/qt5/client/SWGPresetGroup.h | 2 +- .../code/qt5/client/SWGPresetIdentifier.cpp | 2 +- .../code/qt5/client/SWGPresetIdentifier.h | 2 +- .../code/qt5/client/SWGPresetImport.cpp | 2 +- .../code/qt5/client/SWGPresetImport.h | 2 +- .../code/qt5/client/SWGPresetItem.cpp | 2 +- .../sdrangel/code/qt5/client/SWGPresetItem.h | 2 +- .../code/qt5/client/SWGPresetTransfer.cpp | 2 +- .../code/qt5/client/SWGPresetTransfer.h | 2 +- .../sdrangel/code/qt5/client/SWGPresets.cpp | 2 +- swagger/sdrangel/code/qt5/client/SWGPresets.h | 2 +- .../sdrangel/code/qt5/client/SWGRDSReport.cpp | 2 +- .../sdrangel/code/qt5/client/SWGRDSReport.h | 2 +- .../client/SWGRDSReport_altFrequencies.cpp | 2 +- .../qt5/client/SWGRDSReport_altFrequencies.h | 2 +- swagger/sdrangel/code/qt5/client/SWGRange.cpp | 2 +- swagger/sdrangel/code/qt5/client/SWGRange.h | 4 +- .../code/qt5/client/SWGRangeFloat.cpp | 148 +++++ .../sdrangel/code/qt5/client/SWGRangeFloat.h | 70 +++ .../code/qt5/client/SWGRtlSdrReport.cpp | 2 +- .../code/qt5/client/SWGRtlSdrReport.h | 2 +- .../code/qt5/client/SWGRtlSdrSettings.cpp | 2 +- .../code/qt5/client/SWGRtlSdrSettings.h | 2 +- .../code/qt5/client/SWGSDRPlayReport.cpp | 2 +- .../code/qt5/client/SWGSDRPlayReport.h | 2 +- .../code/qt5/client/SWGSDRPlaySettings.cpp | 2 +- .../code/qt5/client/SWGSDRPlaySettings.h | 2 +- .../qt5/client/SWGSDRdaemonSinkReport.cpp | 2 +- .../code/qt5/client/SWGSDRdaemonSinkReport.h | 2 +- .../qt5/client/SWGSDRdaemonSinkSettings.cpp | 2 +- .../qt5/client/SWGSDRdaemonSinkSettings.h | 2 +- .../qt5/client/SWGSDRdaemonSourceReport.cpp | 2 +- .../qt5/client/SWGSDRdaemonSourceReport.h | 2 +- .../qt5/client/SWGSDRdaemonSourceSettings.cpp | 2 +- .../qt5/client/SWGSDRdaemonSourceSettings.h | 2 +- .../code/qt5/client/SWGSSBDemodReport.cpp | 2 +- .../code/qt5/client/SWGSSBDemodReport.h | 2 +- .../code/qt5/client/SWGSSBDemodSettings.cpp | 2 +- .../code/qt5/client/SWGSSBDemodSettings.h | 2 +- .../code/qt5/client/SWGSSBModReport.cpp | 2 +- .../code/qt5/client/SWGSSBModReport.h | 2 +- .../code/qt5/client/SWGSSBModSettings.cpp | 2 +- .../code/qt5/client/SWGSSBModSettings.h | 2 +- .../code/qt5/client/SWGSampleRate.cpp | 2 +- .../sdrangel/code/qt5/client/SWGSampleRate.h | 2 +- .../code/qt5/client/SWGSamplingDevice.cpp | 2 +- .../code/qt5/client/SWGSamplingDevice.h | 2 +- .../client/SWGSoapySDRFrequencySetting.cpp | 135 ++++ .../qt5/client/SWGSoapySDRFrequencySetting.h | 67 ++ .../qt5/client/SWGSoapySDRGainSetting.cpp | 131 ++++ .../code/qt5/client/SWGSoapySDRGainSetting.h | 66 ++ .../qt5/client/SWGSoapySDRInputSettings.cpp | 579 ++++++++++++++++++ .../qt5/client/SWGSoapySDRInputSettings.h | 188 ++++++ .../qt5/client/SWGSoapySDROutputSettings.cpp | 493 +++++++++++++++ .../qt5/client/SWGSoapySDROutputSettings.h | 164 +++++ .../code/qt5/client/SWGSoapySDRReport.cpp | 429 +++++++++++++ .../code/qt5/client/SWGSoapySDRReport.h | 142 +++++ .../code/qt5/client/SWGSuccessResponse.cpp | 2 +- .../code/qt5/client/SWGSuccessResponse.h | 2 +- .../code/qt5/client/SWGTestSourceSettings.cpp | 2 +- .../code/qt5/client/SWGTestSourceSettings.h | 2 +- .../code/qt5/client/SWGUDPSinkReport.cpp | 2 +- .../code/qt5/client/SWGUDPSinkReport.h | 2 +- .../code/qt5/client/SWGUDPSinkSettings.cpp | 2 +- .../code/qt5/client/SWGUDPSinkSettings.h | 2 +- .../code/qt5/client/SWGUDPSourceReport.cpp | 2 +- .../code/qt5/client/SWGUDPSourceReport.h | 2 +- .../code/qt5/client/SWGUDPSourceSettings.cpp | 2 +- .../code/qt5/client/SWGUDPSourceSettings.h | 2 +- .../code/qt5/client/SWGWFMDemodReport.cpp | 2 +- .../code/qt5/client/SWGWFMDemodReport.h | 2 +- .../code/qt5/client/SWGWFMDemodSettings.cpp | 2 +- .../code/qt5/client/SWGWFMDemodSettings.h | 2 +- .../code/qt5/client/SWGWFMModReport.cpp | 2 +- .../code/qt5/client/SWGWFMModReport.h | 2 +- .../code/qt5/client/SWGWFMModSettings.cpp | 2 +- .../code/qt5/client/SWGWFMModSettings.h | 2 +- 247 files changed, 4531 insertions(+), 233 deletions(-) create mode 100644 sdrbase/resources/webapi/doc/swagger/include/SoapySDR.yaml create mode 100644 swagger/sdrangel/api/swagger/include/SoapySDR.yaml create mode 100644 swagger/sdrangel/code/qt5/client/SWGArgInfo.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGArgInfo.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGComplex.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGComplex.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGRangeFloat.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGRangeFloat.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDRFrequencySetting.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDRFrequencySetting.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDRGainSetting.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDRGainSetting.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDRReport.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGSoapySDRReport.h diff --git a/sdrbase/resources/res.qrc b/sdrbase/resources/res.qrc index 36e34505d..be9edc854 100644 --- a/sdrbase/resources/res.qrc +++ b/sdrbase/resources/res.qrc @@ -27,6 +27,7 @@ webapi/doc/swagger/include/SDRDaemonSource.yaml webapi/doc/swagger/include/SDRDaemonSink.yaml webapi/doc/swagger/include/SDRPlay.yaml + webapi/doc/swagger/include/SoapySDR.yaml webapi/doc/swagger/include/SSBDemod.yaml webapi/doc/swagger/include/SSBMod.yaml webapi/doc/swagger/include/Structs.yaml diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 61c526a87..0627afc11 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -1031,6 +1031,20 @@ margin-bottom: 20px; } }, "description" : "Airspy" +}; + defs.ArgInfo = { + "properties" : { + "key" : { + "type" : "string" + }, + "valueType" : { + "type" : "string", + "enum" : [ "bool", "int", "float", "string" ] + }, + "valueString" : { + "type" : "string" + } + } }; defs.AudioDevices = { "required" : [ "nbInputDevices", "nbOutputDevices" ], @@ -1636,6 +1650,19 @@ margin-bottom: 20px; } }, "description" : "All channels detailed information" +}; + defs.Complex = { + "properties" : { + "real" : { + "type" : "number", + "format" : "float" + }, + "imag" : { + "type" : "number", + "format" : "float" + } + }, + "description" : "A complex number" }; defs.DSDDemodReport = { "properties" : { @@ -1996,6 +2023,12 @@ margin-bottom: 20px; }, "sdrPlayReport" : { "$ref" : "#/definitions/SDRPlayReport" + }, + "soapySDRInputReport" : { + "$ref" : "#/definitions/SoapySDRReport" + }, + "soapySDROutputReport" : { + "$ref" : "#/definitions/SoapySDRReport" } }, "description" : "Base device report. Only the device report corresponding to the device specified in the deviceHwType is or should be present." @@ -2112,6 +2145,12 @@ margin-bottom: 20px; "sdrPlaySettings" : { "$ref" : "#/definitions/SDRPlaySettings" }, + "soapySDRInputSettings" : { + "$ref" : "#/definitions/SoapySDRInputSettings" + }, + "soapySDROutputSettings" : { + "$ref" : "#/definitions/SoapySDROutputSettings" + }, "testSourceSettings" : { "$ref" : "#/definitions/TestSourceSettings" } @@ -3331,7 +3370,24 @@ margin-bottom: 20px; "type" : "integer" } }, - "description" : "An arbitrary range of values" + "description" : "An arbitrary range of integer values" +}; + defs.RangeFloat = { + "properties" : { + "min" : { + "type" : "number", + "format" : "float" + }, + "max" : { + "type" : "number", + "format" : "float" + }, + "step" : { + "type" : "number", + "format" : "float" + } + }, + "description" : "An arbitrary range of floating point values" }; defs.RtlSdrReport = { "properties" : { @@ -3828,6 +3884,275 @@ margin-bottom: 20px; } }, "description" : "Information about a logical device available from an attached hardware device that can be used as a sampling device" +}; + defs.SoapySDRFrequencySetting = { + "properties" : { + "name" : { + "type" : "string" + }, + "ranges" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/RangeFloat" + } + } + }, + "description" : "A named frequency setting specified by a range list" +}; + defs.SoapySDRGainSetting = { + "properties" : { + "name" : { + "type" : "string" + }, + "range" : { + "$ref" : "#/definitions/RangeFloat" + } + }, + "description" : "A named gain setting specified by its range" +}; + defs.SoapySDRInputSettings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "LOppmTenths" : { + "type" : "integer" + }, + "devSampleRate" : { + "type" : "integer" + }, + "log2Decim" : { + "type" : "integer" + }, + "fcPos" : { + "type" : "integer" + }, + "softDCCorrection" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "softIQCorrection" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "transverterMode" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "transverterDeltaFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "fileRecordName" : { + "type" : "string" + }, + "antenna" : { + "type" : "string" + }, + "bandwidth" : { + "type" : "integer" + }, + "tunableElements" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + }, + "globalGain" : { + "type" : "integer" + }, + "individualGains" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + }, + "autoGain" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "autoDCCorrection" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "autoIQCorrection" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "dcCorrection" : { + "$ref" : "#/definitions/Complex" + }, + "iqCorrection" : { + "$ref" : "#/definitions/Complex" + }, + "streamArgSettings" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + }, + "deviceArgSettings" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + } + }, + "description" : "SoapySDR" +}; + defs.SoapySDROutputSettings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "LOppmTenths" : { + "type" : "integer" + }, + "devSampleRate" : { + "type" : "integer" + }, + "log2Interp" : { + "type" : "integer" + }, + "transverterMode" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "transverterDeltaFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "antenna" : { + "type" : "string" + }, + "bandwidth" : { + "type" : "integer" + }, + "tunableElements" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + }, + "globalGain" : { + "type" : "integer" + }, + "individualGains" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + }, + "autoGain" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "autoDCCorrection" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "autoIQCorrection" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "dcCorrection" : { + "$ref" : "#/definitions/Complex" + }, + "iqCorrection" : { + "$ref" : "#/definitions/Complex" + }, + "streamArgSettings" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + }, + "deviceArgSettings" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + } + }, + "description" : "SoapySDR" +}; + defs.SoapySDRReport = { + "properties" : { + "deviceSettingsArgs" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + }, + "streamSettingsArgs" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + }, + "hasDCAutoCorrection" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "hasDCOffsetValue" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "hasIQBalanceValue" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "hasFrequencyCorrectionValue" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "antennas" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "hasAGC" : { + "type" : "integer", + "description" : "boolean not zero for true" + }, + "gainRange" : { + "$ref" : "#/definitions/RangeFloat" + }, + "gainSettings" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/SoapySDRGainSetting" + } + }, + "frequencySettings" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/SoapySDRFrequencySetting" + } + }, + "frequencySettingsArgs" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ArgInfo" + } + }, + "ratesRanges" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/RangeFloat" + } + }, + "bandwidthsRanges" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/RangeFloat" + } + } + }, + "description" : "SoapySDR" }; defs.SuccessResponse = { "required" : [ "message" ], @@ -4383,7 +4708,7 @@ margin-bottom: 20px; diff --git a/sdrbase/resources/webapi/doc/swagger/include/SoapySDR.yaml b/sdrbase/resources/webapi/doc/swagger/include/SoapySDR.yaml index 9d0f3c42d..54aea556a 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/SoapySDR.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/SoapySDR.yaml @@ -33,13 +33,13 @@ SoapySDRInputSettings: tunableElements: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" globalGain: type: integer individualGains: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" autoGain: description: boolean not zero for true type: integer @@ -56,11 +56,11 @@ SoapySDRInputSettings: streamArgSettings: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" deviceArgSettings: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" SoapySDROutputSettings: description: SoapySDR @@ -87,13 +87,13 @@ SoapySDROutputSettings: tunableElements: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" globalGain: type: integer individualGains: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" autoGain: description: boolean not zero for true type: integer @@ -110,11 +110,11 @@ SoapySDROutputSettings: streamArgSettings: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" deviceArgSettings: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" SoapySDRReport: description: SoapySDR @@ -122,11 +122,11 @@ SoapySDRReport: deviceSettingsArgs: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgInfo" streamSettingsArgs: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgInfo" hasDCAutoCorrection: description: boolean not zero for true type: integer @@ -159,7 +159,7 @@ SoapySDRReport: frequencySettingsArgs: type: array items: - $ref: "/doc/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgInfo" ratesRanges: type: array items: @@ -188,4 +188,44 @@ definitions: type: array items: $ref: "/doc/swagger/include/Structs.yaml#/RangeFloat" + + ArgValue: + descripion: Generic argument value + properties: + key: + type: string + valueType: + type: string + enum: [bool, int, float, string] + valueString: + type: string + + ArgInfo: + descripion: Generic argument information + properties: + key: + type: string + valueType: + type: string + enum: [bool, int, float, string] + valueString: + type: string + name: + type: string + description: + type: string + units: + type: string + range: + $ref: "/doc/swagger/include/Structs.yaml#/RangeFloat" + valueOptions: + type: array + items: + type: string + optionNames: + type: array + items: + type: string + + \ No newline at end of file diff --git a/sdrbase/resources/webapi/doc/swagger/include/Structs.yaml b/sdrbase/resources/webapi/doc/swagger/include/Structs.yaml index db69cde1f..887ff0ca2 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/Structs.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/Structs.yaml @@ -75,17 +75,6 @@ NamedEnum: value: type: integer -ArgInfo: - descripion: Argument information used in SoapySDR - properties: - key: - type: string - valueType: - type: string - enum: [bool, int, float, string] - valueString: - type: string - Complex: description: A complex number properties: diff --git a/swagger/sdrangel/api/swagger/include/SoapySDR.yaml b/swagger/sdrangel/api/swagger/include/SoapySDR.yaml index e1f220f6f..dd6bc0ba3 100644 --- a/swagger/sdrangel/api/swagger/include/SoapySDR.yaml +++ b/swagger/sdrangel/api/swagger/include/SoapySDR.yaml @@ -33,13 +33,13 @@ SoapySDRInputSettings: tunableElements: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" globalGain: type: integer individualGains: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" autoGain: description: boolean not zero for true type: integer @@ -56,11 +56,11 @@ SoapySDRInputSettings: streamArgSettings: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" deviceArgSettings: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" SoapySDROutputSettings: description: SoapySDR @@ -87,13 +87,13 @@ SoapySDROutputSettings: tunableElements: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" globalGain: type: integer individualGains: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" autoGain: description: boolean not zero for true type: integer @@ -110,11 +110,11 @@ SoapySDROutputSettings: streamArgSettings: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" deviceArgSettings: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgValue" SoapySDRReport: description: SoapySDR @@ -122,11 +122,11 @@ SoapySDRReport: deviceSettingsArgs: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgInfo" streamSettingsArgs: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgInfo" hasDCAutoCorrection: description: boolean not zero for true type: integer @@ -159,7 +159,7 @@ SoapySDRReport: frequencySettingsArgs: type: array items: - $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/ArgInfo" + $ref: "#/definitions/ArgInfo" ratesRanges: type: array items: @@ -188,4 +188,44 @@ definitions: type: array items: $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/RangeFloat" + + ArgValue: + descripion: Generic argument value + properties: + key: + type: string + valueType: + type: string + enum: [bool, int, float, string] + valueString: + type: string + + ArgInfo: + descripion: Generic argument information + properties: + key: + type: string + valueType: + type: string + enum: [bool, int, float, string] + valueString: + type: string + name: + type: string + description: + type: string + units: + type: string + range: + $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/RangeFloat" + valueOptions: + type: array + items: + type: string + optionNames: + type: array + items: + type: string + + \ No newline at end of file diff --git a/swagger/sdrangel/api/swagger/include/Structs.yaml b/swagger/sdrangel/api/swagger/include/Structs.yaml index db69cde1f..887ff0ca2 100644 --- a/swagger/sdrangel/api/swagger/include/Structs.yaml +++ b/swagger/sdrangel/api/swagger/include/Structs.yaml @@ -75,17 +75,6 @@ NamedEnum: value: type: integer -ArgInfo: - descripion: Argument information used in SoapySDR - properties: - key: - type: string - valueType: - type: string - enum: [bool, int, float, string] - valueString: - type: string - Complex: description: A complex number properties: diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 0627afc11..2eefbe096 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -1033,6 +1033,44 @@ margin-bottom: 20px; "description" : "Airspy" }; defs.ArgInfo = { + "properties" : { + "key" : { + "type" : "string" + }, + "valueType" : { + "type" : "string", + "enum" : [ "bool", "int", "float", "string" ] + }, + "valueString" : { + "type" : "string" + }, + "name" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "units" : { + "type" : "string" + }, + "range" : { + "$ref" : "#/definitions/RangeFloat" + }, + "valueOptions" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "optionNames" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } +}; + defs.ArgValue = { "properties" : { "key" : { "type" : "string" @@ -3956,7 +3994,7 @@ margin-bottom: 20px; "tunableElements" : { "type" : "array", "items" : { - "$ref" : "#/definitions/ArgInfo" + "$ref" : "#/definitions/ArgValue" } }, "globalGain" : { @@ -3965,7 +4003,7 @@ margin-bottom: 20px; "individualGains" : { "type" : "array", "items" : { - "$ref" : "#/definitions/ArgInfo" + "$ref" : "#/definitions/ArgValue" } }, "autoGain" : { @@ -3989,13 +4027,13 @@ margin-bottom: 20px; "streamArgSettings" : { "type" : "array", "items" : { - "$ref" : "#/definitions/ArgInfo" + "$ref" : "#/definitions/ArgValue" } }, "deviceArgSettings" : { "type" : "array", "items" : { - "$ref" : "#/definitions/ArgInfo" + "$ref" : "#/definitions/ArgValue" } } }, @@ -4033,7 +4071,7 @@ margin-bottom: 20px; "tunableElements" : { "type" : "array", "items" : { - "$ref" : "#/definitions/ArgInfo" + "$ref" : "#/definitions/ArgValue" } }, "globalGain" : { @@ -4042,7 +4080,7 @@ margin-bottom: 20px; "individualGains" : { "type" : "array", "items" : { - "$ref" : "#/definitions/ArgInfo" + "$ref" : "#/definitions/ArgValue" } }, "autoGain" : { @@ -4066,13 +4104,13 @@ margin-bottom: 20px; "streamArgSettings" : { "type" : "array", "items" : { - "$ref" : "#/definitions/ArgInfo" + "$ref" : "#/definitions/ArgValue" } }, "deviceArgSettings" : { "type" : "array", "items" : { - "$ref" : "#/definitions/ArgInfo" + "$ref" : "#/definitions/ArgValue" } } }, @@ -23576,7 +23614,7 @@ except ApiException as e:
- Generated 2018-11-13T23:30:05.952+01:00 + Generated 2018-11-14T01:13:54.986+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGArgInfo.cpp b/swagger/sdrangel/code/qt5/client/SWGArgInfo.cpp index e32b0a08d..b563a9323 100644 --- a/swagger/sdrangel/code/qt5/client/SWGArgInfo.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGArgInfo.cpp @@ -34,6 +34,18 @@ SWGArgInfo::SWGArgInfo() { m_value_type_isSet = false; value_string = nullptr; m_value_string_isSet = false; + name = nullptr; + m_name_isSet = false; + description = nullptr; + m_description_isSet = false; + units = nullptr; + m_units_isSet = false; + range = nullptr; + m_range_isSet = false; + value_options = nullptr; + m_value_options_isSet = false; + option_names = nullptr; + m_option_names_isSet = false; } SWGArgInfo::~SWGArgInfo() { @@ -48,6 +60,18 @@ SWGArgInfo::init() { m_value_type_isSet = false; value_string = new QString(""); m_value_string_isSet = false; + name = new QString(""); + m_name_isSet = false; + description = new QString(""); + m_description_isSet = false; + units = new QString(""); + m_units_isSet = false; + range = new SWGRangeFloat(); + m_range_isSet = false; + value_options = new QList(); + m_value_options_isSet = false; + option_names = new QList(); + m_option_names_isSet = false; } void @@ -61,6 +85,32 @@ SWGArgInfo::cleanup() { if(value_string != nullptr) { delete value_string; } + if(name != nullptr) { + delete name; + } + if(description != nullptr) { + delete description; + } + if(units != nullptr) { + delete units; + } + if(range != nullptr) { + delete range; + } + if(value_options != nullptr) { + auto arr = value_options; + for(auto o: *arr) { + delete o; + } + delete value_options; + } + if(option_names != nullptr) { + auto arr = option_names; + for(auto o: *arr) { + delete o; + } + delete option_names; + } } SWGArgInfo* @@ -80,6 +130,18 @@ SWGArgInfo::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&value_string, pJson["valueString"], "QString", "QString"); + ::SWGSDRangel::setValue(&name, pJson["name"], "QString", "QString"); + + ::SWGSDRangel::setValue(&description, pJson["description"], "QString", "QString"); + + ::SWGSDRangel::setValue(&units, pJson["units"], "QString", "QString"); + + ::SWGSDRangel::setValue(&range, pJson["range"], "SWGRangeFloat", "SWGRangeFloat"); + + + ::SWGSDRangel::setValue(&value_options, pJson["valueOptions"], "QList", "QString"); + + ::SWGSDRangel::setValue(&option_names, pJson["optionNames"], "QList", "QString"); } QString @@ -105,6 +167,24 @@ SWGArgInfo::asJsonObject() { if(value_string != nullptr && *value_string != QString("")){ toJsonValue(QString("valueString"), value_string, obj, QString("QString")); } + if(name != nullptr && *name != QString("")){ + toJsonValue(QString("name"), name, obj, QString("QString")); + } + if(description != nullptr && *description != QString("")){ + toJsonValue(QString("description"), description, obj, QString("QString")); + } + if(units != nullptr && *units != QString("")){ + toJsonValue(QString("units"), units, obj, QString("QString")); + } + if((range != nullptr) && (range->isSet())){ + toJsonValue(QString("range"), range, obj, QString("SWGRangeFloat")); + } + if(value_options->size() > 0){ + toJsonArray((QList*)value_options, obj, "valueOptions", "QString"); + } + if(option_names->size() > 0){ + toJsonArray((QList*)option_names, obj, "optionNames", "QString"); + } return obj; } @@ -139,6 +219,66 @@ SWGArgInfo::setValueString(QString* value_string) { this->m_value_string_isSet = true; } +QString* +SWGArgInfo::getName() { + return name; +} +void +SWGArgInfo::setName(QString* name) { + this->name = name; + this->m_name_isSet = true; +} + +QString* +SWGArgInfo::getDescription() { + return description; +} +void +SWGArgInfo::setDescription(QString* description) { + this->description = description; + this->m_description_isSet = true; +} + +QString* +SWGArgInfo::getUnits() { + return units; +} +void +SWGArgInfo::setUnits(QString* units) { + this->units = units; + this->m_units_isSet = true; +} + +SWGRangeFloat* +SWGArgInfo::getRange() { + return range; +} +void +SWGArgInfo::setRange(SWGRangeFloat* range) { + this->range = range; + this->m_range_isSet = true; +} + +QList* +SWGArgInfo::getValueOptions() { + return value_options; +} +void +SWGArgInfo::setValueOptions(QList* value_options) { + this->value_options = value_options; + this->m_value_options_isSet = true; +} + +QList* +SWGArgInfo::getOptionNames() { + return option_names; +} +void +SWGArgInfo::setOptionNames(QList* option_names) { + this->option_names = option_names; + this->m_option_names_isSet = true; +} + bool SWGArgInfo::isSet(){ @@ -147,6 +287,12 @@ SWGArgInfo::isSet(){ if(key != nullptr && *key != QString("")){ isObjectUpdated = true; break;} if(value_type != nullptr && *value_type != QString("")){ isObjectUpdated = true; break;} if(value_string != nullptr && *value_string != QString("")){ isObjectUpdated = true; break;} + if(name != nullptr && *name != QString("")){ isObjectUpdated = true; break;} + if(description != nullptr && *description != QString("")){ isObjectUpdated = true; break;} + if(units != nullptr && *units != QString("")){ isObjectUpdated = true; break;} + if(range != nullptr && range->isSet()){ isObjectUpdated = true; break;} + if(value_options->size() > 0){ isObjectUpdated = true; break;} + if(option_names->size() > 0){ isObjectUpdated = true; break;} }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGArgInfo.h b/swagger/sdrangel/code/qt5/client/SWGArgInfo.h index 8defae2d4..87af3cfbf 100644 --- a/swagger/sdrangel/code/qt5/client/SWGArgInfo.h +++ b/swagger/sdrangel/code/qt5/client/SWGArgInfo.h @@ -22,6 +22,8 @@ #include +#include "SWGRangeFloat.h" +#include #include #include "SWGObject.h" @@ -51,6 +53,24 @@ public: QString* getValueString(); void setValueString(QString* value_string); + QString* getName(); + void setName(QString* name); + + QString* getDescription(); + void setDescription(QString* description); + + QString* getUnits(); + void setUnits(QString* units); + + SWGRangeFloat* getRange(); + void setRange(SWGRangeFloat* range); + + QList* getValueOptions(); + void setValueOptions(QList* value_options); + + QList* getOptionNames(); + void setOptionNames(QList* option_names); + virtual bool isSet() override; @@ -64,6 +84,24 @@ private: QString* value_string; bool m_value_string_isSet; + QString* name; + bool m_name_isSet; + + QString* description; + bool m_description_isSet; + + QString* units; + bool m_units_isSet; + + SWGRangeFloat* range; + bool m_range_isSet; + + QList* value_options; + bool m_value_options_isSet; + + QList* option_names; + bool m_option_names_isSet; + }; } diff --git a/swagger/sdrangel/code/qt5/client/SWGArgValue.cpp b/swagger/sdrangel/code/qt5/client/SWGArgValue.cpp new file mode 100644 index 000000000..308db2390 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGArgValue.cpp @@ -0,0 +1,154 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 4.3.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGArgValue.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGArgValue::SWGArgValue(QString* json) { + init(); + this->fromJson(*json); +} + +SWGArgValue::SWGArgValue() { + key = nullptr; + m_key_isSet = false; + value_type = nullptr; + m_value_type_isSet = false; + value_string = nullptr; + m_value_string_isSet = false; +} + +SWGArgValue::~SWGArgValue() { + this->cleanup(); +} + +void +SWGArgValue::init() { + key = new QString(""); + m_key_isSet = false; + value_type = new QString(""); + m_value_type_isSet = false; + value_string = new QString(""); + m_value_string_isSet = false; +} + +void +SWGArgValue::cleanup() { + if(key != nullptr) { + delete key; + } + if(value_type != nullptr) { + delete value_type; + } + if(value_string != nullptr) { + delete value_string; + } +} + +SWGArgValue* +SWGArgValue::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGArgValue::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&key, pJson["key"], "QString", "QString"); + + ::SWGSDRangel::setValue(&value_type, pJson["valueType"], "QString", "QString"); + + ::SWGSDRangel::setValue(&value_string, pJson["valueString"], "QString", "QString"); + +} + +QString +SWGArgValue::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGArgValue::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(key != nullptr && *key != QString("")){ + toJsonValue(QString("key"), key, obj, QString("QString")); + } + if(value_type != nullptr && *value_type != QString("")){ + toJsonValue(QString("valueType"), value_type, obj, QString("QString")); + } + if(value_string != nullptr && *value_string != QString("")){ + toJsonValue(QString("valueString"), value_string, obj, QString("QString")); + } + + return obj; +} + +QString* +SWGArgValue::getKey() { + return key; +} +void +SWGArgValue::setKey(QString* key) { + this->key = key; + this->m_key_isSet = true; +} + +QString* +SWGArgValue::getValueType() { + return value_type; +} +void +SWGArgValue::setValueType(QString* value_type) { + this->value_type = value_type; + this->m_value_type_isSet = true; +} + +QString* +SWGArgValue::getValueString() { + return value_string; +} +void +SWGArgValue::setValueString(QString* value_string) { + this->value_string = value_string; + this->m_value_string_isSet = true; +} + + +bool +SWGArgValue::isSet(){ + bool isObjectUpdated = false; + do{ + if(key != nullptr && *key != QString("")){ isObjectUpdated = true; break;} + if(value_type != nullptr && *value_type != QString("")){ isObjectUpdated = true; break;} + if(value_string != nullptr && *value_string != QString("")){ isObjectUpdated = true; break;} + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGArgValue.h b/swagger/sdrangel/code/qt5/client/SWGArgValue.h new file mode 100644 index 000000000..b4579efbc --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGArgValue.h @@ -0,0 +1,71 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 4.3.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGArgValue.h + * + * + */ + +#ifndef SWGArgValue_H_ +#define SWGArgValue_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGArgValue: public SWGObject { +public: + SWGArgValue(); + SWGArgValue(QString* json); + virtual ~SWGArgValue(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGArgValue* fromJson(QString &jsonString) override; + + QString* getKey(); + void setKey(QString* key); + + QString* getValueType(); + void setValueType(QString* value_type); + + QString* getValueString(); + void setValueString(QString* value_string); + + + virtual bool isSet() override; + +private: + QString* key; + bool m_key_isSet; + + QString* value_type; + bool m_value_type_isSet; + + QString* value_string; + bool m_value_string_isSet; + +}; + +} + +#endif /* SWGArgValue_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index c717fbb26..b0d8f1a03 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -25,6 +25,7 @@ #include "SWGAirspyReport.h" #include "SWGAirspySettings.h" #include "SWGArgInfo.h" +#include "SWGArgValue.h" #include "SWGAudioDevices.h" #include "SWGAudioInputDevice.h" #include "SWGAudioOutputDevice.h" @@ -165,6 +166,9 @@ namespace SWGSDRangel { if(QString("SWGArgInfo").compare(type) == 0) { return new SWGArgInfo(); } + if(QString("SWGArgValue").compare(type) == 0) { + return new SWGArgValue(); + } if(QString("SWGAudioDevices").compare(type) == 0) { return new SWGAudioDevices(); } diff --git a/swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.cpp index b8ba64a68..217951b21 100644 --- a/swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.cpp @@ -104,11 +104,11 @@ SWGSoapySDRInputSettings::init() { m_antenna_isSet = false; bandwidth = 0; m_bandwidth_isSet = false; - tunable_elements = new QList(); + tunable_elements = new QList(); m_tunable_elements_isSet = false; global_gain = 0; m_global_gain_isSet = false; - individual_gains = new QList(); + individual_gains = new QList(); m_individual_gains_isSet = false; auto_gain = 0; m_auto_gain_isSet = false; @@ -120,9 +120,9 @@ SWGSoapySDRInputSettings::init() { m_dc_correction_isSet = false; iq_correction = new SWGComplex(); m_iq_correction_isSet = false; - stream_arg_settings = new QList(); + stream_arg_settings = new QList(); m_stream_arg_settings_isSet = false; - device_arg_settings = new QList(); + device_arg_settings = new QList(); m_device_arg_settings_isSet = false; } @@ -220,11 +220,11 @@ SWGSoapySDRInputSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&bandwidth, pJson["bandwidth"], "qint32", ""); - ::SWGSDRangel::setValue(&tunable_elements, pJson["tunableElements"], "QList", "SWGArgInfo"); + ::SWGSDRangel::setValue(&tunable_elements, pJson["tunableElements"], "QList", "SWGArgValue"); ::SWGSDRangel::setValue(&global_gain, pJson["globalGain"], "qint32", ""); - ::SWGSDRangel::setValue(&individual_gains, pJson["individualGains"], "QList", "SWGArgInfo"); + ::SWGSDRangel::setValue(&individual_gains, pJson["individualGains"], "QList", "SWGArgValue"); ::SWGSDRangel::setValue(&auto_gain, pJson["autoGain"], "qint32", ""); ::SWGSDRangel::setValue(&auto_dc_correction, pJson["autoDCCorrection"], "qint32", ""); @@ -236,9 +236,9 @@ SWGSoapySDRInputSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "SWGComplex", "SWGComplex"); - ::SWGSDRangel::setValue(&stream_arg_settings, pJson["streamArgSettings"], "QList", "SWGArgInfo"); + ::SWGSDRangel::setValue(&stream_arg_settings, pJson["streamArgSettings"], "QList", "SWGArgValue"); - ::SWGSDRangel::setValue(&device_arg_settings, pJson["deviceArgSettings"], "QList", "SWGArgInfo"); + ::SWGSDRangel::setValue(&device_arg_settings, pJson["deviceArgSettings"], "QList", "SWGArgValue"); } QString @@ -292,13 +292,13 @@ SWGSoapySDRInputSettings::asJsonObject() { obj->insert("bandwidth", QJsonValue(bandwidth)); } if(tunable_elements->size() > 0){ - toJsonArray((QList*)tunable_elements, obj, "tunableElements", "SWGArgInfo"); + toJsonArray((QList*)tunable_elements, obj, "tunableElements", "SWGArgValue"); } if(m_global_gain_isSet){ obj->insert("globalGain", QJsonValue(global_gain)); } if(individual_gains->size() > 0){ - toJsonArray((QList*)individual_gains, obj, "individualGains", "SWGArgInfo"); + toJsonArray((QList*)individual_gains, obj, "individualGains", "SWGArgValue"); } if(m_auto_gain_isSet){ obj->insert("autoGain", QJsonValue(auto_gain)); @@ -316,10 +316,10 @@ SWGSoapySDRInputSettings::asJsonObject() { toJsonValue(QString("iqCorrection"), iq_correction, obj, QString("SWGComplex")); } if(stream_arg_settings->size() > 0){ - toJsonArray((QList*)stream_arg_settings, obj, "streamArgSettings", "SWGArgInfo"); + toJsonArray((QList*)stream_arg_settings, obj, "streamArgSettings", "SWGArgValue"); } if(device_arg_settings->size() > 0){ - toJsonArray((QList*)device_arg_settings, obj, "deviceArgSettings", "SWGArgInfo"); + toJsonArray((QList*)device_arg_settings, obj, "deviceArgSettings", "SWGArgValue"); } return obj; @@ -445,12 +445,12 @@ SWGSoapySDRInputSettings::setBandwidth(qint32 bandwidth) { this->m_bandwidth_isSet = true; } -QList* +QList* SWGSoapySDRInputSettings::getTunableElements() { return tunable_elements; } void -SWGSoapySDRInputSettings::setTunableElements(QList* tunable_elements) { +SWGSoapySDRInputSettings::setTunableElements(QList* tunable_elements) { this->tunable_elements = tunable_elements; this->m_tunable_elements_isSet = true; } @@ -465,12 +465,12 @@ SWGSoapySDRInputSettings::setGlobalGain(qint32 global_gain) { this->m_global_gain_isSet = true; } -QList* +QList* SWGSoapySDRInputSettings::getIndividualGains() { return individual_gains; } void -SWGSoapySDRInputSettings::setIndividualGains(QList* individual_gains) { +SWGSoapySDRInputSettings::setIndividualGains(QList* individual_gains) { this->individual_gains = individual_gains; this->m_individual_gains_isSet = true; } @@ -525,22 +525,22 @@ SWGSoapySDRInputSettings::setIqCorrection(SWGComplex* iq_correction) { this->m_iq_correction_isSet = true; } -QList* +QList* SWGSoapySDRInputSettings::getStreamArgSettings() { return stream_arg_settings; } void -SWGSoapySDRInputSettings::setStreamArgSettings(QList* stream_arg_settings) { +SWGSoapySDRInputSettings::setStreamArgSettings(QList* stream_arg_settings) { this->stream_arg_settings = stream_arg_settings; this->m_stream_arg_settings_isSet = true; } -QList* +QList* SWGSoapySDRInputSettings::getDeviceArgSettings() { return device_arg_settings; } void -SWGSoapySDRInputSettings::setDeviceArgSettings(QList* device_arg_settings) { +SWGSoapySDRInputSettings::setDeviceArgSettings(QList* device_arg_settings) { this->device_arg_settings = device_arg_settings; this->m_device_arg_settings_isSet = true; } diff --git a/swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.h b/swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.h index 53c0773d8..a2153653f 100644 --- a/swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGSoapySDRInputSettings.h @@ -22,7 +22,7 @@ #include -#include "SWGArgInfo.h" +#include "SWGArgValue.h" #include "SWGComplex.h" #include #include @@ -81,14 +81,14 @@ public: qint32 getBandwidth(); void setBandwidth(qint32 bandwidth); - QList* getTunableElements(); - void setTunableElements(QList* tunable_elements); + QList* getTunableElements(); + void setTunableElements(QList* tunable_elements); qint32 getGlobalGain(); void setGlobalGain(qint32 global_gain); - QList* getIndividualGains(); - void setIndividualGains(QList* individual_gains); + QList* getIndividualGains(); + void setIndividualGains(QList* individual_gains); qint32 getAutoGain(); void setAutoGain(qint32 auto_gain); @@ -105,11 +105,11 @@ public: SWGComplex* getIqCorrection(); void setIqCorrection(SWGComplex* iq_correction); - QList* getStreamArgSettings(); - void setStreamArgSettings(QList* stream_arg_settings); + QList* getStreamArgSettings(); + void setStreamArgSettings(QList* stream_arg_settings); - QList* getDeviceArgSettings(); - void setDeviceArgSettings(QList* device_arg_settings); + QList* getDeviceArgSettings(); + void setDeviceArgSettings(QList* device_arg_settings); virtual bool isSet() override; @@ -151,13 +151,13 @@ private: qint32 bandwidth; bool m_bandwidth_isSet; - QList* tunable_elements; + QList* tunable_elements; bool m_tunable_elements_isSet; qint32 global_gain; bool m_global_gain_isSet; - QList* individual_gains; + QList* individual_gains; bool m_individual_gains_isSet; qint32 auto_gain; @@ -175,10 +175,10 @@ private: SWGComplex* iq_correction; bool m_iq_correction_isSet; - QList* stream_arg_settings; + QList* stream_arg_settings; bool m_stream_arg_settings_isSet; - QList* device_arg_settings; + QList* device_arg_settings; bool m_device_arg_settings_isSet; }; diff --git a/swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.cpp index 1750cb6a8..dc169a96e 100644 --- a/swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.cpp @@ -88,11 +88,11 @@ SWGSoapySDROutputSettings::init() { m_antenna_isSet = false; bandwidth = 0; m_bandwidth_isSet = false; - tunable_elements = new QList(); + tunable_elements = new QList(); m_tunable_elements_isSet = false; global_gain = 0; m_global_gain_isSet = false; - individual_gains = new QList(); + individual_gains = new QList(); m_individual_gains_isSet = false; auto_gain = 0; m_auto_gain_isSet = false; @@ -104,9 +104,9 @@ SWGSoapySDROutputSettings::init() { m_dc_correction_isSet = false; iq_correction = new SWGComplex(); m_iq_correction_isSet = false; - stream_arg_settings = new QList(); + stream_arg_settings = new QList(); m_stream_arg_settings_isSet = false; - device_arg_settings = new QList(); + device_arg_settings = new QList(); m_device_arg_settings_isSet = false; } @@ -190,11 +190,11 @@ SWGSoapySDROutputSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&bandwidth, pJson["bandwidth"], "qint32", ""); - ::SWGSDRangel::setValue(&tunable_elements, pJson["tunableElements"], "QList", "SWGArgInfo"); + ::SWGSDRangel::setValue(&tunable_elements, pJson["tunableElements"], "QList", "SWGArgValue"); ::SWGSDRangel::setValue(&global_gain, pJson["globalGain"], "qint32", ""); - ::SWGSDRangel::setValue(&individual_gains, pJson["individualGains"], "QList", "SWGArgInfo"); + ::SWGSDRangel::setValue(&individual_gains, pJson["individualGains"], "QList", "SWGArgValue"); ::SWGSDRangel::setValue(&auto_gain, pJson["autoGain"], "qint32", ""); ::SWGSDRangel::setValue(&auto_dc_correction, pJson["autoDCCorrection"], "qint32", ""); @@ -206,9 +206,9 @@ SWGSoapySDROutputSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "SWGComplex", "SWGComplex"); - ::SWGSDRangel::setValue(&stream_arg_settings, pJson["streamArgSettings"], "QList", "SWGArgInfo"); + ::SWGSDRangel::setValue(&stream_arg_settings, pJson["streamArgSettings"], "QList", "SWGArgValue"); - ::SWGSDRangel::setValue(&device_arg_settings, pJson["deviceArgSettings"], "QList", "SWGArgInfo"); + ::SWGSDRangel::setValue(&device_arg_settings, pJson["deviceArgSettings"], "QList", "SWGArgValue"); } QString @@ -250,13 +250,13 @@ SWGSoapySDROutputSettings::asJsonObject() { obj->insert("bandwidth", QJsonValue(bandwidth)); } if(tunable_elements->size() > 0){ - toJsonArray((QList*)tunable_elements, obj, "tunableElements", "SWGArgInfo"); + toJsonArray((QList*)tunable_elements, obj, "tunableElements", "SWGArgValue"); } if(m_global_gain_isSet){ obj->insert("globalGain", QJsonValue(global_gain)); } if(individual_gains->size() > 0){ - toJsonArray((QList*)individual_gains, obj, "individualGains", "SWGArgInfo"); + toJsonArray((QList*)individual_gains, obj, "individualGains", "SWGArgValue"); } if(m_auto_gain_isSet){ obj->insert("autoGain", QJsonValue(auto_gain)); @@ -274,10 +274,10 @@ SWGSoapySDROutputSettings::asJsonObject() { toJsonValue(QString("iqCorrection"), iq_correction, obj, QString("SWGComplex")); } if(stream_arg_settings->size() > 0){ - toJsonArray((QList*)stream_arg_settings, obj, "streamArgSettings", "SWGArgInfo"); + toJsonArray((QList*)stream_arg_settings, obj, "streamArgSettings", "SWGArgValue"); } if(device_arg_settings->size() > 0){ - toJsonArray((QList*)device_arg_settings, obj, "deviceArgSettings", "SWGArgInfo"); + toJsonArray((QList*)device_arg_settings, obj, "deviceArgSettings", "SWGArgValue"); } return obj; @@ -363,12 +363,12 @@ SWGSoapySDROutputSettings::setBandwidth(qint32 bandwidth) { this->m_bandwidth_isSet = true; } -QList* +QList* SWGSoapySDROutputSettings::getTunableElements() { return tunable_elements; } void -SWGSoapySDROutputSettings::setTunableElements(QList* tunable_elements) { +SWGSoapySDROutputSettings::setTunableElements(QList* tunable_elements) { this->tunable_elements = tunable_elements; this->m_tunable_elements_isSet = true; } @@ -383,12 +383,12 @@ SWGSoapySDROutputSettings::setGlobalGain(qint32 global_gain) { this->m_global_gain_isSet = true; } -QList* +QList* SWGSoapySDROutputSettings::getIndividualGains() { return individual_gains; } void -SWGSoapySDROutputSettings::setIndividualGains(QList* individual_gains) { +SWGSoapySDROutputSettings::setIndividualGains(QList* individual_gains) { this->individual_gains = individual_gains; this->m_individual_gains_isSet = true; } @@ -443,22 +443,22 @@ SWGSoapySDROutputSettings::setIqCorrection(SWGComplex* iq_correction) { this->m_iq_correction_isSet = true; } -QList* +QList* SWGSoapySDROutputSettings::getStreamArgSettings() { return stream_arg_settings; } void -SWGSoapySDROutputSettings::setStreamArgSettings(QList* stream_arg_settings) { +SWGSoapySDROutputSettings::setStreamArgSettings(QList* stream_arg_settings) { this->stream_arg_settings = stream_arg_settings; this->m_stream_arg_settings_isSet = true; } -QList* +QList* SWGSoapySDROutputSettings::getDeviceArgSettings() { return device_arg_settings; } void -SWGSoapySDROutputSettings::setDeviceArgSettings(QList* device_arg_settings) { +SWGSoapySDROutputSettings::setDeviceArgSettings(QList* device_arg_settings) { this->device_arg_settings = device_arg_settings; this->m_device_arg_settings_isSet = true; } diff --git a/swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.h b/swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.h index 01c1a2102..d8a3dfdfa 100644 --- a/swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGSoapySDROutputSettings.h @@ -22,7 +22,7 @@ #include -#include "SWGArgInfo.h" +#include "SWGArgValue.h" #include "SWGComplex.h" #include #include @@ -69,14 +69,14 @@ public: qint32 getBandwidth(); void setBandwidth(qint32 bandwidth); - QList* getTunableElements(); - void setTunableElements(QList* tunable_elements); + QList* getTunableElements(); + void setTunableElements(QList* tunable_elements); qint32 getGlobalGain(); void setGlobalGain(qint32 global_gain); - QList* getIndividualGains(); - void setIndividualGains(QList* individual_gains); + QList* getIndividualGains(); + void setIndividualGains(QList* individual_gains); qint32 getAutoGain(); void setAutoGain(qint32 auto_gain); @@ -93,11 +93,11 @@ public: SWGComplex* getIqCorrection(); void setIqCorrection(SWGComplex* iq_correction); - QList* getStreamArgSettings(); - void setStreamArgSettings(QList* stream_arg_settings); + QList* getStreamArgSettings(); + void setStreamArgSettings(QList* stream_arg_settings); - QList* getDeviceArgSettings(); - void setDeviceArgSettings(QList* device_arg_settings); + QList* getDeviceArgSettings(); + void setDeviceArgSettings(QList* device_arg_settings); virtual bool isSet() override; @@ -127,13 +127,13 @@ private: qint32 bandwidth; bool m_bandwidth_isSet; - QList* tunable_elements; + QList* tunable_elements; bool m_tunable_elements_isSet; qint32 global_gain; bool m_global_gain_isSet; - QList* individual_gains; + QList* individual_gains; bool m_individual_gains_isSet; qint32 auto_gain; @@ -151,10 +151,10 @@ private: SWGComplex* iq_correction; bool m_iq_correction_isSet; - QList* stream_arg_settings; + QList* stream_arg_settings; bool m_stream_arg_settings_isSet; - QList* device_arg_settings; + QList* device_arg_settings; bool m_device_arg_settings_isSet; }; From 19dff97a1ce99f74ee6ec8de710aef468dd269f9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 14 Nov 2018 09:19:36 +0100 Subject: [PATCH 038/102] SoapySDR support: REST API: output: format settings and report --- .../soapysdroutput/soapysdroutput.cpp | 251 ++++++++++++++++++ .../soapysdroutput/soapysdroutput.h | 11 + 2 files changed, 262 insertions(+) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index 17fb49e20..9dcafdf0e 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -16,6 +16,12 @@ #include +#include "SWGDeviceSettings.h" +#include "SWGSoapySDROutputSettings.h" +#include "SWGDeviceState.h" +#include "SWGDeviceReport.h" +#include "SWGSoapySDRReport.h" + #include "util/simpleserializer.h" #include "dsp/dspcommands.h" #include "dsp/dspengine.h" @@ -1189,3 +1195,248 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool return true; } + +void SoapySDROutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SoapySDROutputSettings& settings) +{ + response.getSoapySdrOutputSettings()->setCenterFrequency(settings.m_centerFrequency); + response.getSoapySdrOutputSettings()->setLOppmTenths(settings.m_LOppmTenths); + response.getSoapySdrOutputSettings()->setDevSampleRate(settings.m_devSampleRate); + response.getSoapySdrOutputSettings()->setLog2Interp(settings.m_log2Interp); + response.getSoapySdrOutputSettings()->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency); + response.getSoapySdrOutputSettings()->setTransverterMode(settings.m_transverterMode ? 1 : 0); + + if (response.getSoapySdrOutputSettings()->getAntenna()) { + *response.getSoapySdrOutputSettings()->getAntenna() = settings.m_antenna; + } else { + response.getSoapySdrOutputSettings()->setAntenna(new QString(settings.m_antenna)); + } + + if (response.getSoapySdrOutputSettings()->getTunableElements()) { + response.getSoapySdrOutputSettings()->getTunableElements()->clear(); + } else { + response.getSoapySdrOutputSettings()->setTunableElements(new QList); + } + + for (const auto itName : settings.m_tunableElements.keys()) + { + response.getSoapySdrOutputSettings()->getTunableElements()->append(new SWGSDRangel::SWGArgValue); + response.getSoapySdrOutputSettings()->getTunableElements()->back()->setKey(new QString( itName)); + double value = settings.m_tunableElements.value(itName); + response.getSoapySdrOutputSettings()->getTunableElements()->back()->setValueString(new QString(tr("%1").arg(value))); + response.getSoapySdrOutputSettings()->getTunableElements()->back()->setValueType(new QString("float")); + } + + response.getSoapySdrOutputSettings()->setBandwidth(settings.m_bandwidth); + response.getSoapySdrOutputSettings()->setGlobalGain(settings.m_globalGain); + + if (response.getSoapySdrOutputSettings()->getIndividualGains()) { + response.getSoapySdrOutputSettings()->getIndividualGains()->clear(); + } else { + response.getSoapySdrOutputSettings()->setIndividualGains(new QList); + } + + for (const auto itName : settings.m_individualGains.keys()) + { + response.getSoapySdrOutputSettings()->getIndividualGains()->append(new SWGSDRangel::SWGArgValue); + response.getSoapySdrOutputSettings()->getIndividualGains()->back()->setKey(new QString(itName)); + double value = settings.m_individualGains.value(itName); + response.getSoapySdrOutputSettings()->getIndividualGains()->back()->setValueString(new QString(tr("%1").arg(value))); + response.getSoapySdrOutputSettings()->getIndividualGains()->back()->setValueType(new QString("float")); + } + + response.getSoapySdrOutputSettings()->setAutoGain(settings.m_autoGain ? 1 : 0); + response.getSoapySdrOutputSettings()->setAutoDcCorrection(settings.m_autoDCCorrection ? 1 : 0); + response.getSoapySdrOutputSettings()->setAutoIqCorrection(settings.m_autoIQCorrection ? 1 : 0); + + if (!response.getSoapySdrOutputSettings()->getDcCorrection()) { + response.getSoapySdrOutputSettings()->setDcCorrection(new SWGSDRangel::SWGComplex()); + } + + response.getSoapySdrOutputSettings()->getDcCorrection()->setReal(settings.m_dcCorrection.real()); + response.getSoapySdrOutputSettings()->getDcCorrection()->setImag(settings.m_dcCorrection.imag()); + + if (!response.getSoapySdrOutputSettings()->getIqCorrection()) { + response.getSoapySdrOutputSettings()->setIqCorrection(new SWGSDRangel::SWGComplex()); + } + + response.getSoapySdrOutputSettings()->getIqCorrection()->setReal(settings.m_iqCorrection.real()); + response.getSoapySdrOutputSettings()->getIqCorrection()->setImag(settings.m_iqCorrection.imag()); + + if (response.getSoapySdrOutputSettings()->getStreamArgSettings()) { + response.getSoapySdrOutputSettings()->getStreamArgSettings()->clear(); + } else { + response.getSoapySdrOutputSettings()->setStreamArgSettings(new QList); + } + + for (const auto itName : settings.m_streamArgSettings.keys()) + { + response.getSoapySdrOutputSettings()->getStreamArgSettings()->append(new SWGSDRangel::SWGArgValue); + response.getSoapySdrOutputSettings()->getStreamArgSettings()->back()->setKey(new QString(itName)); + const QVariant& v = settings.m_streamArgSettings.value(itName); + webapiFormatArgValue(v, response.getSoapySdrOutputSettings()->getStreamArgSettings()->back()); + } + + if (response.getSoapySdrOutputSettings()->getDeviceArgSettings()) { + response.getSoapySdrOutputSettings()->getDeviceArgSettings()->clear(); + } else { + response.getSoapySdrOutputSettings()->setDeviceArgSettings(new QList); + } + + for (const auto itName : settings.m_deviceArgSettings.keys()) + { + response.getSoapySdrOutputSettings()->getDeviceArgSettings()->append(new SWGSDRangel::SWGArgValue); + response.getSoapySdrOutputSettings()->getDeviceArgSettings()->back()->setKey(new QString(itName)); + const QVariant& v = settings.m_deviceArgSettings.value(itName); + webapiFormatArgValue(v, response.getSoapySdrOutputSettings()->getDeviceArgSettings()->back()); + } +} + +void SoapySDROutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response) +{ + const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getTxChannelSettings(m_deviceShared.m_channel); + + response.getSoapySdrOutputReport()->setDeviceSettingsArgs(new QList); + + for (const auto itArg : m_deviceShared.m_deviceParams->getDeviceArgs()) + { + response.getSoapySdrOutputReport()->getDeviceSettingsArgs()->append(new SWGSDRangel::SWGArgInfo); + webapiFormatArgInfo(itArg, response.getSoapySdrOutputReport()->getDeviceSettingsArgs()->back()); + } + + response.getSoapySdrOutputReport()->setStreamSettingsArgs(new QList); + + for (const auto itArg : channelSettings->m_streamSettingsArgs) + { + response.getSoapySdrOutputReport()->getStreamSettingsArgs()->append(new SWGSDRangel::SWGArgInfo); + webapiFormatArgInfo(itArg, response.getSoapySdrOutputReport()->getStreamSettingsArgs()->back()); + } + + response.getSoapySdrOutputReport()->setFrequencySettingsArgs(new QList); + + for (const auto itArg : channelSettings->m_frequencySettingsArgs) + { + response.getSoapySdrOutputReport()->getFrequencySettingsArgs()->append(new SWGSDRangel::SWGArgInfo); + webapiFormatArgInfo(itArg, response.getSoapySdrOutputReport()->getFrequencySettingsArgs()->back()); + } + + response.getSoapySdrOutputReport()->setHasAgc(channelSettings->m_hasAGC ? 1 : 0); + response.getSoapySdrOutputReport()->setHasDcAutoCorrection(channelSettings->m_hasDCAutoCorrection ? 1 : 0); + response.getSoapySdrOutputReport()->setHasDcOffsetValue(channelSettings->m_hasDCOffsetValue ? 1 : 0); + response.getSoapySdrOutputReport()->setHasFrequencyCorrectionValue(channelSettings->m_hasFrequencyCorrectionValue ? 1 : 0); + response.getSoapySdrOutputReport()->setHasIqBalanceValue(channelSettings->m_hasIQBalanceValue ? 1 : 0); + + if (channelSettings->m_antennas.size() != 0) + { + response.getSoapySdrOutputReport()->setAntennas(new QList); + + for (const auto itAntenna : channelSettings->m_antennas) { + response.getSoapySdrOutputReport()->getAntennas()->append(new QString(itAntenna.c_str())); + } + } + + if ((channelSettings->m_gainRange.maximum() != 0.0) || (channelSettings->m_gainRange.minimum() != 0.0)) + { + response.getSoapySdrOutputReport()->setGainRange(new SWGSDRangel::SWGRangeFloat()); + response.getSoapySdrOutputReport()->getGainRange()->setMin(channelSettings->m_gainRange.minimum()); + response.getSoapySdrOutputReport()->getGainRange()->setMax(channelSettings->m_gainRange.maximum()); + } + + if (channelSettings->m_gainSettings.size() != 0) + { + response.getSoapySdrOutputReport()->setGainSettings(new QList); + + for (const auto itGain : channelSettings->m_gainSettings) + { + response.getSoapySdrOutputReport()->getGainSettings()->append(new SWGSDRangel::SWGSoapySDRGainSetting()); + response.getSoapySdrOutputReport()->getGainSettings()->back()->setRange(new SWGSDRangel::SWGRangeFloat()); + response.getSoapySdrOutputReport()->getGainSettings()->back()->getRange()->setMin(itGain.m_range.minimum()); + response.getSoapySdrOutputReport()->getGainSettings()->back()->getRange()->setMax(itGain.m_range.maximum()); + response.getSoapySdrOutputReport()->getGainSettings()->back()->setName(new QString(itGain.m_name.c_str())); + } + } + + if (channelSettings->m_frequencySettings.size() != 0) + { + response.getSoapySdrOutputReport()->setFrequencySettings(new QList); + + for (const auto itFreq : channelSettings->m_frequencySettings) + { + response.getSoapySdrOutputReport()->getFrequencySettings()->append(new SWGSDRangel::SWGSoapySDRFrequencySetting()); + response.getSoapySdrOutputReport()->getFrequencySettings()->back()->setRanges(new QList); + + for (const auto itRange : itFreq.m_ranges) + { + response.getSoapySdrOutputReport()->getFrequencySettings()->back()->getRanges()->append(new SWGSDRangel::SWGRangeFloat()); + response.getSoapySdrOutputReport()->getFrequencySettings()->back()->getRanges()->back()->setMin(itRange.minimum()); + response.getSoapySdrOutputReport()->getFrequencySettings()->back()->getRanges()->back()->setMax(itRange.maximum()); + } + + response.getSoapySdrOutputReport()->getFrequencySettings()->back()->setName(new QString(itFreq.m_name.c_str())); + } + } + + if (channelSettings->m_ratesRanges.size() != 0) + { + response.getSoapySdrOutputReport()->setRatesRanges(new QList); + + for (const auto itRange : channelSettings->m_ratesRanges) + { + response.getSoapySdrOutputReport()->getRatesRanges()->append(new SWGSDRangel::SWGRangeFloat()); + response.getSoapySdrOutputReport()->getRatesRanges()->back()->setMin(itRange.minimum()); + response.getSoapySdrOutputReport()->getRatesRanges()->back()->setMax(itRange.maximum()); + } + } + + if (channelSettings->m_bandwidthsRanges.size() != 0) + { + response.getSoapySdrOutputReport()->setBandwidthsRanges(new QList); + + for (const auto itBandwidth : channelSettings->m_bandwidthsRanges) + { + response.getSoapySdrOutputReport()->getBandwidthsRanges()->append(new SWGSDRangel::SWGRangeFloat()); + response.getSoapySdrOutputReport()->getBandwidthsRanges()->back()->setMin(itBandwidth.minimum()); + response.getSoapySdrOutputReport()->getBandwidthsRanges()->back()->setMax(itBandwidth.maximum()); + } + } +} + +void SoapySDROutput::webapiFormatArgValue(const QVariant& v, SWGSDRangel::SWGArgValue *argValue) +{ + if (v.type() == QVariant::Bool) + { + argValue->setValueType(new QString("bool")); + argValue->setValueString(new QString(v.toBool() ? "1" : "0")); + } + else if (v.type() == QVariant::Int) + { + argValue->setValueType(new QString("int")); + argValue->setValueString(new QString(tr("%1").arg(v.toInt()))); + } + else if (v.type() == QVariant::Double) + { + argValue->setValueType(new QString("float")); + argValue->setValueString(new QString(tr("%1").arg(v.toDouble()))); + } + else + { + argValue->setValueType(new QString("string")); + argValue->setValueString(new QString(v.toString())); + } +} + +void SoapySDROutput::webapiFormatArgInfo(const SoapySDR::ArgInfo& arg, SWGSDRangel::SWGArgInfo *argInfo) +{ + argInfo->setKey(new QString(arg.key.c_str())); + + if (arg.type == SoapySDR::ArgInfo::BOOL) { + argInfo->setValueType(new QString("bool")); + } else if (arg.type == SoapySDR::ArgInfo::INT) { + argInfo->setValueType(new QString("int")); + } else if (arg.type == SoapySDR::ArgInfo::FLOAT) { + argInfo->setValueType(new QString("float")); + } else { + argInfo->setValueType(new QString("string")); + } + + argInfo->setValueString(new QString(arg.value.c_str())); +} diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.h b/plugins/samplesink/soapysdroutput/soapysdroutput.h index cb7a0973d..a896e5061 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.h @@ -32,6 +32,13 @@ class SoapySDROutputThread; namespace SoapySDR { class Device; + class ArgInfo; +} + +namespace SWGSDRangel +{ + class SWGArgValue; + class SWGArgInfo; } class SoapySDROutput : public DeviceSampleSink { @@ -159,6 +166,10 @@ private: bool applySettings(const SoapySDROutputSettings& settings, bool force = false); bool setDeviceCenterFrequency(SoapySDR::Device *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths); void updateGains(SoapySDR::Device *dev, int requestedChannel, SoapySDROutputSettings& settings); + void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SoapySDROutputSettings& settings); + void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + void webapiFormatArgValue(const QVariant& v, SWGSDRangel::SWGArgValue *argValue); + void webapiFormatArgInfo(const SoapySDR::ArgInfo& arg, SWGSDRangel::SWGArgInfo *argInfo); }; From ee95e1d617525ee8bfcf0808c2a7a8063b7262e1 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 14 Nov 2018 18:02:45 +0100 Subject: [PATCH 039/102] Windows: MSVC2017: include LimeSDR plugins --- devices/devices.pro | 15 +++- devices/limesdr/devicelimesdrshared.h | 8 +- .../limesdroutput/limesdroutput.cpp | 2 +- .../limesdroutput/limesdroutput.pro | 37 ++++++--- .../limesdrinput/limesdrinput.pro | 36 +++++--- sdrangel.windows.pro | 4 +- windowsms.install.bat | 82 +++++++++++++++++++ 7 files changed, 151 insertions(+), 33 deletions(-) create mode 100644 windowsms.install.bat diff --git a/devices/devices.pro b/devices/devices.pro index 0199ff713..549796b6c 100644 --- a/devices/devices.pro +++ b/devices/devices.pro @@ -61,7 +61,7 @@ MINGW32 || MINGW64 || macx { } MSVC { - INCLUDEPATH += "C:\softs\PothosSDR\include" + INCLUDEPATH += "C:\Programs\PothosSDR\include" } INCLUDEPATH += $$LIBPERSEUSSRC @@ -144,6 +144,11 @@ MSVC { limesdr/devicelimesdrparam.cpp\ limesdr/devicelimesdrshared.cpp + SOURCES += soapysdr/devicesoapysdr.cpp\ + soapysdr/devicesoapysdrparams.cpp\ + soapysdr/devicesoapysdrscan.cpp\ + soapysdr/devicesoapysdrshared.cpp + HEADERS += hackrf/devicehackrf.h\ hackrf/devicehackrfparam.h\ hackrf/devicehackrfvalues.h\ @@ -152,6 +157,11 @@ MSVC { HEADERS += limesdr/devicelimesdr.h\ limesdr/devicelimesdrparam.h\ limesdr/devicelimesdrshared.h + + HEADERS += soapysdr/devicesoapysdr.h\ + soapysdr/devicesoapysdrparams.h\ + soapysdr/devicesoapysdrscan.h\ + soapysdr/devicesoapysdrshared.h } LIBS += -L../sdrbase/$${build_subdir} -lsdrbase @@ -171,5 +181,6 @@ macx { MSVC { LIBS += -L../libhackrf/$${build_subdir} -llibhackrf - LIBS += -LC:\softs\PothosSDR\lib -lLimeSuite + LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lLimeSuite + LIBS += -LC:\Programs\PothosSDR\bin -lSoapySDR } diff --git a/devices/limesdr/devicelimesdrshared.h b/devices/limesdr/devicelimesdrshared.h index c8df559e2..3d98d0923 100644 --- a/devices/limesdr/devicelimesdrshared.h +++ b/devices/limesdr/devicelimesdrshared.h @@ -28,7 +28,7 @@ class DEVICES_API DeviceLimeSDRShared { public: - class MsgReportBuddyChange : public Message { + class DEVICES_API MsgReportBuddyChange : public Message { MESSAGE_CLASS_DECLARATION public: @@ -69,7 +69,7 @@ public: { } }; - class MsgReportClockSourceChange : public Message { + class DEVICES_API MsgReportClockSourceChange : public Message { MESSAGE_CLASS_DECLARATION public: @@ -98,7 +98,7 @@ public: { } }; - class MsgReportDeviceInfo : public Message { + class DEVICES_API MsgReportDeviceInfo : public Message { MESSAGE_CLASS_DECLARATION public: @@ -118,7 +118,7 @@ public: { } }; - class ThreadInterface + class DEVICES_API ThreadInterface { public: virtual void startWork() = 0; diff --git a/plugins/samplesink/limesdroutput/limesdroutput.cpp b/plugins/samplesink/limesdroutput/limesdroutput.cpp index 09c8fd387..1cffadf56 100644 --- a/plugins/samplesink/limesdroutput/limesdroutput.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutput.cpp @@ -772,7 +772,7 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || (m_settings.m_log2SoftInterp != settings.m_log2SoftInterp) || force) { - int fifoSize = std::max( + int fifoSize = (std::max)( (int) ((settings.m_devSampleRate/(1< Date: Wed, 14 Nov 2018 19:11:32 +0100 Subject: [PATCH 040/102] Windows: MSVC2017: added missing libraries in the deployment script --- windowsms.install.bat | 3 +++ 1 file changed, 3 insertions(+) diff --git a/windowsms.install.bat b/windowsms.install.bat index c972d08c1..0a3a67576 100644 --- a/windowsms.install.bat +++ b/windowsms.install.bat @@ -4,6 +4,7 @@ SET libxml2dir="C:\softs\libxml2-2.7.8.win32" SET libiconvdir="C:\softs\iconv-1.9.2.win32" SET libzlib1dir="C:\softs\zlib-1.2.5" SET pothosdir="C:\Programs\PothosSDR" +SET pthreadsdir="C:\softs\pthreads-w32" copy app\%1\sdrangel.exe %2 copy sdrbase\%1\sdrbase.dll %2 @@ -26,8 +27,10 @@ copy libairspyhf\%1\libairspyhf.dll %2 REM copy libbladerf\%1\libbladerf.dll %2 REM copy libiio\%1\libiio.dll %2 copy %pothosdir%\bin\LimeSuite.dll %2 +copy %pothosdir%\bin\SoapySDR.dll %2 copy %libusbdir%\dll\libusb-1.0.dll %2 +copy %pthreadsdir%\dll\x64\pthreadVC2.dll %2 REM copy libsqlite3\%1\libsqlite3.dll %2 REM copy %libxml2dir%\bin\libxml2.dll %2 REM copy %libiconvdir%\bin\iconv.dll %2 From da5ac0f0c63f56929f4ee21a2f8d223c88cf1db8 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 14 Nov 2018 23:34:03 +0100 Subject: [PATCH 041/102] SoapySDR support: REST API: rest of input and output methods --- .../soapysdroutput/soapysdroutput.cpp | 175 ++++++++++++++++ .../soapysdroutput/soapysdroutput.h | 23 +++ .../soapysdrinput/soapysdrinput.cpp | 187 ++++++++++++++++++ .../soapysdrinput/soapysdrinput.h | 23 +++ 4 files changed, 408 insertions(+) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index 9dcafdf0e..20cb58ac7 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -1196,6 +1196,181 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool return true; } +int SoapySDROutput::webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setSoapySdrOutputSettings(new SWGSDRangel::SWGSoapySDROutputSettings()); + response.getSoapySdrOutputSettings()->init(); + webapiFormatDeviceSettings(response, m_settings); + return 200; +} + +int SoapySDROutput::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage) +{ + (void) errorMessage; + SoapySDROutputSettings settings = m_settings; + + if (deviceSettingsKeys.contains("centerFrequency")) { + settings.m_centerFrequency = response.getSoapySdrOutputSettings()->getCenterFrequency(); + } + if (deviceSettingsKeys.contains("LOppmTenths")) { + settings.m_LOppmTenths = response.getSoapySdrOutputSettings()->getLOppmTenths(); + } + if (deviceSettingsKeys.contains("devSampleRate")) { + settings.m_devSampleRate = response.getSoapySdrOutputSettings()->getDevSampleRate(); + } + if (deviceSettingsKeys.contains("bandwidth")) { + settings.m_bandwidth = response.getSoapySdrOutputSettings()->getBandwidth(); + } + if (deviceSettingsKeys.contains("log2Interp")) { + settings.m_log2Interp = response.getSoapySdrOutputSettings()->getLog2Interp(); + } + if (deviceSettingsKeys.contains("transverterDeltaFrequency")) { + settings.m_transverterDeltaFrequency = response.getSoapySdrOutputSettings()->getTransverterDeltaFrequency(); + } + if (deviceSettingsKeys.contains("transverterMode")) { + settings.m_transverterMode = response.getSoapySdrOutputSettings()->getTransverterMode() != 0; + } + if (deviceSettingsKeys.contains("antenna")) { + settings.m_antenna = *response.getSoapySdrOutputSettings()->getAntenna(); + } + + if (deviceSettingsKeys.contains("tunableElements")) + { + QList *tunableElements = response.getSoapySdrOutputSettings()->getTunableElements(); + + for (const auto itArg : *tunableElements) + { + auto ovalue = settings.m_tunableElements.find(*itArg->getKey()); + + if ((ovalue != settings.m_tunableElements.end()) && (m_settings.m_tunableElements[*itArg->getKey()] != *ovalue)) { + m_settings.m_tunableElements[*itArg->getKey()] = *ovalue; + } + } + } + + if (deviceSettingsKeys.contains("globalGain")) { + settings.m_globalGain = response.getSoapySdrOutputSettings()->getGlobalGain(); + } + + if (deviceSettingsKeys.contains("individualGains")) + { + QList *individualGains = response.getSoapySdrOutputSettings()->getIndividualGains(); + + for (const auto itArg : *individualGains) + { + auto ovalue = settings.m_individualGains.find(*itArg->getKey()); + + if ((ovalue != settings.m_individualGains.end()) && (m_settings.m_individualGains[*itArg->getKey()] != *ovalue)) { + m_settings.m_individualGains[*itArg->getKey()] = *ovalue; + } + } + } + + if (deviceSettingsKeys.contains("autoGain")) { + settings.m_autoGain = response.getSoapySdrOutputSettings()->getAutoGain() != 0; + } + if (deviceSettingsKeys.contains("autoDCCorrection")) { + settings.m_autoDCCorrection = response.getSoapySdrOutputSettings()->getAutoDcCorrection() != 0; + } + if (deviceSettingsKeys.contains("autoIQCorrection")) { + settings.m_autoIQCorrection = response.getSoapySdrOutputSettings()->getAutoIqCorrection() != 0; + } + if (deviceSettingsKeys.contains("dcCorrection")) + { + settings.m_dcCorrection.real(response.getSoapySdrOutputSettings()->getDcCorrection()->getReal()); + settings.m_dcCorrection.imag(response.getSoapySdrOutputSettings()->getDcCorrection()->getImag()); + } + if (deviceSettingsKeys.contains("iqCorrection")) + { + settings.m_iqCorrection.real(response.getSoapySdrOutputSettings()->getIqCorrection()->getReal()); + settings.m_iqCorrection.imag(response.getSoapySdrOutputSettings()->getIqCorrection()->getImag()); + } + + if (deviceSettingsKeys.contains("streamArgSettings")) + { + QList *streamArgSettings = response.getSoapySdrOutputSettings()->getStreamArgSettings(); + + for (const auto itArg : *streamArgSettings) + { + auto ovalue = settings.m_streamArgSettings.find(*itArg->getKey()); + + if ((ovalue != settings.m_streamArgSettings.end()) && (m_settings.m_streamArgSettings[*itArg->getKey()] != *ovalue)) { + m_settings.m_streamArgSettings[*itArg->getKey()] = *ovalue; + } + } + } + + if (deviceSettingsKeys.contains("deviceArgSettings")) + { + QList *deviceArgSettings = response.getSoapySdrOutputSettings()->getDeviceArgSettings(); + + for (const auto itArg : *deviceArgSettings) + { + auto ovalue = settings.m_deviceArgSettings.find(*itArg->getKey()); + + if ((ovalue != settings.m_deviceArgSettings.end()) && (m_settings.m_deviceArgSettings[*itArg->getKey()] != *ovalue)) { + m_settings.m_deviceArgSettings[*itArg->getKey()] = *ovalue; + } + } + } + + MsgConfigureSoapySDROutput *msg = MsgConfigureSoapySDROutput::create(settings, force); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureSoapySDROutput *msgToGUI = MsgConfigureSoapySDROutput::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatDeviceSettings(response, settings); + return 200; +} + +int SoapySDROutput::webapiReportGet(SWGSDRangel::SWGDeviceReport& response, QString& errorMessage) +{ + (void) errorMessage; + response.setSoapySdrOutputReport(new SWGSDRangel::SWGSoapySDRReport()); + response.getSoapySdrOutputReport()->init(); + webapiFormatDeviceReport(response); + return 200; +} + +int SoapySDROutput::webapiRunGet( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) errorMessage; + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + return 200; +} + +int SoapySDROutput::webapiRun( + bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) errorMessage; + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + MsgStartStop *message = MsgStartStop::create(run); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgStartStop *msgToGUI = MsgStartStop::create(run); + m_guiMessageQueue->push(msgToGUI); + } + + return 200; +} + void SoapySDROutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SoapySDROutputSettings& settings) { response.getSoapySdrOutputSettings()->setCenterFrequency(settings.m_centerFrequency); diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.h b/plugins/samplesink/soapysdroutput/soapysdroutput.h index a896e5061..df2945549 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.h @@ -150,6 +150,29 @@ public: bool hasIQAutoCorrection() { return false; } // not in SoapySDR interface bool hasIQCorrectionValue(); + virtual int webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage); + + virtual int webapiReportGet( + SWGSDRangel::SWGDeviceReport& response, + QString& errorMessage); + + virtual int webapiRunGet( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + + virtual int webapiRun( + bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + private: DeviceSinkAPI *m_deviceAPI; QMutex m_mutex; diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 8f24adc80..c5c9421d2 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -1248,6 +1248,193 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo return true; } +int SoapySDRInput::webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setSoapySdrInputSettings(new SWGSDRangel::SWGSoapySDRInputSettings()); + response.getSoapySdrInputSettings()->init(); + webapiFormatDeviceSettings(response, m_settings); + return 200; +} + +int SoapySDRInput::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage) +{ + (void) errorMessage; + SoapySDRInputSettings settings = m_settings; + + if (deviceSettingsKeys.contains("centerFrequency")) { + settings.m_centerFrequency = response.getSoapySdrInputSettings()->getCenterFrequency(); + } + if (deviceSettingsKeys.contains("LOppmTenths")) { + settings.m_LOppmTenths = response.getSoapySdrInputSettings()->getLOppmTenths(); + } + if (deviceSettingsKeys.contains("devSampleRate")) { + settings.m_devSampleRate = response.getSoapySdrInputSettings()->getDevSampleRate(); + } + if (deviceSettingsKeys.contains("bandwidth")) { + settings.m_bandwidth = response.getSoapySdrInputSettings()->getBandwidth(); + } + if (deviceSettingsKeys.contains("log2Decim")) { + settings.m_log2Decim = response.getSoapySdrInputSettings()->getLog2Decim(); + } + if (deviceSettingsKeys.contains("fcPos")) { + settings.m_fcPos = static_cast(response.getSoapySdrInputSettings()->getFcPos()); + } + if (deviceSettingsKeys.contains("softDCCorrection")) { + settings.m_softDCCorrection = response.getSoapySdrInputSettings()->getSoftDcCorrection() != 0; + } + if (deviceSettingsKeys.contains("softIQCorrection")) { + settings.m_softIQCorrection = response.getSoapySdrInputSettings()->getSoftIqCorrection() != 0; + } + if (deviceSettingsKeys.contains("transverterDeltaFrequency")) { + settings.m_transverterDeltaFrequency = response.getSoapySdrInputSettings()->getTransverterDeltaFrequency(); + } + if (deviceSettingsKeys.contains("transverterMode")) { + settings.m_transverterMode = response.getSoapySdrInputSettings()->getTransverterMode() != 0; + } + if (deviceSettingsKeys.contains("fileRecordName")) { + settings.m_fileRecordName = *response.getSoapySdrInputSettings()->getFileRecordName(); + } + if (deviceSettingsKeys.contains("antenna")) { + settings.m_antenna = *response.getSoapySdrInputSettings()->getAntenna(); + } + + if (deviceSettingsKeys.contains("tunableElements")) + { + QList *tunableElements = response.getSoapySdrInputSettings()->getTunableElements(); + + for (const auto itArg : *tunableElements) + { + auto ovalue = settings.m_tunableElements.find(*itArg->getKey()); + + if ((ovalue != settings.m_tunableElements.end()) && (m_settings.m_tunableElements[*itArg->getKey()] != *ovalue)) { + m_settings.m_tunableElements[*itArg->getKey()] = *ovalue; + } + } + } + + if (deviceSettingsKeys.contains("globalGain")) { + settings.m_globalGain = response.getSoapySdrInputSettings()->getGlobalGain(); + } + + if (deviceSettingsKeys.contains("individualGains")) + { + QList *individualGains = response.getSoapySdrInputSettings()->getIndividualGains(); + + for (const auto itArg : *individualGains) + { + auto ovalue = settings.m_individualGains.find(*itArg->getKey()); + + if ((ovalue != settings.m_individualGains.end()) && (m_settings.m_individualGains[*itArg->getKey()] != *ovalue)) { + m_settings.m_individualGains[*itArg->getKey()] = *ovalue; + } + } + } + + if (deviceSettingsKeys.contains("autoGain")) { + settings.m_autoGain = response.getSoapySdrInputSettings()->getAutoGain() != 0; + } + if (deviceSettingsKeys.contains("autoDCCorrection")) { + settings.m_autoDCCorrection = response.getSoapySdrInputSettings()->getAutoDcCorrection() != 0; + } + if (deviceSettingsKeys.contains("autoIQCorrection")) { + settings.m_autoIQCorrection = response.getSoapySdrInputSettings()->getAutoIqCorrection() != 0; + } + if (deviceSettingsKeys.contains("dcCorrection")) + { + settings.m_dcCorrection.real(response.getSoapySdrInputSettings()->getDcCorrection()->getReal()); + settings.m_dcCorrection.imag(response.getSoapySdrInputSettings()->getDcCorrection()->getImag()); + } + if (deviceSettingsKeys.contains("iqCorrection")) + { + settings.m_iqCorrection.real(response.getSoapySdrInputSettings()->getIqCorrection()->getReal()); + settings.m_iqCorrection.imag(response.getSoapySdrInputSettings()->getIqCorrection()->getImag()); + } + + if (deviceSettingsKeys.contains("streamArgSettings")) + { + QList *streamArgSettings = response.getSoapySdrInputSettings()->getStreamArgSettings(); + + for (const auto itArg : *streamArgSettings) + { + auto ovalue = settings.m_streamArgSettings.find(*itArg->getKey()); + + if ((ovalue != settings.m_streamArgSettings.end()) && (m_settings.m_streamArgSettings[*itArg->getKey()] != *ovalue)) { + m_settings.m_streamArgSettings[*itArg->getKey()] = *ovalue; + } + } + } + + if (deviceSettingsKeys.contains("deviceArgSettings")) + { + QList *deviceArgSettings = response.getSoapySdrInputSettings()->getDeviceArgSettings(); + + for (const auto itArg : *deviceArgSettings) + { + auto ovalue = settings.m_deviceArgSettings.find(*itArg->getKey()); + + if ((ovalue != settings.m_deviceArgSettings.end()) && (m_settings.m_deviceArgSettings[*itArg->getKey()] != *ovalue)) { + m_settings.m_deviceArgSettings[*itArg->getKey()] = *ovalue; + } + } + } + + MsgConfigureSoapySDRInput *msg = MsgConfigureSoapySDRInput::create(settings, force); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureSoapySDRInput *msgToGUI = MsgConfigureSoapySDRInput::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatDeviceSettings(response, settings); + return 200; +} + +int SoapySDRInput::webapiReportGet(SWGSDRangel::SWGDeviceReport& response, QString& errorMessage) +{ + (void) errorMessage; + response.setSoapySdrInputReport(new SWGSDRangel::SWGSoapySDRReport()); + response.getSoapySdrInputReport()->init(); + webapiFormatDeviceReport(response); + return 200; +} + +int SoapySDRInput::webapiRunGet( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) errorMessage; + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + return 200; +} + +int SoapySDRInput::webapiRun( + bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) errorMessage; + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + MsgStartStop *message = MsgStartStop::create(run); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgStartStop *msgToGUI = MsgStartStop::create(run); + m_guiMessageQueue->push(msgToGUI); + } + + return 200; +} + void SoapySDRInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SoapySDRInputSettings& settings) { response.getSoapySdrInputSettings()->setCenterFrequency(settings.m_centerFrequency); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.h b/plugins/samplesource/soapysdrinput/soapysdrinput.h index 06e45379f..6249e4d3a 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.h @@ -172,6 +172,29 @@ public: bool hasIQAutoCorrection() { return false; } // not in SoapySDR interface bool hasIQCorrectionValue(); + virtual int webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage); + + virtual int webapiReportGet( + SWGSDRangel::SWGDeviceReport& response, + QString& errorMessage); + + virtual int webapiRunGet( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + + virtual int webapiRun( + bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + private: DeviceSourceAPI *m_deviceAPI; QMutex m_mutex; From 5bf18ade3f88109055850f76828095decb4d8b4f Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 00:47:15 +0100 Subject: [PATCH 042/102] SoapySDR support: REST API: fixed device report --- .../soapysdroutput/soapysdroutput.cpp | 22 ++++++++++++++ .../soapysdrinput/soapysdrinput.cpp | 30 ++++++++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index 20cb58ac7..447b3e7e5 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -1614,4 +1614,26 @@ void SoapySDROutput::webapiFormatArgInfo(const SoapySDR::ArgInfo& arg, SWGSDRang } argInfo->setValueString(new QString(arg.value.c_str())); + argInfo->setName(new QString(arg.name.c_str())); + argInfo->setDescription(new QString(arg.description.c_str())); + argInfo->setUnits(new QString(arg.units.c_str())); + + if ((arg.range.minimum() != 0.0) || (arg.range.maximum() != 0.0)) + { + argInfo->setRange(new SWGSDRangel::SWGRangeFloat()); + argInfo->getRange()->setMin(arg.range.minimum()); + argInfo->getRange()->setMax(arg.range.maximum()); + } + + argInfo->setValueOptions(new QList); + + for (const auto itOpt : arg.options) { + argInfo->getValueOptions()->append(new QString(itOpt.c_str())); + } + + argInfo->setOptionNames(new QList); + + for (const auto itOpt : arg.optionNames) { + argInfo->getOptionNames()->append(new QString(itOpt.c_str())); + } } diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index c5c9421d2..a0ba0989f 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -1468,7 +1468,7 @@ void SoapySDRInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& r for (const auto itName : settings.m_tunableElements.keys()) { response.getSoapySdrInputSettings()->getTunableElements()->append(new SWGSDRangel::SWGArgValue); - response.getSoapySdrInputSettings()->getTunableElements()->back()->setKey(new QString( itName)); + response.getSoapySdrInputSettings()->getTunableElements()->back()->setKey(new QString(itName)); double value = settings.m_tunableElements.value(itName); response.getSoapySdrInputSettings()->getTunableElements()->back()->setValueString(new QString(tr("%1").arg(value))); response.getSoapySdrInputSettings()->getTunableElements()->back()->setValueType(new QString("float")); @@ -1547,7 +1547,7 @@ void SoapySDRInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respo for (const auto itArg : m_deviceShared.m_deviceParams->getDeviceArgs()) { - response.getSoapySdrInputReport()->getDeviceSettingsArgs()->append(new SWGSDRangel::SWGArgInfo); + response.getSoapySdrInputReport()->getDeviceSettingsArgs()->append(new SWGSDRangel::SWGArgInfo()); webapiFormatArgInfo(itArg, response.getSoapySdrInputReport()->getDeviceSettingsArgs()->back()); } @@ -1555,7 +1555,7 @@ void SoapySDRInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respo for (const auto itArg : channelSettings->m_streamSettingsArgs) { - response.getSoapySdrInputReport()->getStreamSettingsArgs()->append(new SWGSDRangel::SWGArgInfo); + response.getSoapySdrInputReport()->getStreamSettingsArgs()->append(new SWGSDRangel::SWGArgInfo()); webapiFormatArgInfo(itArg, response.getSoapySdrInputReport()->getStreamSettingsArgs()->back()); } @@ -1563,7 +1563,7 @@ void SoapySDRInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respo for (const auto itArg : channelSettings->m_frequencySettingsArgs) { - response.getSoapySdrInputReport()->getFrequencySettingsArgs()->append(new SWGSDRangel::SWGArgInfo); + response.getSoapySdrInputReport()->getFrequencySettingsArgs()->append(new SWGSDRangel::SWGArgInfo()); webapiFormatArgInfo(itArg, response.getSoapySdrInputReport()->getFrequencySettingsArgs()->back()); } @@ -1687,4 +1687,26 @@ void SoapySDRInput::webapiFormatArgInfo(const SoapySDR::ArgInfo& arg, SWGSDRange } argInfo->setValueString(new QString(arg.value.c_str())); + argInfo->setName(new QString(arg.name.c_str())); + argInfo->setDescription(new QString(arg.description.c_str())); + argInfo->setUnits(new QString(arg.units.c_str())); + + if ((arg.range.minimum() != 0.0) || (arg.range.maximum() != 0.0)) + { + argInfo->setRange(new SWGSDRangel::SWGRangeFloat()); + argInfo->getRange()->setMin(arg.range.minimum()); + argInfo->getRange()->setMax(arg.range.maximum()); + } + + argInfo->setValueOptions(new QList); + + for (const auto itOpt : arg.options) { + argInfo->getValueOptions()->append(new QString(itOpt.c_str())); + } + + argInfo->setOptionNames(new QList); + + for (const auto itOpt : arg.optionNames) { + argInfo->getOptionNames()->append(new QString(itOpt.c_str())); + } } From 430f411e8d961a1853a8e855ccec6a617f7f0c89 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 08:46:29 +0100 Subject: [PATCH 043/102] SoapySDR support: REST API: recognize SoapySDR --- sdrbase/webapi/webapirequestmapper.cpp | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index 5e53838cd..2a89d054d 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -1993,6 +1993,36 @@ bool WebAPIRequestMapper::validateDeviceSettings( return false; } } + else if ((*deviceHwType == "SoapySDR") && (deviceSettings.getTx() == 0)) + { + if (jsonObject.contains("soapySDRInputSettings") && jsonObject["soapySDRInputSettings"].isObject()) + { + QJsonObject soapySdrInputSettingsJsonObject = jsonObject["soapySDRInputSettings"].toObject(); + deviceSettingsKeys = soapySdrInputSettingsJsonObject.keys(); + deviceSettings.setSoapySdrInputSettings(new SWGSDRangel::SWGSoapySDRInputSettings()); + deviceSettings.getSoapySdrInputSettings()->fromJsonObject(soapySdrInputSettingsJsonObject); + return true; + } + else + { + return false; + } + } + else if ((*deviceHwType == "SoapySDR") && (deviceSettings.getTx() != 0)) + { + if (jsonObject.contains("soapySDROutputSettings") && jsonObject["soapySDROutputSettings"].isObject()) + { + QJsonObject soapySdrOutputSettingsJsonObject = jsonObject["soapySDROutputSettings"].toObject(); + deviceSettingsKeys = soapySdrOutputSettingsJsonObject.keys(); + deviceSettings.setSoapySdrOutputSettings(new SWGSDRangel::SWGSoapySDROutputSettings()); + deviceSettings.getSoapySdrOutputSettings()->fromJsonObject(soapySdrOutputSettingsJsonObject); + return true; + } + else + { + return false; + } + } else if (*deviceHwType == "TestSource") { if (jsonObject.contains("testSourceSettings") && jsonObject["testSourceSettings"].isObject()) From df2b0c116a43d0f32f641c467eff4bd211a7f1f3 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 11:27:20 +0100 Subject: [PATCH 044/102] SoapySDR support: REST API: fixed settings structure initialization in request mapper --- sdrbase/webapi/webapirequestmapper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index 2a89d054d..977344f67 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -2000,6 +2000,7 @@ bool WebAPIRequestMapper::validateDeviceSettings( QJsonObject soapySdrInputSettingsJsonObject = jsonObject["soapySDRInputSettings"].toObject(); deviceSettingsKeys = soapySdrInputSettingsJsonObject.keys(); deviceSettings.setSoapySdrInputSettings(new SWGSDRangel::SWGSoapySDRInputSettings()); + deviceSettings.getSoapySdrInputSettings()->init(); // contains complex objects deviceSettings.getSoapySdrInputSettings()->fromJsonObject(soapySdrInputSettingsJsonObject); return true; } @@ -2015,6 +2016,7 @@ bool WebAPIRequestMapper::validateDeviceSettings( QJsonObject soapySdrOutputSettingsJsonObject = jsonObject["soapySDROutputSettings"].toObject(); deviceSettingsKeys = soapySdrOutputSettingsJsonObject.keys(); deviceSettings.setSoapySdrOutputSettings(new SWGSDRangel::SWGSoapySDROutputSettings()); + deviceSettings.getSoapySdrInputSettings()->init(); // contains complex objects deviceSettings.getSoapySdrOutputSettings()->fromJsonObject(soapySdrOutputSettingsJsonObject); return true; } From 53c0474e004061b8da6a730f3680af3c33c126d2 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 14:09:00 +0100 Subject: [PATCH 045/102] SoapySDR support: fixed arg info display for discrete strings --- sdrgui/soapygui/arginfogui.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sdrgui/soapygui/arginfogui.cpp b/sdrgui/soapygui/arginfogui.cpp index ae3705771..fd60e0eb3 100644 --- a/sdrgui/soapygui/arginfogui.cpp +++ b/sdrgui/soapygui/arginfogui.cpp @@ -349,6 +349,24 @@ void ArgInfoGUI::updateUIFromString() ui->argEdit->setText(m_stringValue); ui->argEdit->blockSignals(false); } + else if (m_type == ArgInfoDiscrete) + { + for (int i = 0; i < ui->argCombo->count(); i++) + { + if (ui->argCombo->itemData(i).type() == QVariant::String) + { + QVariant v = ui->argCombo->itemData(i); + + if (m_stringValue == v.toString()) + { + ui->argCombo->blockSignals(true); + ui->argCombo->setCurrentIndex(i); + ui->argCombo->blockSignals(false); + break; + } + } + } + } } void ArgInfoGUI::on_argCheck_toggled(bool checked) From 69cd5645ebf3b31d5b69a513c7b0fbf759ec3745 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 14:11:52 +0100 Subject: [PATCH 046/102] SoapySDR support: fixed input and output stream and device displays --- .../samplesink/soapysdroutput/soapysdroutputgui.cpp | 11 +++++++---- .../samplesource/soapysdrinput/soapysdrinputgui.cpp | 12 +++++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp index 3d997a8f3..aab300296 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp @@ -438,12 +438,15 @@ QByteArray SoapySDROutputGui::serialize() const bool SoapySDROutputGui::deserialize(const QByteArray& data) { - if(m_settings.deserialize(data)) { + if(m_settings.deserialize(data)) + { displaySettings(); m_forceSettings = true; sendSettings(); return true; - } else { + } + else + { resetToDefaults(); return false; } @@ -769,7 +772,7 @@ void SoapySDROutputGui::displayStreamArgsSettings() if (elIt != m_settings.m_streamArgSettings.end()) { - it->setValue(*elIt); + it->setValue(elIt.value()); *elIt = it->getValue(); } } @@ -783,7 +786,7 @@ void SoapySDROutputGui::displayDeviceArgsSettings() if (elIt != m_settings.m_deviceArgSettings.end()) { - it->setValue(*elIt); + it->setValue(elIt.value()); *elIt = it->getValue(); } } diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp index b8382d0c1..5f9ca4f2a 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -441,12 +441,15 @@ QByteArray SoapySDRInputGui::serialize() const bool SoapySDRInputGui::deserialize(const QByteArray& data) { - if(m_settings.deserialize(data)) { + if (m_settings.deserialize(data)) + { displaySettings(); m_forceSettings = true; sendSettings(); return true; - } else { + } + else + { resetToDefaults(); return false; } @@ -716,7 +719,6 @@ void SoapySDRInputGui::displaySettings() ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); if (m_antennas) { - qDebug("SoapySDRInputGui::displaySettings: m_antenna: %s", m_settings.m_antenna.toStdString().c_str()); m_antennas->setValue(m_settings.m_antenna.toStdString()); } if (m_sampleRateGUI) @@ -815,7 +817,7 @@ void SoapySDRInputGui::displayStreamArgsSettings() if (elIt != m_settings.m_streamArgSettings.end()) { - it->setValue(*elIt); + it->setValue(elIt.value()); *elIt = it->getValue(); } } @@ -829,7 +831,7 @@ void SoapySDRInputGui::displayDeviceArgsSettings() if (elIt != m_settings.m_deviceArgSettings.end()) { - it->setValue(*elIt); + it->setValue(elIt.value()); *elIt = it->getValue(); } } From dbbabd4b572319fd7630a6828e3c10494ab0a6b1 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 14:14:49 +0100 Subject: [PATCH 047/102] SoapySDR support: input and output: display mapped setting elements after applying settings --- .../soapysdroutput/soapysdroutput.cpp | 32 +++++++++++++++++++ .../soapysdrinput/soapysdrinput.cpp | 32 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index 447b3e7e5..a821007b8 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -1193,6 +1193,38 @@ bool SoapySDROutput::applySettings(const SoapySDROutputSettings& settings, bool << " m_globalGain: " << m_settings.m_globalGain << " force: " << force; + QMap::const_iterator doubleIt = m_settings.m_individualGains.begin(); + + for(; doubleIt != m_settings.m_individualGains.end(); ++doubleIt) { + qDebug("SoapySDROutput::applySettings: m_individualGains[%s]: %lf", doubleIt.key().toStdString().c_str(), doubleIt.value()); + } + + doubleIt = m_settings.m_tunableElements.begin(); + + for(; doubleIt != m_settings.m_tunableElements.end(); ++doubleIt) { + qDebug("SoapySDROutput::applySettings: m_tunableElements[%s]: %lf", doubleIt.key().toStdString().c_str(), doubleIt.value()); + } + + QMap::const_iterator varIt = m_settings.m_deviceArgSettings.begin(); + + for(; varIt != m_settings.m_deviceArgSettings.end(); ++varIt) + { + qDebug("SoapySDROutput::applySettings: m_deviceArgSettings[%s] (type %d): %s", + varIt.key().toStdString().c_str(), + (int) varIt.value().type(), // bool: 1, int: 2, double: 6, string: 10 (http://doc.qt.io/archives/qt-4.8/qvariant.html) + varIt.value().toString().toStdString().c_str()); + } + + varIt = m_settings.m_streamArgSettings.begin(); + + for(; varIt != m_settings.m_streamArgSettings.end(); ++varIt) + { + qDebug("SoapySDROutput::applySettings: m_streamArgSettings[%s] (type %d): %s", + varIt.key().toStdString().c_str(), + (int) varIt.value().type(), + varIt.value().toString().toStdString().c_str()); + } + return true; } diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index a0ba0989f..2942dec7f 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -1245,6 +1245,38 @@ bool SoapySDRInput::applySettings(const SoapySDRInputSettings& settings, bool fo << " m_globalGain: " << m_settings.m_globalGain << " force: " << force; + QMap::const_iterator doubleIt = m_settings.m_individualGains.begin(); + + for(; doubleIt != m_settings.m_individualGains.end(); ++doubleIt) { + qDebug("SoapySDRInput::applySettings: m_individualGains[%s]: %lf", doubleIt.key().toStdString().c_str(), doubleIt.value()); + } + + doubleIt = m_settings.m_tunableElements.begin(); + + for(; doubleIt != m_settings.m_tunableElements.end(); ++doubleIt) { + qDebug("SoapySDRInput::applySettings: m_tunableElements[%s]: %lf", doubleIt.key().toStdString().c_str(), doubleIt.value()); + } + + QMap::const_iterator varIt = m_settings.m_deviceArgSettings.begin(); + + for(; varIt != m_settings.m_deviceArgSettings.end(); ++varIt) + { + qDebug("SoapySDRInput::applySettings: m_deviceArgSettings[%s] (type %d): %s", + varIt.key().toStdString().c_str(), + (int) varIt.value().type(), // bool: 1, int: 2, double: 6, string: 10 (http://doc.qt.io/archives/qt-4.8/qvariant.html) + varIt.value().toString().toStdString().c_str()); + } + + varIt = m_settings.m_streamArgSettings.begin(); + + for(; varIt != m_settings.m_streamArgSettings.end(); ++varIt) + { + qDebug("SoapySDRInput::applySettings: m_streamArgSettings[%s] (type %d): %s", + varIt.key().toStdString().c_str(), + (int) varIt.value().type(), + varIt.value().toString().toStdString().c_str()); + } + return true; } From 6ad678e05951dfa8172c134bb7fe36679e41778d Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 16:54:23 +0100 Subject: [PATCH 048/102] SoapySDR support: REST API: input and output: corrected mapped elements setting --- .../soapysdroutput/soapysdroutput.cpp | 20 +++++------ .../soapysdroutput/soapysdroutput.h | 1 + .../soapysdrinput/soapysdrinput.cpp | 33 +++++++++++++------ .../soapysdrinput/soapysdrinput.h | 1 + 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index a821007b8..9e56248a6 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -1281,8 +1281,8 @@ int SoapySDROutput::webapiSettingsPutPatch( { auto ovalue = settings.m_tunableElements.find(*itArg->getKey()); - if ((ovalue != settings.m_tunableElements.end()) && (m_settings.m_tunableElements[*itArg->getKey()] != *ovalue)) { - m_settings.m_tunableElements[*itArg->getKey()] = *ovalue; + if ((ovalue != settings.m_tunableElements.end()) && (atof(itArg->getValueString()->toStdString().c_str()) != *ovalue)) { + m_settings.m_tunableElements[*itArg->getKey()] = atof(itArg->getValueString()->toStdString().c_str()); } } } @@ -1299,8 +1299,8 @@ int SoapySDROutput::webapiSettingsPutPatch( { auto ovalue = settings.m_individualGains.find(*itArg->getKey()); - if ((ovalue != settings.m_individualGains.end()) && (m_settings.m_individualGains[*itArg->getKey()] != *ovalue)) { - m_settings.m_individualGains[*itArg->getKey()] = *ovalue; + if ((ovalue != settings.m_individualGains.end()) && (atof(itArg->getValueString()->toStdString().c_str()) != *ovalue)) { + m_settings.m_individualGains[*itArg->getKey()] = atof(itArg->getValueString()->toStdString().c_str()); } } } @@ -1331,10 +1331,10 @@ int SoapySDROutput::webapiSettingsPutPatch( for (const auto itArg : *streamArgSettings) { - auto ovalue = settings.m_streamArgSettings.find(*itArg->getKey()); + QMap::iterator itSettings = settings.m_streamArgSettings.find(*itArg->getKey()); - if ((ovalue != settings.m_streamArgSettings.end()) && (m_settings.m_streamArgSettings[*itArg->getKey()] != *ovalue)) { - m_settings.m_streamArgSettings[*itArg->getKey()] = *ovalue; + if (itSettings != settings.m_streamArgSettings.end()) { + itSettings.value() = webapiVariantFromArgValue(itArg); } } } @@ -1345,10 +1345,10 @@ int SoapySDROutput::webapiSettingsPutPatch( for (const auto itArg : *deviceArgSettings) { - auto ovalue = settings.m_deviceArgSettings.find(*itArg->getKey()); + QMap::iterator itSettings = settings.m_deviceArgSettings.find(*itArg->getKey()); - if ((ovalue != settings.m_deviceArgSettings.end()) && (m_settings.m_deviceArgSettings[*itArg->getKey()] != *ovalue)) { - m_settings.m_deviceArgSettings[*itArg->getKey()] = *ovalue; + if (itSettings != settings.m_deviceArgSettings.end()) { + itSettings.value() = webapiVariantFromArgValue(itArg); } } } diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.h b/plugins/samplesink/soapysdroutput/soapysdroutput.h index df2945549..0facbc805 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.h @@ -191,6 +191,7 @@ private: void updateGains(SoapySDR::Device *dev, int requestedChannel, SoapySDROutputSettings& settings); void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SoapySDROutputSettings& settings); void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + QVariant webapiVariantFromArgValue(SWGSDRangel::SWGArgValue *argValue); void webapiFormatArgValue(const QVariant& v, SWGSDRangel::SWGArgValue *argValue); void webapiFormatArgInfo(const SoapySDR::ArgInfo& arg, SWGSDRangel::SWGArgInfo *argInfo); }; diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 2942dec7f..5d0d96b03 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -1345,8 +1345,8 @@ int SoapySDRInput::webapiSettingsPutPatch( { auto ovalue = settings.m_tunableElements.find(*itArg->getKey()); - if ((ovalue != settings.m_tunableElements.end()) && (m_settings.m_tunableElements[*itArg->getKey()] != *ovalue)) { - m_settings.m_tunableElements[*itArg->getKey()] = *ovalue; + if ((ovalue != settings.m_tunableElements.end()) && (atof(itArg->getValueString()->toStdString().c_str()) != *ovalue)) { + m_settings.m_tunableElements[*itArg->getKey()] = atof(itArg->getValueString()->toStdString().c_str()); } } } @@ -1363,8 +1363,8 @@ int SoapySDRInput::webapiSettingsPutPatch( { auto ovalue = settings.m_individualGains.find(*itArg->getKey()); - if ((ovalue != settings.m_individualGains.end()) && (m_settings.m_individualGains[*itArg->getKey()] != *ovalue)) { - m_settings.m_individualGains[*itArg->getKey()] = *ovalue; + if ((ovalue != settings.m_individualGains.end()) && (atof(itArg->getValueString()->toStdString().c_str()) != *ovalue)) { + m_settings.m_individualGains[*itArg->getKey()] = atof(itArg->getValueString()->toStdString().c_str()); } } } @@ -1395,10 +1395,10 @@ int SoapySDRInput::webapiSettingsPutPatch( for (const auto itArg : *streamArgSettings) { - auto ovalue = settings.m_streamArgSettings.find(*itArg->getKey()); + QMap::iterator itSettings = settings.m_streamArgSettings.find(*itArg->getKey()); - if ((ovalue != settings.m_streamArgSettings.end()) && (m_settings.m_streamArgSettings[*itArg->getKey()] != *ovalue)) { - m_settings.m_streamArgSettings[*itArg->getKey()] = *ovalue; + if (itSettings != settings.m_streamArgSettings.end()) { + itSettings.value() = webapiVariantFromArgValue(itArg); } } } @@ -1409,10 +1409,10 @@ int SoapySDRInput::webapiSettingsPutPatch( for (const auto itArg : *deviceArgSettings) { - auto ovalue = settings.m_deviceArgSettings.find(*itArg->getKey()); + QMap::iterator itSettings = settings.m_deviceArgSettings.find(*itArg->getKey()); - if ((ovalue != settings.m_deviceArgSettings.end()) && (m_settings.m_deviceArgSettings[*itArg->getKey()] != *ovalue)) { - m_settings.m_deviceArgSettings[*itArg->getKey()] = *ovalue; + if (itSettings != settings.m_deviceArgSettings.end()) { + itSettings.value() = webapiVariantFromArgValue(itArg); } } } @@ -1680,6 +1680,19 @@ void SoapySDRInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respo } } +QVariant SoapySDRInput::webapiVariantFromArgValue(SWGSDRangel::SWGArgValue *argValue) +{ + if (*argValue->getValueType() == "bool") { + return QVariant((bool) (*argValue->getValueString() == "1")); + } else if (*argValue->getValueType() == "int") { + return QVariant((int) (atoi(argValue->getValueString()->toStdString().c_str()))); + } else if (*argValue->getValueType() == "float") { + return QVariant((double) (atof(argValue->getValueString()->toStdString().c_str()))); + } else { + return QVariant(QString(*argValue->getValueString())); + } +} + void SoapySDRInput::webapiFormatArgValue(const QVariant& v, SWGSDRangel::SWGArgValue *argValue) { if (v.type() == QVariant::Bool) diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.h b/plugins/samplesource/soapysdrinput/soapysdrinput.h index 6249e4d3a..c7aa959a5 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.h @@ -214,6 +214,7 @@ private: void updateGains(SoapySDR::Device *dev, int requestedChannel, SoapySDRInputSettings& settings); void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SoapySDRInputSettings& settings); void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + QVariant webapiVariantFromArgValue(SWGSDRangel::SWGArgValue *argValue); void webapiFormatArgValue(const QVariant& v, SWGSDRangel::SWGArgValue *argValue); void webapiFormatArgInfo(const SoapySDR::ArgInfo& arg, SWGSDRangel::SWGArgInfo *argInfo); }; From cb9d3001093911a03f701719a63c88f32db53eba Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 19:07:15 +0100 Subject: [PATCH 049/102] Windows: MSVC2017: soapysdrinput (1) --- devices/devices.pro | 2 +- devices/soapysdr/devicesoapysdrshared.h | 4 +- .../soapysdrinput/soapysdrinput.pro | 42 +++++++++++++++++++ .../soapysdrinput/soapysdrinputgui.cpp | 8 ++-- sdrgui/sdrgui.pro | 23 ++++++++++ 5 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 plugins/samplesource/soapysdrinput/soapysdrinput.pro diff --git a/devices/devices.pro b/devices/devices.pro index 549796b6c..0b8741487 100644 --- a/devices/devices.pro +++ b/devices/devices.pro @@ -182,5 +182,5 @@ macx { MSVC { LIBS += -L../libhackrf/$${build_subdir} -llibhackrf LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lLimeSuite - LIBS += -LC:\Programs\PothosSDR\bin -lSoapySDR + LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lSoapySDR } diff --git a/devices/soapysdr/devicesoapysdrshared.h b/devices/soapysdr/devicesoapysdrshared.h index d219b70ac..f64108692 100644 --- a/devices/soapysdr/devicesoapysdrshared.h +++ b/devices/soapysdr/devicesoapysdrshared.h @@ -35,7 +35,7 @@ class SoapySDROutput; class DEVICES_API DeviceSoapySDRShared { public: - class MsgReportBuddyChange : public Message { + class DEVICES_API MsgReportBuddyChange : public Message { MESSAGE_CLASS_DECLARATION public: @@ -82,7 +82,7 @@ public: { } }; - class MsgReportDeviceArgsChange : public Message { + class DEVICES_API MsgReportDeviceArgsChange : public Message { MESSAGE_CLASS_DECLARATION public: diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.pro b/plugins/samplesource/soapysdrinput/soapysdrinput.pro new file mode 100644 index 000000000..7a0e0a9b0 --- /dev/null +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.pro @@ -0,0 +1,42 @@ +#------------------------------------------------- +# +# Pro file for Windows MSVC builds with Qt Creator +# +#------------------------------------------------- + +TEMPLATE = lib +CONFIG += plugin + +QT += core gui multimedia opengl + +TARGET = inputsoapysdrinput + +INCLUDEPATH += $$PWD +INCLUDEPATH += ../../../exports +INCLUDEPATH += ../../../sdrbase +INCLUDEPATH += ../../../sdrgui +INCLUDEPATH += ../../../devices +INCLUDEPATH += ../../../swagger/sdrangel/code/qt5/client +INCLUDEPATH += "C:\Programs\PothosSDR\include" + +CONFIG(Release):build_subdir = release +CONFIG(Debug):build_subdir = debug + +SOURCES += soapysdrinput.cpp\ + soapysdrinputgui.cpp\ + soapysdrinputplugin.cpp\ + soapysdrinputsettings.cpp\ + soapysdrinputthread.cpp + +HEADERS += soapysdrinput.h\ + soapysdrinputgui.h\ + soapysdrinputplugin.h\ + soapysdrinputsettings.h\ + soapysdrinputthread.h + +FORMS += soapysdrinputgui.ui + +LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase +LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui +LIBS += -L../../../swagger/$${build_subdir} -lswagger +LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lSoapySDR diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp index 5f9ca4f2a..5a3363311 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -594,7 +594,7 @@ void SoapySDRInputGui::autoIQCorrectionChanged(bool set) void SoapySDRInputGui::dcCorrectionModuleChanged(double value) { - std::complex dcCorrection = std::polar(value, arg(m_settings.m_dcCorrection)); + std::complex dcCorrection = std::polar(value, arg(m_settings.m_dcCorrection)); m_settings.m_dcCorrection = dcCorrection; sendSettings(); } @@ -602,14 +602,14 @@ void SoapySDRInputGui::dcCorrectionModuleChanged(double value) void SoapySDRInputGui::dcCorrectionArgumentChanged(double value) { double angleInRadians = (value / 180.0) * M_PI; - std::complex dcCorrection = std::polar(abs(m_settings.m_dcCorrection), angleInRadians); + std::complex dcCorrection = std::polar(abs(m_settings.m_dcCorrection), angleInRadians); m_settings.m_dcCorrection = dcCorrection; sendSettings(); } void SoapySDRInputGui::iqCorrectionModuleChanged(double value) { - std::complex iqCorrection = std::polar(value, arg(m_settings.m_iqCorrection)); + std::complex iqCorrection = std::polar(value, arg(m_settings.m_iqCorrection)); m_settings.m_iqCorrection = iqCorrection; sendSettings(); } @@ -617,7 +617,7 @@ void SoapySDRInputGui::iqCorrectionModuleChanged(double value) void SoapySDRInputGui::iqCorrectionArgumentChanged(double value) { double angleInRadians = (value / 180.0) * M_PI; - std::complex iqCorrection = std::polar(abs(m_settings.m_iqCorrection), angleInRadians); + std::complex iqCorrection = std::polar(abs(m_settings.m_iqCorrection), angleInRadians); m_settings.m_iqCorrection = iqCorrection; sendSettings(); } diff --git a/sdrgui/sdrgui.pro b/sdrgui/sdrgui.pro index a10c0e74d..2df36a04d 100644 --- a/sdrgui/sdrgui.pro +++ b/sdrgui/sdrgui.pro @@ -86,6 +86,15 @@ SOURCES += mainwindow.cpp\ gui/tvscreen.cpp\ gui/valuedial.cpp\ gui/valuedialz.cpp\ + soapygui/arginfogui.cpp\ + soapygui/complexfactorgui.cpp\ + soapygui/discreterangegui.cpp\ + soapygui/dynamicargsettinggui.cpp\ + soapygui/dynamicitemsettinggui.cpp\ + soapygui/intervalrangegui.cpp\ + soapygui/intervalslidergui.cpp\ + soapygui/itemsettinggui.cpp\ + soapygui/stringrangegui.cpp\ webapi/webapiadaptergui.cpp HEADERS += mainwindow.h\ @@ -135,6 +144,15 @@ HEADERS += mainwindow.h\ gui/tvscreen.h\ gui/valuedial.h\ gui/valuedialz.h\ + soapygui/arginfogui.h\ + soapygui/complexfactorgui.h\ + soapygui/discreterangegui.h\ + soapygui/dynamicargsettinggui.h\ + soapygui/dynamicitemsettinggui.h\ + soapygui/intervalrangegui.h\ + soapygui/intervalslidergui.h\ + soapygui/itemsettinggui.h\ + soapygui/stringrangegui.h\ webapi/webapiadaptergui.h FORMS += mainwindow.ui\ @@ -156,6 +174,11 @@ FORMS += mainwindow.ui\ gui/loggingdialog.ui\ gui/glspectrumgui.ui\ gui/transverterdialog.ui\ + soapygui/arginfogui.ui\ + soapygui/complexfactorgui.ui\ + soapygui/discreterangegui.ui\ + soapygui/intervalrangegui.ui\ + soapygui/intervalslidergui.ui\ mainwindow.ui LIBS += -L../sdrbase/$${build_subdir} -lsdrbase From 2ab09f7e6c6f6f2d11f2c05995dc311e84ef211d Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 22:25:33 +0100 Subject: [PATCH 050/102] SoapySDR support: fixed tunable elements inital settings --- .../soapysdroutput/soapysdroutput.cpp | 32 +++++++++++++++++++ .../soapysdroutput/soapysdroutput.h | 2 ++ .../soapysdroutput/soapysdroutputgui.cpp | 1 + .../soapysdrinput/soapysdrinput.cpp | 32 +++++++++++++++++++ .../soapysdrinput/soapysdrinput.h | 2 ++ .../soapysdrinput/soapysdrinputgui.cpp | 1 + 6 files changed, 70 insertions(+) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index 9e56248a6..c775143cd 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -44,6 +44,7 @@ SoapySDROutput::SoapySDROutput(DeviceSinkAPI *deviceAPI) : { openDevice(); initGainSettings(m_settings); + initTunableElementsSettings(m_settings); initStreamArgSettings(m_settings); initDeviceArgSettings(m_settings); } @@ -263,6 +264,26 @@ void SoapySDROutput::initGainSettings(SoapySDROutputSettings& settings) updateGains(m_deviceShared.m_device, m_deviceShared.m_channel, settings); } +void SoapySDROutput::initTunableElementsSettings(SoapySDROutputSettings& settings) +{ + const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getTxChannelSettings(m_deviceShared.m_channel); + settings.m_tunableElements.clear(); + bool first = true; + + for (const auto &it : channelSettings->m_frequencySettings) + { + if (first) + { + first = false; + continue; + } + + settings.m_tunableElements[QString(it.m_name.c_str())] = 0.0; + } + + updateTunableElements(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); @@ -692,6 +713,17 @@ void SoapySDROutput::updateGains(SoapySDR::Device *dev, int requestedChannel, So } } +void SoapySDROutput::updateTunableElements(SoapySDR::Device *dev, int requestedChannel, SoapySDROutputSettings& settings) +{ + if (dev == 0) { + return; + } + + for (const auto &name : settings.m_tunableElements.keys()) { + settings.m_tunableElements[name] = dev->getFrequency(SOAPY_SDR_TX, requestedChannel, name.toStdString()); + } +} + bool SoapySDROutput::handleMessage(const Message& message) { if (MsgConfigureSoapySDROutput::match(message)) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.h b/plugins/samplesink/soapysdroutput/soapysdroutput.h index 0facbc805..7be726329 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.h +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.h @@ -143,6 +143,7 @@ public: const SoapySDR::ArgInfoList& getStreamArgInfoList(); const SoapySDR::ArgInfoList& getDeviceArgInfoList(); void initGainSettings(SoapySDROutputSettings& settings); + void initTunableElementsSettings(SoapySDROutputSettings& settings); void initStreamArgSettings(SoapySDROutputSettings& settings); void initDeviceArgSettings(SoapySDROutputSettings& settings); bool hasDCAutoCorrection(); @@ -189,6 +190,7 @@ private: bool applySettings(const SoapySDROutputSettings& settings, bool force = false); bool setDeviceCenterFrequency(SoapySDR::Device *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths); void updateGains(SoapySDR::Device *dev, int requestedChannel, SoapySDROutputSettings& settings); + void updateTunableElements(SoapySDR::Device *dev, int requestedChannel, SoapySDROutputSettings& settings); void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SoapySDROutputSettings& settings); void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); QVariant webapiVariantFromArgValue(SWGSDRangel::SWGArgValue *argValue); diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp index aab300296..cdd528ce7 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp @@ -72,6 +72,7 @@ SoapySDROutputGui::SoapySDROutputGui(DeviceUISet *deviceUISet, QWidget* parent) createArgumentsControl(m_sampleSink->getDeviceArgInfoList(), true); createArgumentsControl(m_sampleSink->getStreamArgInfoList(), false); m_sampleSink->initGainSettings(m_settings); + m_sampleSink->initTunableElementsSettings(m_settings); m_sampleSink->initStreamArgSettings(m_settings); m_sampleSink->initDeviceArgSettings(m_settings); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 5d0d96b03..8bdbc2b36 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -48,6 +48,7 @@ SoapySDRInput::SoapySDRInput(DeviceSourceAPI *deviceAPI) : { openDevice(); initGainSettings(m_settings); + initTunableElementsSettings(m_settings); initStreamArgSettings(m_settings); initDeviceArgSettings(m_settings); @@ -301,6 +302,26 @@ void SoapySDRInput::initGainSettings(SoapySDRInputSettings& settings) updateGains(m_deviceShared.m_device, m_deviceShared.m_channel, settings); } +void SoapySDRInput::initTunableElementsSettings(SoapySDRInputSettings& settings) +{ + const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(m_deviceShared.m_channel); + settings.m_tunableElements.clear(); + bool first = true; + + for (const auto &it : channelSettings->m_frequencySettings) + { + if (first) + { + first = false; + continue; + } + + settings.m_tunableElements[QString(it.m_name.c_str())] = 0.0; + } + + updateTunableElements(m_deviceShared.m_device, m_deviceShared.m_channel, settings); +} + void SoapySDRInput::initStreamArgSettings(SoapySDRInputSettings& settings) { const DeviceSoapySDRParams::ChannelSettings* channelSettings = m_deviceShared.m_deviceParams->getRxChannelSettings(m_deviceShared.m_channel); @@ -719,6 +740,17 @@ void SoapySDRInput::updateGains(SoapySDR::Device *dev, int requestedChannel, Soa } } +void SoapySDRInput::updateTunableElements(SoapySDR::Device *dev, int requestedChannel, SoapySDRInputSettings& settings) +{ + if (dev == 0) { + return; + } + + for (const auto &name : settings.m_tunableElements.keys()) { + settings.m_tunableElements[name] = dev->getFrequency(SOAPY_SDR_RX, requestedChannel, name.toStdString()); + } +} + bool SoapySDRInput::handleMessage(const Message& message) { if (MsgConfigureSoapySDRInput::match(message)) diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.h b/plugins/samplesource/soapysdrinput/soapysdrinput.h index c7aa959a5..d0cfb2739 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.h +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.h @@ -165,6 +165,7 @@ public: const SoapySDR::ArgInfoList& getStreamArgInfoList(); const SoapySDR::ArgInfoList& getDeviceArgInfoList(); void initGainSettings(SoapySDRInputSettings& settings); + void initTunableElementsSettings(SoapySDRInputSettings& settings); void initStreamArgSettings(SoapySDRInputSettings& settings); void initDeviceArgSettings(SoapySDRInputSettings& settings); bool hasDCAutoCorrection(); @@ -212,6 +213,7 @@ private: bool applySettings(const SoapySDRInputSettings& settings, bool force = false); bool setDeviceCenterFrequency(SoapySDR::Device *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths); void updateGains(SoapySDR::Device *dev, int requestedChannel, SoapySDRInputSettings& settings); + void updateTunableElements(SoapySDR::Device *dev, int requestedChannel, SoapySDRInputSettings& settings); void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SoapySDRInputSettings& settings); void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); QVariant webapiVariantFromArgValue(SWGSDRangel::SWGArgValue *argValue); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp index 5a3363311..b96f3bb71 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -73,6 +73,7 @@ SoapySDRInputGui::SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) : createArgumentsControl(m_sampleSource->getDeviceArgInfoList(), true); createArgumentsControl(m_sampleSource->getStreamArgInfoList(), false); m_sampleSource->initGainSettings(m_settings); + m_sampleSource->initTunableElementsSettings(m_settings); m_sampleSource->initStreamArgSettings(m_settings); m_sampleSource->initDeviceArgSettings(m_settings); From 3da7933fa7ff9879d96d95fb3c7010d32c082e7f Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 15 Nov 2018 23:00:55 +0100 Subject: [PATCH 051/102] SoapySDR support: REST API: fixed individual gains and tunable elements settings --- .../soapysdroutput/soapysdroutput.cpp | 20 +++++++++++-------- .../soapysdrinput/soapysdrinput.cpp | 20 +++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index c775143cd..68374f2ff 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -1309,12 +1309,14 @@ int SoapySDROutput::webapiSettingsPutPatch( { QList *tunableElements = response.getSoapySdrOutputSettings()->getTunableElements(); - for (const auto itArg : *tunableElements) + for (const auto &itArg : *tunableElements) { - auto ovalue = settings.m_tunableElements.find(*itArg->getKey()); + QMap::iterator itSettings = settings.m_tunableElements.find(*(itArg->getKey())); - if ((ovalue != settings.m_tunableElements.end()) && (atof(itArg->getValueString()->toStdString().c_str()) != *ovalue)) { - m_settings.m_tunableElements[*itArg->getKey()] = atof(itArg->getValueString()->toStdString().c_str()); + if (itSettings != settings.m_tunableElements.end()) + { + QVariant v = webapiVariantFromArgValue(itArg); + itSettings.value() = v.toDouble(); } } } @@ -1327,12 +1329,14 @@ int SoapySDROutput::webapiSettingsPutPatch( { QList *individualGains = response.getSoapySdrOutputSettings()->getIndividualGains(); - for (const auto itArg : *individualGains) + for (const auto &itArg : *individualGains) { - auto ovalue = settings.m_individualGains.find(*itArg->getKey()); + QMap::iterator itSettings = settings.m_individualGains.find(*(itArg->getKey())); - if ((ovalue != settings.m_individualGains.end()) && (atof(itArg->getValueString()->toStdString().c_str()) != *ovalue)) { - m_settings.m_individualGains[*itArg->getKey()] = atof(itArg->getValueString()->toStdString().c_str()); + if (itSettings != settings.m_individualGains.end()) + { + QVariant v = webapiVariantFromArgValue(itArg); + itSettings.value() = v.toDouble(); } } } diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp index 8bdbc2b36..b516f9eb6 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -1373,12 +1373,14 @@ int SoapySDRInput::webapiSettingsPutPatch( { QList *tunableElements = response.getSoapySdrInputSettings()->getTunableElements(); - for (const auto itArg : *tunableElements) + for (const auto &itArg : *tunableElements) { - auto ovalue = settings.m_tunableElements.find(*itArg->getKey()); + QMap::iterator itSettings = settings.m_tunableElements.find(*(itArg->getKey())); - if ((ovalue != settings.m_tunableElements.end()) && (atof(itArg->getValueString()->toStdString().c_str()) != *ovalue)) { - m_settings.m_tunableElements[*itArg->getKey()] = atof(itArg->getValueString()->toStdString().c_str()); + if (itSettings != settings.m_tunableElements.end()) + { + QVariant v = webapiVariantFromArgValue(itArg); + itSettings.value() = v.toDouble(); } } } @@ -1391,12 +1393,14 @@ int SoapySDRInput::webapiSettingsPutPatch( { QList *individualGains = response.getSoapySdrInputSettings()->getIndividualGains(); - for (const auto itArg : *individualGains) + for (const auto &itArg : *individualGains) { - auto ovalue = settings.m_individualGains.find(*itArg->getKey()); + QMap::iterator itSettings = settings.m_individualGains.find(*(itArg->getKey())); - if ((ovalue != settings.m_individualGains.end()) && (atof(itArg->getValueString()->toStdString().c_str()) != *ovalue)) { - m_settings.m_individualGains[*itArg->getKey()] = atof(itArg->getValueString()->toStdString().c_str()); + if (itSettings != settings.m_individualGains.end()) + { + QVariant v = webapiVariantFromArgValue(itArg); + itSettings.value() = v.toDouble(); } } } From b0fa7c2591b1383ad81ecea01721444dc77a8a3c Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 16 Nov 2018 08:15:10 +0100 Subject: [PATCH 052/102] Windows: MSVC2017: completed SoapySDR support --- .../soapysdroutput/soapysdroutput.cpp | 13 ++++++ .../soapysdroutput/soapysdroutput.pro | 43 +++++++++++++++++++ .../soapysdrinput/soapysdrinput.pro | 3 +- sdrangel.windows.pro | 2 + sdrbase/dsp/inthalfbandfilterdb.h | 32 ++++++-------- windowsms.install.bat | 2 + 6 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 plugins/samplesink/soapysdroutput/soapysdroutput.pro diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp index 68374f2ff..d6effe288 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.cpp @@ -1643,6 +1643,19 @@ void SoapySDROutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& resp } } +QVariant SoapySDROutput::webapiVariantFromArgValue(SWGSDRangel::SWGArgValue *argValue) +{ + if (*argValue->getValueType() == "bool") { + return QVariant((bool) (*argValue->getValueString() == "1")); + } else if (*argValue->getValueType() == "int") { + return QVariant((int) (atoi(argValue->getValueString()->toStdString().c_str()))); + } else if (*argValue->getValueType() == "float") { + return QVariant((double) (atof(argValue->getValueString()->toStdString().c_str()))); + } else { + return QVariant(QString(*argValue->getValueString())); + } +} + void SoapySDROutput::webapiFormatArgValue(const QVariant& v, SWGSDRangel::SWGArgValue *argValue) { if (v.type() == QVariant::Bool) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.pro b/plugins/samplesink/soapysdroutput/soapysdroutput.pro new file mode 100644 index 000000000..41e2d7a4a --- /dev/null +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.pro @@ -0,0 +1,43 @@ +#------------------------------------------------- +# +# Pro file for Windows MSVC builds with Qt Creator +# +#------------------------------------------------- + +TEMPLATE = lib +CONFIG += plugin + +QT += core gui multimedia opengl + +TARGET = outputsoapysdr + +INCLUDEPATH += $$PWD +INCLUDEPATH += ../../../exports +INCLUDEPATH += ../../../sdrbase +INCLUDEPATH += ../../../sdrgui +INCLUDEPATH += ../../../devices +INCLUDEPATH += ../../../swagger/sdrangel/code/qt5/client +INCLUDEPATH += "C:\Programs\PothosSDR\include" + +CONFIG(Release):build_subdir = release +CONFIG(Debug):build_subdir = debug + +SOURCES += soapysdroutput.cpp\ + soapysdroutputgui.cpp\ + soapysdroutputplugin.cpp\ + soapysdroutputsettings.cpp\ + soapysdroutputthread.cpp + +HEADERS += soapysdroutput.h\ + soapysdroutputgui.h\ + soapysdroutputplugin.h\ + soapysdroutputsettings.h\ + soapysdroutputthread.h + +FORMS += soapysdroutputgui.ui + +LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase +LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui +LIBS += -L../../../swagger/$${build_subdir} -lswagger +LIBS += -L../../../devices/$${build_subdir} -ldevices +LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lSoapySDR diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.pro b/plugins/samplesource/soapysdrinput/soapysdrinput.pro index 7a0e0a9b0..41f302c51 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.pro +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.pro @@ -9,7 +9,7 @@ CONFIG += plugin QT += core gui multimedia opengl -TARGET = inputsoapysdrinput +TARGET = inputsoapysdr INCLUDEPATH += $$PWD INCLUDEPATH += ../../../exports @@ -39,4 +39,5 @@ FORMS += soapysdrinputgui.ui LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui LIBS += -L../../../swagger/$${build_subdir} -lswagger +LIBS += -L../../../devices/$${build_subdir} -ldevices LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lSoapySDR diff --git a/sdrangel.windows.pro b/sdrangel.windows.pro index b777b9cbf..3b6221a55 100644 --- a/sdrangel.windows.pro +++ b/sdrangel.windows.pro @@ -39,6 +39,7 @@ SUBDIRS += plugins/samplesource/limesdrinput CONFIG(!MSVC):SUBDIRS += plugins/samplesource/plutosdrinput CONFIG(MSVC):SUBDIRS += plugins/samplesource/sdrdaemonsource SUBDIRS += plugins/samplesource/rtlsdr +CONFIG(MSVC):SUBDIRS += plugins/samplesource/soapysdrinput SUBDIRS += plugins/samplesource/testsource SUBDIRS += plugins/samplesink/filesink CONFIG(!MSVC):SUBDIRS += plugins/samplesink/bladerf1output @@ -47,6 +48,7 @@ SUBDIRS += plugins/samplesink/hackrfoutput SUBDIRS += plugins/samplesink/limesdroutput CONFIG(!MSVC):SUBDIRS += plugins/samplesink/plutosdroutput CONFIG(MSVC):SUBDIRS += plugins/samplesink/sdrdaemonsink +CONFIG(MSVC):SUBDIRS += plugins/samplesink/soapysdroutput SUBDIRS += plugins/channelrx/chanalyzer SUBDIRS += plugins/channelrx/demodam SUBDIRS += plugins/channelrx/demodatv diff --git a/sdrbase/dsp/inthalfbandfilterdb.h b/sdrbase/dsp/inthalfbandfilterdb.h index a4b00bd8f..702e1281e 100644 --- a/sdrbase/dsp/inthalfbandfilterdb.h +++ b/sdrbase/dsp/inthalfbandfilterdb.h @@ -24,12 +24,23 @@ #include #include "dsp/dsptypes.h" #include "dsp/hbfiltertraits.h" -#include "export.h" template -class SDRBASE_API IntHalfbandFilterDB { +class IntHalfbandFilterDB { public: - IntHalfbandFilterDB(); + IntHalfbandFilterDB() + { + m_size = HBFIRFilterTraits::hbOrder - 1; + + for (int i = 0; i < m_size; i++) + { + m_samplesDB[i][0] = 0; + m_samplesDB[i][1] = 0; + } + + m_ptr = 0; + m_state = 0; + } // downsample by 2, return center part of original spectrum bool workDecimateCenter(Sample* sample) @@ -754,19 +765,4 @@ protected: } }; -template -IntHalfbandFilterDB::IntHalfbandFilterDB() -{ - m_size = HBFIRFilterTraits::hbOrder - 1; - - for (int i = 0; i < m_size; i++) - { - m_samplesDB[i][0] = 0; - m_samplesDB[i][1] = 0; - } - - m_ptr = 0; - m_state = 0; -} - #endif // INCLUDE_INTHALFBANDFILTER_DB_H diff --git a/windowsms.install.bat b/windowsms.install.bat index 0a3a67576..7fd3cb16a 100644 --- a/windowsms.install.bat +++ b/windowsms.install.bat @@ -75,6 +75,7 @@ REM copy plugins\samplesource\bladerf2input\%1\inputbladerf2.dll %2\plugins\samp copy plugins\samplesource\limesdrinput\%1\inputlimesdr.dll %2\plugins\samplesource REM copy plugins\samplesource\plutosdrinput\%1\inputplutosdr.dll %2\plugins\samplesource copy plugins\samplesource\sdrdaemonsource\%1\inputsdrdaemonsource.dll %2\plugins\samplesource +copy plugins\samplesource\soapysdrinput\%1\inputsoapysdr.dll %2\plugins\samplesource copy plugins\samplesink\filesink\%1\outputfilesink.dll %2\plugins\samplesink REM copy plugins\samplesink\bladerf1output\%1\outputbladerf1.dll %2\plugins\samplesink @@ -83,3 +84,4 @@ copy plugins\samplesink\hackrfoutput\%1\outputhackrf.dll %2\plugins\samplesink copy plugins\samplesink\limesdroutput\%1\outputlimesdr.dll %2\plugins\samplesink REM copy plugins\samplesink\plutosdroutput\%1\outputplutosdr.dll %2\plugins\samplesink copy plugins\samplesink\sdrdaemonsink\%1\outputsdrdaemonsink.dll %2\plugins\samplesink +copy plugins\samplesink\soapysdroutput\%1\outputsoapysdr.dll %2\plugins\samplesink From 8e5a332b508d23432a4b6637e9536b7b69f43384 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 16 Nov 2018 10:47:30 +0100 Subject: [PATCH 053/102] Windows: MSVC2017: use default PothosSDR install directory --- devices/devices.pro | 6 +++--- plugins/samplesink/soapysdroutput/soapysdroutput.pro | 4 ++-- plugins/samplesource/soapysdrinput/soapysdrinput.pro | 4 ++-- windowsms.install.bat | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/devices/devices.pro b/devices/devices.pro index 0b8741487..d1781bdba 100644 --- a/devices/devices.pro +++ b/devices/devices.pro @@ -61,7 +61,7 @@ MINGW32 || MINGW64 || macx { } MSVC { - INCLUDEPATH += "C:\Programs\PothosSDR\include" + INCLUDEPATH += "C:\Program Files\PothosSDR\include" } INCLUDEPATH += $$LIBPERSEUSSRC @@ -181,6 +181,6 @@ macx { MSVC { LIBS += -L../libhackrf/$${build_subdir} -llibhackrf - LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lLimeSuite - LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lSoapySDR + LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lLimeSuite + LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lSoapySDR } diff --git a/plugins/samplesink/soapysdroutput/soapysdroutput.pro b/plugins/samplesink/soapysdroutput/soapysdroutput.pro index 41e2d7a4a..83b0e42ee 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutput.pro +++ b/plugins/samplesink/soapysdroutput/soapysdroutput.pro @@ -17,7 +17,7 @@ INCLUDEPATH += ../../../sdrbase INCLUDEPATH += ../../../sdrgui INCLUDEPATH += ../../../devices INCLUDEPATH += ../../../swagger/sdrangel/code/qt5/client -INCLUDEPATH += "C:\Programs\PothosSDR\include" +INCLUDEPATH += "C:\Program Files\PothosSDR\include" CONFIG(Release):build_subdir = release CONFIG(Debug):build_subdir = debug @@ -40,4 +40,4 @@ LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui LIBS += -L../../../swagger/$${build_subdir} -lswagger LIBS += -L../../../devices/$${build_subdir} -ldevices -LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lSoapySDR +LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lSoapySDR diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.pro b/plugins/samplesource/soapysdrinput/soapysdrinput.pro index 41f302c51..f16575928 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinput.pro +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.pro @@ -17,7 +17,7 @@ INCLUDEPATH += ../../../sdrbase INCLUDEPATH += ../../../sdrgui INCLUDEPATH += ../../../devices INCLUDEPATH += ../../../swagger/sdrangel/code/qt5/client -INCLUDEPATH += "C:\Programs\PothosSDR\include" +INCLUDEPATH += "C:\Program Files\PothosSDR\include" CONFIG(Release):build_subdir = release CONFIG(Debug):build_subdir = debug @@ -40,4 +40,4 @@ LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui LIBS += -L../../../swagger/$${build_subdir} -lswagger LIBS += -L../../../devices/$${build_subdir} -ldevices -LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lSoapySDR +LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lSoapySDR diff --git a/windowsms.install.bat b/windowsms.install.bat index 7fd3cb16a..0a71a6dbb 100644 --- a/windowsms.install.bat +++ b/windowsms.install.bat @@ -3,7 +3,7 @@ SET opencvdir="C:\softs\opencv\build\mw32\install\x86\mingw\bin" SET libxml2dir="C:\softs\libxml2-2.7.8.win32" SET libiconvdir="C:\softs\iconv-1.9.2.win32" SET libzlib1dir="C:\softs\zlib-1.2.5" -SET pothosdir="C:\Programs\PothosSDR" +SET pothosdir="C:\Program Files\PothosSDR" SET pthreadsdir="C:\softs\pthreads-w32" copy app\%1\sdrangel.exe %2 @@ -27,7 +27,7 @@ copy libairspyhf\%1\libairspyhf.dll %2 REM copy libbladerf\%1\libbladerf.dll %2 REM copy libiio\%1\libiio.dll %2 copy %pothosdir%\bin\LimeSuite.dll %2 -copy %pothosdir%\bin\SoapySDR.dll %2 +REM copy %pothosdir%\bin\SoapySDR.dll %2 copy %libusbdir%\dll\libusb-1.0.dll %2 copy %pthreadsdir%\dll\x64\pthreadVC2.dll %2 From 710718682f7a77b3098a95059918d31a9b0c551c Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 16 Nov 2018 11:19:04 +0100 Subject: [PATCH 054/102] SoapySDR support: if no label is registered for the device then create one with the driver name and sequence --- devices/soapysdr/devicesoapysdrscan.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/devices/soapysdr/devicesoapysdrscan.cpp b/devices/soapysdr/devicesoapysdrscan.cpp index 61b44d0c2..234f6e6ef 100644 --- a/devices/soapysdr/devicesoapysdrscan.cpp +++ b/devices/soapysdr/devicesoapysdrscan.cpp @@ -66,15 +66,17 @@ void DeviceSoapySDRScan::scan() SoapySDR::Kwargs::const_iterator kargIt; - if ((kargIt = kit->find("label")) != kit->end()) - { + if ((kargIt = kit->find("label")) != kit->end()) { m_deviceEnums.back().m_label = QString(kargIt->second.c_str()); - qDebug("DeviceSoapySDRScan::scan: %s #%u %s", - m_deviceEnums.back().m_driverName.toStdString().c_str(), - deviceSeq, - kargIt->second.c_str()); + } else { // if no label is registered for this device then create a label with the driver name and sequence + m_deviceEnums.back().m_label = QString("%1-%2").arg(m_deviceEnums.back().m_driverName).arg(deviceSeq); } + qDebug("DeviceSoapySDRScan::scan: %s #%u %s", + m_deviceEnums.back().m_driverName.toStdString().c_str(), + deviceSeq, + m_deviceEnums.back().m_label.toStdString().c_str()); + if ((kargIt = kit->find("serial")) != kit->end()) { m_deviceEnums.back().m_idKey = QString(kargIt->first.c_str()); From 1462834c138d782f19d05d7182416e8f5d35e3b2 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 16 Nov 2018 11:34:00 +0100 Subject: [PATCH 055/102] Windows: MSVC2017: install SoapySDR.dll with the installation script --- windowsms.install.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windowsms.install.bat b/windowsms.install.bat index 0a71a6dbb..43823e403 100644 --- a/windowsms.install.bat +++ b/windowsms.install.bat @@ -27,7 +27,7 @@ copy libairspyhf\%1\libairspyhf.dll %2 REM copy libbladerf\%1\libbladerf.dll %2 REM copy libiio\%1\libiio.dll %2 copy %pothosdir%\bin\LimeSuite.dll %2 -REM copy %pothosdir%\bin\SoapySDR.dll %2 +copy %pothosdir%\bin\SoapySDR.dll %2 copy %libusbdir%\dll\libusb-1.0.dll %2 copy %pthreadsdir%\dll\x64\pthreadVC2.dll %2 From 1da6f64a25d9bd521cefa66d35f14162e6de5902 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 16 Nov 2018 13:07:21 +0100 Subject: [PATCH 056/102] Windows: MSVC2017: use default path for SoapySDR --- devices/bladerf1/devicebladerf1.h | 2 +- plugins/samplesink/limesdroutput/limesdroutput.pro | 4 ++-- plugins/samplesource/limesdrinput/limesdrinput.pro | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/devices/bladerf1/devicebladerf1.h b/devices/bladerf1/devicebladerf1.h index f8a9d1cad..41aa5272c 100644 --- a/devices/bladerf1/devicebladerf1.h +++ b/devices/bladerf1/devicebladerf1.h @@ -30,7 +30,7 @@ private: static struct bladerf *open_bladerf_from_serial(const char *serial); }; -class BladerfBandwidths { +class DEVICES_API BladerfBandwidths { public: static unsigned int getBandwidth(unsigned int bandwidth_index); static unsigned int getBandwidthIndex(unsigned int bandwidth); diff --git a/plugins/samplesink/limesdroutput/limesdroutput.pro b/plugins/samplesink/limesdroutput/limesdroutput.pro index 64de5cb99..8f4f60b51 100644 --- a/plugins/samplesink/limesdroutput/limesdroutput.pro +++ b/plugins/samplesink/limesdroutput/limesdroutput.pro @@ -42,7 +42,7 @@ MINGW32 || MINGW64 || macx { } MSVC { - INCLUDEPATH += "C:\Programs\PothosSDR\include" + INCLUDEPATH += "C:\Program Files\PothosSDR\include" } CONFIG(Release):build_subdir = release @@ -71,7 +71,7 @@ MINGW32 || MINGW64 || macx { LIBS += -L../../../liblimesuite/$${build_subdir} -lliblimesuite } MSVC { - LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lLimeSuite + LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lLimeSuite } RESOURCES = ../../../sdrgui/resources/res.qrc diff --git a/plugins/samplesource/limesdrinput/limesdrinput.pro b/plugins/samplesource/limesdrinput/limesdrinput.pro index 8cd60fe61..8c6ec1fe0 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.pro +++ b/plugins/samplesource/limesdrinput/limesdrinput.pro @@ -44,7 +44,7 @@ MINGW32 || MINGW64 || macx { } MSVC { - INCLUDEPATH += "C:\Programs\PothosSDR\include" + INCLUDEPATH += "C:\Program Files\PothosSDR\include" } CONFIG(Release):build_subdir = release @@ -72,7 +72,7 @@ MINGW32 || MINGW64 || macx { LIBS += -L../../../liblimesuite/$${build_subdir} -lliblimesuite } MSVC { - LIBS += -LC:\Programs\PothosSDR\bin -LC:\Programs\PothosSDR\lib -lLimeSuite + LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lLimeSuite } RESOURCES = ../../../sdrgui/resources/res.qrc From bc50bf9afae32ccc7c15df07c9ad45f5b4c2dc7e Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 16 Nov 2018 13:44:58 +0100 Subject: [PATCH 057/102] Windows: MSVC2017: BladeRF support --- devices/bladerf1/devicebladerf1.cpp | 4 ++-- devices/bladerf2/devicebladerf2shared.h | 2 +- devices/devices.pro | 16 ++++++++++++++ .../bladerf1output/bladerf1output.cpp | 2 +- .../bladerf1output/bladerf1output.pro | 19 +++++++++++++++-- .../bladerf2output/bladerf2output.cpp | 2 +- .../bladerf2output/bladerf2output.pro | 21 +++++++++++++++---- .../bladerf1input/bladerf1input.pro | 21 +++++++++++++++---- .../bladerf2input/bladerf2input.pro | 21 +++++++++++++++---- windowsms.install.bat | 10 ++++----- 10 files changed, 94 insertions(+), 24 deletions(-) diff --git a/devices/bladerf1/devicebladerf1.cpp b/devices/bladerf1/devicebladerf1.cpp index 14ab43374..618c96761 100644 --- a/devices/bladerf1/devicebladerf1.cpp +++ b/devices/bladerf1/devicebladerf1.cpp @@ -14,13 +14,13 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "../bladerf1/devicebladerf1.h" - #include #include #include +#include "devicebladerf1.h" + bool DeviceBladeRF1::open_bladerf(struct bladerf **dev, const char *serial) { int fpga_loaded; diff --git a/devices/bladerf2/devicebladerf2shared.h b/devices/bladerf2/devicebladerf2shared.h index f4664e6fb..590f7b559 100644 --- a/devices/bladerf2/devicebladerf2shared.h +++ b/devices/bladerf2/devicebladerf2shared.h @@ -31,7 +31,7 @@ class BladeRF2Output; class DEVICES_API DeviceBladeRF2Shared { public: - class MsgReportBuddyChange : public Message { + class DEVICES_API MsgReportBuddyChange : public Message { MESSAGE_CLASS_DECLARATION public: diff --git a/devices/devices.pro b/devices/devices.pro index d1781bdba..4d34d5297 100644 --- a/devices/devices.pro +++ b/devices/devices.pro @@ -136,6 +136,13 @@ macx { } MSVC { + SOURCES += bladerf1/devicebladerf1.cpp\ + bladerf1/devicebladerf1values.cpp\ + bladerf1/devicebladerf1shared.cpp + + SOURCES += bladerf2/devicebladerf2.cpp\ + bladerf2/devicebladerf2shared.cpp + SOURCES += hackrf/devicehackrf.cpp\ hackrf/devicehackrfvalues.cpp\ hackrf/devicehackrfshared.cpp @@ -149,6 +156,14 @@ MSVC { soapysdr/devicesoapysdrscan.cpp\ soapysdr/devicesoapysdrshared.cpp + HEADERS += bladerf1/devicebladerf1.h\ + bladerf1/devicebladerf1param.h\ + bladerf1/devicebladerf1values.h\ + bladerf1/devicebladerf1shared.h + + HEADERS += bladerf2/devicebladerf2.h\ + bladerf2/devicebladerf2shared.h + HEADERS += hackrf/devicehackrf.h\ hackrf/devicehackrfparam.h\ hackrf/devicehackrfvalues.h\ @@ -181,6 +196,7 @@ macx { MSVC { LIBS += -L../libhackrf/$${build_subdir} -llibhackrf + LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lbladeRF LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lLimeSuite LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lSoapySDR } diff --git a/plugins/samplesink/bladerf1output/bladerf1output.cpp b/plugins/samplesink/bladerf1output/bladerf1output.cpp index 17fbecbb0..9255cf3c3 100644 --- a/plugins/samplesink/bladerf1output/bladerf1output.cpp +++ b/plugins/samplesink/bladerf1output/bladerf1output.cpp @@ -321,7 +321,7 @@ bool Bladerf1Output::applySettings(const BladeRF1OutputSettings& settings, bool } else { - fifoSize = std::max( + fifoSize = (std::max)( (int) ((settings.m_devSampleRate/(1< Date: Sun, 18 Nov 2018 09:39:22 +0100 Subject: [PATCH 058/102] PVS-Studio Analysis corrections for serious issues --- .../channelrx/daemonsink/daemonsinkthread.h | 2 +- plugins/channelrx/demodatv/atvdemod.h | 3 ++- .../daemonsource/daemonsourcethread.h | 2 +- .../bladerf1output/bladerf1outputgui.cpp | 6 +----- .../bladerf2output/bladerf2output.cpp | 8 ++++++++ .../sdrdaemonsink/udpsinkfecworker.cpp | 6 +++++- .../sdrdaemonsink/udpsinkfecworker.h | 2 +- .../bladerf1input/bladerf1inputgui.cpp | 6 +----- .../bladerf2input/bladerf2input.cpp | 10 ++++++++++ .../sdrdaemonsourceudphandler.cpp | 18 +++++++++--------- sdrbase/channel/sdrdaemondatablock.h | 9 ++++++++- sdrbase/dsp/downchannelizer.cpp | 2 +- 12 files changed, 48 insertions(+), 26 deletions(-) diff --git a/plugins/channelrx/daemonsink/daemonsinkthread.h b/plugins/channelrx/daemonsink/daemonsinkthread.h index 5e468f7a9..e4f5cb332 100644 --- a/plugins/channelrx/daemonsink/daemonsinkthread.h +++ b/plugins/channelrx/daemonsink/daemonsinkthread.h @@ -68,7 +68,7 @@ public slots: private: QMutex m_startWaitMutex; QWaitCondition m_startWaiter; - bool m_running; + volatile bool m_running; CM256 m_cm256; CM256 *m_cm256p; diff --git a/plugins/channelrx/demodatv/atvdemod.h b/plugins/channelrx/demodatv/atvdemod.h index d4a5d4a7e..9d99c09ac 100644 --- a/plugins/channelrx/demodatv/atvdemod.h +++ b/plugins/channelrx/demodatv/atvdemod.h @@ -65,7 +65,8 @@ public: ATV_FM3, //!< Classical frequency modulation with phase derivative discriminator ATV_AM, //!< Classical amplitude modulation ATV_USB, //!< AM with vestigial lower side band (main signal is in the upper side) - ATV_LSB //!< AM with vestigial upper side band (main signal is in the lower side) + ATV_LSB, //!< AM with vestigial upper side band (main signal is in the lower side) + ATV_NONE //!< No modulation just produces zeros }; struct ATVConfig diff --git a/plugins/channeltx/daemonsource/daemonsourcethread.h b/plugins/channeltx/daemonsource/daemonsourcethread.h index a5371bed7..690d902a0 100644 --- a/plugins/channeltx/daemonsource/daemonsourcethread.h +++ b/plugins/channeltx/daemonsource/daemonsourcethread.h @@ -83,7 +83,7 @@ public: private: QMutex m_startWaitMutex; QWaitCondition m_startWaiter; - bool m_running; + volatile bool m_running; MessageQueue m_inputMessageQueue; SDRDaemonDataQueue *m_dataQueue; diff --git a/plugins/samplesink/bladerf1output/bladerf1outputgui.cpp b/plugins/samplesink/bladerf1output/bladerf1outputgui.cpp index 76562676f..d94afe77d 100644 --- a/plugins/samplesink/bladerf1output/bladerf1outputgui.cpp +++ b/plugins/samplesink/bladerf1output/bladerf1outputgui.cpp @@ -395,14 +395,10 @@ unsigned int Bladerf1OutputGui::getXb200Index(bool xb_200, bladerf_xb200_path xb { return 6; } - else if (xb200Filter == BLADERF_XB200_222M) + else // xb200Filter == BLADERF_XB200_222M { return 7; } - else - { - return 0; - } } } else diff --git a/plugins/samplesink/bladerf2output/bladerf2output.cpp b/plugins/samplesink/bladerf2output/bladerf2output.cpp index c11c5a638..caea1d0a5 100644 --- a/plugins/samplesink/bladerf2output/bladerf2output.cpp +++ b/plugins/samplesink/bladerf2output/bladerf2output.cpp @@ -303,6 +303,10 @@ bool BladeRF2Output::start() m_deviceShared.m_dev->closeTx(i); } + // was used as temporary storage: + delete[] fifos; + delete[] log2Interps; + needsStart = true; } else @@ -450,6 +454,10 @@ void BladeRF2Output::stop() bladeRF2OutputThread->startWork(); } + + // was used as temporary storage: + delete[] fifos; + delete[] log2Interps; } else // remove channel from existing thread { diff --git a/plugins/samplesink/sdrdaemonsink/udpsinkfecworker.cpp b/plugins/samplesink/sdrdaemonsink/udpsinkfecworker.cpp index 7618c4421..29f2c14c4 100644 --- a/plugins/samplesink/sdrdaemonsink/udpsinkfecworker.cpp +++ b/plugins/samplesink/sdrdaemonsink/udpsinkfecworker.cpp @@ -46,9 +46,13 @@ void UDPSinkFECWorker::startWork() qDebug("UDPSinkFECWorker::startWork"); m_startWaitMutex.lock(); m_udpSocket = new QUdpSocket(this); + start(); - while(!m_running) + + while(!m_running) { m_startWaiter.wait(&m_startWaitMutex, 100); + } + m_startWaitMutex.unlock(); } diff --git a/plugins/samplesink/sdrdaemonsink/udpsinkfecworker.h b/plugins/samplesink/sdrdaemonsink/udpsinkfecworker.h index 32580aa3f..fb61b602c 100644 --- a/plugins/samplesink/sdrdaemonsink/udpsinkfecworker.h +++ b/plugins/samplesink/sdrdaemonsink/udpsinkfecworker.h @@ -135,7 +135,7 @@ private: QMutex m_startWaitMutex; QWaitCondition m_startWaiter; - bool m_running; + volatile bool m_running; CM256 m_cm256; //!< CM256 library object bool m_cm256Valid; //!< true if CM256 library is initialized correctly QUdpSocket *m_udpSocket; diff --git a/plugins/samplesource/bladerf1input/bladerf1inputgui.cpp b/plugins/samplesource/bladerf1input/bladerf1inputgui.cpp index 3865fedce..3978c3f6e 100644 --- a/plugins/samplesource/bladerf1input/bladerf1inputgui.cpp +++ b/plugins/samplesource/bladerf1input/bladerf1inputgui.cpp @@ -463,14 +463,10 @@ unsigned int Bladerf1InputGui::getXb200Index(bool xb_200, bladerf_xb200_path xb2 { return 6; } - else if (xb200Filter == BLADERF_XB200_222M) + else // xb200Filter == BLADERF_XB200_222M { return 7; } - else - { - return 0; - } } } else diff --git a/plugins/samplesource/bladerf2input/bladerf2input.cpp b/plugins/samplesource/bladerf2input/bladerf2input.cpp index e2c46c04a..2f3faa600 100644 --- a/plugins/samplesource/bladerf2input/bladerf2input.cpp +++ b/plugins/samplesource/bladerf2input/bladerf2input.cpp @@ -329,6 +329,11 @@ bool BladeRF2Input::start() ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_source->setThread(0); } + // was used as temporary storage: + delete[] fifos; + delete[] log2Decims; + delete[] fcPoss; + needsStart = true; } else @@ -470,6 +475,11 @@ void BladeRF2Input::stop() if (stillActiveFIFO) { bladerf2InputThread->startWork(); } + + // was used as temporary storage: + delete[] fifos; + delete[] log2Decims; + delete[] fcPoss; } else // remove channel from existing thread { diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp index d24579eaa..9dfa8e7af 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp @@ -262,13 +262,7 @@ void SDRdaemonSourceUDPHandler::tick() const SDRDaemonMetaDataFEC& metaData = m_sdrDaemonBuffer.getCurrentMeta(); m_readLength = m_readLengthSamples * (metaData.m_sampleBytes & 0xF) * 2; - if (SDR_RX_SAMP_SZ == metaData.m_sampleBits) // same sample size - { - // read samples directly feeding the SampleFifo (no callback) - m_sampleFifo->write(reinterpret_cast(m_sdrDaemonBuffer.readData(m_readLength)), m_readLength); - m_samplesCount += m_readLengthSamples; - } - else if (metaData.m_sampleBits == 16) // 16 -> 24 bits + if ((metaData.m_sampleBits == 16) && (SDR_RX_SAMP_SZ == 24)) // 16 -> 24 bits { if (m_readLengthSamples > m_converterBufferNbSamples) { @@ -288,7 +282,7 @@ void SDRdaemonSourceUDPHandler::tick() m_sampleFifo->write(reinterpret_cast(m_converterBuffer), m_readLengthSamples*sizeof(Sample)); } - else if (metaData.m_sampleBits == 24) // 24 -> 16 bits + else if ((metaData.m_sampleBits == 24) && (SDR_RX_SAMP_SZ == 16)) // 24 -> 16 bits { if (m_readLengthSamples > m_converterBufferNbSamples) { @@ -307,7 +301,13 @@ void SDRdaemonSourceUDPHandler::tick() m_sampleFifo->write(reinterpret_cast(m_converterBuffer), m_readLengthSamples*sizeof(Sample)); } - else + else if ((metaData.m_sampleBits == 16) || (metaData.m_sampleBits == 24)) // same sample size and valid size + { + // read samples directly feeding the SampleFifo (no callback) + m_sampleFifo->write(reinterpret_cast(m_sdrDaemonBuffer.readData(m_readLength)), m_readLength); + m_samplesCount += m_readLengthSamples; + } + else // invalid size { qWarning("SDRdaemonSourceUDPHandler::tick: unexpected sample size in stream: %d bits", (int) metaData.m_sampleBits); } diff --git a/sdrbase/channel/sdrdaemondatablock.h b/sdrbase/channel/sdrdaemondatablock.h index 1b877f8f1..ed0b2241e 100644 --- a/sdrbase/channel/sdrdaemondatablock.h +++ b/sdrbase/channel/sdrdaemondatablock.h @@ -42,13 +42,20 @@ struct SDRDaemonMetaDataFEC uint8_t m_sampleBits; //!< 10 number of effective bits per sample (deprecated) uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data uint8_t m_nbFECBlocks; //!< 12 number of blocks carrying FEC + uint32_t m_tv_sec; //!< 16 seconds of timestamp at start time of super-frame processing uint32_t m_tv_usec; //!< 20 microseconds of timestamp at start time of super-frame processing uint32_t m_crc32; //!< 24 CRC32 of the above bool operator==(const SDRDaemonMetaDataFEC& rhs) { - return (memcmp((const void *) this, (const void *) &rhs, 12) == 0); // Only the 12 first bytes are relevant + // Only the first 6 fields are relevant + return (m_centerFrequency == rhs.m_centerFrequency) + && (m_sampleRate == rhs.m_sampleRate) + && (m_sampleBytes == rhs.m_sampleBytes) + && (m_sampleBits == rhs.m_sampleBits) + && (m_nbOriginalBlocks == rhs.m_nbOriginalBlocks) + && (m_nbFECBlocks == rhs.m_nbFECBlocks); } void init() diff --git a/sdrbase/dsp/downchannelizer.cpp b/sdrbase/dsp/downchannelizer.cpp index b8fe5f3f3..4d53b3b45 100644 --- a/sdrbase/dsp/downchannelizer.cpp +++ b/sdrbase/dsp/downchannelizer.cpp @@ -295,7 +295,7 @@ void DownChannelizer::freeFilterChain() void DownChannelizer::debugFilterChain() { - qDebug("DownChannelizer::debugFilterChain: %lu stages", m_filterStages.size()); + qDebug("DownChannelizer::debugFilterChain: %u stages", m_filterStages.size()); for(FilterStages::iterator it = m_filterStages.begin(); it != m_filterStages.end(); ++it) { From f5357e9917bcdfa7c905d8b0fcf4d24b4ca30a82 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 18 Nov 2018 11:06:41 +0100 Subject: [PATCH 059/102] PVS-Studio Analysis corrections for less serious issues --- plugins/channelrx/daemonsink/daemonsink.cpp | 5 +- .../daemonsink/daemonsinksettings.cpp | 1 + .../channelrx/demoddatv/datvconstellation.h | 8 +-- .../channelrx/demoddatv/leansdr/framework.h | 7 +- plugins/channelrx/demoddatv/leansdr/rs.h | 2 +- .../daemonsource/daemonsourcesettings.cpp | 1 + .../samplesink/sdrdaemonsink/udpsinkfec.cpp | 5 +- .../filesource/filesourcesettings.cpp | 2 +- qrtplib/rtcpcompoundpacketbuilder.h | 5 +- sdrbase/channel/sdrdaemondatareadqueue.cpp | 11 ++- sdrbase/channel/sdrdaemondatareadqueue.h | 12 ++-- sdrgui/gui/glspectrum.cpp | 28 ++------ sdrgui/gui/glspectrumgui.cpp | 2 +- sdrgui/gui/valuedial.cpp | 69 +++++++++++-------- sdrgui/gui/valuedialz.cpp | 49 +++++++------ 15 files changed, 103 insertions(+), 104 deletions(-) diff --git a/plugins/channelrx/daemonsink/daemonsink.cpp b/plugins/channelrx/daemonsink/daemonsink.cpp index 80313d68d..797e5b429 100644 --- a/plugins/channelrx/daemonsink/daemonsink.cpp +++ b/plugins/channelrx/daemonsink/daemonsink.cpp @@ -135,7 +135,10 @@ void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVec superBlock.m_header.m_blockIndex = m_txBlockIndex; superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4); superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ; - memcpy((void *) &superBlock.m_protectedBlock, (const void *) &metaData, sizeof(SDRDaemonMetaDataFEC)); + + SDRDaemonMetaDataFEC *destMeta = (SDRDaemonMetaDataFEC *) &superBlock.m_protectedBlock; + *destMeta = metaData; + //memcpy((void *) &superBlock.m_protectedBlock, (const void *) &metaData, sizeof(SDRDaemonMetaDataFEC)); if (!(metaData == m_currentMetaFEC)) { diff --git a/plugins/channelrx/daemonsink/daemonsinksettings.cpp b/plugins/channelrx/daemonsink/daemonsinksettings.cpp index 9b81702f0..1579bc80f 100644 --- a/plugins/channelrx/daemonsink/daemonsinksettings.cpp +++ b/plugins/channelrx/daemonsink/daemonsinksettings.cpp @@ -39,6 +39,7 @@ void DaemonSinkSettings::resetToDefaults() m_dataPort = 9090; m_rgbColor = QColor(140, 4, 4).rgb(); m_title = "Daemon sink"; + m_channelMarker = nullptr; } QByteArray DaemonSinkSettings::serialize() const diff --git a/plugins/channelrx/demoddatv/datvconstellation.h b/plugins/channelrx/demoddatv/datvconstellation.h index f3d21b32c..dc97744e8 100644 --- a/plugins/channelrx/demoddatv/datvconstellation.h +++ b/plugins/channelrx/demoddatv/datvconstellation.h @@ -69,12 +69,8 @@ template struct datvconstellation: runnable for (; p < pend; ++p) { - if (m_objDATVScreen != 0) - { - m_objDATVScreen->selectRow(256 * (p->re - xymin) / (xymax - xymin)); - m_objDATVScreen->setDataColor(256 - 256 * ((p->im - xymin) / (xymax - xymin)), 255, 0, 255); - } - + m_objDATVScreen->selectRow(256 * (p->re - xymin) / (xymax - xymin)); + m_objDATVScreen->setDataColor(256 - 256 * ((p->im - xymin) / (xymax - xymin)), 255, 0, 255); } if (cstln && (*cstln)) diff --git a/plugins/channelrx/demoddatv/leansdr/framework.h b/plugins/channelrx/demoddatv/leansdr/framework.h index f6abfd1e3..d894c74b5 100644 --- a/plugins/channelrx/demoddatv/leansdr/framework.h +++ b/plugins/channelrx/demoddatv/leansdr/framework.h @@ -2,6 +2,8 @@ #define LEANSDR_FRAMEWORK_H #include +#include + #include #include #include @@ -106,9 +108,10 @@ struct scheduler bool verbose, debug; scheduler() : - npipes(0), nrunnables(0), windows(NULL), verbose(false), debug( - false) + npipes(0), nrunnables(0), windows(nullptr), verbose(false), debug(false) { + std::fill(pipes, pipes + MAX_PIPES, nullptr); + std::fill(runnables, runnables + MAX_RUNNABLES, nullptr); } void add_pipe(pipebuf_common *p) diff --git a/plugins/channelrx/demoddatv/leansdr/rs.h b/plugins/channelrx/demoddatv/leansdr/rs.h index 0df614409..32e5c0a93 100644 --- a/plugins/channelrx/demoddatv/leansdr/rs.h +++ b/plugins/channelrx/demoddatv/leansdr/rs.h @@ -162,7 +162,7 @@ struct rs_engine { // TBD Avoid copying u8 p[204]; - memcpy(p, msg, 188); + memcpy(p, msg, 204); // was 188 but causing underflow (PVS https://www.viva64.com/en/w/v512/) memset(p + 188, 0, 16); // p = msg*X^16 #if DEBUG_RS diff --git a/plugins/channeltx/daemonsource/daemonsourcesettings.cpp b/plugins/channeltx/daemonsource/daemonsourcesettings.cpp index e55462390..ca0dafbe5 100644 --- a/plugins/channeltx/daemonsource/daemonsourcesettings.cpp +++ b/plugins/channeltx/daemonsource/daemonsourcesettings.cpp @@ -31,6 +31,7 @@ void DaemonSourceSettings::resetToDefaults() m_dataPort = 9090; m_rgbColor = QColor(140, 4, 4).rgb(); m_title = "Daemon source"; + m_channelMarker = nullptr; } QByteArray DaemonSourceSettings::serialize() const diff --git a/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp b/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp index 14b9ef820..1013f2bde 100644 --- a/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp +++ b/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp @@ -141,7 +141,10 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk m_superBlock.m_header.m_blockIndex = m_txBlockIndex; m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4); m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ; - memcpy((char *) &m_superBlock.m_protectedBlock, (const char *) &metaData, sizeof(SDRDaemonMetaDataFEC)); + + SDRDaemonMetaDataFEC *destMeta = (SDRDaemonMetaDataFEC *) &m_superBlock.m_protectedBlock; + *destMeta = metaData; + //memcpy((char *) &m_superBlock.m_protectedBlock, (const char *) &metaData, sizeof(SDRDaemonMetaDataFEC)); if (!(metaData == m_currentMetaFEC)) { diff --git a/plugins/samplesource/filesource/filesourcesettings.cpp b/plugins/samplesource/filesource/filesourcesettings.cpp index 950f1c1af..f8a6b370a 100644 --- a/plugins/samplesource/filesource/filesourcesettings.cpp +++ b/plugins/samplesource/filesource/filesourcesettings.cpp @@ -103,7 +103,7 @@ int FileSourceSettings::getAccelerationValue(int accelerationIndex) unsigned int v = accelerationIndex - 1; int m = pow(10.0, v/3 > m_accelerationMaxScale ? m_accelerationMaxScale : v/3); - int x; + int x = 1; if (v % 3 == 0) { x = 2; diff --git a/qrtplib/rtcpcompoundpacketbuilder.h b/qrtplib/rtcpcompoundpacketbuilder.h index 7daff9dc1..f105f9959 100644 --- a/qrtplib/rtcpcompoundpacketbuilder.h +++ b/qrtplib/rtcpcompoundpacketbuilder.h @@ -38,13 +38,15 @@ #define RTCPCOMPOUNDPACKETBUILDER_H +#include +#include + #include "rtpconfig.h" #include "rtcpcompoundpacket.h" #include "rtptimeutilities.h" #include "rtcpsdespacket.h" #include "rtperrors.h" #include "rtpendian.h" -#include #include "export.h" @@ -151,6 +153,7 @@ private: Report() { headerdata = (uint8_t *) headerdata32; + std::fill(&headerdata32[0], &headerdata32[0] + ((sizeof(uint32_t) + sizeof(RTCPSenderReport)) / sizeof(uint32_t)), 0U); isSR = false; headerlength = 0; } diff --git a/sdrbase/channel/sdrdaemondatareadqueue.cpp b/sdrbase/channel/sdrdaemondatareadqueue.cpp index 601a5f12a..a1fd28f48 100644 --- a/sdrbase/channel/sdrdaemondatareadqueue.cpp +++ b/sdrbase/channel/sdrdaemondatareadqueue.cpp @@ -130,14 +130,11 @@ void SDRDaemonDataReadQueue::readSample(Sample& s, bool scaleForTx) } else { - if (m_dataBlock) - { - delete m_dataBlock; - m_dataBlock = 0; + delete m_dataBlock; + m_dataBlock = 0; - if (length() == 0) { - qWarning("SDRDaemonDataReadQueue::readSample: try to pop new block but queue is empty"); - } + if (length() == 0) { + qWarning("SDRDaemonDataReadQueue::readSample: try to pop new block but queue is empty"); } if (length() > 0) diff --git a/sdrbase/channel/sdrdaemondatareadqueue.h b/sdrbase/channel/sdrdaemondatareadqueue.h index ce120f8d2..46645c33b 100644 --- a/sdrbase/channel/sdrdaemondatareadqueue.h +++ b/sdrbase/channel/sdrdaemondatareadqueue.h @@ -59,11 +59,7 @@ private: int samplebits = m_dataBlock->m_superBlocks[blockIndex].m_header.m_sampleBits; // I or Q sample size in bits int32_t iconv, qconv; - if (sizeof(Sample) == sampleSize) // generally 16->16 or 24->24 bits - { - s = *((Sample*) &(m_dataBlock->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize])); - } - else if ((sizeof(Sample) == 4) && (sampleSize == 8)) // generally 24->16 bits + if ((sizeof(Sample) == 4) && (sampleSize == 8)) // generally 24->16 bits { iconv = ((int32_t*) &(m_dataBlock->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]))[0]; qconv = ((int32_t*) &(m_dataBlock->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+4]))[0]; @@ -81,7 +77,11 @@ private: s.setReal(iconv); s.setImag(qconv); } - else + else if ((sampleSize == 4) || (sampleSize == 8)) // generally 16->16 or 24->24 bits + { + s = *((Sample*) &(m_dataBlock->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize])); + } + else // invalid size { s = Sample{0, 0}; } diff --git a/sdrgui/gui/glspectrum.cpp b/sdrgui/gui/glspectrum.cpp index f7d9767d4..52de69c5f 100644 --- a/sdrgui/gui/glspectrum.cpp +++ b/sdrgui/gui/glspectrum.cpp @@ -1561,18 +1561,9 @@ void GLSpectrum::applyChanges() m_waterfallBuffer = new QImage(m_fftSize, waterfallHeight, QImage::Format_ARGB32); - if(m_waterfallBuffer != 0) - { - m_waterfallBuffer->fill(qRgb(0x00, 0x00, 0x00)); - m_glShaderWaterfall.initTexture(*m_waterfallBuffer); - m_waterfallBufferPos = 0; - } - else - { - m_fftSize = 0; - m_changesPending = true; - return; - } + m_waterfallBuffer->fill(qRgb(0x00, 0x00, 0x00)); + m_glShaderWaterfall.initTexture(*m_waterfallBuffer); + m_waterfallBufferPos = 0; } if(fftSizeChanged) @@ -1588,17 +1579,8 @@ void GLSpectrum::applyChanges() m_histogramBuffer = new QImage(m_fftSize, 100, QImage::Format_RGB32); - if(m_histogramBuffer != 0) - { - m_histogramBuffer->fill(qRgb(0x00, 0x00, 0x00)); - m_glShaderHistogram.initTexture(*m_histogramBuffer, QOpenGLTexture::ClampToEdge); - } - else - { - m_fftSize = 0; - m_changesPending = true; - return; - } + m_histogramBuffer->fill(qRgb(0x00, 0x00, 0x00)); + m_glShaderHistogram.initTexture(*m_histogramBuffer, QOpenGLTexture::ClampToEdge); m_histogram = new quint8[100 * m_fftSize]; memset(m_histogram, 0x00, 100 * m_fftSize); diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp index 808325521..64bf9b78f 100644 --- a/sdrgui/gui/glspectrumgui.cpp +++ b/sdrgui/gui/glspectrumgui.cpp @@ -499,7 +499,7 @@ int GLSpectrumGUI::getAveragingValue(int averagingIndex) const int v = averagingIndex - 1; int m = pow(10.0, v/3 > m_averagingMaxScale ? m_averagingMaxScale : v/3); - int x; + int x = 1; if (v % 3 == 0) { x = 2; diff --git a/sdrgui/gui/valuedial.cpp b/sdrgui/gui/valuedial.cpp index 4fc002cd7..1d1b359ec 100644 --- a/sdrgui/gui/valuedial.cpp +++ b/sdrgui/gui/valuedial.cpp @@ -182,13 +182,16 @@ void ValueDial::paintEvent(QPaintEvent*) painter.setPen(m_colorMapper.getBoundaryColor()); painter.setBrush(Qt::NoBrush); - for(int i = 1; i < m_numDigits + m_numDecimalPoints; i++) { + + for (int i = 1; i < m_numDigits + m_numDecimalPoints; i++) + { painter.setPen(m_colorMapper.getBoundaryColor()); painter.drawLine(1 + i * m_digitWidth, 1, 1 + i * m_digitWidth, height() - 1); painter.setPen(m_colorMapper.getBoundaryAlphaColor()); painter.drawLine(0 + i * m_digitWidth, 1, 0 + i * m_digitWidth, height() - 1); painter.drawLine(2 + i * m_digitWidth, 1, 2 + i * m_digitWidth, height() - 1); } + painter.setPen(m_colorMapper.getBoundaryAlphaColor()); painter.drawLine(1, 1, 1, height() - 1); painter.drawLine(width() - 2, 1, width() - 2, height() - 1); @@ -201,13 +204,15 @@ void ValueDial::paintEvent(QPaintEvent*) painter.drawLine(1, height() - 1, width() - 1, height() - 1); painter.drawLine(width() - 1, height() - 1, width() - 1, 0); - if(m_hightlightedDigit >= 0) { + if (m_hightlightedDigit >= 0) + { painter.setPen(Qt::NoPen); painter.setBrush(m_colorMapper.getHighlightColor()); painter.drawRect(2 + m_hightlightedDigit * m_digitWidth, 1, m_digitWidth - 1, height() - 1); } - if(m_animationState == 0) { + if (m_animationState == 0) + { for(int i = 0; i < m_text.length(); i++) { painter.setClipRect(1 + i * m_digitWidth, 1, m_digitWidth, m_digitHeight * 2); painter.setPen(m_colorMapper.getSecondaryForegroundColor()); @@ -224,31 +229,39 @@ void ValueDial::paintEvent(QPaintEvent*) painter.setBrush(m_colorMapper.getSecondaryForegroundColor()); painter.drawRect(4 + m_cursor * m_digitWidth, 1 + m_digitHeight * 1.5, m_digitWidth - 5, m_digitHeight / 6); } - } else { - if(m_animationState != 0) { - for(int i = 0; i < m_text.length(); i++) { - if(m_text[i] == m_textNew[i]) { - painter.setClipRect(1 + i * m_digitWidth, 1, m_digitWidth, m_digitHeight * 2); - painter.setPen(m_colorMapper.getSecondaryForegroundColor()); - painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * 0.6, m_digitWidth, m_digitHeight), Qt::AlignCenter, m_text.mid(i, 1)); - if(m_text[i] != m_groupSeparator) { - painter.setPen(m_colorMapper.getForegroundColor()); - painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * -0.7, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], true)); - painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * 1.9, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], false)); - } - } else { - int h = m_digitHeight * 0.6 + m_digitHeight * m_animationState / 2.0; - painter.setClipRect(1 + i * m_digitWidth, 1, m_digitWidth, m_digitHeight * 2); - painter.setPen(m_colorMapper.getSecondaryForegroundColor()); - painter.drawText(QRect(1 + i * m_digitWidth, h, m_digitWidth, m_digitHeight), Qt::AlignCenter, m_text.mid(i, 1)); - if(m_text[i] != m_groupSeparator) { - painter.setPen(m_colorMapper.getForegroundColor()); - painter.drawText(QRect(1 + i * m_digitWidth, h + m_digitHeight * -0.7, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], true)); - painter.drawText(QRect(1 + i * m_digitWidth, h + m_digitHeight * 1.9, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], false)); - } - } - } - } + } + else + { + for (int i = 0; i < m_text.length(); i++) + { + if (m_text[i] == m_textNew[i]) + { + painter.setClipRect(1 + i * m_digitWidth, 1, m_digitWidth, m_digitHeight * 2); + painter.setPen(m_colorMapper.getSecondaryForegroundColor()); + painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * 0.6, m_digitWidth, m_digitHeight), Qt::AlignCenter, m_text.mid(i, 1)); + + if (m_text[i] != m_groupSeparator) + { + painter.setPen(m_colorMapper.getForegroundColor()); + painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * -0.7, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], true)); + painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * 1.9, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], false)); + } + } + else + { + int h = m_digitHeight * 0.6 + m_digitHeight * m_animationState / 2.0; + painter.setClipRect(1 + i * m_digitWidth, 1, m_digitWidth, m_digitHeight * 2); + painter.setPen(m_colorMapper.getSecondaryForegroundColor()); + painter.drawText(QRect(1 + i * m_digitWidth, h, m_digitWidth, m_digitHeight), Qt::AlignCenter, m_text.mid(i, 1)); + + if (m_text[i] != m_groupSeparator) + { + painter.setPen(m_colorMapper.getForegroundColor()); + painter.drawText(QRect(1 + i * m_digitWidth, h + m_digitHeight * -0.7, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], true)); + painter.drawText(QRect(1 + i * m_digitWidth, h + m_digitHeight * 1.9, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], false)); + } + } + } } } diff --git a/sdrgui/gui/valuedialz.cpp b/sdrgui/gui/valuedialz.cpp index d8c74f342..52b706577 100644 --- a/sdrgui/gui/valuedialz.cpp +++ b/sdrgui/gui/valuedialz.cpp @@ -256,7 +256,7 @@ void ValueDialZ::paintEvent(QPaintEvent*) painter.setPen(m_colorMapper.getSecondaryForegroundColor()); painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * 0.6, m_digitWidth, m_digitHeight), Qt::AlignCenter, m_text.mid(i, 1)); - if(m_text[i] != m_groupSeparator) + if (m_text[i] != m_groupSeparator) { painter.setPen(m_colorMapper.getForegroundColor()); painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * -0.7, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], true)); @@ -275,36 +275,33 @@ void ValueDialZ::paintEvent(QPaintEvent*) } else { - if(m_animationState != 0) + for(int i = 0; i < m_text.length(); i++) { - for(int i = 0; i < m_text.length(); i++) + if (m_text[i] == m_textNew[i]) { - if(m_text[i] == m_textNew[i]) - { - painter.setClipRect(1 + i * m_digitWidth, 1, m_digitWidth, m_digitHeight * 2); - painter.setPen(m_colorMapper.getSecondaryForegroundColor()); - painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * 0.6, m_digitWidth, m_digitHeight), Qt::AlignCenter, m_text.mid(i, 1)); + painter.setClipRect(1 + i * m_digitWidth, 1, m_digitWidth, m_digitHeight * 2); + painter.setPen(m_colorMapper.getSecondaryForegroundColor()); + painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * 0.6, m_digitWidth, m_digitHeight), Qt::AlignCenter, m_text.mid(i, 1)); - if(m_text[i] != m_groupSeparator) - { - painter.setPen(m_colorMapper.getForegroundColor()); - painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * -0.7, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], true)); - painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * 1.9, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], false)); - } + if (m_text[i] != m_groupSeparator) + { + painter.setPen(m_colorMapper.getForegroundColor()); + painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * -0.7, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], true)); + painter.drawText(QRect(1 + i * m_digitWidth, m_digitHeight * 1.9, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], false)); } - else - { - int h = m_digitHeight * 0.6 + m_digitHeight * m_animationState / 2.0; - painter.setClipRect(1 + i * m_digitWidth, 1, m_digitWidth, m_digitHeight * 2); - painter.setPen(m_colorMapper.getSecondaryForegroundColor()); - painter.drawText(QRect(1 + i * m_digitWidth, h, m_digitWidth, m_digitHeight), Qt::AlignCenter, m_text.mid(i, 1)); + } + else + { + int h = m_digitHeight * 0.6 + m_digitHeight * m_animationState / 2.0; + painter.setClipRect(1 + i * m_digitWidth, 1, m_digitWidth, m_digitHeight * 2); + painter.setPen(m_colorMapper.getSecondaryForegroundColor()); + painter.drawText(QRect(1 + i * m_digitWidth, h, m_digitWidth, m_digitHeight), Qt::AlignCenter, m_text.mid(i, 1)); - if(m_text[i] != m_groupSeparator) - { - painter.setPen(m_colorMapper.getForegroundColor()); - painter.drawText(QRect(1 + i * m_digitWidth, h + m_digitHeight * -0.7, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], true)); - painter.drawText(QRect(1 + i * m_digitWidth, h + m_digitHeight * 1.9, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], false)); - } + if (m_text[i] != m_groupSeparator) + { + painter.setPen(m_colorMapper.getForegroundColor()); + painter.drawText(QRect(1 + i * m_digitWidth, h + m_digitHeight * -0.7, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], true)); + painter.drawText(QRect(1 + i * m_digitWidth, h + m_digitHeight * 1.9, m_digitWidth, m_digitHeight), Qt::AlignCenter, digitNeigh(m_text[i], false)); } } } From 865d26cc150df1e678e466f1a243d3d0aeddea68 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 18 Nov 2018 21:56:33 +0100 Subject: [PATCH 060/102] FCDProPlus: moved open/close source to input so that open source failure is correctly reported as an error --- .../samplesource/fcdproplus/fcdproplusgui.cpp | 15 ++- .../fcdproplus/fcdproplusinput.cpp | 96 +++++++++++++-- .../samplesource/fcdproplus/fcdproplusinput.h | 5 + .../fcdproplus/fcdproplusthread.cpp | 109 ++++-------------- .../fcdproplus/fcdproplusthread.h | 9 +- 5 files changed, 129 insertions(+), 105 deletions(-) diff --git a/plugins/samplesource/fcdproplus/fcdproplusgui.cpp b/plugins/samplesource/fcdproplus/fcdproplusgui.cpp index e557f160a..7b261a9ca 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusgui.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusgui.cpp @@ -159,18 +159,20 @@ void FCDProPlusGui::handleInputMessages() while ((message = m_inputMessageQueue.pop()) != 0) { - qDebug("RTLSDRGui::handleInputMessages: message: %s", message->getIdentifier()); - if (DSPSignalNotification::match(*message)) { DSPSignalNotification* notif = (DSPSignalNotification*) message; m_sampleRate = notif->getSampleRate(); m_deviceCenterFrequency = notif->getCenterFrequency(); - qDebug("RTLSDRGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency()); + qDebug("FCDProPlusGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency()); updateSampleRateAndFrequency(); delete message; } + else + { + qWarning("FCDProPlusGui::handleInputMessages: message: %s. No action.", message->getIdentifier()); + } } } @@ -322,11 +324,8 @@ void FCDProPlusGui::on_ppm_valueChanged(int value) void FCDProPlusGui::on_startStop_toggled(bool checked) { - if (m_doApplySettings) - { - FCDProPlusInput::MsgStartStop *message = FCDProPlusInput::MsgStartStop::create(checked); - m_sampleSource->getInputMessageQueue()->push(message); - } + FCDProPlusInput::MsgStartStop *message = FCDProPlusInput::MsgStartStop::create(checked); + m_sampleSource->getInputMessageQueue()->push(message); } void FCDProPlusGui::on_record_toggled(bool checked) diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp index be4902914..dcb17cd09 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp @@ -41,6 +41,7 @@ MESSAGE_CLASS_DEFINITION(FCDProPlusInput::MsgFileRecord, Message) FCDProPlusInput::FCDProPlusInput(DeviceSourceAPI *deviceAPI) : m_deviceAPI(deviceAPI), m_dev(0), + fcd_handle(0), m_settings(), m_FCDThread(0), m_deviceDescription(fcd_traits::displayedName), @@ -87,14 +88,15 @@ void FCDProPlusInput::init() bool FCDProPlusInput::start() { - // QMutexLocker mutexLocker(&m_mutex); if (!m_dev) { return false; } - if (m_running) stop(); + if (m_running) { + stop(); + } qDebug() << "FCDProPlusInput::start"; @@ -105,13 +107,23 @@ bool FCDProPlusInput::start() //applySettings(m_settings, true); - if(!m_sampleFifo.setSize(96000*4)) + if (!m_sampleFifo.setSize(96000*4)) { - qCritical("Could not allocate SampleFifo"); + qCritical("FCDProPlusInput::start: could not allocate SampleFifo"); return false; } - m_FCDThread = new FCDProPlusThread(&m_sampleFifo); + if (!openSource(fcd_traits::alsaDeviceName)) + { + qCritical("FCDProPlusInput::start: could not open source"); + return false; + } + else + { + qDebug("FCDProPlusInput::start: source opened"); + } + + m_FCDThread = new FCDProPlusThread(&m_sampleFifo, fcd_handle); m_FCDThread->startWork(); // mutexLocker.unlock(); @@ -133,6 +145,75 @@ void FCDProPlusInput::closeDevice() m_dev = 0; } +bool FCDProPlusInput::openSource(const char* cardname) +{ + bool fail = false; + snd_pcm_hw_params_t* params; + //fcd_rate = FCDPP_RATE; + //fcd_channels =2; + //fcd_format = SND_PCM_SFMT_U16_LE; + snd_pcm_stream_t fcd_stream = SND_PCM_STREAM_CAPTURE; + + if (fcd_handle) + { + qDebug("FCDProPlusInput::OpenSource: already opened"); + return false; + } + + if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0) + { + qCritical("FCDProPlusInput::OpenSource: cannot open %s", cardname); + return false; + } + + snd_pcm_hw_params_alloca(¶ms); + + if (snd_pcm_hw_params_any(fcd_handle, params) < 0) + { + qCritical("FCDProPlusInput::OpenSource: snd_pcm_hw_params_any failed"); + fail = true; + } + else if (snd_pcm_hw_params(fcd_handle, params) < 0) + { + qCritical("FCDProPlusInput::OpenSource: snd_pcm_hw_params failed"); + fail = true; + // TODO: check actual samplerate, may be crippled firmware + } + else + { + if (snd_pcm_start(fcd_handle) < 0) + { + qCritical("FCDProPlusInput::OpenSource: snd_pcm_start failed"); + fail = true; + } + else + { + qDebug("FCDProPlusInput::OpenSource: snd_pcm_start OK"); + } + } + + if (fail) + { + snd_pcm_close(fcd_handle); + return false; + } + else + { + qDebug("FCDProPlusInput::OpenSource: Funcube stream started"); + } + + return true; +} + +void FCDProPlusInput::closeSource() +{ + if (fcd_handle) { + snd_pcm_close(fcd_handle); + } + + fcd_handle = nullptr; +} + void FCDProPlusInput::stop() { QMutexLocker mutexLocker(&m_mutex); @@ -142,7 +223,8 @@ void FCDProPlusInput::stop() m_FCDThread->stopWork(); // wait for thread to quit ? delete m_FCDThread; - m_FCDThread = 0; + m_FCDThread = nullptr; + closeSource(); } m_running = false; @@ -217,7 +299,7 @@ bool FCDProPlusInput::handleMessage(const Message& message) else if (MsgStartStop::match(message)) { MsgStartStop& cmd = (MsgStartStop&) message; - qDebug() << "BladerfInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop"); + qDebug() << "FCDProPlusInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop"); if (cmd.getStartStop()) { diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.h b/plugins/samplesource/fcdproplus/fcdproplusinput.h index 38c4cac11..26eb53e61 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.h +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.h @@ -21,6 +21,8 @@ #include #include +#include + #include #include "fcdproplussettings.h" #include "fcdhid.h" @@ -147,11 +149,14 @@ public: private: bool openDevice(); void closeDevice(); + bool openSource(const char *filename); + void closeSource(); void applySettings(const FCDProPlusSettings& settings, bool force); void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const FCDProPlusSettings& settings); DeviceSourceAPI *m_deviceAPI; hid_device *m_dev; + snd_pcm_t* fcd_handle; QMutex m_mutex; FCDProPlusSettings m_settings; FCDProPlusThread* m_FCDThread; diff --git a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp index a29ca1411..1be59d82a 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp @@ -23,9 +23,9 @@ #include "dsp/samplesinkfifo.h" #include "fcdtraits.h" -FCDProPlusThread::FCDProPlusThread(SampleSinkFifo* sampleFifo, QObject* parent) : +FCDProPlusThread::FCDProPlusThread(SampleSinkFifo* sampleFifo, snd_pcm_t *fcd_handle, QObject* parent) : QThread(parent), - fcd_handle(NULL), + m_fcd_handle(fcd_handle), m_running(false), m_convertBuffer(fcd_traits::convBufSize), m_sampleFifo(sampleFifo) @@ -59,89 +59,17 @@ void FCDProPlusThread::stopWork() void FCDProPlusThread::run() { - if ( !OpenSource(fcd_traits::alsaDeviceName) ) - { - qCritical() << "FCDThread::run: cannot open FCD sound card"; - return; - } - // TODO: fallback to original fcd - m_running = true; + qDebug("FCDThread::run: start running loop"); - while(m_running) + while (m_running) { - if (work(fcd_traits::convBufSize) < 0) - { + if (work(fcd_traits::convBufSize) < 0) { break; } } - CloseSource(); -} - -bool FCDProPlusThread::OpenSource(const char* cardname) -{ - bool fail = false; - snd_pcm_hw_params_t* params; - //fcd_rate = FCDPP_RATE; - //fcd_channels =2; - //fcd_format = SND_PCM_SFMT_U16_LE; - snd_pcm_stream_t fcd_stream = SND_PCM_STREAM_CAPTURE; - - if (fcd_handle) - { - return false; - } - - if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0) - { - qCritical("FCDThread::OpenSource: cannot open %s", cardname); - return false; - } - - snd_pcm_hw_params_alloca(¶ms); - - if (snd_pcm_hw_params_any(fcd_handle, params) < 0) - { - qCritical("FCDProPlusThread::OpenSource: snd_pcm_hw_params_any failed"); - fail = true; - } - else if (snd_pcm_hw_params(fcd_handle, params) < 0) - { - qCritical("FCDProPlusThread::OpenSource: snd_pcm_hw_params failed"); - fail = true; - // TODO: check actual samplerate, may be crippled firmware - } - else - { - if (snd_pcm_start(fcd_handle) < 0) - { - qCritical("FCDProPlusThread::OpenSource: snd_pcm_start failed"); - fail = true; - } - } - - if (fail) - { - snd_pcm_close( fcd_handle ); - return false; - } - else - { - qDebug("FCDProPlusThread::OpenSource: Funcube stream started"); - } - - return true; -} - -void FCDProPlusThread::CloseSource() -{ - if (fcd_handle) - { - snd_pcm_close( fcd_handle ); - } - - fcd_handle = NULL; + qDebug("FCDThread::run: running loop stopped"); } int FCDProPlusThread::work(int n_items) @@ -152,14 +80,25 @@ int FCDProPlusThread::work(int n_items) it = m_convertBuffer.begin(); out = (void *)&it[0]; - l = snd_pcm_mmap_readi(fcd_handle, out, (snd_pcm_uframes_t)n_items); + + l = snd_pcm_mmap_readi(m_fcd_handle, out, (snd_pcm_uframes_t)n_items); + if (l > 0) - m_sampleFifo->write(it, it + l); - if (l == -EPIPE) { - qDebug("FCDProPlusThread::work: Overrun detected"); - return 0; + { + m_sampleFifo->write(it, it + l); } + else + { + if (l == -EPIPE) { + qDebug("FCDProPlusThread::work: Overrun detected"); + } else if (l < 0) { + qDebug("FCDProPlusThread::work: snd_pcm_mmap_readi failed with code %d", l); + } else { + qDebug("FCDProPlusThread::work: snd_pcm_mmap_readi empty"); + } + + return 0; + } + return l; } - - diff --git a/plugins/samplesource/fcdproplus/fcdproplusthread.h b/plugins/samplesource/fcdproplus/fcdproplusthread.h index 74e7f6d75..e797433cb 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusthread.h +++ b/plugins/samplesource/fcdproplus/fcdproplusthread.h @@ -21,24 +21,23 @@ #include #include #include -#include "dsp/inthalfbandfilter.h" #include + +#include "dsp/inthalfbandfilter.h" #include "dsp/samplesinkfifo.h" class FCDProPlusThread : public QThread { Q_OBJECT public: - FCDProPlusThread(SampleSinkFifo* sampleFifo, QObject* parent = NULL); + FCDProPlusThread(SampleSinkFifo* sampleFifo, snd_pcm_t *fcd_handle, QObject* parent = nullptr); ~FCDProPlusThread(); void startWork(); void stopWork(); - bool OpenSource(const char *filename); - void CloseSource(); private: - snd_pcm_t* fcd_handle; + snd_pcm_t* m_fcd_handle; QMutex m_startWaitMutex; QWaitCondition m_startWaiter; From a10b29d6d30a95e5c1f3924b68039cf194b93ffb Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 19 Nov 2018 02:33:44 +0100 Subject: [PATCH 061/102] FCDProPlus: use Qt for FCD audio device handling. Fixes start up error --- fcdlib/fcdtraits.cpp | 26 ++++-- fcdlib/fcdtraits.h | 28 ++++-- .../fcdproplus/fcdproplusinput.cpp | 89 +++++-------------- .../samplesource/fcdproplus/fcdproplusinput.h | 11 ++- .../fcdproplus/fcdproplusthread.cpp | 52 +++-------- .../fcdproplus/fcdproplusthread.h | 14 +-- sdrbase/audio/audioinput.cpp | 9 +- 7 files changed, 98 insertions(+), 131 deletions(-) diff --git a/fcdlib/fcdtraits.cpp b/fcdlib/fcdtraits.cpp index 41f8b66a6..40592dd80 100644 --- a/fcdlib/fcdtraits.cpp +++ b/fcdlib/fcdtraits.cpp @@ -1,15 +1,27 @@ -/* - * fcdtraits.cpp - * - * Created on: Sep 5, 2015 - * Author: f4exb - */ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// #include "fcdtraits.h" const char *fcd_traits::alsaDeviceName = "hw:CARD=V10"; const char *fcd_traits::alsaDeviceName = "hw:CARD=V20"; +const char *fcd_traits::qtDeviceName = "FUNcube_Dongle_V1.0"; +const char *fcd_traits::qtDeviceName = "FUNcube_Dongle_V2.0"; + const char *fcd_traits::hardwareID = "FCDPro"; const char *fcd_traits::hardwareID = "FCDPro+"; @@ -23,7 +35,7 @@ const char *fcd_traits::pluginDisplayedName = "FunCube Pro Input"; const char *fcd_traits::pluginDisplayedName = "FunCube Pro+ Input"; const char *fcd_traits::pluginVersion = "4.0.0"; -const char *fcd_traits::pluginVersion = "4.0.0"; +const char *fcd_traits::pluginVersion = "4.3.0"; const int64_t fcd_traits::loLowLimitFreq = 64000000L; const int64_t fcd_traits::loLowLimitFreq = 150000L; diff --git a/fcdlib/fcdtraits.h b/fcdlib/fcdtraits.h index a649edc39..b7b5a8365 100644 --- a/fcdlib/fcdtraits.h +++ b/fcdlib/fcdtraits.h @@ -1,9 +1,18 @@ -/* - * fcdtraits.h - * - * Created on: 3 Sep 2015 - * Author: egriffiths - */ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// #ifndef FCDLIB_FCDTRAITS_H_ #define FCDLIB_FCDTRAITS_H_ @@ -25,6 +34,7 @@ struct fcd_traits static const int convBufSize = (1<<11); static const int fcdBufSize = (1<<12); static const char *alsaDeviceName; + static const char *qtDeviceName; static const char *hardwareID; static const char *interfaceIID; static const char *displayedName; @@ -43,6 +53,7 @@ struct fcd_traits static const int convBufSize = (1<<11); static const int fcdBufSize = (1<<12); static const char *alsaDeviceName; + static const char *qtDeviceName; static const char *hardwareID; static const char *interfaceIID; static const char *displayedName; @@ -58,9 +69,10 @@ struct fcd_traits static const uint16_t vendorId = 0x04D8; static const uint16_t productId = 0xFB31; static const int sampleRate = 192000; - static const int convBufSize = (1<<12); - static const int fcdBufSize = (1<<18); + static const int convBufSize = (1<<10); + static const int fcdBufSize = (1<<18); // used in FCDProPlusReader static const char *alsaDeviceName; + static const char *qtDeviceName; static const char *hardwareID; static const char *interfaceIID; static const char *displayedName; diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp index dcb17cd09..9e431137f 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2016-2018 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // @@ -14,8 +14,6 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -// FIXME: FCD is handled very badly! - #include #include #include @@ -47,6 +45,7 @@ FCDProPlusInput::FCDProPlusInput(DeviceSourceAPI *deviceAPI) : m_deviceDescription(fcd_traits::displayedName), m_running(false) { + m_fcdFIFO.setSize(4*fcd_traits::convBufSize); openDevice(); m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID())); m_deviceAPI->addSink(m_fileSink); @@ -113,17 +112,17 @@ bool FCDProPlusInput::start() return false; } - if (!openSource(fcd_traits::alsaDeviceName)) + if (!openFCDAudio(fcd_traits::qtDeviceName)) { - qCritical("FCDProPlusInput::start: could not open source"); + qCritical("FCDProPlusInput::start: could not open FCD audio source"); return false; } else { - qDebug("FCDProPlusInput::start: source opened"); + qDebug("FCDProPlusInput::start: FCD audio source opened"); } - m_FCDThread = new FCDProPlusThread(&m_sampleFifo, fcd_handle); + m_FCDThread = new FCDProPlusThread(&m_sampleFifo, &m_fcdFIFO); m_FCDThread->startWork(); // mutexLocker.unlock(); @@ -145,73 +144,33 @@ void FCDProPlusInput::closeDevice() m_dev = 0; } -bool FCDProPlusInput::openSource(const char* cardname) +bool FCDProPlusInput::openFCDAudio(const char* cardname) { - bool fail = false; - snd_pcm_hw_params_t* params; - //fcd_rate = FCDPP_RATE; - //fcd_channels =2; - //fcd_format = SND_PCM_SFMT_U16_LE; - snd_pcm_stream_t fcd_stream = SND_PCM_STREAM_CAPTURE; + AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); + const QList& audioList = audioDeviceManager->getInputDevices(); - if (fcd_handle) + for (const auto &itAudio : audioList) { - qDebug("FCDProPlusInput::OpenSource: already opened"); - return false; - } - - if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0) - { - qCritical("FCDProPlusInput::OpenSource: cannot open %s", cardname); - return false; - } - - snd_pcm_hw_params_alloca(¶ms); - - if (snd_pcm_hw_params_any(fcd_handle, params) < 0) - { - qCritical("FCDProPlusInput::OpenSource: snd_pcm_hw_params_any failed"); - fail = true; - } - else if (snd_pcm_hw_params(fcd_handle, params) < 0) - { - qCritical("FCDProPlusInput::OpenSource: snd_pcm_hw_params failed"); - fail = true; - // TODO: check actual samplerate, may be crippled firmware - } - else - { - if (snd_pcm_start(fcd_handle) < 0) + if (itAudio.deviceName().contains(QString(cardname))) { - qCritical("FCDProPlusInput::OpenSource: snd_pcm_start failed"); - fail = true; - } - else - { - qDebug("FCDProPlusInput::OpenSource: snd_pcm_start OK"); + int fcdDeviceIndex = audioDeviceManager->getInputDeviceIndex(itAudio.deviceName()); + m_fcdAudioInput.start(fcdDeviceIndex, fcd_traits::sampleRate); + int fcdSampleRate = m_fcdAudioInput.getRate(); + qDebug("FCDProPlusInput::openFCDAudio: %s index %d at %d S/s", + itAudio.deviceName().toStdString().c_str(), fcdDeviceIndex, fcdSampleRate); + m_fcdAudioInput.addFifo(&m_fcdFIFO); + return true; } } - if (fail) - { - snd_pcm_close(fcd_handle); - return false; - } - else - { - qDebug("FCDProPlusInput::OpenSource: Funcube stream started"); - } - - return true; + qCritical("FCDProPlusInput::openFCDAudio: device with name %s not found", cardname); + return false; } -void FCDProPlusInput::closeSource() +void FCDProPlusInput::closeFCDAudio() { - if (fcd_handle) { - snd_pcm_close(fcd_handle); - } - - fcd_handle = nullptr; + m_fcdAudioInput.removeFifo(&m_fcdFIFO); + m_fcdAudioInput.stop(); } void FCDProPlusInput::stop() @@ -224,7 +183,7 @@ void FCDProPlusInput::stop() // wait for thread to quit ? delete m_FCDThread; m_FCDThread = nullptr; - closeSource(); + closeFCDAudio(); } m_running = false; diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.h b/plugins/samplesource/fcdproplus/fcdproplusinput.h index 26eb53e61..99a139dff 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.h +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.h @@ -23,7 +23,10 @@ #include -#include +#include "dsp/devicesamplesource.h" +#include "audio/audioinput.h" +#include "audio/audiofifo.h" + #include "fcdproplussettings.h" #include "fcdhid.h" @@ -149,13 +152,15 @@ public: private: bool openDevice(); void closeDevice(); - bool openSource(const char *filename); - void closeSource(); + bool openFCDAudio(const char *filename); + void closeFCDAudio(); void applySettings(const FCDProPlusSettings& settings, bool force); void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const FCDProPlusSettings& settings); DeviceSourceAPI *m_deviceAPI; hid_device *m_dev; + AudioInput m_fcdAudioInput; + AudioFifo m_fcdFIFO; snd_pcm_t* fcd_handle; QMutex m_mutex; FCDProPlusSettings m_settings; diff --git a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp index 1be59d82a..0f742bde7 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp @@ -1,6 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // -// written by Christian Daniel // +// Copyright (C) 2016-2018 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // @@ -21,13 +20,13 @@ #include "fcdproplusthread.h" #include "dsp/samplesinkfifo.h" -#include "fcdtraits.h" +#include "audio/audiofifo.h" -FCDProPlusThread::FCDProPlusThread(SampleSinkFifo* sampleFifo, snd_pcm_t *fcd_handle, QObject* parent) : +FCDProPlusThread::FCDProPlusThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent) : QThread(parent), - m_fcd_handle(fcd_handle), + m_fcdFIFO(fcdFIFO), m_running(false), - m_convertBuffer(fcd_traits::convBufSize), + m_convertBuffer(fcd_traits::convBufSize), // nb samples m_sampleFifo(sampleFifo) { start(); @@ -62,43 +61,18 @@ void FCDProPlusThread::run() m_running = true; qDebug("FCDThread::run: start running loop"); - while (m_running) - { - if (work(fcd_traits::convBufSize) < 0) { - break; - } + while (m_running) { + work(fcd_traits::convBufSize); } qDebug("FCDThread::run: running loop stopped"); + m_running = false; } -int FCDProPlusThread::work(int n_items) +void FCDProPlusThread::work(unsigned int n_items) { - int l; - SampleVector::iterator it; - void *out; - - it = m_convertBuffer.begin(); - out = (void *)&it[0]; - - l = snd_pcm_mmap_readi(m_fcd_handle, out, (snd_pcm_uframes_t)n_items); - - if (l > 0) - { - m_sampleFifo->write(it, it + l); - } - else - { - if (l == -EPIPE) { - qDebug("FCDProPlusThread::work: Overrun detected"); - } else if (l < 0) { - qDebug("FCDProPlusThread::work: snd_pcm_mmap_readi failed with code %d", l); - } else { - qDebug("FCDProPlusThread::work: snd_pcm_mmap_readi empty"); - } - - return 0; - } - - return l; + uint32_t nbRead = m_fcdFIFO->read((unsigned char *) m_buf, n_items); // number of samples + SampleVector::iterator it = m_convertBuffer.begin(); + m_decimators.decimate1(&it, m_buf, 2*nbRead); + m_sampleFifo->write(m_convertBuffer.begin(), it); } diff --git a/plugins/samplesource/fcdproplus/fcdproplusthread.h b/plugins/samplesource/fcdproplus/fcdproplusthread.h index e797433cb..d8b7a7961 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusthread.h +++ b/plugins/samplesource/fcdproplus/fcdproplusthread.h @@ -21,32 +21,36 @@ #include #include #include -#include -#include "dsp/inthalfbandfilter.h" #include "dsp/samplesinkfifo.h" +#include "dsp/decimators.h" +#include "fcdtraits.h" + +class AudioFifo; class FCDProPlusThread : public QThread { Q_OBJECT public: - FCDProPlusThread(SampleSinkFifo* sampleFifo, snd_pcm_t *fcd_handle, QObject* parent = nullptr); + FCDProPlusThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent = nullptr); ~FCDProPlusThread(); void startWork(); void stopWork(); private: - snd_pcm_t* m_fcd_handle; + AudioFifo* m_fcdFIFO; QMutex m_startWaitMutex; QWaitCondition m_startWaiter; bool m_running; + qint16 m_buf[fcd_traits::convBufSize*2]; // stereo (I, Q) SampleVector m_convertBuffer; SampleSinkFifo* m_sampleFifo; + Decimators m_decimators; void run(); - int work(int n_items); + void work(unsigned int n_items); }; #endif // INCLUDE_FCDTHREAD_H diff --git a/sdrbase/audio/audioinput.cpp b/sdrbase/audio/audioinput.cpp index 316100dbb..28f4acb65 100644 --- a/sdrbase/audio/audioinput.cpp +++ b/sdrbase/audio/audioinput.cpp @@ -64,12 +64,12 @@ bool AudioInput::start(int device, int rate) if (device < devicesInfo.size()) { devInfo = devicesInfo[device]; - qWarning("AudioInput::start: using audio device #%d: %s", device, qPrintable(devInfo.defaultInputDevice().deviceName())); + qWarning("AudioInput::start: using audio device #%d: %s", device, qPrintable(devInfo.deviceName())); } else { devInfo = QAudioDeviceInfo::defaultInputDevice(); - qWarning("AudioInput::start: audio device #%d does not exist. Using default device %s", device, qPrintable(devInfo.defaultInputDevice().deviceName())); + qWarning("AudioInput::start: audio device #%d does not exist. Using default device %s", device, qPrintable(devInfo.deviceName())); } } @@ -80,12 +80,13 @@ bool AudioInput::start(int device, int rate) m_audioFormat.setSampleSize(16); m_audioFormat.setCodec("audio/pcm"); m_audioFormat.setByteOrder(QAudioFormat::LittleEndian); - m_audioFormat.setSampleType(QAudioFormat::SignedInt); + m_audioFormat.setSampleType(QAudioFormat::SignedInt); // Unknown, SignedInt, UnSignedInt, Float if (!devInfo.isFormatSupported(m_audioFormat)) { m_audioFormat = devInfo.nearestFormat(m_audioFormat); - qWarning("AudioInput::start: %d Hz S16_LE audio format not supported. New rate: %d", rate, m_audioFormat.sampleRate()); + qWarning("AudioInput::start: %d Hz S16_LE audio format not supported. Nearest is sampleRate: %d channelCount: %d sampleSize: %d sampleType: %d", + rate, m_audioFormat.sampleRate(), m_audioFormat.channelCount(), m_audioFormat.sampleSize(), (int) m_audioFormat.sampleType()); } else { From 1640c06926b8ddbd64b77ece88da65488e169898 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 19 Nov 2018 02:34:55 +0100 Subject: [PATCH 062/102] FCDProPlus: unused code cleanup --- fcdlib/fcdtraits.h | 3 - .../fcdproplus/fcdproplusinputqt.cpp | 321 ------------------ .../fcdproplus/fcdproplusinputqt.h | 90 ----- .../fcdproplus/fcdproplusreader.cpp | 146 -------- .../fcdproplus/fcdproplusreader.h | 59 ---- 5 files changed, 619 deletions(-) delete mode 100644 plugins/samplesource/fcdproplus/fcdproplusinputqt.cpp delete mode 100644 plugins/samplesource/fcdproplus/fcdproplusinputqt.h delete mode 100644 plugins/samplesource/fcdproplus/fcdproplusreader.cpp delete mode 100644 plugins/samplesource/fcdproplus/fcdproplusreader.h diff --git a/fcdlib/fcdtraits.h b/fcdlib/fcdtraits.h index b7b5a8365..ebdfa20a0 100644 --- a/fcdlib/fcdtraits.h +++ b/fcdlib/fcdtraits.h @@ -32,7 +32,6 @@ struct fcd_traits static const uint16_t productId = 0x0; static const int sampleRate = 48000; static const int convBufSize = (1<<11); - static const int fcdBufSize = (1<<12); static const char *alsaDeviceName; static const char *qtDeviceName; static const char *hardwareID; @@ -51,7 +50,6 @@ struct fcd_traits static const uint16_t productId = 0xFB56; static const int sampleRate = 96000; static const int convBufSize = (1<<11); - static const int fcdBufSize = (1<<12); static const char *alsaDeviceName; static const char *qtDeviceName; static const char *hardwareID; @@ -70,7 +68,6 @@ struct fcd_traits static const uint16_t productId = 0xFB31; static const int sampleRate = 192000; static const int convBufSize = (1<<10); - static const int fcdBufSize = (1<<18); // used in FCDProPlusReader static const char *alsaDeviceName; static const char *qtDeviceName; static const char *hardwareID; diff --git a/plugins/samplesource/fcdproplus/fcdproplusinputqt.cpp b/plugins/samplesource/fcdproplus/fcdproplusinputqt.cpp deleted file mode 100644 index 391a4f0ef..000000000 --- a/plugins/samplesource/fcdproplus/fcdproplusinputqt.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // -// // -// This is a pure Qt (non ALSA) FCD sound card reader for Windows build // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation as version 3 of the License, or // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include "dsp/dspcommands.h" -#include "dsp/dspengine.h" -#include "fcdproplusinputqt.h" - -#include "fcdproplusgui.h" -#include "fcdproplusreader.h" -#include "fcdtraits.h" -#include "fcdproplusconst.h" - -MESSAGE_CLASS_DEFINITION(FCDProPlusInput::MsgConfigureFCDProPlus, Message) - -FCDProPlusInput::FCDProPlusInput() : - m_dev(0), - m_settings(), - m_deviceDescription(fcd_traits::displayedName), - m_FCDThread(0), - m_running(false), - m_deviceAPI(0) -{ - m_FCDReader = new FCDProPlusReader(&m_sampleFifo); -} - -FCDProPlusInput::~FCDProPlusInput() -{ - stop(); - delete m_FCDReader; -} - -bool FCDProPlusInput::init(const Message& cmd) -{ - return false; -} - -bool FCDProPlusInput::start(int device) -{ - qDebug() << "FCDProPlusInput::start with device #" << device; - - QMutexLocker mutexLocker(&m_mutex); - - m_dev = fcdOpen(fcd_traits::vendorId, fcd_traits::productId, device); - - if (m_dev == 0) - { - qCritical("FCDProPlusInput::start: could not open FCD"); - return false; - } - - /* Apply settings before streaming to avoid bus contention; - * there is very little spare bandwidth on a full speed USB device. - * Failure is harmless if no device is found - * ... This is rubbish...*/ - - //applySettings(m_settings, true); - - if(!m_sampleFifo.setSize(96000*4)) - { - qCritical("Could not allocate SampleFifo"); - return false; - } - - m_FCDReader->startWork(); - - mutexLocker.unlock(); - applySettings(m_settings, true); - - qDebug("FCDProPlusInput::started"); - return true; -} - -void FCDProPlusInput::stop() -{ - QMutexLocker mutexLocker(&m_mutex); - - m_FCDReader->stopWork(); - - fcdClose(m_dev); - m_dev = 0; -} - -const QString& FCDProPlusInput::getDeviceDescription() const -{ - return m_deviceDescription; -} - -int FCDProPlusInput::getSampleRate() const -{ - return fcd_traits::sampleRate; -} - -quint64 FCDProPlusInput::getCenterFrequency() const -{ - return m_settings.m_centerFrequency; -} - -bool FCDProPlusInput::handleMessage(const Message& message) -{ - if(MsgConfigureFCDProPlus::match(message)) - { - qDebug() << "FCDProPlusInput::handleMessage: MsgConfigureFCD"; - MsgConfigureFCDProPlus& conf = (MsgConfigureFCDProPlus&) message; - applySettings(conf.getSettings(), false); - return true; - } - else - { - return false; - } -} - -void FCDProPlusInput::applySettings(const FCDProPlusSettings& settings, bool force) -{ - bool signalChange = false; - - if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) - { - qDebug() << "FCDProPlusInput::applySettings: fc: " << settings.m_centerFrequency; - m_settings.m_centerFrequency = settings.m_centerFrequency; - - if (m_dev != 0) - { - set_center_freq((double) m_settings.m_centerFrequency); - } - - signalChange = true; - } - - if ((m_settings.m_lnaGain != settings.m_lnaGain) || force) - { - m_settings.m_lnaGain = settings.m_lnaGain; - - if (m_dev != 0) - { - set_lna_gain(settings.m_lnaGain); - } - } - - if ((m_settings.m_biasT != settings.m_biasT) || force) - { - m_settings.m_biasT = settings.m_biasT; - - if (m_dev != 0) - { - set_bias_t(settings.m_biasT); - } - } - - if ((m_settings.m_mixGain != settings.m_mixGain) || force) - { - m_settings.m_mixGain = settings.m_mixGain; - - if (m_dev != 0) - { - set_mixer_gain(settings.m_mixGain); - } - } - - if ((m_settings.m_ifGain != settings.m_ifGain) || force) - { - m_settings.m_ifGain = settings.m_ifGain; - - if (m_dev != 0) - { - set_if_gain(settings.m_ifGain); - } - } - - if ((m_settings.m_ifFilterIndex != settings.m_ifFilterIndex) || force) - { - m_settings.m_ifFilterIndex = settings.m_ifFilterIndex; - - if (m_dev != 0) - { - set_if_filter(settings.m_ifFilterIndex); - } - } - - if ((m_settings.m_rfFilterIndex != settings.m_rfFilterIndex) || force) - { - m_settings.m_rfFilterIndex = settings.m_rfFilterIndex; - - if (m_dev != 0) - { - set_rf_filter(settings.m_rfFilterIndex); - } - } - - if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) - { - m_settings.m_LOppmTenths = settings.m_LOppmTenths; - - if (m_dev != 0) - { - set_lo_ppm(); - } - } - - if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) - { - m_settings.m_dcBlock = settings.m_dcBlock; - DSPEngine::instance()->configureCorrections(m_settings.m_dcBlock, m_settings.m_iqImbalance); - } - - if ((m_settings.m_iqImbalance != settings.m_iqImbalance) || force) - { - m_settings.m_iqImbalance = settings.m_iqImbalance; - DSPEngine::instance()->configureCorrections(m_settings.m_dcBlock, m_settings.m_iqImbalance); - } - - if (signalChange) - { - DSPSignalNotification *notif = new DSPSignalNotification(fcd_traits::sampleRate, m_settings.m_centerFrequency); - DSPEngine::instance()->getInputMessageQueue()->push(notif); - } -} - -void FCDProPlusInput::set_center_freq(double freq) -{ - freq += freq*(((double) m_settings.m_LOppmTenths)/10000000.0); - - if (fcdAppSetFreq(m_dev, freq) == FCD_MODE_NONE) - { - qDebug("No FCD HID found for frquency change"); - } -} - -void FCDProPlusInput::set_bias_t(bool on) -{ - quint8 cmd = on ? 1 : 0; - - fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_BIAS_TEE, &cmd, 1); -} - -void FCDProPlusInput::set_lna_gain(bool on) -{ - quint8 cmd = on ? 1 : 0; - - fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_LNA_GAIN, &cmd, 1); -} - -void FCDProPlusInput::set_mixer_gain(bool on) -{ - quint8 cmd = on ? 1 : 0; - - fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_MIXER_GAIN, &cmd, 1); -} - -void FCDProPlusInput::set_if_gain(int gain) -{ - if (gain < 0) - { - return; - } - - quint8 cmd_value = gain; - - if (fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_IF_GAIN, &cmd_value, 1) != FCD_MODE_APP) - { - qWarning() << "FCDProPlusInput::set_if_gain: failed to set at " << cmd_value; - } -} - -void FCDProPlusInput::set_if_filter(int filterIndex) -{ - if ((filterIndex < 0) || (filterIndex >= FCDProPlusConstants::fcdproplus_if_filter_nb_values())) - { - return; - } - - quint8 cmd_value = FCDProPlusConstants::if_filters[filterIndex].value; - - if (fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_IF_FILTER, &cmd_value, 1) != FCD_MODE_APP) - { - qWarning() << "FCDProPlusInput::set_if_filter: failed to set at " << cmd_value; - } -} - - -void FCDProPlusInput::set_rf_filter(int filterIndex) -{ - if ((filterIndex < 0) || (filterIndex >= FCDProPlusConstants::fcdproplus_rf_filter_nb_values())) - { - return; - } - - quint8 cmd_value = FCDProPlusConstants::rf_filters[filterIndex].value; - - if (fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_RF_FILTER, &cmd_value, 1) != FCD_MODE_APP) - { - qWarning() << "FCDProPlusInput::set_rf_filter: failed to set at " << cmd_value; - } -} - -void FCDProPlusInput::set_lo_ppm() -{ - set_center_freq((double) m_settings.m_centerFrequency); -} - - - - diff --git a/plugins/samplesource/fcdproplus/fcdproplusinputqt.h b/plugins/samplesource/fcdproplus/fcdproplusinputqt.h deleted file mode 100644 index af974e582..000000000 --- a/plugins/samplesource/fcdproplus/fcdproplusinputqt.h +++ /dev/null @@ -1,90 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // -// // -// This is a pure Qt (non ALSA) FCD sound card reader for Windows build // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation as version 3 of the License, or // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef INCLUDE_FCDINPUT_H -#define INCLUDE_FCDINPUT_H - -#include - -#include "fcdproplussettings.h" -#include "fcdhid.h" -#include -#include - -struct fcd_buffer { - void *start; - std::size_t length; -}; - -class FCDProPlusReader; - -class FCDProPlusInput : public DeviceSampleSource { -public: - class MsgConfigureFCDProPlus : public Message { - MESSAGE_CLASS_DECLARATION - - public: - const FCDProPlusSettings& getSettings() const { return m_settings; } - - static MsgConfigureFCDProPlus* create(const FCDProPlusSettings& settings) - { - return new MsgConfigureFCDProPlus(settings); - } - - private: - FCDProPlusSettings m_settings; - - MsgConfigureFCD(const FCDProPlusSettings& settings) : - Message(), - m_settings(settings) - { } - }; - - FCDProPlusInput(); - virtual ~FCDProPlusInput(); - - virtual bool init(const Message& cmd); - virtual bool start(int device); - virtual void stop(); - - virtual const QString& getDeviceDescription() const; - virtual int getSampleRate() const; - virtual quint64 getCenterFrequency() const; - - virtual bool handleMessage(const Message& message); - - void set_center_freq(double freq); - void set_bias_t(bool on); - void set_lna_gain(bool on); - void set_mixer_gain(bool on); - void set_if_gain(int gain); - void set_rf_filter(int filterIndex); - void set_if_filter(int filterIndex); - void set_lo_ppm(); - -private: - void applySettings(const FCDProPlusSettings& settings, bool force); - - hid_device *m_dev; - QMutex m_mutex; - FCDProPlusSettings m_settings; - FCDProPlusReader* m_FCDReader; - QString m_deviceDescription; -}; - -#endif // INCLUDE_FCD_H diff --git a/plugins/samplesource/fcdproplus/fcdproplusreader.cpp b/plugins/samplesource/fcdproplus/fcdproplusreader.cpp deleted file mode 100644 index c12366a5c..000000000 --- a/plugins/samplesource/fcdproplus/fcdproplusreader.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation as version 3 of the License, or // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "fcdproplusreader.h" - -#include "dsp/samplesinkfifo.h" -#include "fcdtraits.h" - -FCDProPlusReader::FCDProPlusReader(SampleSinkFifo* sampleFifo, QObject* parent) : - QObject(parent), - m_fcdAudioInput(0), - m_fcdInput(0), - m_running(false), - m_convertBuffer(fcd_traits::convBufSize), - m_fcdBuffer(fcd_traits::fcdBufSize, 0), - m_sampleFifo(sampleFifo) -{ -} - -FCDProPlusReader::~FCDProPlusReader() -{ - if (m_fcdAudioInput) { - delete m_fcdAudioInput; - } -} - -void FCDProPlusReader::startWork() -{ - QList audioDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); - - QList::iterator audioDeviceIt, fcdDeviceIt = audioDevices.end(); - - for (audioDeviceIt = audioDevices.begin(); audioDeviceIt != audioDevices.end(); ++audioDeviceIt) - { - QAudioFormat fcdAudioFormat = audioDeviceIt->preferredFormat(); - int sampleRate = fcdAudioFormat.sampleRate(); - int sampleBits = fcdAudioFormat.sampleSize(); - - if ((sampleRate == 192000) && (sampleBits == 16)) - { - qDebug() << "FCDProPlusReader::startWork: found: " << audioDeviceIt->deviceName() - << " sampleRate: " << fcdAudioFormat.sampleRate() - << " sampleBits: " << fcdAudioFormat.sampleSize(); - fcdDeviceIt = audioDeviceIt; - break; - } - } - - if (fcdDeviceIt == audioDevices.end()) - { - qCritical() << "FCDProPlusReader::startWork: FCD Pro+ sound card not found"; - return; - } - - openFcdAudio(*fcdDeviceIt); - - if (!m_fcdAudioInput) - { - qCritical() << "FCDProPlusReader::startWork: cannot open FCD Pro+ sound card"; - return; - } - - m_fcdAudioInput->stop(); - m_fcdInput = m_fcdAudioInput->start(); - - if (!m_fcdInput) - { - qCritical() << "FCDProPlusReader::startWork: cannot start FCD Pro+ sound card"; - return; - } - - connect(m_fcdInput, SIGNAL(readyRead()), this, SLOT(readFcdAudio())); - m_running = true; - - qDebug() << "FCDProPlusReader::startWork: started"; -} - -void FCDProPlusReader::stopWork() -{ - m_running = false; - disconnect(m_fcdInput, SIGNAL(readyRead()), this, SLOT(readFcdAudio())); - m_fcdAudioInput->stop(); - - qDebug() << "FCDProPlusReader::stopWork: stopped"; -} - -void FCDProPlusReader::openFcdAudio(const QAudioDeviceInfo& fcdAudioDeviceInfo) -{ - QAudioFormat fcdAudioFormat = fcdAudioDeviceInfo.preferredFormat(); - - qDebug() << "FCDProPlusReader::openFcdAudio: device: " << fcdAudioDeviceInfo.deviceName() - << " sampleRate: " << fcdAudioFormat.sampleRate() - << " sampleBits: " << fcdAudioFormat.sampleSize(); - - m_fcdAudioInput = new QAudioInput(fcdAudioDeviceInfo, fcdAudioFormat, this); - //m_fcdAudioInput->setBufferSize(1<<14); - //m_fcdAudioInput->setNotifyInterval(50); -} - -void FCDProPlusReader::readFcdAudio() -{ - if (!m_fcdAudioInput) { - return; - } - - int len = m_fcdAudioInput->bytesReady(); - -// qDebug() << "FCDProPlusReader::readFcdAudio:" -// << " buffer size: " << m_fcdAudioInput->bufferSize() -// << " interval: " << m_fcdAudioInput->notifyInterval() -// << " len: " << len; - - if (len > fcd_traits::fcdBufSize) { - len = fcd_traits::fcdBufSize; - } - - int readLen = m_fcdInput->read(m_fcdBuffer.data(), len); - - if (readLen > 0) { - m_sampleFifo->write((const quint8*) m_fcdBuffer.constData(), (uint) readLen); - } -} - diff --git a/plugins/samplesource/fcdproplus/fcdproplusreader.h b/plugins/samplesource/fcdproplus/fcdproplusreader.h deleted file mode 100644 index db78b5e29..000000000 --- a/plugins/samplesource/fcdproplus/fcdproplusreader.h +++ /dev/null @@ -1,59 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation as version 3 of the License, or // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef INCLUDE_FCDPROPLUSREADER_H -#define INCLUDE_FCDPROPLUSREADER_H - -#include -#include -#include -#include - -#include "dsp/samplesinkfifo.h" -#include "dsp/inthalfbandfilter.h" - -class QAudioInput; -class QIODevice; -class QAudioDeviceInfo; - -class FCDProPlusReader : public QObject { - Q_OBJECT - -public: - FCDProPlusReader(SampleSinkFifo* sampleFifo, QObject* parent = NULL); - ~FCDProPlusReader(); - - void startWork(); - void stopWork(); - -private: - QAudioInput *m_fcdAudioInput; - QIODevice *m_fcdInput; - - QMutex m_startWaitMutex; - QWaitCondition m_startWaiter; - bool m_running; - - SampleVector m_convertBuffer; - QByteArray m_fcdBuffer; - SampleSinkFifo* m_sampleFifo; - - void openFcdAudio(const QAudioDeviceInfo& fcdAudioDeviceInfo); - -private slots: - void readFcdAudio(); -}; -#endif // INCLUDE_FCDPROPLUSREADER_H From b63c7789255be3387108406e83ac93d6e4c255a7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 19 Nov 2018 02:45:01 +0100 Subject: [PATCH 063/102] FCDProPlus: corrected FCD audio FIFO size --- plugins/samplesource/fcdproplus/fcdproplusinput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp index 9e431137f..30d77a5e8 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp @@ -45,7 +45,7 @@ FCDProPlusInput::FCDProPlusInput(DeviceSourceAPI *deviceAPI) : m_deviceDescription(fcd_traits::displayedName), m_running(false) { - m_fcdFIFO.setSize(4*fcd_traits::convBufSize); + m_fcdFIFO.setSize(20*fcd_traits::convBufSize); openDevice(); m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID())); m_deviceAPI->addSink(m_fileSink); From 7d9ca913ec73c005ae9cd193426709dafb94e850 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 19 Nov 2018 18:49:12 +0100 Subject: [PATCH 064/102] Attempt to fix race condition in glScope traces processing --- sdrgui/dsp/scopevis.cpp | 17 +++++++++++++---- sdrgui/gui/glscope.cpp | 25 +++++++++++++++++++++++-- sdrgui/gui/glscope.h | 5 +++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/sdrgui/dsp/scopevis.cpp b/sdrgui/dsp/scopevis.cpp index 872d34f05..30c817191 100644 --- a/sdrgui/dsp/scopevis.cpp +++ b/sdrgui/dsp/scopevis.cpp @@ -607,15 +607,24 @@ int ScopeVis::processTraces(const SampleVector::const_iterator& cbegin, const Sa float traceTime = ((float) m_traceSize) / m_sampleRate; if (traceTime >= 1.0f) { // display continuously if trace time is 1 second or more - m_glScope->newTraces(&m_traces.m_traces[m_traces.currentBufferIndex()]); + m_glScope->newTraces(m_traces.m_traces, m_traces.currentBufferIndex()); } if (m_nbSamples == 0) // finished { - if (traceTime < 1.0f) { // display only at trace end if trace time is less than 1 second - m_glScope->newTraces(&m_traces.m_traces[m_traces.currentBufferIndex()]); + // display only at trace end if trace time is less than 1 second + if (traceTime < 1.0f) + { + if (m_glScope->getProcessingTraceIndex().load() < 0) { + m_glScope->newTraces(m_traces.m_traces, m_traces.currentBufferIndex()); + } } - m_traces.switchBuffer(); + + // switch to next buffer only if it is not being processed by the scope + if (m_glScope->getProcessingTraceIndex().load() != ((m_traces.currentBufferIndex() + 1) % 2)) { + m_traces.switchBuffer(); + } + return end - begin; // return remainder count } else diff --git a/sdrgui/gui/glscope.cpp b/sdrgui/gui/glscope.cpp index 76418b698..bdba1e1eb 100644 --- a/sdrgui/gui/glscope.cpp +++ b/sdrgui/gui/glscope.cpp @@ -30,6 +30,7 @@ GLScope::GLScope(QWidget* parent) : QGLWidget(parent), m_tracesData(0), m_traces(0), + m_processingTraceIndex(-1), m_bufferIndex(0), m_displayMode(DisplayX), m_dataChanged(false), @@ -112,6 +113,21 @@ void GLScope::newTraces(std::vector* traces) } } +void GLScope::newTraces(std::vector* traces, int traceIndex) +{ + if (traces->size() > 0) + { + if(!m_mutex.tryLock(2)) + return; + + m_processingTraceIndex.store(traceIndex); + m_traces = &traces[traceIndex]; + m_dataChanged = true; + + m_mutex.unlock(); + } +} + void GLScope::initializeGL() { QOpenGLContext *glCurrentContext = QOpenGLContext::currentContext(); @@ -176,11 +192,15 @@ void GLScope::resizeGL(int width, int height) void GLScope::paintGL() { - if(!m_mutex.tryLock(2)) + if (!m_mutex.tryLock(2)) + { + m_processingTraceIndex.store(-1); return; + } - if(m_configChanged) + if (m_configChanged) { applyConfig(); + } // qDebug("GLScope::paintGL: m_traceCounter: %d", m_traceCounter); // m_traceCounter = 0; @@ -920,6 +940,7 @@ void GLScope::paintGL() } // trace length > 0 } // XY mixed + polar display + m_processingTraceIndex.store(-1); m_mutex.unlock(); } diff --git a/sdrgui/gui/glscope.h b/sdrgui/gui/glscope.h index c33e91cc0..6120a2217 100644 --- a/sdrgui/gui/glscope.h +++ b/sdrgui/gui/glscope.h @@ -24,6 +24,8 @@ #include #include #include +#include + #include "dsp/dsptypes.h" #include "dsp/scopevis.h" #include "gui/scaleengine.h" @@ -54,6 +56,7 @@ public: void setTraces(std::vector* tracesData, std::vector* traces); void newTraces(std::vector* traces); + void newTraces(std::vector* traces, int traceIndex); int getSampleRate() const { return m_sampleRate; } int getTraceSize() const { return m_traceSize; } @@ -75,6 +78,7 @@ public: bool getDataChanged() const { return m_dataChanged; } DisplayMode getDisplayMode() const { return m_displayMode; } void setDisplayXYPoints(bool value) { m_displayXYPoints = value; } + const QAtomicInt& getProcessingTraceIndex() const { return m_processingTraceIndex; } signals: void sampleRateChanged(int); @@ -84,6 +88,7 @@ signals: private: std::vector *m_tracesData; std::vector *m_traces; + QAtomicInt m_processingTraceIndex; ScopeVis::TriggerData m_focusedTriggerData; //int m_traceCounter; uint32_t m_bufferIndex; From 47b9852bcce25199d9d03c37149d3d1d250d7c06 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 19 Nov 2018 23:54:54 +0100 Subject: [PATCH 065/102] Race condition in glScope traces processing: fixed compilation warning --- sdrgui/dsp/scopevis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdrgui/dsp/scopevis.cpp b/sdrgui/dsp/scopevis.cpp index 30c817191..302b4b04f 100644 --- a/sdrgui/dsp/scopevis.cpp +++ b/sdrgui/dsp/scopevis.cpp @@ -621,7 +621,7 @@ int ScopeVis::processTraces(const SampleVector::const_iterator& cbegin, const Sa } // switch to next buffer only if it is not being processed by the scope - if (m_glScope->getProcessingTraceIndex().load() != ((m_traces.currentBufferIndex() + 1) % 2)) { + if (m_glScope->getProcessingTraceIndex().load() != (((int) m_traces.currentBufferIndex() + 1) % 2)) { m_traces.switchBuffer(); } From f04201a528f1fa626c9e11240d239de53e7cec9e Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 20 Nov 2018 00:30:44 +0100 Subject: [PATCH 066/102] SoapySDR support: allow overflow on reads. Changed timeout to 10 times the block time (actually) --- plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp | 6 +++++- plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp b/plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp index b7303d401..3b2cc4175 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp @@ -124,7 +124,7 @@ void SoapySDROutputThread::run() int flags(0); long long timeNs(0); float blockTime = ((float) numElems) / (m_sampleRate <= 0 ? 1024000 : m_sampleRate); - long timeoutUs = 2000000 * blockTime; // 10 times the block time + long timeoutUs = 10000000 * blockTime; // 10 times the block time qDebug("SoapySDROutputThread::run: numElems: %u elemSize: %u timeoutUs: %ld", numElems, elemSize, timeoutUs); qDebug("SoapySDROutputThread::run: start running loop"); @@ -137,6 +137,10 @@ void SoapySDROutputThread::run() { qWarning("SoapySDROutputThread::run: timeout: flags: %d timeNs: %lld timeoutUs: %ld", flags, timeNs, timeoutUs); } + else if (ret == SOAPY_SDR_OVERFLOW) + { + qWarning("SoapySDROutputThread::run: overflow: flags: %d timeNs: %lld timeoutUs: %ld", flags, timeNs, timeoutUs); + } else if (ret < 0) { qCritical("SoapySDROutputThread::run: Unexpected write stream error: %s", SoapySDR::errToStr(ret)); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp index dd969a8f6..97ab36586 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp @@ -129,7 +129,7 @@ void SoapySDRInputThread::run() int flags(0); long long timeNs(0); float blockTime = ((float) numElems) / (m_sampleRate <= 0 ? 1024000 : m_sampleRate); - long timeoutUs = 2000000 * blockTime; // 10 times the block time + long timeoutUs = 10000000 * blockTime; // 10 times the block time qDebug("SoapySDRInputThread::run: numElems: %u elemSize: %u timeoutUs: %ld", numElems, elemSize, timeoutUs); qDebug("SoapySDRInputThread::run: start running loop"); @@ -142,6 +142,10 @@ void SoapySDRInputThread::run() { qWarning("SoapySDRInputThread::run: timeout: flags: %d timeNs: %lld timeoutUs: %ld", flags, timeNs, timeoutUs); } + else if (ret == SOAPY_SDR_OVERFLOW) + { + qWarning("SoapySDRInputThread::run: overflow: flags: %d timeNs: %lld timeoutUs: %ld", flags, timeNs, timeoutUs); + } else if (ret < 0) { qCritical("SoapySDRInputThread::run: Unexpected read stream error: %s", SoapySDR::errToStr(ret)); From af9c693412429861de3a1d6e1763ba85a8df7360 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 20 Nov 2018 01:48:17 +0100 Subject: [PATCH 067/102] FCDPro: use Qt for FCD audio device handling. Fixes in FCDProPlus --- fcdlib/fcdtraits.cpp | 2 +- plugins/samplesource/fcdpro/fcdprogui.ui | 102 +++++++++++--- plugins/samplesource/fcdpro/fcdproinput.cpp | 68 +++++++--- plugins/samplesource/fcdpro/fcdproinput.h | 12 +- plugins/samplesource/fcdpro/fcdprothread.cpp | 125 +++--------------- plugins/samplesource/fcdpro/fcdprothread.h | 20 +-- .../fcdproplus/fcdproplusinput.cpp | 19 ++- .../samplesource/fcdproplus/fcdproplusinput.h | 5 +- .../fcdproplus/fcdproplusthread.cpp | 9 +- 9 files changed, 200 insertions(+), 162 deletions(-) diff --git a/fcdlib/fcdtraits.cpp b/fcdlib/fcdtraits.cpp index 40592dd80..ac008da78 100644 --- a/fcdlib/fcdtraits.cpp +++ b/fcdlib/fcdtraits.cpp @@ -34,7 +34,7 @@ const char *fcd_traits::displayedName = "FunCube Dongle Pro+"; const char *fcd_traits::pluginDisplayedName = "FunCube Pro Input"; const char *fcd_traits::pluginDisplayedName = "FunCube Pro+ Input"; -const char *fcd_traits::pluginVersion = "4.0.0"; +const char *fcd_traits::pluginVersion = "4.3.0"; const char *fcd_traits::pluginVersion = "4.3.0"; const int64_t fcd_traits::loLowLimitFreq = 64000000L; diff --git a/plugins/samplesource/fcdpro/fcdprogui.ui b/plugins/samplesource/fcdpro/fcdprogui.ui index 5e3d747d7..ad9e7c918 100644 --- a/plugins/samplesource/fcdpro/fcdprogui.ui +++ b/plugins/samplesource/fcdpro/fcdprogui.ui @@ -31,9 +31,6 @@ FunCubeDongle - - start/stop acquisition - 3 @@ -61,6 +58,9 @@ + + start/stop acquisition + @@ -287,7 +287,11 @@ - + + + LNA enhancement + + @@ -297,7 +301,11 @@ - + + + Band optimizations + +
@@ -311,7 +319,11 @@ - + + + Band bias + + @@ -321,7 +333,11 @@ - + + + Mode ? + + @@ -335,7 +351,11 @@ - + + + LNA gain + + @@ -345,7 +365,11 @@ - + + + RF filter selection + + @@ -359,7 +383,11 @@ - + + + Mixer gain + + @@ -369,7 +397,11 @@ - + + + Mixer filter selection + + @@ -383,7 +415,11 @@ - + + + Gain block #1 + + @@ -393,7 +429,11 @@ - + + + Baseband RC filter selection + + @@ -407,7 +447,11 @@ - + + + Gain block #2 + + @@ -417,7 +461,11 @@ - + + + Gain block #3 + + @@ -431,7 +479,11 @@ - + + + Gain block #4 + + @@ -441,7 +493,11 @@ - + + + IF filter selection + + @@ -455,7 +511,11 @@ - + + + Gain block #5 + + @@ -465,7 +525,11 @@ - + + + Gain block #6 + + diff --git a/plugins/samplesource/fcdpro/fcdproinput.cpp b/plugins/samplesource/fcdpro/fcdproinput.cpp index 03f1ec662..2ba8b52c0 100644 --- a/plugins/samplesource/fcdpro/fcdproinput.cpp +++ b/plugins/samplesource/fcdpro/fcdproinput.cpp @@ -1,6 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // -// written by Christian Daniel // +// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // @@ -15,8 +14,6 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -// FIXME: FCD is handled very badly! - #include #include #include @@ -27,10 +24,9 @@ #include "dsp/dspcommands.h" #include "dsp/dspengine.h" #include "dsp/filerecord.h" +#include "device/devicesourceapi.h" + #include "fcdproinput.h" - -#include - #include "fcdprothread.h" #include "fcdtraits.h" #include "fcdproconst.h" @@ -47,6 +43,7 @@ FCDProInput::FCDProInput(DeviceSourceAPI *deviceAPI) : m_deviceDescription(fcd_traits::displayedName), m_running(false) { + m_fcdFIFO.setSize(20*fcd_traits::convBufSize); openDevice(); m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID())); m_deviceAPI->addSink(m_fileSink); @@ -54,9 +51,13 @@ FCDProInput::FCDProInput(DeviceSourceAPI *deviceAPI) : FCDProInput::~FCDProInput() { - if (m_running) stop(); + if (m_running) { + stop(); + } + m_deviceAPI->removeSink(m_fileSink); delete m_fileSink; + closeDevice(); } @@ -67,15 +68,12 @@ void FCDProInput::destroy() bool FCDProInput::openDevice() { - int device = m_deviceAPI->getSampleSourceSequence(); - - if (m_dev != 0) - { + if (m_dev != 0) { closeDevice(); } + int device = m_deviceAPI->getSampleSourceSequence(); qDebug() << "FCDProInput::openDevice with device #" << device; - m_dev = fcdOpen(fcd_traits::vendorId, fcd_traits::productId, device); if (m_dev == 0) @@ -117,7 +115,17 @@ bool FCDProInput::start() return false; } - m_FCDThread = new FCDProThread(&m_sampleFifo); + if (!openFCDAudio(fcd_traits::qtDeviceName)) + { + qCritical("FCDProInput::start: could not open FCD audio source"); + return false; + } + else + { + qDebug("FCDProInput::start: FCD audio source opened"); + } + + m_FCDThread = new FCDProThread(&m_sampleFifo, &m_fcdFIFO); m_FCDThread->startWork(); // mutexLocker.unlock(); @@ -139,6 +147,35 @@ void FCDProInput::closeDevice() m_dev = 0; } +bool FCDProInput::openFCDAudio(const char* cardname) +{ + AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); + const QList& audioList = audioDeviceManager->getInputDevices(); + + for (const auto &itAudio : audioList) + { + if (itAudio.deviceName().contains(QString(cardname))) + { + int fcdDeviceIndex = audioDeviceManager->getInputDeviceIndex(itAudio.deviceName()); + m_fcdAudioInput.start(fcdDeviceIndex, fcd_traits::sampleRate); + int fcdSampleRate = m_fcdAudioInput.getRate(); + qDebug("FCDProPlusInput::openFCDAudio: %s index %d at %d S/s", + itAudio.deviceName().toStdString().c_str(), fcdDeviceIndex, fcdSampleRate); + m_fcdAudioInput.addFifo(&m_fcdFIFO); + return true; + } + } + + qCritical("FCDProInput::openFCDAudio: device with name %s not found", cardname); + return false; +} + +void FCDProInput::closeFCDAudio() +{ + m_fcdAudioInput.removeFifo(&m_fcdFIFO); + m_fcdAudioInput.stop(); +} + void FCDProInput::stop() { // QMutexLocker mutexLocker(&m_mutex); @@ -148,7 +185,8 @@ void FCDProInput::stop() m_FCDThread->stopWork(); // wait for thread to quit ? delete m_FCDThread; - m_FCDThread = 0; + m_FCDThread = nullptr; + closeFCDAudio(); } m_running = false; diff --git a/plugins/samplesource/fcdpro/fcdproinput.h b/plugins/samplesource/fcdpro/fcdproinput.h index dfdbabe0d..aa0c7240f 100644 --- a/plugins/samplesource/fcdpro/fcdproinput.h +++ b/plugins/samplesource/fcdpro/fcdproinput.h @@ -1,6 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // -// written by Christian Daniel // +// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // @@ -22,7 +21,10 @@ #include #include -#include +#include "dsp/devicesamplesource.h" +#include "audio/audioinput.h" +#include "audio/audiofifo.h" + #include "fcdprosettings.h" #include "fcdhid.h" @@ -158,6 +160,8 @@ public: private: bool openDevice(); void closeDevice(); + bool openFCDAudio(const char *filename); + void closeFCDAudio(); void applySettings(const FCDProSettings& settings, bool force); void set_lo_ppm(); @@ -165,6 +169,8 @@ private: DeviceSourceAPI *m_deviceAPI; hid_device *m_dev; + AudioInput m_fcdAudioInput; + AudioFifo m_fcdFIFO; QMutex m_mutex; FCDProSettings m_settings; FCDProThread* m_FCDThread; diff --git a/plugins/samplesource/fcdpro/fcdprothread.cpp b/plugins/samplesource/fcdpro/fcdprothread.cpp index e1fbbb721..7b4152b2e 100644 --- a/plugins/samplesource/fcdpro/fcdprothread.cpp +++ b/plugins/samplesource/fcdpro/fcdprothread.cpp @@ -18,16 +18,19 @@ #include #include #include -#include "fcdprothread.h" +#include +#include #include "dsp/samplesinkfifo.h" -#include "fcdtraits.h" +#include "audio/audiofifo.h" -FCDProThread::FCDProThread(SampleSinkFifo* sampleFifo, QObject* parent) : +#include "fcdprothread.h" + +FCDProThread::FCDProThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent) : QThread(parent), - fcd_handle(NULL), + m_fcdFIFO(fcdFIFO), m_running(false), - m_convertBuffer(fcd_traits::convBufSize), + m_convertBuffer(fcd_traits::convBufSize), // nb samples m_sampleFifo(sampleFifo) { start(); @@ -59,107 +62,23 @@ void FCDProThread::stopWork() void FCDProThread::run() { - if ( !OpenSource(fcd_traits::alsaDeviceName) ) - { - qCritical() << "FCDThread::run: cannot open FCD sound card"; - return; - } - // TODO: fallback to original fcd + m_running = true; + qDebug("FCDProThread::run: start running loop"); - m_running = true; + while (m_running) + { + work(fcd_traits::convBufSize); + std::this_thread::sleep_for(std::chrono::microseconds(200)); + } - while(m_running) - { - if (work(fcd_traits::convBufSize) < 0) - { - break; - } - } - - CloseSource(); + qDebug("FCDProThread::run: running loop stopped"); + m_running = false; } -bool FCDProThread::OpenSource(const char* cardname) +void FCDProThread::work(unsigned int n_items) { - bool fail = false; - snd_pcm_hw_params_t* params; - //fcd_rate = FCDPP_RATE; - //fcd_channels =2; - //fcd_format = SND_PCM_SFMT_U16_LE; - snd_pcm_stream_t fcd_stream = SND_PCM_STREAM_CAPTURE; - - if (fcd_handle) - { - return false; - } - - if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0) - { - qCritical("FCDThread::OpenSource: cannot open %s", cardname); - return false; - } - - snd_pcm_hw_params_alloca(¶ms); - - if (snd_pcm_hw_params_any(fcd_handle, params) < 0) - { - qCritical("FCDThread::OpenSource: snd_pcm_hw_params_any failed"); - fail = true; - } - else if (snd_pcm_hw_params(fcd_handle, params) < 0) - { - qCritical("FCDThread::OpenSource: snd_pcm_hw_params failed"); - fail = true; - // TODO: check actual samplerate, may be crippled firmware - } - else - { - if (snd_pcm_start(fcd_handle) < 0) - { - qCritical("FCDThread::OpenSource: snd_pcm_start failed"); - fail = true; - } - } - - if (fail) - { - snd_pcm_close( fcd_handle ); - return false; - } - else - { - qDebug("FCDThread::OpenSource: Funcube stream started"); - } - - return true; + uint32_t nbRead = m_fcdFIFO->read((unsigned char *) m_buf, n_items); // number of samples + SampleVector::iterator it = m_convertBuffer.begin(); + m_decimators.decimate1(&it, m_buf, 2*nbRead); + m_sampleFifo->write(m_convertBuffer.begin(), it); } - -void FCDProThread::CloseSource() -{ - if (fcd_handle) - { - snd_pcm_close( fcd_handle ); - } - - fcd_handle = NULL; -} - -int FCDProThread::work(int n_items) -{ - int l; - SampleVector::iterator it; - void *out; - - it = m_convertBuffer.begin(); - out = (void *)&it[0]; - l = snd_pcm_mmap_readi(fcd_handle, out, (snd_pcm_uframes_t)n_items); - if (l > 0) - m_sampleFifo->write(it, it + l); - if (l == -EPIPE) { - qDebug("FCD: Overrun detected"); - return 0; - } - return l; -} - - diff --git a/plugins/samplesource/fcdpro/fcdprothread.h b/plugins/samplesource/fcdpro/fcdprothread.h index ce3e47da5..05891cd92 100644 --- a/plugins/samplesource/fcdpro/fcdprothread.h +++ b/plugins/samplesource/fcdpro/fcdprothread.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2015 Edouard Griffiths, F4EXB // +// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // @@ -20,33 +20,37 @@ #include #include #include -#include "dsp/inthalfbandfilter.h" -#include + #include "dsp/samplesinkfifo.h" +#include "dsp/decimators.h" +#include "fcdtraits.h" + +class AudioFifo; class FCDProThread : public QThread { Q_OBJECT public: - FCDProThread(SampleSinkFifo* sampleFifo, QObject* parent = NULL); + FCDProThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent = nullptr); ~FCDProThread(); void startWork(); void stopWork(); - bool OpenSource(const char *filename); - void CloseSource(); private: - snd_pcm_t* fcd_handle; + AudioFifo* m_fcdFIFO; QMutex m_startWaitMutex; QWaitCondition m_startWaiter; bool m_running; + qint16 m_buf[fcd_traits::convBufSize*2]; // stereo (I, Q) SampleVector m_convertBuffer; SampleSinkFifo* m_sampleFifo; + Decimators m_decimators; void run(); - int work(int n_items); + void work(unsigned int n_items); }; + #endif // INCLUDE_FCDPROTHREAD_H diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp index 30d77a5e8..4c9776e13 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp @@ -23,11 +23,10 @@ #include "dsp/dspcommands.h" #include "dsp/dspengine.h" -#include +#include "dsp/filerecord.h" +#include "device/devicesourceapi.h" + #include "fcdproplusinput.h" - -#include - #include "fcdproplusthread.h" #include "fcdtraits.h" #include "fcdproplusconst.h" @@ -39,7 +38,6 @@ MESSAGE_CLASS_DEFINITION(FCDProPlusInput::MsgFileRecord, Message) FCDProPlusInput::FCDProPlusInput(DeviceSourceAPI *deviceAPI) : m_deviceAPI(deviceAPI), m_dev(0), - fcd_handle(0), m_settings(), m_FCDThread(0), m_deviceDescription(fcd_traits::displayedName), @@ -53,9 +51,13 @@ FCDProPlusInput::FCDProPlusInput(DeviceSourceAPI *deviceAPI) : FCDProPlusInput::~FCDProPlusInput() { - if (m_running) stop(); + if (m_running) { + stop(); + } + m_deviceAPI->removeSink(m_fileSink); delete m_fileSink; + closeDevice(); } @@ -66,9 +68,12 @@ void FCDProPlusInput::destroy() bool FCDProPlusInput::openDevice() { + if (m_dev != 0) { + closeDevice(); + } + int device = m_deviceAPI->getSampleSourceSequence(); qDebug() << "FCDProPlusInput::openDevice with device #" << device; - m_dev = fcdOpen(fcd_traits::vendorId, fcd_traits::productId, device); if (m_dev == 0) diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.h b/plugins/samplesource/fcdproplus/fcdproplusinput.h index 99a139dff..94206cd61 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.h +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2016-2018 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // @@ -21,8 +21,6 @@ #include #include -#include - #include "dsp/devicesamplesource.h" #include "audio/audioinput.h" #include "audio/audiofifo.h" @@ -161,7 +159,6 @@ private: hid_device *m_dev; AudioInput m_fcdAudioInput; AudioFifo m_fcdFIFO; - snd_pcm_t* fcd_handle; QMutex m_mutex; FCDProPlusSettings m_settings; FCDProPlusThread* m_FCDThread; diff --git a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp index 0f742bde7..4a6f27f2a 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp @@ -17,11 +17,14 @@ #include #include #include -#include "fcdproplusthread.h" +#include +#include #include "dsp/samplesinkfifo.h" #include "audio/audiofifo.h" +#include "fcdproplusthread.h" + FCDProPlusThread::FCDProPlusThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent) : QThread(parent), m_fcdFIFO(fcdFIFO), @@ -61,8 +64,10 @@ void FCDProPlusThread::run() m_running = true; qDebug("FCDThread::run: start running loop"); - while (m_running) { + while (m_running) + { work(fcd_traits::convBufSize); + std::this_thread::sleep_for(std::chrono::microseconds(100)); } qDebug("FCDThread::run: running loop stopped"); From 02a6cee99fdb0cd8c19d2f89d0b04c7f4af1f45c Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 20 Nov 2018 08:00:19 +0100 Subject: [PATCH 068/102] glScope: use atomic variable for the data changed indicator --- sdrgui/gui/glscope.cpp | 30 ++++++++++++++++-------------- sdrgui/gui/glscope.h | 2 +- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/sdrgui/gui/glscope.cpp b/sdrgui/gui/glscope.cpp index bdba1e1eb..6cb63c444 100644 --- a/sdrgui/gui/glscope.cpp +++ b/sdrgui/gui/glscope.cpp @@ -33,7 +33,7 @@ GLScope::GLScope(QWidget* parent) : m_processingTraceIndex(-1), m_bufferIndex(0), m_displayMode(DisplayX), - m_dataChanged(false), + m_dataChanged(0), m_configChanged(false), m_sampleRate(0), m_timeOfsProMill(0), @@ -103,11 +103,13 @@ void GLScope::newTraces(std::vector* traces) { if (traces->size() > 0) { - if(!m_mutex.tryLock(2)) + if (!m_mutex.tryLock(2)) { return; + } - m_traces = traces; - m_dataChanged = true; + if (m_dataChanged.testAndSetOrdered(0, 1)) { + m_traces = traces; + } m_mutex.unlock(); } @@ -117,12 +119,15 @@ void GLScope::newTraces(std::vector* traces, int traceIndex) { if (traces->size() > 0) { - if(!m_mutex.tryLock(2)) + if(!m_mutex.tryLock(2)) { return; + } - m_processingTraceIndex.store(traceIndex); - m_traces = &traces[traceIndex]; - m_dataChanged = true; + if (m_dataChanged.testAndSetOrdered(0, 1)) + { + m_processingTraceIndex.store(traceIndex); + m_traces = &traces[traceIndex]; + } m_mutex.unlock(); } @@ -192,9 +197,7 @@ void GLScope::resizeGL(int width, int height) void GLScope::paintGL() { - if (!m_mutex.tryLock(2)) - { - m_processingTraceIndex.store(-1); + if (!m_mutex.tryLock(2)) { return; } @@ -205,8 +208,6 @@ void GLScope::paintGL() // qDebug("GLScope::paintGL: m_traceCounter: %d", m_traceCounter); // m_traceCounter = 0; - m_dataChanged = false; - QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions(); glFunctions->glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glFunctions->glClear(GL_COLOR_BUFFER_BIT); @@ -940,6 +941,7 @@ void GLScope::paintGL() } // trace length > 0 } // XY mixed + polar display + m_dataChanged.store(0); m_processingTraceIndex.store(-1); m_mutex.unlock(); } @@ -1995,7 +1997,7 @@ void GLScope::drawChannelOverlay( void GLScope::tick() { - if(m_dataChanged) { + if (m_dataChanged.load()) { update(); } } diff --git a/sdrgui/gui/glscope.h b/sdrgui/gui/glscope.h index 6120a2217..c93ed46d7 100644 --- a/sdrgui/gui/glscope.h +++ b/sdrgui/gui/glscope.h @@ -95,7 +95,7 @@ private: DisplayMode m_displayMode; QTimer m_timer; QMutex m_mutex; - bool m_dataChanged; + QAtomicInt m_dataChanged; bool m_configChanged; int m_sampleRate; int m_timeOfsProMill; From c1511d255e63e54430a41fdbc6f94ac0e3789e2d Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 21 Nov 2018 00:47:17 +0100 Subject: [PATCH 069/102] Scope: comments and fixes mostly doubling trace size so that enough memory is present before trigger --- sdrgui/dsp/scopevis.cpp | 30 +++++++++++++++++------------- sdrgui/dsp/scopevis.h | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/sdrgui/dsp/scopevis.cpp b/sdrgui/dsp/scopevis.cpp index 302b4b04f..f5abef980 100644 --- a/sdrgui/dsp/scopevis.cpp +++ b/sdrgui/dsp/scopevis.cpp @@ -219,6 +219,15 @@ void ScopeVis::setMemoryIndex(uint32_t memoryIndex) void ScopeVis::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly) { (void) positiveOnly; + + if (m_currentTraceMemoryIndex > 0) { // in memory mode live trace is suspended + return; + } + + if (!m_mutex.tryLock(0)) { // prevent conflicts with configuration process + return; + } + if (m_freeRun) { m_triggerPoint = cbegin; } @@ -228,41 +237,36 @@ void ScopeVis::feed(const SampleVector::const_iterator& cbegin, const SampleVect else if (m_triggerState == TriggerUntriggered) { m_triggerPoint = end; } - else if ((m_triggerWaitForReset) || (m_currentTraceMemoryIndex > 0)) { + else if (m_triggerWaitForReset) { m_triggerPoint = end; } else { m_triggerPoint = cbegin; } - if ((m_triggerWaitForReset) || (m_currentTraceMemoryIndex > 0)) { - return; - } - - if(!m_mutex.tryLock(2)) // prevent conflicts with configuration process - return; - SampleVector::const_iterator begin(cbegin); int triggerPointToEnd; while (begin < end) { - if (begin + m_traceSize > end) + if (begin + m_traceSize > end) // buffer smaller than trace size (end - bagin) < m_traceSize { triggerPointToEnd = -1; - processTrace(begin, end, triggerPointToEnd); + processTrace(begin, end, triggerPointToEnd); // use all buffer if (triggerPointToEnd >= 0) { m_triggerPoint = end - triggerPointToEnd; } - begin = end; + + begin = end; // effectively breaks out the loop } - else + else // trace size fits in buffer { triggerPointToEnd = -1; - processTrace(begin, begin + m_traceSize, triggerPointToEnd); + processTrace(begin, begin + m_traceSize, triggerPointToEnd); // use part of buffer to fit trace size if (triggerPointToEnd >= 0) { m_triggerPoint = begin + m_traceSize -triggerPointToEnd; } + begin += m_traceSize; } } diff --git a/sdrgui/dsp/scopevis.h b/sdrgui/dsp/scopevis.h index b00f0dcc3..34ff6a387 100644 --- a/sdrgui/dsp/scopevis.h +++ b/sdrgui/dsp/scopevis.h @@ -723,7 +723,7 @@ private: for (std::vector::iterator it = m_traceBackBuffers.begin(); it != m_traceBackBuffers.end(); ++it) { - it->resize(m_traceSize); // was multiplied by 4 + it->resize(2*m_traceSize); // was multiplied by 4 } } From 635a1bd34b2ac180643c6e6bcff3dfd9ac9a5ed9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 21 Nov 2018 00:50:01 +0100 Subject: [PATCH 070/102] glScope: set all try locks to zero timeout --- sdrgui/gui/glscope.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdrgui/gui/glscope.cpp b/sdrgui/gui/glscope.cpp index 6cb63c444..87e375866 100644 --- a/sdrgui/gui/glscope.cpp +++ b/sdrgui/gui/glscope.cpp @@ -103,7 +103,7 @@ void GLScope::newTraces(std::vector* traces) { if (traces->size() > 0) { - if (!m_mutex.tryLock(2)) { + if (!m_mutex.tryLock(0)) { return; } @@ -119,7 +119,7 @@ void GLScope::newTraces(std::vector* traces, int traceIndex) { if (traces->size() > 0) { - if(!m_mutex.tryLock(2)) { + if(!m_mutex.tryLock(0)) { return; } @@ -197,7 +197,7 @@ void GLScope::resizeGL(int width, int height) void GLScope::paintGL() { - if (!m_mutex.tryLock(2)) { + if (!m_mutex.tryLock(0)) { return; } From f1eeed38dafaf564038fb28a11f6312712f568b0 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 21 Nov 2018 08:58:33 +0100 Subject: [PATCH 071/102] Scope + Spectrum: fixed trigger point to avoid invalid iterator --- sdrgui/dsp/scopevis.cpp | 15 ++++++++------- sdrgui/dsp/scopevis.h | 4 ++-- sdrgui/dsp/spectrumscopecombovis.cpp | 10 ++++++++-- sdrgui/dsp/spectrumvis.cpp | 11 +++++++---- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/sdrgui/dsp/scopevis.cpp b/sdrgui/dsp/scopevis.cpp index f5abef980..c64165386 100644 --- a/sdrgui/dsp/scopevis.cpp +++ b/sdrgui/dsp/scopevis.cpp @@ -229,19 +229,19 @@ void ScopeVis::feed(const SampleVector::const_iterator& cbegin, const SampleVect } if (m_freeRun) { - m_triggerPoint = cbegin; + m_triggerLocation = end - cbegin; } else if (m_triggerState == TriggerTriggered) { - m_triggerPoint = cbegin; + m_triggerLocation = end - cbegin; } else if (m_triggerState == TriggerUntriggered) { - m_triggerPoint = end; + m_triggerLocation = 0; } else if (m_triggerWaitForReset) { - m_triggerPoint = end; + m_triggerLocation = 0; } else { - m_triggerPoint = cbegin; + m_triggerLocation = end - cbegin; } SampleVector::const_iterator begin(cbegin); @@ -254,7 +254,7 @@ void ScopeVis::feed(const SampleVector::const_iterator& cbegin, const SampleVect triggerPointToEnd = -1; processTrace(begin, end, triggerPointToEnd); // use all buffer if (triggerPointToEnd >= 0) { - m_triggerPoint = end - triggerPointToEnd; + m_triggerLocation = triggerPointToEnd; } begin = end; // effectively breaks out the loop @@ -264,7 +264,8 @@ void ScopeVis::feed(const SampleVector::const_iterator& cbegin, const SampleVect triggerPointToEnd = -1; processTrace(begin, begin + m_traceSize, triggerPointToEnd); // use part of buffer to fit trace size if (triggerPointToEnd >= 0) { - m_triggerPoint = begin + m_traceSize -triggerPointToEnd; + //m_triggerPoint = begin + m_traceSize - triggerPointToEnd; + m_triggerLocation = triggerPointToEnd - m_traceSize; } begin += m_traceSize; diff --git a/sdrgui/dsp/scopevis.h b/sdrgui/dsp/scopevis.h index 34ff6a387..489fc27ac 100644 --- a/sdrgui/dsp/scopevis.h +++ b/sdrgui/dsp/scopevis.h @@ -243,7 +243,7 @@ public: virtual void start(); virtual void stop(); virtual bool handleMessage(const Message& message); - SampleVector::const_iterator getTriggerPoint() const { return m_triggerPoint; } + int getTriggerLocation() const { return m_triggerLocation; } private: // === messages === @@ -1132,7 +1132,7 @@ private: uint32_t m_timeBase; //!< Trace display time divisor uint32_t m_timeOfsProMill; //!< Start trace shift in 1/1000 trace size bool m_traceStart; //!< Trace is at start point - SampleVector::const_iterator m_triggerPoint; //!< Trigger start location in the samples vector + int m_triggerLocation; //!< Trigger location from end point int m_sampleRate; //!< Actual sample rate being used int m_liveSampleRate; //!< Sample rate in live mode int m_liveLog2Decim; //!< Sample rate decimation log2 in live mode diff --git a/sdrgui/dsp/spectrumscopecombovis.cpp b/sdrgui/dsp/spectrumscopecombovis.cpp index 627be45a5..e7b6e2feb 100644 --- a/sdrgui/dsp/spectrumscopecombovis.cpp +++ b/sdrgui/dsp/spectrumscopecombovis.cpp @@ -18,8 +18,14 @@ void SpectrumScopeComboVis::feed(const SampleVector::const_iterator& begin, cons { (void) positiveOnly; m_scopeVis->feed(begin, end, false); - SampleVector::const_iterator triggerPoint = m_scopeVis->getTriggerPoint(); - m_spectrumVis->feedTriggered(triggerPoint, end, positiveOnly); + //SampleVector::const_iterator triggerPoint = m_scopeVis->getTriggerPoint(); + //m_spectrumVis->feedTriggered(triggerPoint, end, positiveOnly); + int triggerPointLocation = m_scopeVis->getTriggerLocation(); + if ((triggerPointLocation >= 0) && (triggerPointLocation < end - begin)) { + m_spectrumVis->feedTriggered(end - triggerPointLocation, end, positiveOnly); + } else { + m_spectrumVis->feedTriggered(begin, end, positiveOnly); + } } void SpectrumScopeComboVis::start() diff --git a/sdrgui/dsp/spectrumvis.cpp b/sdrgui/dsp/spectrumvis.cpp index 0fbeb0384..9f52ce9b3 100644 --- a/sdrgui/dsp/spectrumvis.cpp +++ b/sdrgui/dsp/spectrumvis.cpp @@ -78,11 +78,14 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV { // if no visualisation is set, send the samples to /dev/null - if(m_glSpectrum == 0) - { + if (m_glSpectrum == 0) { return; } + if (!m_mutex.tryLock(0)) { // prevent conflicts with configuration process + return; + } + SampleVector::const_iterator begin(cbegin); while (begin < end) @@ -92,8 +95,6 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV if (todo >= samplesNeeded) { - QMutexLocker mutexLocker(&m_mutex); - // fill up the buffer std::vector::iterator it = m_fftBuffer.begin() + m_fftBufferFill; @@ -296,6 +297,8 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV m_needMoreSamples = true; } } + + m_mutex.unlock(); } void SpectrumVis::start() From e2440afd87abdd9ea19dfa6b62c15883f9f28f98 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 21 Nov 2018 11:08:43 +0100 Subject: [PATCH 072/102] Scope: rationalize trigger location computation --- sdrgui/dsp/scopevis.cpp | 13 ++++++------- sdrgui/dsp/spectrumscopecombovis.cpp | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/sdrgui/dsp/scopevis.cpp b/sdrgui/dsp/scopevis.cpp index c64165386..0ef38c492 100644 --- a/sdrgui/dsp/scopevis.cpp +++ b/sdrgui/dsp/scopevis.cpp @@ -253,9 +253,8 @@ void ScopeVis::feed(const SampleVector::const_iterator& cbegin, const SampleVect { triggerPointToEnd = -1; processTrace(begin, end, triggerPointToEnd); // use all buffer - if (triggerPointToEnd >= 0) { - m_triggerLocation = triggerPointToEnd; - } + m_triggerLocation = triggerPointToEnd < 0 ? 0 : triggerPointToEnd; // trim negative values + m_triggerLocation = m_triggerLocation > end - begin ? end - begin : m_triggerLocation; // trim past begin values begin = end; // effectively breaks out the loop } @@ -263,10 +262,10 @@ void ScopeVis::feed(const SampleVector::const_iterator& cbegin, const SampleVect { triggerPointToEnd = -1; processTrace(begin, begin + m_traceSize, triggerPointToEnd); // use part of buffer to fit trace size - if (triggerPointToEnd >= 0) { - //m_triggerPoint = begin + m_traceSize - triggerPointToEnd; - m_triggerLocation = triggerPointToEnd - m_traceSize; - } + //m_triggerPoint = begin + m_traceSize - triggerPointToEnd; + m_triggerLocation = end - begin + m_traceSize - triggerPointToEnd; // should always refer to end iterator + m_triggerLocation = m_triggerLocation < 0 ? 0 : m_triggerLocation; // trim negative values + m_triggerLocation = m_triggerLocation > end - begin ? end - begin : m_triggerLocation; // trim past begin values begin += m_traceSize; } diff --git a/sdrgui/dsp/spectrumscopecombovis.cpp b/sdrgui/dsp/spectrumscopecombovis.cpp index e7b6e2feb..62de78b74 100644 --- a/sdrgui/dsp/spectrumscopecombovis.cpp +++ b/sdrgui/dsp/spectrumscopecombovis.cpp @@ -21,7 +21,7 @@ void SpectrumScopeComboVis::feed(const SampleVector::const_iterator& begin, cons //SampleVector::const_iterator triggerPoint = m_scopeVis->getTriggerPoint(); //m_spectrumVis->feedTriggered(triggerPoint, end, positiveOnly); int triggerPointLocation = m_scopeVis->getTriggerLocation(); - if ((triggerPointLocation >= 0) && (triggerPointLocation < end - begin)) { + if ((triggerPointLocation >= 0) && (triggerPointLocation <= end - begin)) { m_spectrumVis->feedTriggered(end - triggerPointLocation, end, positiveOnly); } else { m_spectrumVis->feedTriggered(begin, end, positiveOnly); From fb92612f60ebf40bf34a61c921f9040825374b1b Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 22 Nov 2018 00:41:28 +0100 Subject: [PATCH 073/102] SoapySDR support: input: documentation --- debian/changelog | 4 +- doc/img/SoapySDRInput_plugin1.png | Bin 0 -> 29135 bytes doc/img/SoapySDR_arg_bool1.png | Bin 0 -> 1456 bytes doc/img/SoapySDR_arg_bool1.xcf | Bin 0 -> 2921 bytes doc/img/SoapySDR_arg_bool2.png | Bin 0 -> 1837 bytes doc/img/SoapySDR_arg_bool2.xcf | Bin 0 -> 3677 bytes doc/img/SoapySDR_arg_str.png | Bin 0 -> 2993 bytes doc/img/SoapySDR_arg_str.xcf | Bin 0 -> 5461 bytes doc/img/SoapySDR_arg_strlist.png | Bin 0 -> 1907 bytes doc/img/SoapySDR_arg_strlist.xcf | Bin 0 -> 4616 bytes doc/img/SoapySDR_range_discrete.png | Bin 0 -> 2155 bytes doc/img/SoapySDR_range_discrete.xcf | Bin 0 -> 4304 bytes doc/img/SoapySDR_range_gain.png | Bin 0 -> 2116 bytes doc/img/SoapySDR_range_gain.xcf | Bin 0 -> 4107 bytes doc/img/SoapySDR_range_list1.png | Bin 0 -> 3071 bytes doc/img/SoapySDR_range_list1.xcf | Bin 0 -> 13834 bytes doc/img/SoapySDR_range_neg.png | Bin 0 -> 2892 bytes doc/img/SoapySDR_range_neg.xcf | Bin 0 -> 14201 bytes doc/img/SoapySDR_range_pos.png | Bin 0 -> 3334 bytes doc/img/SoapySDR_range_pos.xcf | Bin 0 -> 12708 bytes .../channelrx/chanalyzer/chanalyzerplugin.cpp | 2 +- plugins/channelrx/demodatv/atvdemodplugin.cpp | 2 +- plugins/samplesource/soapysdrinput/readme.md | 208 ++++++++++++++++++ 23 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 doc/img/SoapySDRInput_plugin1.png create mode 100644 doc/img/SoapySDR_arg_bool1.png create mode 100644 doc/img/SoapySDR_arg_bool1.xcf create mode 100644 doc/img/SoapySDR_arg_bool2.png create mode 100644 doc/img/SoapySDR_arg_bool2.xcf create mode 100644 doc/img/SoapySDR_arg_str.png create mode 100644 doc/img/SoapySDR_arg_str.xcf create mode 100644 doc/img/SoapySDR_arg_strlist.png create mode 100644 doc/img/SoapySDR_arg_strlist.xcf create mode 100644 doc/img/SoapySDR_range_discrete.png create mode 100644 doc/img/SoapySDR_range_discrete.xcf create mode 100644 doc/img/SoapySDR_range_gain.png create mode 100644 doc/img/SoapySDR_range_gain.xcf create mode 100644 doc/img/SoapySDR_range_list1.png create mode 100644 doc/img/SoapySDR_range_list1.xcf create mode 100644 doc/img/SoapySDR_range_neg.png create mode 100644 doc/img/SoapySDR_range_neg.xcf create mode 100644 doc/img/SoapySDR_range_pos.png create mode 100644 doc/img/SoapySDR_range_pos.xcf create mode 100644 plugins/samplesource/soapysdrinput/readme.md diff --git a/debian/changelog b/debian/changelog index 91461fb1d..ef646f6cb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,8 +2,10 @@ sdrangel (4.3.0-1) unstable; urgency=medium * SoapySDR support * BladeRF2 corrections + * Scope fixes possible seg fault and correct memory processing + * FCDPro/FCDProPlus critical fixes to make it work again - -- Edouard Griffiths, F4EXB Sun, 18 Nov 2018 21:14:18 +0100 + -- Edouard Griffiths, F4EXB Thu, 22 Nov 2018 21:14:18 +0100 sdrangel (4.2.4-1) unstable; urgency=medium diff --git a/doc/img/SoapySDRInput_plugin1.png b/doc/img/SoapySDRInput_plugin1.png new file mode 100644 index 0000000000000000000000000000000000000000..5abf4f7d35374cf99d1c3fd6bb8c28310fafc084 GIT binary patch literal 29135 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 z]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 literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDR_arg_bool1.png b/doc/img/SoapySDR_arg_bool1.png new file mode 100644 index 0000000000000000000000000000000000000000..c9acf58168bb226ed2476ea6703da8f067fbc917 GIT binary patch literal 1456 zcmV;h1yA~kP)WFU8GbZ8()Nlj2>E@cM*00k6DL_t(o!|j++NYi^1 z$3OnPn``25{~ks(n!W}>sV@?9rG-!o@;{j*MUf!3r;U^-86owwMfH*p$dDL;sDBMg zXz3C{BwP^GL--O|6jPa-ORN9fb{{VOxy!n>%T>Fu1B0FO`+v_lJKw|k?SG1@s;aUp zD=UCX+#@)8z&J^5sjRf}24GKyh(# zp(4Kv8Ji(4mkX!UNmo}FGcz;4jB9RgW@uv4OZxiy zc>n&r`kc{dq@$w)tJR7qiYzTHF*P+sZ*MQLSZrI!5H{0!ad9!njveFHty?%8j$g)! zqDXst`@fER@7_IXYiqIDY;<;ZlFeob27_2E767zbEq#4`n9XL~ZZ~yxb#!!eU@#a6 z1Oj=F>;DBAhYlU$_3PI>eE5+4`}bos8r8FF*RJ7mxm4Y1wIa(h8jXfvFo@A;M3!at z?Ae3KWa8${o5-@v@bEC*-QDQ*`k%&6r_;Q7^M;dv%P6Xkv@*OyEfV+3^BFi#^gM*wp zbxOtEzki>zXU{S=Hb!G(BVMnU3l}ahFfc$@SJ&2&;cz$@85tp!N)ZZ$u-olF#iUXx zyk0NycpOQRn46p9>eZ{fd-o1Wk~n$tBxbXjwzjssa*<`3+S*zG4jw$n`1m-fR4V70 zwY4>dhK5KclN<1DZEaXA7LFf3PIGfJRaI3uoleTi%D8dk27y2TNs@56T%0*`MvbK? z3f0xsG&MEx=+PrmsTB3~^|;+`{C@w|kYP5Pu~;ljPfr6dIyy>IQxio+MS1xtD=VYA zx|(1xsQx%vma$r`dHG2ula!X0A_xKogMo#Gg}m_f_4SO7j-n_EtE;QDx3@DgGD1yF z4T(g8$;n9o78Vu=hr`s>)d7&rW(kMGeEs@W)nB}L!N-pux9$RWI2?$g$de~eRGVI} zr>3SRuZw)=&Yb`(EiI|GL?WTu^J$J)EJh}iAs&yjYuB#4@a5&@EH5vs`lnBy)cpRQ z8$diBr=p@FNB{PG%kB(~MuXjMr=_I@o6V+v{C+=@B&qX!edYo`+yJb1uqcW-|AZD7 z7xT*L#EBC;efkuDXV0F|*x0z?-Vp?W?(S~PX7dJoEEdbjK@>$yCKHQ`i#hi1<(JK7 zbI!ljHmL-8!8Ptyas*$_g_x zGqkq00#H&?g2Uk;91j09kD{U?cJJOzPfrh(m6hDNa|eLI!9kXnm+9^8W#7Ji=yWz44X`<060IRF3oI7`p^XJdw^ZC?H zo|u@x>-C~2$_AhP{r!ld$b$zDP!xs9$w>wV21uvVcsw3F9uID}n{+zO?c2ABL?U_D zt!RBw_)nwaM^acYZqggLAPB6JlFy>BAe%r&Vf(uMQfTepNd5#Qs0V^C9_{J?0000< KMNUMnLSTZ`%dX4- literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDR_arg_bool1.xcf b/doc/img/SoapySDR_arg_bool1.xcf new file mode 100644 index 0000000000000000000000000000000000000000..0df4d94c59779550016e99aa16ee4cd4db68954d GIT binary patch literal 2921 zcmeHJ-A_|z7(cB{5hR)f^+XLCE$8 zf^JFld)-QPPDZv%c6!}jpO`&8i>pjBJWE191>%%9S zRq62afqv}>N8x%1t)@dQnKnqwMFD28UrF=d#ha*zjuDKl@%Gy|Xq3o+R= zCSx(C8jy)Mo!Z2BFB{_n0J9a`BFqK$SoqhQ;gV_RU2+|;oK z_Fl6LmjaiX0IzBp)YMA*bv1I%h6T__W5jsZRUGZN=ry-IIMbNaK#BsPGqB$NC8hDa zME9?l)uf@nV!({;57#CZVo^!_OJH9(CHf|A?m40tX{RS%7+#EMvQD)%ZUJhZrBnx^ zxYd$UEx@GZX(gS;$oGGt;}lS*@?yntI}q$m$wGhNSkyMVLwee}9(vl5vNs!>uEE@; z!tu(A?q(E*ekK*4-`dR`Q9EprdwNyqIAx!Nj@s|vxqd{&y52FT{clxmEu=8l=Izst zOK|_Vuy80=c6Kg zipkF#N~l2%S=*z7EoL|$sC_>IkB<)qFZ|ZqN-ci)WVhAU^FzsVAIhV<(RZT|Z3ACn z310Wr0qYC>kEjogx1UA$AaM3FvY|V z&i~$uu#fUB)Yv9=6>aVM$IAWkr@OYIJBQal_rgBvN-<(XvHoU$iHum=Mu*!9P<1~N bK7=HpUTDPpbADj;G;ZUsuYB_9FQtD0kIFw% literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDR_arg_bool2.png b/doc/img/SoapySDR_arg_bool2.png new file mode 100644 index 0000000000000000000000000000000000000000..cefddca78fcab78179a6af62d0515d920910bab2 GIT binary patch literal 1837 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 literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDR_arg_strlist.png b/doc/img/SoapySDR_arg_strlist.png new file mode 100644 index 0000000000000000000000000000000000000000..d71a604bb54a607f3f23377f00f299a812136964 GIT binary patch literal 1907 zcmV-(2aNcMP)WFU8GbZ8()Nlj2>E@cM*00!4dL_t(|+U=WdNKeaLZQHBv&pQQ29!!AAt52Wd-qOO zMt7BQ{`~ne5oZA1-Q5HP1W0QtCopb6cFlk1TF%J?#_4q8bUI}w&CpuPWR%G$lW{UP zU0q#GLqh`wg8_rVKz)5ZckkXME-p?o&dtrmY&K&unOs_4UfvHE-oJl8H*enjZ9hb( z(-9RFHR)%Cg@r%3q)V4Bv17*$m%arH7En=9!R5=BUHbHTJ*!u*cCjrkE+!)*!=*1i zKAzIj(!YwZwy}cb#6nXvnH5!cutJMmCzrQ~!l?s1v6|IH{?r^z`&hErA&w9i_g$o{t|t5)l#M7W)ed3IK?Wjph3F>!hTl zP*_;Vg9i^tNJ#jti(Xt@Oj1%3ix)5csa;%L9930S==FLRuh7uYfJUQ{&edu)&CSj9 z_xBSP7WVDVRw#&!jKpX({?)F%tE&sGR?C(xTYzuH^Yrv|bUGcCm6a407P4&FGRZ?; zyLOG-++51a%E-ydAvidg{QP`kV`HZlGb$7cwr}4~aBwiq&CS!A{P6HF8#Zj9sHlj7 zf&x~oSV4JtIhB=_3=9m+Xv{cS|NHmv(d+e`Jb9AL%*+YLtXZ>$p`jsKTU)W&Y?PFg zaO1`ehKGkS8jU0;C*$YmM{jR0YPFiCrY7mQrKN>ct5yMEwOap(GRDWpOLO=hR;!gK zPoB(J%qR!~BO@aKBqb#g5fQ=R!-p9h9OT4_6J%v&k(88#-EL>yx^eMMdeE2ZAGUnvuP+MC|ZEYDzlY!VU@uvjcEEhQ!8Unl?h^JiYY zdLCwX$v7HUK_-`b1}ECmT0z#KXe_ zwOWnYY{p`-NQ$Y^XfT;f(kA_GJbwI`uCA^Lm24s+x{D=CmXMg3$g^k90NA;6C-?5% zV{mW~fQpI=)~;PE#fAO-{SpzUoK25sZ)RpDzP`TH*VnrYxPANflw!v3A&R1O>~J`~ z-3jyDD|5ONGmbs}x^m?Tr%#`zv9Zx*%)*5W*}8Qrn>TMJIXPLn`~Cg>rA0Ryjc7C) z+S}Xt`t>Uv9Ub)a^lC*8`V7yR$51Y-#qD70O^RcAPX0s6z5;EoW zm{gj+eEC92NeLMl8F+bl{Z#>YetteNF)=J%y41x**VNRw*f|^yolpo5G^e&E(-A{k(ZY@Vae@(Rr)!2@Syav#gQXNuvjeg_4Q3? zKQb~hVOi*>ezLs09Du~c#960`-#38l>};y5tEE<4Tr7Py-qvQbQCeC`P*4y6>({SG zrBcz*(D1``YieqUiHSj>P++&)u~;mGhKADE*eKbU&1P1vTq&vITx-+Cty{Nv`}Qq& z?%YAA(-9mT%(-*tCbie=^%NBqarEd>*SLPJz3JW8*GFVzP&k zXA<(`!2fg1%Ey5+WXQ_s1{@BDtc)|bmNFULgr}z`qA2puKmSa*ekEgKD3wY?QI!7! z<1Pe2prfOMpr9ZE0|RA7O#`AR(%IRGAP6!U-GP^v7ehlsw70i2JUlEjYMNd~5QJG% tN1l^0<5+Rk$Hzxz)L#TSo0c(a@E<2F?t2&0C&K^$002ovPDHLkV1lR=i!cBH literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDR_arg_strlist.xcf b/doc/img/SoapySDR_arg_strlist.xcf new file mode 100644 index 0000000000000000000000000000000000000000..2f707a3ef2ba112b991e4c9788d5ea2ec9a4c975 GIT binary patch literal 4616 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 BR>lAT literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDR_range_gain.png b/doc/img/SoapySDR_range_gain.png new file mode 100644 index 0000000000000000000000000000000000000000..d62ace47d7c27f60142c342e348c49c67550b97b GIT binary patch literal 2116 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 literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDR_range_neg.png b/doc/img/SoapySDR_range_neg.png new file mode 100644 index 0000000000000000000000000000000000000000..d25f4e3835657216ad679cd386a4bab3dd14bb94 GIT binary patch literal 2892 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 RI^Zz=Tk3D&oc^cO{{fj(<0}9F literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDR_range_pos.png b/doc/img/SoapySDR_range_pos.png new file mode 100644 index 0000000000000000000000000000000000000000..7b42b8ef40d98422354c8436ac408689da4ad8d5 GIT binary patch literal 3334 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 LW29ZK=^XvP2|0Rs literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDR_range_pos.xcf b/doc/img/SoapySDR_range_pos.xcf new file mode 100644 index 0000000000000000000000000000000000000000..37c687b23a5be5cc9ff94f8bb1d69349c77ec6fa GIT binary patch literal 12708 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 literal 0 HcmV?d00001 diff --git a/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp b/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp index 8dcb43823..60aa4b978 100644 --- a/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp @@ -23,7 +23,7 @@ const PluginDescriptor ChannelAnalyzerPlugin::m_pluginDescriptor = { QString("Channel Analyzer"), - QString("4.2.4"), + QString("4.3.0"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/channelrx/demodatv/atvdemodplugin.cpp b/plugins/channelrx/demodatv/atvdemodplugin.cpp index f728462f5..bd1efedba 100644 --- a/plugins/channelrx/demodatv/atvdemodplugin.cpp +++ b/plugins/channelrx/demodatv/atvdemodplugin.cpp @@ -27,7 +27,7 @@ const PluginDescriptor ATVDemodPlugin::m_ptrPluginDescriptor = { QString("ATV Demodulator"), - QString("4.2.4"), + QString("4.3.0"), QString("(c) F4HKW for F4EXB / SDRAngel"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/soapysdrinput/readme.md b/plugins/samplesource/soapysdrinput/readme.md new file mode 100644 index 000000000..55191f7d6 --- /dev/null +++ b/plugins/samplesource/soapysdrinput/readme.md @@ -0,0 +1,208 @@ +

SoapySDR input plugin

+ +

Introduction

+ +This input sample source plugin gets its samples from a device interfaced with [SoapySDR](https://github.com/pothosware/SoapySDR/wiki). + +SoapySDR is a [C/C++ API](https://github.com/pothosware/SoapySDR/blob/master/include/SoapySDR/Device.hpp) that interfaces SDR hardware on one side and application software on the other. Due to its very generic nature it was fairly difficult to implement and specific UI widgets were developped to handle specific types of parameters. The level of control depends on how the device API was implemented by the vendors. On application side some parts of the API have not been implemented and can be left as possible enhancements (see next). In any case it is recommended to use the native plugins if they are available. + +

Binary distributions

+ +The binary distributions provide only the SoapySDR base library. It is your responsibility to install SoapySDR in your system with the SoapySDR plugins suitable for your hardware. + +

SoapySDR API implementation

+ +Not all parts are implemented. Currently the following have been left out: + + - Frequency API tuning arguments. The tuning elements are of course supported. + - Clocking API + - Time API + - Sensor API + - Register API + - GPIO API + - I2C API + - SPI API + - UART API + +

Particular considerations concerning hardware

+ +In general as previously stated you should choose the native plugins if they are available. These are: + + - Airspy + - AirspyHF + - BladeRF + - HackRF + - LimeSDR + - PlutoSDR + - RTLSDR + - SDRplay RSP1 + +The following paragraphs list the known issues or oddities. + +

BladeRF

+ +It is very important NOT to use SoapySDR. The default parameters are set to flash the FPGA but as this does not suceeds it results in a FPGA image wipe out and the device returns in "Cypress" mode. It is not too difficult to recover but there is no point risking the hassle. + +

SDRplay RSP2

+ +Do not use sample rates lower than 2 MS/s + +

Red Pitaya

+ +When installed the Red Pitaya SoapySDR plugin lists a Red Pitaya device even if there is no Red Pitaya attached. Trying to select and start it when there is no Red Pitaya will result in program crash. + +

Interface

+ +![SoapySDR input plugin GUI](../../../doc/img/SoapySDRInput_plugin1.png) + +The top part described by number tags is common for all devices. The bottom part under the "A" tag depends on the SoapySDR device implementation. The corresponding widgets are stacked vertically inside a scrollable area as there may be many controls depending on how the device interface is implemented in SoapySDR. Move the slider on the right to see all parameters available. + +

1: Common stream parameters

+ +![SDR Daemon source input stream GUI](../../../doc/img/SDRdaemonSource_plugin_01.png) + +

1.1: Frequency

+ +This is the center frequency of reception in kHz. The center frequency is the same for all Rx channels. The GUI of the sibling channel if present is adjusted automatically. This control corresponds to the first SoapySDR tuning element usually labeled as "RF" and would generally control the main local oscillator (LO). + +Use the wheels to adjust the value. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2. + +

1.2: Start/Stop

+ +Device start / stop button. + + - Blue triangle icon: device is ready and can be started + - Green square icon: device is running and can be stopped + - Magenta (or pink) square icon: an error occurred. In the case the device was accidentally disconnected you may click on the icon, plug back in and start again. Check the console log for possible errors. + +

1.3: Record

+ +Record baseband I/Q stream toggle button + +

1.4: Stream sample rate

+ +Baseband I/Q sample rate in kS/s. This is the device sample rate (the "SR" SoapySDR control) divided by the decimation factor (4). + +

2: Software auto correction options

+ +These buttons control the SDRangel internal DSP auto correction options: + + - **DC**: auto remove DC component + - **IQ**: auto make I/Q balance. The DC correction must be enabled for this to be effective. + +

3: Baseband center frequency position relative the LO center frequency

+ +Possible values are: + + - **Cen**: the decimation operation takes place around the LO frequency Fs + - **Inf**: the decimation operation takes place around Fs - Fc. + - **Sup**: the decimation operation takes place around Fs + Fc. + +With SR as the sample rate before decimation Fc is calculated as: + + - if decimation n is 4 or lower: Fc = SR/2^(log2(n)-1). The device center frequency is on the side of the baseband. You need a RF filter bandwidth at least twice the baseband. + - if decimation n is 8 or higher: Fc = SR/n. The device center frequency is half the baseband away from the side of the baseband. You need a RF filter bandwidth at least 3 times the baseband. + +

4: Decimation factor

+ +The I/Q stream from the SoapySDR I/Q stream is downsampled by a power of two before being sent to the passband. Possible values are increasing powers of two: 1 (no decimation), 2, 4, 8, 16, 32, 64. + +

5: Transverter mode open dialog

+ +This button opens a dialog to set the transverter mode frequency translation options: + +![Input stream transverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png) + +Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit. + +

5.1: Translating frequency

+ +You can set the translating frequency in Hz with this dial. The manipulation of the dial is described in (1.1: Frequency). + +The frequency set in the device is the frequency on the main dial (1) minus this frequency. Thus it is positive for down converters and negative for up converters. + +For example a mixer at 120 MHz for HF operation you would set the value to -120,000,000 Hz so that if the main dial frequency is set at 7,130 kHz the PlutoSDR will be set to 127.130 MHz. + +If you use a down converter to receive the 6 cm band narrowband center frequency of 5670 MHz at 432 MHz you would set the translating frequency to 5760 - 432 = 5328 MHz thus dial +5,328,000,000 Hz. + +For bands even higher in the frequency spectrum the GHz digits are not really significant so you can have them set at 1 GHz. Thus to receive the 10368 MHz frequency at 432 MHz you would set the translating frequency to 1368 - 432 = 936 MHz. Note that in this case the frequency of the LO used in the mixer of the transverter is set at 9936 MHz. + +The Hz precision allows a fine tuning of the transverter LO offset + +

5.2: Translating frequency enable/disable

+ +Use this toggle button to activate or deactivate the frequency translation + +

5.3: Confirmation buttons

+ +Use these buttons to confirm ("OK") or dismiss ("Cancel") your changes. + +

6: Software LO ppm correction

+ +Use this slider to adjust SDRangel internal LO correction in ppm. It can be varied from -100.0 to 100.0 in 0.1 steps and is applied in software when calculating the frequency at which the LO should be set. + +

A: SoapySDR variable interface

+ +The form of widgets is closely related to the type of setting defined in the [SoapySDR interface](https://github.com/pothosware/SoapySDR/blob/master/include/SoapySDR/Types.hpp). These are: + + - Ranges + - Continuous range when maximum and minimum are different + - Discrete value when maximum and minimum are equal. Usually this appears in a range list to define a set of values + - List of ranges: more than one range applies to the same setting + - Arguments defined by + - type: boolean, integer, floating point, string + - nature: continuous or discrete + - String list + +

A.1: Continuous range

+ +If the range is all in the positive domain the unsigned variation is used: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_pos.png) + +Note that the same widget is used for single ranges and ranges list. In this case the range selection combo on the right is disabled. The manipulation of the dial is described in (1.1: Frequency) + +If the range is in both the positive and negative domains the signed variation is used: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_neg.png) + +If the range applies to a gain a slider is used: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_gain.png) + +

A.2: Discrete range

+ +Appears with a combo box to select a discrete value: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_discrete.png) + +

A.3: List of ranges

+ +In this case the range selection combo on the right is enabled: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_list1.png) + +

A.4: Boolean argument

+ +A checkbox is used to control boolean values: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool2.png) + +For AGC, Auto DC and Auto IQ corrections a block with the text on the rihgt: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool1.png) + +

A.5: Int, Float and String arguments

+ +For all these types of values a line editor is used. Numerical values are parsed from string: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_str.png) + +

A.6 String lists

+ +Some parameters like the antenna ports are expressed as a list of possible string values. These are presented in a combo box: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_strlist.png) + + + From e36bd24330970c225d7798800d39da847f3cd822 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 22 Nov 2018 08:52:15 +0100 Subject: [PATCH 074/102] SoapySDR support: output: documentation --- doc/img/SoapySDRInput_plugin1.xcf | Bin 0 -> 125300 bytes doc/img/SoapySDROutput_plugin1.png | Bin 0 -> 21255 bytes plugins/samplesink/bladerf1output/readme.md | 16 ++ plugins/samplesink/soapysdroutput/readme.md | 184 +++++++++++++++++++ plugins/samplesource/soapysdrinput/readme.md | 16 +- 5 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 doc/img/SoapySDRInput_plugin1.xcf create mode 100644 doc/img/SoapySDROutput_plugin1.png create mode 100644 plugins/samplesink/soapysdroutput/readme.md diff --git a/doc/img/SoapySDRInput_plugin1.xcf b/doc/img/SoapySDRInput_plugin1.xcf new file mode 100644 index 0000000000000000000000000000000000000000..51ace5345285806fd71cf8b4d66a03e52782c5df GIT binary patch literal 125300 zcmeEP2YeM(_MVpl2*F(q?y6CYA%+?VlU`p-LP97Z^dcqHC`EcF&w>@~U6I%YU36u2 z5m2!_REP!Fx;9iq6i@;rdC7Y-^Z(Ah)81nO0g=DE%lqZz&OLMQ)H~mI&$;K$Os<%A zMeKs{lVT@TOr0nQg6;2++ps{tvmiDb{zXGtxo#B%68zdhA|U5M{-Q2ZxpPqd0;GSQ zjLjxiOdB_OV&ddk6%(Kmu-+zgnmuRX)QPdPXH2b_(7AP|Nt4IVm^x!tY$ui^&YE04 zE;gxq68l*!^i)@MM%8kQs@nS4rWdH{g4tJ$8(%Sfa%@j+Ur;WzQmVSdxzj7=#8yln zKV{-d*FuAVhvC2p3Eego_6VLYF@aLicrokoK)0 zWNpTkzC{pv)e6FZw*_IyFhLmO7KHIL1mTMB1lxC5#?SWS`Rc~bMN0R9?mq-M>QCLRvz!`sQ{* z$4YuSE@~%KkGGRK6Bo=$oH}md#92_Wb2!wAbg^+bl{j48Ni(J+GjQDW*;+1fcEzHJ zu{|@i2EofPEx+PdR4kY{m2TF!>2oT^O|2L=J9Z(vc~i$tpF9`sGB$4F^u)PrgXQC9 zPfVOpF>B)ZITbUe$4;Fy3-v-9rqQOfMq}K66u)fl>^T*a7RFAUIB5>DhI5vp{mLB5(1W?eT9>6pwJW;P;r*7J~mQpE3;R%JoR6 zDs`Jo`NsD@y+Mw}Ir9RMLW8Kx>!@65()jKQoF{DkHjEC1Z9PJ$Z}rQ1L71Qvnsp^%0f(*D4i}`0*_D}LQps1*)!CtI!UTWVcZb^26YbJK>MPf6)X^BsJ|9B^9B8g(dJvA&0pYx^n;8DUf*&VHiP1NrWQybSpk7bOzXSrFPxfXoquGd&QH+?iF7=O9}^gVhi~ zb-O(fAJ7YMcMhJzb2iwN@P-v_443cmq8xQ))lrxNLi2cb9Pa989LG~zZuxB-)=Vgnh z74-bc$@+t*t%S-mwg{CrL8*+yE!1usbaqdr;8F0O^ryH?u3{4mIhnUm+mH!aXF{KiGJ1q(BvIur%F#iTS^%gjN@(`FVLnU;&hk*2_u*|9Iikp29v|QQh zD!m!}_jH0Am?K(%yQ5(XIlM#NAlV+-Ayl@y@(AxjWd!uUr-VC&N|V5i`5EMG2>qr) z;7et{H2i0NPNd}PHHN6tVv#*nK4{xj*w^h4D<3osQJv7xRN5bMXeuLk?39K(Pv+26 z`&3*m`f0ZlZu<7cT&3yS52t(&FzzHPvj6)! zNgGD;`xW^BMigm;34=!x1}fD>zZ@oGw26kJ*ebReKHd}|)M7J%Uk*yLe2@({sg*IF zB4ZqjhMS;~u(=>j?EzU1?5{zs1FTG>AWKSwc5pcI0PT|xiD~C^HqNa_HF8W^2)?(r zZLhB0zKKq+8mIU6_UiCzdApje-(J1_owaXm-^TJ7!9o5FI=yNf&-UtVbb44sv3Is( z)iydkzG{1Q1QsaMK-<`~dAn`9yqOMDT~DX7z4~oUv#okN*HA)bYTu}?e&@xvu-P}5 z1}FCpwy7Q(PVSxUVcX?**dDdh!O2xu+8Tww(xBT}s;l)Z)wQ6dk%I568^5Uk{Hil? zQrxP=Xy8TP&~05{Qq{kqROhrhe^G_5L-9Oi_n&e8yc$Nou2+`e8fe-2XO*0*f2yw@ zLxWum0#RhM@&s+V(zKb{^~&DZ>_D}I!Her?IHxHbg?k#_LtB>w>H|KTM~icsX{#3 z75iBs9!8+FUmPA^`k6=F;^GCN^F9bhy1Im{k2@>~9iZy~)a-zA9WeUUAs;dbG66CN zat-88$YYRyK;DFWBnX#GfjkGnb`ujj|`0uMTMgXBQ^Kt@5pAf1*#RzMzvJOkMb zsfK(B*#`;W_@W>eK)OM4AblXCAX6brAS)mbLY{$ahEzkoq_h34KF4F$H;=f{@(KDj zn_Vw-e-X2VC`AmC-#X$JyuHfEE$CxlFV)zKNy4jPSN;YuZ!4;r?S-x#_Jm$&dtV8&N4qrCU zvWR@`NXz0>ed1etzKOfRweVDX$K68 zrOGfiQRx8n;Ca+yXfAL75s0ciX)H=u43j14djUrTGm&jUl6TW?k*zx*2M!#T$P^_7 zj<^w9p+%g8OjS%O6qlvOeTSLl%IhO8GD4B$J?iG9Ly~E4I1ANK?tzHCqu5;Gg8XMX zu{}6Q&D=Rs6Zo@otI3)Q$=3f_+4)ob$IDuUZbNz-7e(J}-JjOl|MZu^-zf8RH4*x;A4DYlysp{J;tUg%#{vzXef{iK< zBG7ps?^wnab4#2ekW!x^YmlO-X7$%&9A7XSS3Ryogf~JD)82u69K1dWQQ%3alQa{8 za!I#A9)|oK@)~3Z2 zvyGM$CHGKc=R~)2w0cpih4xjkK@wi|7r<34J;%laum&zygUO zSMfz;G{q>gCuoU3UFWENo{LlnI7dzYXnC}*Q*ig&pQL--bXy5-Ta{5^0`_@Q@BNW& z$lT7_D}0}vNB*dHyLqi|i^piaRxMm>|CLenJfKr-mZM?7$yjIJ7cHNRZ60kK|KI!j zPcUdwVu_|sQD4DE9h3PGD}&}t=ugO?N%`X#H2O?ClV!u_@11OeCgV9=F8Y}anv6HO zO4DV)&ukug!Z5>Oj0>@TeJga@Yyl$JDl#HTmOJ|l-tvR2G`(QFBjNp{Rp7)lA2J$OJ5ro{=1tD)ap2m5e4%E#)4_j0d-ogG0 z^t`imvWF!8!a6iPmA04*s!6CP{Al^Mrc-bTNn|NR2}xuo=t<)5JmDtFI0UV4^Bemy z9nhOT+DTil3vLIMZMNvg^?Ths>&CFfL(L_)8L_rShm?2%r>3W8Fb#&2u|`gXKdb*%J%ZGZm>z4hc+qLEX@<>z8w@Mu}~ z)+u=HgnH}Af1KWWQupMZVp?VzUR{tbW~THMvCuOmBRwVgWcSwdN8@tQ&(vGbpT$+0 zE}!D^gdU~n`7%Ka(cpglZT$nK{Y$AYUJ6%y|I)}(xdc9A$~Bbs?_WH)Z>bH-;iavG zFqXCwb^QPw9RB*U1JsTjV-Tf1HX_FaR>I&78(w;8N^2$+p6>VaQgoS}3~ypIT9z z$xE~+Y-;evjp}Y}8+`vgFPZmK)^_>bm-M8(+fyH$KlctsOW{V`Gm5f_!7Fr(Z1OV9D0J>L0znmV+VCf0y`@0U~%XP z#~44U59|HR&blw|k3&V?8H2r+LxU0ryJFj#sxD(~pO{u%o>K1Bl`z=il*jcftjEYp z9#Mwq3Ix`TQf!L!Rk^-tRTZecqorO9_0C9qM7cv(U>N1AeR>Xi3H#osXEBU&{ldgH zXQn-)ylPU)RdmEPm_w`|as4?9w$=DPzbjVX`-vJ($@D;;DzK$}(a*|ofc8E;Zx|p3vyTxfHy*EJ4iev1(FXL1epMt1GxrrC*(26 zKOk>HK7#Cm9LBLmK-xj#At{i2$RNlB$Q;NukUQyoj=S@6tjYF5dBkDIx)cOgiZ<6o?)NhvX`shT*dCsSvb)2Fn+(5es`rpSu zyNDTR38m)>hBWuGQMq$@{f(%vOLH$9l~d~{puR59H|w%dIbQz~>ZJcwxP%NtJ&F6B z4MUT89ol-e{BgG8^PAaTapIRpI|tPvDA$?Red@1sRZ<= zEcc7yV3z^T4OMO4AM8METITz52T!qENi5Rb&`d z!CZTYMbF&@OM$WtRjXIsce@r`*IKYu$$C`YLuynW&BIw;#iRFViq7h)2ie9jv~=I< z)vM^mfmL|J9zyh13wYBYq6Ga9uCBTtx1ILjf3RxxgEX}X%Lv_z)OHY@gT8wSVi zNe6gb+&Z4Jl2 zTgI>+jvv#}FeV5+jvtfJ{61N3pyS6b{C-)kr{m{)$Eywb4%o5iIUIj;Blhb5Jmr-= z2X`!r!a;EMfW>()*>C@9W3u1suDjcDZreUTD3|F<*n&fq73OS-GC|Mc)WYBR$_UxR z>4iUbAW7c~PVtPt?@Pw%^1UKG=j|W6;goqEN7Lbp?=Hbc#Q|uKjEoOygs_Br+z9? zOMbcOlGuc*%CIfWtYb5Q)Mb5^59R5SqHIhRh9-4s?q#BK9eDkqp-t$UJuJrSpHE%R zIN^LU`}E|mzq8pFcl<5WqNRz=Y*WTXHMhyAs!ELAV;jxBVEp0+w@tncj4JygV{mM=joRiY->ty(Grh)8%=H7O8>vMzyAc&t7k0H>#6GF(70q4#Hx=& zx)UHJb zufybm0Ro!>O(9&N@Ix{)PBg`U5*b9QNfMkhn;=gnVCh7`^*} z=NdfQw{6?bb2y~!IJD{$O(TUC+Dj!&i#RCtB^k|lqeO(z*m-favI|G2nIv)qT}rd2 zA^el&DPJ0zmV$IjbGU|Y(k-ag&7vbUCu$b;q-J%hAcOWrKP$+Hc?I$wB4u9kL8^Gvp!2Iy#@qw#mn7V!*7RI;Qs^(DKpWgP^{V5cPgn za|C7wZU#3q=+xM9b!8Y*>P;Z8cm7EC2PvBYCygP;GFw`(j+UgTrlg#W+w!OvrYqf+HV}GUim_a+-7Z?EqnEM%|Fvw&ahkm+{y3goSTN%) zEmwwLC*WNEBOh-w570853q9T`zq32xY0()vuC16e?8NaQ^zDHr!PoO z?Kx)l_*paNbiZQyWGZ^9Y%v-SBWVeNeZ_w5)Ma$Zwcku;o8UaObAbKOr1Rp$a8c^kCH|~< zsY{~RLiAw^Vrkf4~hiv_I{hIfGo#VXXmk-xG|I7AaPUldg?rm3v zT_xT42^=Dg(&2aRznZeQ>2#q8jtSE=xdT{Z=77L{t^qS7e?>E*C%mz^y%XY z?NCXBjeRbk8#cFb!DFx7K7VfOxzcj2URYj~Jv^x3)w9EAOY`Q>j+!l9%}Wi+jn0(@ z8JoIlX7o(yD!y)DPIQhm&{$VFJ$kxS$=8+9x-weFp1yW-7fd~CYGA?KcJyp@?p2a~ zR(7DIS7)rRr)TTJ&a)RU`O^~r;@O=pq!Qf{dzGD47Unx5|H3+d_Z z+L@m2&fV~I9~&8tjvmosp!l6bVwiYn@y?o$MvCH?9W_7Rf}J$H^1UcNyIMSh?c!|F z-+$)=hj1V@gAR>JUjAchZp~HV@Y)H`_!jR9DOyxGhKfoLtjB-<50hOUq`&T1E{cV_ z=kv1mFK<-Ot(_?G(wlClI$LkV!TefOTPBLHUp7oTW5`HONol?6kt-#*J#>qu-q9i2F+M6-#53ZEcxP}LJ84yt;h#6fjWlsKsFi4h0Y zJYnLX$|p=5RQbe+gKC}_aZt@>5eF4KI&n~mrig>qHANg)cU0oQ`eP7B1%YIf#BnTS zAlPZTOtXliLTom1u%gF792KGt@W&($Q`ut@hpFtbh{Gs)Y~nD=9-TPoGBlewn!Y_{50CIv_U{~< zILzZ25*ra4$cf2`jpj*MtTfR>28m$r5Z*!RG~HwK$d&jfjf(FO(IH@uv3H2(NmvJ| z^AuLpiP`M+UHVL0ux$Q#dqRtZfHTIK5Y3Z_1lntU=XRX~`7!yOqj?h1nY4x7+I0&Q z#uRpo=1D|1(iU}Z*F8`aQ`9}0ClTFAThg;#&p=5`NzZ7WMD!$W-;{PKfxa<)Q=)ki zkwV)3Y3ew6sud;%b9FiB7=f6#nit{4!{4*703i9erX`p+P z*9WdLx=Mp{!*cy&6{QmQ*1t|U=t5q-#|?C=b4w1}4pYHFIpI0}Pn9oSIbk{ep+02| z@~kCA=J-EQl=pI41vRYf@a#jE$;$gvT)h_ksO&FBo;Avd>_%6kqRh;0rR8bk1G6Hs zr0eJdP13L9u*_O@M3#SsqI{NhhL)w0Wtowg^&|eitFi9$hk9X|Jrxm|Xe`R2%rmqs zl`KtfmmVmMDNT<^_kW~(o0)!wmZi1&GZ~)dcLbEH(^{LK&3>uvQUm>B`lW`a;_CgB zmD-wTBT}iZ{*;HO1RhsbrnE6X?0u8lB@+ZBNAn~inX2>wi3Iw@^bx^kl(d1acT&5g zK<}8|NzpusNTQO~aMLTXU1FeDOs~Xfoe{!)*pdu)qPG#<*)IP=057fNwM2#vd9F_0OPd0{k9!Y-6XQ6X6< zO)IUmc|-tyg#q}91o%beTxOr^^|a^&mpJ>ClS&A^)7;X zSB#6Go)QlA)>=0~y*tKDP)`Ym`h0?V5Eel_B^>Gt2dP>(D@JtZ9K z3jpu+LvLTd<<)i9_aUf1qC_D<{lYiB5nk!l@dWi~Sp@ZzaH#J^P(Q)zts3ccPgv)D zr5`~(S|vd}B^>ID2U#qW{Y$*B7ZTKu^?J(*9P!K$)KkKto=Vl+>3!bmoH%#xNM~=acadee5`y}N zypOwF4|%=Ux?Eel%L$Z0;{^4T0P6Eu!|Fp&|G4*Iw|g~;y4{<-D+%iH>=M*d0;s>9 z6=hp}!uznc)y>`&AzKC1Pk57+r6UdC2ngz5^Ij8jlz{q@4O>`2#(cMX|3Oe+;`PoC zxjKOQ2fcGy$zBBY3%qX>5Y(4@y(0UQSTI!n@f)P|xpi z10}h=UbekV1q%r3*La_C5Y+eI;=O^Oo|+4w{xPrjQG$9?!y>33^``gH5f1m{e|TRi zAgIS`w8loq>t63Tf_k23=tNLI^9^cc8;20o^X5!9cP&A^(YoCP^`$pI|Jo~SJ+!Po z4*sjX-pK^@#?#>>s7EJ{p#BN(a~TBnJWG4jpGiP{?i=1|1og(VX(y;hHc#>9D;h|Vb3F|N0y+T5)Spb1ogQwxdio;5Y%TA)Mv+J6Vy|}q23y9 zG6?E3VloKoDdA9`PEZe|BB-Z?L%lV)i3IgW0AUhAy$M7))F%?uJIl*E6VwOea3ROx zE(G-#7nIw|<&FgPU1GWr)KdbeFQ!6fs7F+n*0;Zapg!5*Na_$9k3=M>zaZuUf_h2- z_2~}QgfAkfza$%NT}~yazbNJ+f_h2-^_OI@LKhR%ckG#!XV1+@B&feQ=3;_+N;uTV z6V%7Y#1qt0!l6EapgticfuNoe4)vV~>N~}BBB-Z?Lw#3*`mQlu3F;}~P@hOpk849v zPYH+m9t8D0VtNqNQ^KLXCqaGBn4SdnlyIoG)`|r6xK9N2lyIm|Ca6!2NhYYLghPD_ zL48V03PC+39O_dD>X9X=r-Va&3PFAE$@7;jom-wyP=7>;R6u|{(i7>CmX;FIgBS_v zDd9+;Mo5ny!1O*2N9kP8(n3P|w3swPdP+FbrxVi8^~`b*(ibfDOd+I4>m;P7gd=?h zA$>oOXCNW{IL}fyVHsLBAw4A==`(?a{!2ZTZbEwOc>rM}NSKhG5{~p#s;0s--{~wH zF`}Qdz~dQZSuTr^e!6F-%QfBODR;S+;UADbD<+GOo)RFvo3*QKLi(AW8E!XKV>TrV-M^R(286;}Z2Dq~|xKfs#Bo`eTH6sf6^!9?u{` z`U##Tc0zi7j~gh-buF96q2Wk}Dnv`77s1kz_!dddjtjYqRPA$|9l z?u7Iuo(1WI^pxdDuRr8K`q7@jg!IOEXpe=U%AwOia6^Q+m0_GYNRl zoHw>uf5HM!MQjw$o)PQs?(sMP|8kC}g-5!)3-F$~ZfqR_0EWs|m9h&+&s1l0@F#gZ zE;x5;?e6jOmM)t&p`arGo;h)B3G!gf@s&X5OK zs509I`EH^!<+7}{L5`c~EO}sd+aRw^bhbPwr)`i!COQYIu$;!ccNJv`pq^RZ;W@Rr zOW*j}-|+JrSLSKTupIemrIjMzg2!1Ngoj_g59YqSl%SrB`mkK7=sohz?l9_9%PpP={laQZ*9p2e1Hh^w?k& z-1qnZ%08p`9pPLHg#1={$`R$L9p=1N`OrNIA5I4&FsDyzr@!PIFD9?ac0wcdJa$$49JFLqeF=ozF`;^+5Y~%1mp-7)=uN{YMW3R83 zz);YRG-51B#cw{p*3QO~kCd9eL^k9PYvc68F}D&~c{nbm-+ZClIQ)|oWd*SfIoOab zR+LAP#bKlA?4=t^_t%yen0faDd69YkLaf)cZSwqm73BeB!~*O8wz)h-RpL z*>e3)D@qx$4|aK{NqzlmZ|9MEv7#)bb~%^`2p2_f&$b-$=xszx_CKd66VTpSGl%+S zMY##38}q+X4&*~G4+8!8hoUa{hxwMmvJb&8_x6b{Hk5VFo8LVUIQ->PgTQ2RS$bRUc8b;#xzqwlQrmI|Q?!=I z{VX6TxowbZDLPs1E4B^tD@BWPpQN@yZl&lXxwi%ACAJN6C`BjAy}Gsy@+L)hl?yE} zHKA>gA1NBh+o5fc6DhibZ1=SE$i*5Tw2E!KcnW6##t)IPzTEQp%jQjV#74$SIh9LW zER_o`4Cnr%Ru{^B(2tSxE{x!caFEhy>Z^{s2xa8V(maz}i7`-l{~jGKN$Oi(UP^le zLC1oD;x8>PBL<=@7^ri3c^WZLVtI>lX;4REATow*9b^Ygn^xoG3}PTsfq}Y}muG;1 z>XI`1jT}36WdE#$NN!PqfC|c6m&@5iKe(Bmy!ym_R@|boa^9RJ}_epgd|eCf5=O$U$sl@+*OWTox)KAd^Q4 z1mq?HGP#pLK>0*KWTvaWBoI&m5fB;rsv`*mR6qoj`-sNuk?5U5fE1e?)1L-T8r1@IYdB( zL_j0oc-8B@j0lJv86cnsyxx_=3X4at@_KL9d{4lsRo(}QfO^^Oh3ns#1rG-i5V@K_ zKyY|mO$6jv3!Ti2sMa+$Oi=iDtgv?KT!&0fxR2Ol|(?j2fnho)M+jX0?HpS=Xvi7 z{fyGJuX`6ReB$NTH{3UY2&nfO@8vERDorD{A)gcosMH(g4XnSex26Ie6nVW{ypdk% z&V1sC67MZUK!d&B>BKhVp8^35VAXCe(^Md!GOzcw>xcI$nfiCH_a-8sKI;mJU4nO5 zmtQty;`JN6uavWm;~-F^c;?JuL_me>yl)I30xB7blck!bOVL>Lq<2#>T?D!oARxF4 z=OHWiCIT{FXfV!5uXiq8TDro>7J9wQiGYf!>HL$ZhHg6usC;oH5s=&Ky++f5fQr4| zN+O_MFNeR}@Cq)+%g>@=vBm@fy3y+`A*R6zFEXiT-nW_&&=fe4s9hEk0rfYvXE4oZ zulFt@pqstkVMIXG%%Ps^_0A>&a{bM_iAF(W@^tz8!G%c#M2`*#=pnE7p^?tQQTKbj ztBHU}4FYnm_r88@zr6e@>%HD9h=2-+fT%7J5Iu9Y8$|C|YdAmSBxkNxFXBP-4+XD26fJ|;K5KsmY5IMJ09~THH z-2zjIfCze3H$MnSBmyGnR>ucGKuP5-%Vio|X82D8G=LKT%Y%SY`i&YpvNVkdC~@4_ z7Gvei3qe5S)dB(Kk+&;_2#6FQp!U7XBg>^e?XfI(F$f6GE=E9(^p0^II;A-r>9j{O zu0TL>xsD7XAj*P(E^#=z5&>P{XyK4DFChXV8w~{1)6v=?CldXT0`$|-;YcL<^{dA>!58~83UZ9^uYBVNy7wD%4agE8>1^Ve}p(6Sr3tshdfqq1yACrp<^pi~V zL%svmzXke9A^IWjgX-J@{iHDZfoGzOn1_a*{n&UmKJo0d2 zpA>q^FQpE}Kw=+qe}H|QGdwUvuW%Cka8+Q6r*c_~W%4j$pHyO>K9x)1LLv4c=L*>8 za*t@(9d znb;@Y;i&M8g`;LL(GB^+z&^c4mlslYf@c}A4`~6B^E~5;eKMTG;MBrahYaWyC(2vps`d zt`cmYsD}JxV4q@7m?toQe4(ZS7r^nhjJjkMZX$>*&tzgBxQ2!j)sW8&?9-c7o77uV zfqif^%f|OB=rv?ME+Mf`_S}4;mf#)MxqFuk9KXo3bO75p4ubYLY*-&+ADnDuF|kip z39*m){9yj%<2o16MWAZ|_9^ptMiBdC68o4hH0TC?sNr;J=?Ww3_ISn-`(#klSx7uX zw;k+LI%+hrj}y02(}I0ad^E97+LG`k4QMD!m&`@OVvPyxGagO}VxL}c=o#w3(95Rf zMuL;jfT>xg68XUAr?+OX4326FkB2MXa)wS{T)AZSI2y2#MdBWE z&w+b*A}3kE2yqWN;=nyTk-J;q4{;Cq-c%PHxF?ag$K-zl_jDufF}dHsJzXpikGRL= zcmwxzBrB)`3ZkAAc!s4^Mm^^l)T4UeBy+5kRUlPZ>>(q( zDkxgYGMEbEErvcY$_ShaKQg2$JmIh&Wo5)tsUcNSoh2iZN)4!r>LwX+RBAX?RCmdU zqEdsYqIyb343!#66_p|x5mag*RaBZ}#80VVR8bk$x-uI;rippjkV`ZoV)69jN2(_{~51L}IjF>80Q!!UI*FjS- zmJwNHYbx>zv|a4+YFt)Sk~M1S!B}ccR#YMoPYcCTBeJ5pN|wl|$D^uYsZj}%fz4__ zYg7jlxVH=r$Z8qu!vJ9SSR?Ez@`!jWO(S)^(4Y-OVv)rnnIo>O!m&UbMv#_aSyALw za7dP>fxWMrWZ;U>m@IIGt}?sGn8S>?!sH`k9y8(!JrGNc$0DxK!?4t7EaD22n~XWl zh%59EEHx5~xIz!WQsc0QE39;S@Rb^aMO>kWUa1jS#1$rI88h^WD@@)p<~Sg(&~@O7 z&=4$eg{CsXtw0Q+fmoU<@G5*FYP=Ol!73UnNNvPjffTHwvVzob#HjICAO)-FEJGc* z1`ZxI3=5=S6{KaT17ppFn~2o{SD1phjG!!Vg>}#tkleJw2+aalSch(bD@-eb_Fx^r zg*}*7n9so?iVIx9L%SsNWeiwEae*ti77jlBZh{o7!nh1|pxkI7AO)*XE<+tyfo2yH zumw`E3hN3|qfv(jZh;i6;=6*>EG981hzrCJ8s?>`0vqAI0#^h_a#_TB)oS5iN5*!k z?kwU82XTctvdi?y9}(B3I=F}{@`x);QC+I9ozO#%=~6?xh%5AnE;X==xI&NUQUkk) zE38mUkLFT?x`-=GelF(qBCaqE9_YxZ!>a1=BCasGx|rjOxI&Mi1y?vt5nbR4mNnwG zzziV)U7AMfXyOXhyCs=Jwyfg0z!gT6S8(W7a7-5kbCCw8riX5UD?)?1z!kd6h~`p* zx`-?ESS~fBi?~9Mn7BfZ-BLrih$~Efu-n^0p+@i7 zRJe&)FEE8E2+RoT0#jHAeF4W!D~!-CFokvK7ns7dB4`iR0btmJX@&V5ETX``6g)Ic zGG9ikC@?Suj}61PhJH6e307fXh8h=959k9WScQTa>c9jvx{!b`P=ZxhSdbb`IyCSL zlwcJf7Nlk&jX^@Yc`n0tztLXQYj1H*_Z^oTGuFpQYO3bXWRFf}NQm_m;Q zQ$xatDfB2;6E5nYs)of9Q|OVjYCtV9g&u+nrZ7i@fhkzli2DLBgam|X8Y#}i6wDcQ zksz0f7mBhzhc7I2W}lS93g|QUf}Bl!MxSJ-BI=yIV4suZWUI6wFDaj8wE!=vkY%;t zE~$uRwZJZ^gk`m$E~zieY5`sNrZDYP3+9prSY@>!E~$*I)dIMrfh?;9Z%Kn#R&y5x zWrICMe3h(Es?(f75}Riy4W{i##%wx3b%pn1JWQWP2QUtqT_+7Mr3h5KdIxX%IWPn7i;;FO#EWWBOP^F{a~|meYN}qqG|A4& z6C{nG{ncTA^iCeO!@%x^1AemoRR61zD~hIxcUFEOX{1`6-qORX)A3^7a>|>JQ(~Hp zhuxdJL3{<@z5iKyaStZ^A2_%_Y`-M24XoOpN*gdu)6+dfs*<0x|5`L5LV#Z zvrrUg|KP%f!zI(_?ddKfZ8jg>3p#K1ZXbT&4LI;Y`$yoyqozKM4^SU6yN_A}zhv~j zA9l$acQ4G_xkQXW12E?G0rx|kOw`nPO?vqctLfjp@H%OC*zU&3qG-(Y1Nw)!ns^(Q zjOl$q`VhC0+RXJ?eL!~8L_hWE(dO-$-9_qiriD$}O52MqLLOKxSW40WCU7%43DK$Rx?ZvRYJ<VuJV&j8Uos0MHBFl{d@b5+I%;aXrX`XZ6X}9HE=d*ZiPJGTG$Ug?!ZzW@FV52 zCsYgek+NAf1UIxGA1Q;a)dGA}kO_exEwD!gC@rW*g)$z?V|X`I?BhW?ng@eTQj@yS z&U7qgjtqvS?ZrqQkOLq!d=@k_O}c;`A0Nxr92IOjnsgCc!v}tY-4)WsY?T&wBgM0< z7IPydu&fquBXwd~E!IZr%CcIVje0U#jE&TTt<~adq@Gq;Ev`nrTv|+xl*|fi@ibBj z%WAPSLD^s@179WUQ^JB=3!Eh+V=7pX^MI+PG}@D7%mWMZ7%(-z?*Y>+FvCxvO%CHt z1ra;?95BN@piK=URXG$HXS%yVn~FyFqG=rU z$od>K!}*|1O{3P(B#xRUr5T@LDQ>(39pOU8e z8u%OvlGErf-hcHk%vUXi-7qFUez2d@?( zu%QL4NF7;WEm%dxm=FZgf>cy|(gIXeB;yEZ*#0W?@rV=6zGqXwr1NNJ97m&4+ia0j z>D{YaPX9l3S3us9iYs5iuY3jD@9F=iHnwh3dlmLgf~pn+rxtY zU&P)be_lN4+pF(zJa-h&v3E9}SI9H;lE(83wB?be-g{LlWqFAT)Aa4H=p`crpbwNY#(O8NU(`C*8X z-CwiFRXpQgUlh4|eY<^PuQ9LfDn{5UFaP7*SJHoWi{gt9isFo&>3gJ|rNyu9{N`^t zWdTii(>U-V#YhGgX)Jl z8=vwz-&^Bs#j4?ri~W8~5eI#ntnQcU*_9$uoc|@OH-zE}YZfBrwef)+jxX+Vv_hC6 zd$0Gy4To%p_DYjY70Z-#QJnH?XvG&^byPotitLr*>A#f1f6-?sw>RJCdhiu7<<*_yxY`VH z+oNJ;^?j`VV1(iBuUU}in*7NJ&b(gVemtdc)El3>DOMZDEmq%-8@aFgmg0YX@Y>3q zV)hpY#}{wex%0_Py)xa?#vdLnKn-7?XZJSld8!B@ymZp-aUTZdo}X*AT$Xcw4%f5S zq@S0qX6TLR=ao?g%@VIa=gsoSM*CYdNihdyHaLu zd?b6E_%>1L@<1wid4E`rs=JrS6UEX%NwIRbn7MPQ_|*n6$M>v=SJI$}oJ;d1d5d9Q zLuv8Pw8; z#Y&DSqAh$mLlnQqtA&3mx7uwWr`Cg7fpV#YRo+9DcP=Sb`ibH*&jwePGID~>7uWFm z+N<2@SL|JdP48Y3m?n;rii?$pM8}>*=BgONVP`5Ikiw+8PvFhnQRn;AgY(_JyC0~G!>rh*rRn1xucNvkdgK&>ZJu0RS{QJQH zA*Gr|J2WfQ2@~sH-4t45P70LKNP#bNQc(4b6! zcJ&F90&fkR6pmcxq(FL|6j(+hg$ffXST$ODwog=VMGEW|0fj?JLDL@>DJ1t~AZe=G zOi}>)Kk(S25s%WjX@t^zR*>S?u8Le`u6rD`ASFM(E^=K^<>TRnWHIQJkBb-RT#uU< zDvl(9=Bk3*jvv>W^8%%e7eW^rSP>I1PyrJ!u&lugrfieEU@CJIUI;4HG~j6%&v+rY zPLm*~)#1Eg^@3u97la^Qpq$PNl+k#BFLPc{^^6zzGUo;1xOhQ0PF|q$O8?niB)1j2J=}*jF*k1_Ko^ z5d+H_#9+!cNerekM}rfsK7;5Um(KrgPaczWRdY zaQ2Bo(vKuPJ~xOOST4x7u@4Ng8u{n4Wm+>LU;E%6tr_kQGS@qMb0IB^pDDu1FGSZ+niVUX|A+XwVNDLSjWrbvummYA>6WNBWgbW zKFuf}u3U;)>E@a~)qg-VNT2_}+*S!+-lLt8_X$-U>o?IX_k86t%z3AEbYl1hU|=e9 zAV^;=@X4+Ass7=Zi7(yv z4LPOQezm&fKadbN#p>F%FZaVm%d%kHgT;D3H#TSm@jH`;4viM{q;E`H_B6xaS(B3^L%xj+5f zpMLKD2+zI!QTrZv7OnjGlb6z4- z;wG_Pttn-_SKM9ROT_~3lVXAOK`X=lAxeo|$a3$JD2ierQ5-xba!g=wayKza^e1&0 zG`u*n*gt$wmn5-=80a2KY?{uXnD9hfpt*$ zGTx!MqV8^YdtEgQ-4Oq?uYP=&t3B&_go}s2{c&}QsJc?n{lrP5NQG;gsYpr|oMqgb zLf$O+>fp%RcBk{KkUj~bvX|`;zgi@Uc|5F2D|mKDM+DOqcQ^j@mAHSZh%a-1|IiKD zb|+pLVD5Re5*xl)CW`sRY@b8$-b`uR9rkv5Pa{ICO}^D5-n%0w>w^_RW!kg81$MHl z?q#=_vG%~vYg1W)!3gNGHTtDM<8yfzu-*e*r@?s%`tqRM1lF4%y?MDTCxP`Ua95aL zi+3%MBX3qb?_WeSKNs#M{9Kjc%i-9`+df!B#!8<3zGmYBMRCSP&!ggN94E3r~Ght8#hlQ+`i{N$alMk9E4p! zxE$f~6@7J|%k|E4sv^?WF!s=-o4+Y$`JwojRO8C;YsNc`Y)S2BE}k8N7fUy8UjNx$ z4z_j(4Rl=hU9ZuH$Eo=UyKm&dNp|~PUoi#yP_O&*Rj|n<#|NsaO&%TEpxidO=CmxQ zO%BeDaItkZ76=ksm-S?5*gC#4JVR_;ytC$`kz$5eH|WrqyC`OypTSG94`ch^zJYJ7Qx6pL z-TQ(lCjUH9Oc(1093Gc)^LHuYEDR&m&;RD&dxJ&s6PQgHap<^6j2NFK;=^6J7XL6T z`yvg9ju*v$zJ&#?SQsp=(|47|a!%jX)6eQ3{aM9Sjo_(h@e!<_jgihRsiVS2)w2

e2%Oc8rGzN=BI!p9F*;&#EZtyiYL5)pAaGSUf8x(aErwqgITEcJ2G3c%(=%yS) z?OH-@$}zzHlmMG@8dM`QSk%B8nH89W!qB?e=g_fbM_x8kY?#-Pwmv>$yzgSZh#-9H z#X7aX6Hmf6s8ustxBe5?POI>i?XB9EMA33f4XPIHEO^41(atJN?X1FRXBB!o<4e@e zD)e?%k*c+`3ZtD>=&j4Vq_wUJy`5F0YVE8-Z)e!F*3K$Y^>$XFx3dbpb(xp6c2;4u zvkIe~RhZgY@Yz!fJ7JBvona$JJEM%z&M0TJGs+q5jB-XhqnzH(D$MPyBB-6ATr-ZF zw=9jDUu5mfYO(HOu2tI^&uHz8=d^ZaRlPy2j&>#lO|moEnP6&Xg3-ZFj z8>^(4rvf3)|0rRx+#99paC7+wP7H?1A+j&lFPr;K4_t)ZSAZkuIHVv}DchZ&;D$PqT2=C;->M%>}vnosl9;+S=p zI<4VS5p%X$ic*Gyl_cjOW~<^;EQf1;yj?FDCN}>2T3)ga+g!YD_1151rZ3_$ZzHd; zx5jf&uOOz)YaGHW)S|+?z&LS8ARBFxoR5e?#Dv&z=f0ZJYt}Ps6b*;fhQX zUsjiB|Iq)soFwl_<6m)Z&SN@uWCg z+@Wp*#*QsZisPq3+LVs1wCRkL&FI#uo2gDtQmZ6W)}GQT#guiWw@No<^D|pznz991 zt+GtnLVTI}SH9oE7k@smXI+kXgWOqBMH<$5ZzfQyIMpprq!{ao2KZ^N;V!OS3>qJDI z9$fJXFSlmz&BIctE(kSAX!UU(!y+{`JG~j*fjoU$=YJv+g^#PA}zU3TO&&<4`4= z@A2Us$=K9kp~UIDXT7tamwV7wJ}pR{-PwE|sGt~ejXavo1EyNX!vjIpn#}{jwW^z( z>k-5Qrb@&Elr`}HWi2OHHL{Ywb(O&bY)57uP!&24sCkVC^epEAJA zFWwv;&`LI&2eb;!=K)^hczHnI&vEd8UZ?pypj9~@9x&BuJ`b=;1`p_2&I3(lIS;67 zbso_28V|6%!2>KyVE-EyI1jK55X9#Z5A>Y0c*&HsIKElZx)=}Wg$fxD=-J+k2lQ-T z#shk`l<|O`En_^OX9qGK(6fUW53sB?574)(_Z0nozyG`2a{2LD^S}`Bzz2J;oBp75 zA1`Lj14HfhnaW(^foBf$a!v5SFo)wYALD^J3NL8M10!6nmv^~dR6L{9QWiWg((U$s z?S4_YatJTe1P=^%IyZmsEbQ&RRN=FLbVzTmJz$!Ta~$@7sn+rEKv1=2^FVN|>gMr) zsS@!3WlcOlSqApM&w{}NZ2M*&P!&24sCkVC^epEAJAFWwv;&`LI& z2eb;!=K)^hczHnI&vEd8UZ?pypj9~@9x&BuJ`b=;1`p_2&I3(lIS;67bso_28V|6% z!2>KyJn$P9I1jK55aPEd9_W~nXV2&q$2UvbIK~5dp#;VQdbSJW0X>_@ctFo4F&@yf zBI5x)o6LAX&!#XQU|DM(NF^R{PFz$uZ$vIXJ}VxO1o}Yefh!gc?LWHmQeMuQ2-5BL zQqKS)f(c7_xh9AJpNcGBO7rA?9N^&vEr}q@<+^OXYl>$`iCW5n2(sPoX>;9EJVT3l znI?!J)9JiyzSEtLugXfFt%UQco`?6${to6!-P3EtFRvEGHUFd+d%pby`L+Dew?niSlvuv*#-BbRrZ@yeEYDFr;+f($-D0^Y0 z;3=@@yWG-_Yw)hF`o4QVbi4cdr(;?AawGk}^;?8=!)fus)tDo>|MoRsk9E1;ebnU| z`0IYR%k}0OSG=onh|9%Se?9T;XI!qkKXbXRd-dB%uEN@xSpCE6PUi<#JDt-$b(Zcc zbdHuwottic?tbSLwFUU3HjCQcwZi$+VpeG53a4|+a;Ni$t6jg2So*&6@h#2^d2rPC z4?CR;e=7dqDo0;m?cu}qI~Er>n2D-?<6xrN+7c zQu~~r?s?8`|JRjLsr@1ZM`1{5;K3iRw12w@zKBE5uC?da|9i3BzWVde5OR-~Vcn`+ zIsLF3{)0o)YutHn28#3YE?27ZCgtH$<=S)X+4eF7EZMf;J8)rfhw)+7xVTG-E-fFH z9TyfyUlWRJt!h<+JuI$~wD$3lqcMI?bg~lku#EP zNr9Z0oTS#)iJX&SOQG+Or?j?CWP7?TJ>ZIQrMI?DWLKswlRl!J+1fgh^RsMO^rGdg z*47EW?rzJbkI5tA!7`Bxff4kDdiuU^|IJnODQU{J&OJ;?uIfz)%RR)hMJw08w*DG7 z>d5p>``V(IqC7|c#hYHKqEAUvu65oaN;Llh3bDL%?Mt)ARlac-@-;<>wl9t;wqL#V znMrG^;DZWKuC?7q3HLZ0TJefnXu{SCG@yMqd)=rs*5T+K)7#OvufwtCVVX5dxz-LJ zCENpXXu?*tkfWG-qK9sH!;MO_U9LVc^yOt~?ZfyVpiFDmeo8c#gjxh2j2`mJEqKO! zeHP#mjOk0WnAbjn{{hOhcJHS|^HJzU{KH;&x`^Jg*LSAVSrSu1vme$xO!J8;)7rV8 z63u0y7Qu&~r@XSd7yN`m$!XBq|Gx)Xc`$O5{NVT7&V;S%B7%ns*4aCP<@=kq?-{JIKCka(E4N>ffi)|T9jz^ zwORzAwczkuy$Q62p9Zb}LC|U+(>^Y)LrShayE}mvWdT}DtC~UpEz0&lh=)HlF0MU+ zR$NRRftFPw#}R1ZtMvq0R*9TIpw$H*9|LGvC2|)6E&7%jK+7tT6A84?{Ugw_O5`L0 zExeL}K+7tTMFOqlm}CMit3*yF&_aijK+7tTQwX$D@ku*?R^j4l1X`2>Xi<`@+GzkS zmUT^-zij?k2Z2^9fmRwmoM$f_wRp*N0xik`v?$3_4L1TUR%rI3VKC&T5NM@2?e=th z5pk?%cG;}y1X`2>Xi>sVxkD3{sD%c21`=pZtfYK@hXZ|IM`5AEF>5-37Uck1lyKAT z&;XBG$WcJ1-l6f!oTxP1<;uc`1_4^LXAo#n2B1ZWX6va%09qwWCJ|_5jdHuQ@i{|) z*6bMsT9g53QKA`tdJ%u$1#=1rw6cdeotgMVAwX-^bOJ5P0JJF4Y(cdMKx^QVY54?N znUxU^F^omnWr{X+4hxJpK7A!a#QSd$S;tbup&(^bR*pIKXRAx52#8Fet%!txsJ z4{zR@570Q86=$;Qe9X#&!G>AZS3d38S^(@gnjIHv*OkL$vpE{ZZ62_6Yay17X3BBX z?q}V!yB21ftM7)(UCXu>0Y6l0Zij_67h>Gq3)3zCk(=D^%B{tK5Y?jFVPVmQ7G7(MQQnqip)W9~w%85}TP(yh^TO_0^>G1$T=0qwzzsLYzOpdKLaejRr{U(0 z4mYr#I;H2?b5ausZY<5G5NpcEjH{*%C?8o>9hwCm-2USxs9`)O!Qmq!Qe?7kbDhvbLN;3@INoq+lY2=lQ2E z_BaV`j$$~O3@INotY9MnZN|(V?Qv1(<|w99s3}znD+y>*y13|4kDJiuDAp6Vrhe9~ zsd89Ku3ifVyGDBo2yM6lwZp=I3bCgygSF(IG12WF<0&MxA?vBNdj};UMpS4P2Gf{X zE~j&}C!f%U+fiRx*ij*7)n%1!wur6igW00kpm)aU+p6OKwf8O1aTHhD8rgavK^|uV z`zIu83u`SK$z!=RmPWE{S&}VV7{&MvHeeisjYD|Ec+D#y5fYN!<=^GC{|xvBveZ z=OK1pq3CxVoTBkq9mt2%YWpG{Ddo8?5Cg7fQ*3`)Ocf6ATTHVT0hz9$fUrliA6p#7 zW4DX0-|XA_dHhmwc-LZ@6-#8mE)YY~p$U4HL(7mzTP%I9UVK>et6ht55g;*kfjH`V zGuOQ-5{DmLfh~#sYSSVd0!T!Bis++_jrTk##K*sV=)moGtA4dz5w?F^16xhBBlG85 ziH-ZR)H=MAc|)}cn35vn##B&3XB?}Xi}+aWY~o|W+04f}XA2+eoy+;y;B4dLJb4_{ zR#E4Z^d)j`soDudxAY3?5WJX55*-)OmkX!1RW+)S8?k#0!dYUaT$a8GHrR+*iGeXRvZkAiBTZ`OvWj`*yZWiy>w z)#8H`XboE3cnzZEr;r6H5f>kjjhR{CRxTr3(k!>hnYn)PG#Hg;dJP+>VS~}Ie$h0T znT&=DTBpI@Y@KXdZ6k3iXugK$dRiZ6LK{nSAPV#+CCvy6LNL(as^|5Zpd|6L758f-dVVF zh@-r*7>^^~JLH-iOF2rI_{1=Z*0%-GPuv}OcU(3A65X6AZW3MDxTA0fiSBqq$V0Bl zPbBA^CR!(MiJYuszYi|K0Euo+U^t1cY}{VBokVxMQRyMqWFgIYr-{~yTOvhw?DxUt zERfN=i;v&cC|bY!s*1{OJaQ{X(IVXTbI&y6x6zR;Dn54oGw%!>d8|!FKVtJl(4U0R)j=iX~+N|Yv2@YQ=QEp?@JDY)yrmPPfY z^(pw{y_Urdr41=~;Juc%d8PB-h7(V=U?)g=|2^W06G$$-(7BcNT0Hq}q8Z?TY|oJS z7QF3h#MPqalH*qw?|I_$uM2T#<(n6aFFh~*4E=Si_8!-ruKJ(oPiJ-|M0XUKsq-52p5a@8G_ z5WPQKg4=lPRowl|Ka6bQ{(7eL-TfcU3l`|RNdiRkC9UQQUZ(WZq?0sl2Gz954?O$U zWN9+hdS@D`!nLr8R!Z%azWCcxgNZJHL0GWMyfkU#9(XKbA>V zEsEVq1u{fTs)DoB45ezKqQE6DplY(Jz$GuBYGZYQOI|?LrbK~DUO?5Bx&oKHfU1k? z3taL7sxEFQaLEg(+BUCX-eLW?Xuc46!QinUuY&b^xaQfT*NHzzwX)g5atF`1UOgp!8muQ;jNKExm3 zU@P3APq;(Xlp&IX>>DdF^f(Pgl#zJ!aeSuX{hz#!!jGJ{QXc54k39n@(Edtmj z;kB%yMF9IEyq49p2w*3KY_Tr_6pigUU*5tV2sOgC2pD16v%f05hd*~uy1aZqv=DK^>BA{o;f$K)L z@t%Cu-LeSinbP-oZ_9!O`fic{(R@j(`9h0;ewuWWrp=(5Hdq9F&wd3h0xQm3A>W#M zFQ-Ld`I*bTmRvdOphdtZdAZWLlokP6sk8*Q(IViJX}{c$Wm3sSfG!0=l}27Xe*e&5Hn6)qDwE1lI5(AiLQYfwi;< zEZL-<{&*LGb+iavtym$jJ8c|`!1=TYT;mQM=ORGy9NA9~^>SFOWf4G}?IpJ?q(xw* z3XBb31hD!0<6SFh5!iZ@46`M;PtYQ8<&A4QHg=uwwbsxgFn{w6ojcYvc&&4I5zrCE zvw0EF)j)9aEM5fk*+3-o3|<8E+3CCp=&BJEP4dd^5ijH-z`ba4QK0ppcHXA2A4Xn* z&YeYz0CvE5Ez@Zcz@8VcWske3Uyle~ z1$3159(VJJ>Tg*EjBstag%2-92;_Fe13+u6^A-Y!%Q`rAIrz$esx!H<|s`jlJ+SW;;f_zPYIboDG= z1$1>fuL8PyHm?G@I*V5UU9IL-KvxB?0=inmtAMU1copDk)G9zUoQKs@wXXuSyX$!K zIlABYehSplDzN+(J$f9gK$2F0^W351Tm>jVCcE;MLHR2dAHvBAgqFW_Q|>QatOmn3 zK7ZRn^i8+RAG7%87>576WgnZ{mVfpp&@=PSd}$%lzk3%fxbgX`K-ipJ3IQL2GSRqX zZEWrF#~xn0_T0uss>d2LH*|lYadKln)f&BD#7hD8U4qO6h&40G3;HR}#Rz{HP;oEHUhQF20LKRDHaz~q^RegOd7=CHJ0fNw_?um$lc6v$W* zCpTnn>~03S$@r`0I{;myAXt8~)Ws??35LN}eyyHX7VN^*3P&tPv;3M-CT%!YF^=WO zOT&SRK`g(rG@J}YK}lx}na}eIg1jn$U_2GE*T-jL644JL3b&QTRx7J44RS9ER;M&M%<+|ZuvM?GH6DUpFN|;+m*C1 zQ0XYVL20ldeJ6)QL7F{Nu2F~doqL=ISl?ME?KT7xuW8N(3LSdjUeb3cG)NjlwTWlJ zf_pNbC4FZt={qp%G@iRDw(0nruWZ`1sAPR13+%)`en8=~9rwlm4;9dW)V>0*Ft3Y$`{`Pl+vLv-^u zY|P)-^T^1Sm29Y{ktQ@n0~t}}khb#=Ba2DfQLq+7r%)JU8Xjmn_l~rZwxd9ew4G@D zVr?fHyja_jlgffztnGy16@wUSJ5f_M9H|(-SlbDMDaJ0=b|_LeluRkVLTfvWLjkbT zRTVJYXLe$3$9iSfcB~M^+K%=6vbJM|DAsnY5XIV#6{1+%u|gDUJ64EdZAXC)lMd$x ziI@~UQ=i$1wH<{x%s~u8c94ciMF;o!x{tG6INX7br0l>H zO3Dr$lJz%TO3IFGQitpuQg&b-C1r;WwTnBON!gK2>X4o7vH8f*({)=(+3^wkWM`4G zgCR8h2cImQIEj^=FuEk>P-11rcT3G1%*qaaz=iWAv9d!!y`f}Dtn84e zgfb}$dgPSq)@UX4*m5afytplW0cF}sOvJx;Y#AT zUn359KyfE28lqNsB>pIcc#k!81Qx@Q2T_+5#7{gfCiJGzDK*i|Ax=t8MF?6x66GpzKa761m z3_}5|(pAM)&}VjHUB`N5)^)51#k!95`?9WMMJU#FtO&)rjuoL;*RdiL>pE71VqHgJ z4ijrb*YQ^sH$k7-%DRq19H!YOT_;di+ys5TX4VKo$l9c%H>FX_$LW?qGwC`CZxEB| zk+n&>fs{rqAE#Re&7|un#9?M`#nu)e8-T9k>onwAdQW(kUS(~Pj;wy|$ddJAUR_yv zPk2_|Fke=`wiZj@mQgpYylnHeIf_z zL3jL^u`O9RnxCsMSu~oTtFTs2I18p>(na{W3TsB0&JljD!gx`HpR2I4C=z6(HWVA1 zpDW<~f>*wxf{@UXR{+1btEzyc^qVd00FswiD#}EH=q4>m1#qkD>R@}aNMZe#|4v@n6^ZigZR%DYNUc=Wlc4U*T({1c=@v8Uriqvh##TRAs9&rRJ`8OqW~;Hy6&CP}DN4a;XIPru zWTW`P((EN;$Ct&R3{{CtqzStxjLt(<8jXO_>Ib7OR#26!ZZO(21y#vnS}v&=BIB^D zDh+cUIjBme2^q}VRLw~TV0I!^$!cY0Rmo~)W>v{*WoA{$YGr0s$!cY0Rmo~)W>v{* zWoA{$YGsD16lq)zkWIQ?Fd8$8c{ylxcKu*9j8p+_QI51Q2fJk-B~?iql_QPJ!EXC^ zaC$sN?;oI*gsSATGs`pqsuQQoQw;wBR!OKzcIrvap{F?h1Ei8rm6QW4q!ZmA51%-6 z$@7mz!dmt^Qk4Qw<$1}*0&IhibEp%kO3K~k)}yh_b&gSQ4vT`Sq?}%=I%aGmRVms@ z#;Q`ZlZ;g*IpHjr#;OvbR;X{ERi&uu9N{EmRf+H_)TPg=QUu6oRml%tCQRX1U^te+ zp>|jRF$eKD}3z&8arDO2`h~8Dp6Nw1+tPl(CF6JTcNC^9yGdg zJ4mQkzl8j#^X6IMtYjXfaQ=MLBW81(H^uMUpj{$m)ZR+zO!Bh zfHILuFlR|5u)U`6&xcVXHeBn?!L?y!Wlm`;GcZLNn+bZf15G;Aj(K%uVLstmn1Luc zPPBe)sg_PPqi$N5+1_mRqJ?_Z8sP!aW@a`z+Z<^DznY>$jdrD_*~vDFCoRoBHYRqp z*rPEC$ikYi`_bq;R3&Tf4MiSn^`fQ8wHCKK(TJQDs**K3$Pkm;Dyz~kr&@%nWLlsB zFI3G*LSl9zRmp0kW>v{*q-IsgYNTdW$!er#Rmp0kW>v{*q-IsgYNTdW$!esAsuXFP z4p^*R9~zAr#X21{TDxvE8bAx*)WL4qOUG`b4w|y}uZT2LzvMGh%j6`=md!~e zRbG(*B`#DYJ8v#$nN*oY0*ts&mF%>+A$aAv*CJspOF@1HG;z?M=VTiTunlhIfIw1} zAU39_EgIWg-x`hP;6bQL%4epkW5za8m7;xYtSUwO*jQDP6V8HZtSS*|h3*VsRVivZ zNBG!SRkHfnSXGJu8LcY$!OMgxQk6on4BG)JDy-Lrs&p1qB`btMRhkY}$@;CKDxD2g z$qHk64_hEr?ha=i6(_C+EYcE}Q$UHwV`owo|9sZVk@s z$>R5JcyUu-omlgKn?-XkaZEcdc@Uz=m^=G~iY~tXKZ!_V*Z%$c{tkrI204miRN>h&p_xm=rX$5`#FJT^lVC ziKFV;OX(`8x~?9g6-U+e?a+Ip>N<0XWE@r3dqbZXRoAphUj$Xxl1bka)u1be2*@dc z3GxLWya9J6dkdj)!0RGu$jxp8ZVFRrmNd!8`C^%aH>~K1^<;WS=7TzCz|C7KEs+K% zxpz%UOZ@ydKy7olJJ*TA%;e6|z9acZ9Oni+$;^E(&E>wijuTLng9zp5XBOu#P9M5K zh-(kDh|_V^Tvv&@Dt-AueEHQ!){8UnSykMkbmeN1qia&np@TOp*!vmqxeO@U9gnce zl{wjQ_}~p+a1Q1l%x=XU$nFSnd8kJc^kk?9=XxpBV|6_eB#(HG0g-TB4N5`+^5Z%a zNLDe{^&Ti;Gexm8cDDE^N$yl}0$HcDZ!_QsaKPw2Rb&lEfCJ8Lv>2v;C&?{F3Skm` z^fAo)B>iYH4EjzBw-{N0okiSYSnKI)V3c8|r+I=;Z07V080MWNQY>6a|DZUYo5~z?2>URX6b~WeGslP4i000#J2hM(Dj!byK)f>Ht*Tgsqf8 z097|VD}51E-DIq)8raX?DkOkp&E z5=pl7mid5j&{@DxWjIR|z!^b261=j8!^Qz90N{-HCt3v1Vk9PxomVEZE4@6#4%8y_ zFv4&gWc@&k5qjfb#RE*5S%d@TH%G0W22AFr4mM14G)>(HPVn_XF_fDz*cAPBUjG10 z<|Yg_C&BsNI6qA0{0YP;QK$P+WRX5cvW&S|b zO)N_ZKu~peo6~!v>L!h)bRej@DPk!r2&!&ESo$KUy6In4HMl)crV8<}3NU#Q!K827 zA7GMirrB-4P1GuXkeF#h!eG+P&MJR{7}-O-YkDvl@-u^Th=jppSFXtfiVaD45GK2F zjU>n_;?4yFCKZK?+HJq~dPzXpdZ}3xmn?LyR5jp#*Ihs@b(qkSO9wx`7D} zBofttP`GgiN=5<_6#erYm&Rp+F zOVm5g`|WM^MW;5{e<(Lau_^g=UjG0}=4L21=Kxf0SFZdhnUkQ{-0~_1<)Y-wwXo`? zn-ARGeAU2)rVk@|uFhuS%v?i>4mZ8hzxU<^A3;uB-e%+NWYVrUA<&w8M5iliR0&)6R)CFHC1uZng10|T=OwbT=Nl? zv*t{dv*yEs)75-TrmKNr0GVp0aHbl1y@6gMNe#Czn!@>M==BAyQ#b*Qe66$6oS_?i z329E}gf!IGpNqz8_otyL4y2)>k^T%crvx(4P!E6dnG#>}89tAPe+oY_YByi6Y@EW+33r#C(#PaeLXDo$$K*3Y<}o}YJeBvz zGdi7~(VxIX*)cIu%&aF96Xj10%>Gm+%JzwgGBHus{|T@9r$dQ*H#vR6vNIJ5m8NOp z1u`hTmu|u^r{@aIg#?R7bT*@~WJ&VgA#2jai}%<~AW7ObH#9X7OHx#>n6TVMQh<=e zXyV0t>?V*T<<0Gx`?L@h0){>2R;KI}wO1cq1?Q^FG4ZevKkPpkJ2-sw=G$MP922in zj)@`4zw$_Tes@X_hesc2S1=yl>tFo69{-RK4}KdNE1c{1(&&RUdM~A8S-pP!Up=Qs zGxajPdCiv86&TF9F}{hxmmKL3%buFwp1DNaFf7ws_|s}A9%jn%k$U4+ywf1(#&`(t z)_2RBZ@qbo5T84A@LMm-v6RpweTmAe0U~A9+}1d$F}*RT*+?zo^=$>+h>_TYctwnA zAazMoO@W)#h?tNAc}^PQ1#VI!I-9I4aFZHQ)kv8_%*y@Ujd%VeMWdN(_Yy|Z|? zr;f;vA+G)T@zkDOwW56_i3ggYLy2&{^8lO zWyj7H+m5%ik33SdsOLuU!q-Lfk)1R)UmR>3zF6Eg*l9HK;O+g8lI%B+#EuLu#}yv_ z4ywQ3v$K6<1v0BVChC(yJaezS#IJAs4TSSZr_solxCEOj#Dc|(Q!8 z9~aah>BohaU3SN?9z7nY@h5K>AJkCVi1bw|dxHlbs|jkZ%xN|fSa^L`Fx2R*7RwoG zbTyD5ql2MFpABTwSjteN&$cnt=&F&JgOGvS?JpQ=s1HNUD4iK<-c6q)@?(q&HGJ(+ zp@w>$1k}**cMUZ(_#~l*E^%^DLsvK{sG$p-4Ak)WcMml@JODM+Mo_bjp@#lv=Wd(7 zji5%d{*PCy0kP5cuKcc)9zHIpL1u|_Iy%;O>e1tY8h?g>@j(scCP=&41w8mj5Y%+2 z%mH4rktM-voWoGVca3z9*$g$h8py&hi=jrJ4Ww+C!BC^mPG_jmRU`WYAq=;^d%)u5eONLl-z1sNwPN z9%^`a0BWd>peB!@hW=;g=FQJ*nw#JK`faVPi2k!sgLJE1u_dj2zE107>tF9^ZnkrS zxSM24n)`g6h^dJ=+++NCr$JMC*tsNs|^oSoaf$^!a)dv7_{GU!@{Sx{{Nmamg?o@M1Y}?C?%j}t9>q1I5X8HCdqYxr z6vqqPt-efw@6Y2=Tv_1m{G}+F0H;T>q=+qRs_&eXCkEfT<3E4#%XaLzcIxMsPc0vO z^Vx*>(F3Sw=Z}<)48DP1ykGtSRm-`$U5I~t(mU%`on#{oenZxi!hLnUXsYPU>k>`S z*z-qTzrVHB9?R`+WQ1({I$ajK?Ddt+&Guk!cV8o9+t-O?n;2Ka`6(>%-WhDM_0zMD zFW5VS&~TFNKxB8Y?vM2D^Ytd#_Q!Pxs{SzVKC>^&wvVelhsB*`+eg%%L*dS{?TbMU z26(em&W29M$OBNmn`1aXgn5gYs8#YyerQ# z#QQ@cQ(jh^n36E%yLI~1>4rR4)GwR5%&5m_M9Vi+lUVB>pUM%criAgDjZH1dm>PWzI2s>M>9>28g$US_;A>o6fAMiO4vH^P`b_#p6W7XvsGQipI)HqG9x_ zDY^#out@STCvm2Xq$iyvAJ+d_XO|b0J7>=l0($|)nvDe;Giz$9M70>MK6~{A?FH?_ z7py+JTFe%ic=<(3izp$;SEpy?tvhsNO@W}7VH!Ln%oY^pK&fNH1 zs;*yDv?#NFny8J}QuX|nqL$40(-O&elE$uUE^5xKlVe4^eC@)bg_*U};&`9o>Y2-y zHx)DuFF$8SHGPh%c>Ai=lU5I}S~{x==RG9|v&g61gepW~ls98jfO08sbV3K3MPsA9 z=~dlyHV2wT<6^uyta{6&HAb46Xf-H!7E~jWs>I7x6R8OWPJ+oKnT*zjFpE}T7Da1A zCADDh3UIOn^&#eEsj0DQL?tyCF&ghnJWdQP01$;FXEwrEyyRIJ4-% zUA|d#-(9|0^w?Mb;Ijz27G{x8hYHoZ!q^bTrf21{A!w>_nnfO43rCw+G_79MP4k4) zEDG?pM3W&LR=s651S9`Jw6+yIdo-b<*u5kOkqTGfB!b+N$!L`evuF-xQMA&9Su{Hs zt{+spIAp)3#;SN>7R?%!5+EM8DqkgW5W7@XTGcPiqUq6;1ePU>- zio6c0ZfU8Uc|(jy>=JQ2(wL+IiOoE(0i{a?9}_ROQo1ON8WALv)m3R&PBXXU209!3 z)++QlH$2)uR zZrZXB+jUMWcc6Ss5yMN{HgfB=ucGyRbF(uLC*yEa>ek=Bbok{h*p+cwZMNKN-uB43 zb8kJ-E|RAub?-uv`E{2lKegPMIa~L1RxGEF@a9cWz2qg+ckO9UboDQS*3-9ZaA;(3 zaB1Sf-yQqqCb7^^d-iPz=Dadl{=!A=f?&QYli<&j0YlVmrXCr=Y6K{HqUPq{3+gv% zslj+};}9LOCH#k=D=22-92OAUms{*Mqf=mz`d1yhcgEJ@*_Rv%0^ViF{IGGK@r=M4!_24obV z5#{BHnwtSBs05_tGVi^OU(|f8N5QpSMYNd-jsnZKih?6vHbrCP%wd6`bVe$75k+l6 zL~_IJ3^pPafR`JjXK<)FGx$12>LC@{7YP6RA0cX3K=D)bzjqKPTU;hM)J+sp>7U9YU1Vu zZ_ajgb1=JRkS}wvuh`^La09K*#fuAqxC_+C z(uT4YWedtql-p5up*)20eUxsL-6#i9PUOW76r!AgG99HBr43~*$`+KJD7T~RLU{<~ z`zYNgyHO6JoWSQRL^%UxI!Y}{8_HUgEhsxtZb#XL@({}RQMyrfqa38~)A<2k8To_P zPhFVT>6JhH^@E?^doOz5iT4ZMpYhiJtMBJz$d6Y>jMvnD^7Tp0d7WM%EczA7i!?Xz z_bC(xD;#T41PcB%ti6BLWuLli^Nwv-Up2L3)3sO7ITvDFccmm{ENN)72^}cfJ{&2#d^*|xe(=Y)k&gQ?9d%~u|s#F+>7!hl&_$C73J$FkDxq? z@~5M!O@8T literal 0 HcmV?d00001 diff --git a/doc/img/SoapySDROutput_plugin1.png b/doc/img/SoapySDROutput_plugin1.png new file mode 100644 index 0000000000000000000000000000000000000000..c0c10d9c4af0678fbdfb397c5093dab3be91c80a GIT binary patch literal 21255 zcmaI81yq$$v@S|0AgPj4il_)kNGdIeNJ@7~Z@L>qBoq)qx^EuEW= zH@D~9bIyJD-NzVvfV=+nuQk`4U(DrOMFlA$d}@3Q3=AUa=TDU}Ffa$<;fRL=&&a)G zO@m)JFJ+~k!f*IFlBo5AUsvp(YdK+H5RjrDm>7x4RPZFOv$VV(IZQDzn1cbE@Ue038$5y}54B2<-lwyc>04F z`G3Fa&+`BJ(0{!8e|+eF`^x|Eq0A1R{!8MTOs0)Th(ZC`6MP1LmZ!pB8L=v)R1NA= zF@G_Njj5rpzLKzhjnhUNHI&3BgQXTibGPl^xRx{U89K6*znwkVT5I`r#Aopr=gQJd z#2Kg8jqi74Xs*E5y{RfLru!53p}$3&k6R>YKQR58J5!E>wcdew0q2gh{%_x?>D%lcd2t?s>x^Y;P-y$u9~ejh8YW!C(B2zLjuw;=He?;vr$LXH>##eS%RjeAm!3@6e*k zGPj{GRbL)>bx2-8=6WV^A}gKq_3TBipq#^ zxX{$3-`V{_eX>~^eo#V?U4zG$2 z5|D7f9c|9-I z;>jOOEr~+u7yHtTcnn=;{pU5P?0N-#PkV27CM^{RPXW|7*@ zwY8_0%k^wgs*pLPIAN0wv*;_HMatbYRfeb8Pm}F$&wl#I^Co*=k%P8lq4`@KqHw8C zDMAYOghjZmr{q$ch-7SEbEA@z|Cm7N(n;D!q&A)sbLbPSp-gO)A$^;M?&k_m8~YN+ zf7?a-=--?yr|ni<_w^!18G3LBBpy8p^= zRoS^(y6WsCMk4LypR&xeBTO&5juS8UA-H_Yiu#_pEUPH4`qx~1VwC0Mi{;hDQ_{Y8 zdPTL6M3v_6Znj+!n}zlm>HN}3RJ4hP4X<7G-JA6y_!=XdMLXT1_F}#-@4R_TM8)~) z@X*~7@5&$|N6btYQ@Zx6^h8W|irwUE?c9RMI0bp1*Z1T%Oy}G8|2hw8RF+@q^rUbpCh$rFE$UZDYE#rF2Rh8j;{p%ZJtDUYS{p<)aKk{VgF_HYsV zVS@Xk@tMWEAJZe`eg+z3VQ!xq*Y>JuiJzKBpLiSFT)tnt#cS(3#aetZvaRYlv7x}I zAy_ww%CWE4mNCQhqmyNGJ7+1F&Uwr2sy#PNq_<8r)wxu&TeJIHa#q=~Fx$s^@Ivq5 zU~6mZ?eXb})d(t@RUtV5kj#B^!<*|?NVRa`=k*aEsM&GmVd$+F-a2NND zt7ugF&X4Ne?p>Tx)X|VSnWtd>Jn_+c@*tz)-(4dA-R1jlhN)t_nn&iXy7iRC>({vt zK748ztUUd9HD>0AA|1thtx^u#;Uma>G31vo4|Qyu8iEGnj)xTuo~I8#ewP`&EMGA6 zD>D%P#fwKi+A|Z?1)I%9oweSDSrv~BBvxd7tnxVSD6S^&xE>*p_Nzs|3S!<37pWzS z6qWilio3clxGi+BPj{d&y2@nb;q9Fz=(kIzv*72cwx$*ovN~^ko~;;HO@5SNKYJ

%kHpazTtd*TXT!?2nDl%q){49K_Tg~y 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

*i`;b-|b8+FawNE%W+MrS%t(G(by{G;5 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 VI>BUt<^h)kb-C}d63 +SoapySDR[0:0] Generic RTL...
+SoapySDR[1:0] Generic RTL... + + +If the same device exposes several channels they appear as distinct devices with the channel number incremented like: + +

+SoapySDR[1:0] LimeSDR...
+SoapySDR[1:1] LimeSDR... +
+ +This works similarly to LimeSDR USB or BladeRF 2.0 micro +

Build

The plugin will be built only if the [BladeRF host library](https://github.com/Nuand/bladeRF) is installed in your system. If you build it from source and install it in a custom location say: `/opt/install/libbladeRF` you will have to add `-DLIBBLADERF_INCLUDE_DIR=/opt/install/libbladeRF/include -DLIBBLADERF_LIBRARIES=/opt/install/libbladeRF/lib/libbladeRF.so` to the cmake command line. diff --git a/plugins/samplesink/soapysdroutput/readme.md b/plugins/samplesink/soapysdroutput/readme.md new file mode 100644 index 000000000..ac8225971 --- /dev/null +++ b/plugins/samplesink/soapysdroutput/readme.md @@ -0,0 +1,184 @@ +

SoapySDR output plugin

+ +

Introduction

+ +This output sample sink plugin sends its samples to a device interfaced with [SoapySDR](https://github.com/pothosware/SoapySDR/wiki). + +SoapySDR is a [C/C++ API](https://github.com/pothosware/SoapySDR/blob/master/include/SoapySDR/Device.hpp) that interfaces SDR hardware on one side and application software on the other. Due to its very generic nature it was fairly difficult to implement and specific UI widgets were developped to handle specific types of parameters. The level of control depends on how the device API was implemented by the vendors. On application side some parts of the API have not been implemented and can be left as possible enhancements (see next). In any case it is recommended to use the native plugins if they are available. + +SoapySDR devices appear in the list of available devices in the order they are listed in the API call to SoapySDR. If more than one device controlled by SoapySDR is listed then its sequence number is incremented like: + + - SoapySDR[0:0] HackRF One... + - SoapySDR[1:0] HackRF One... + +If the same device exposes several channels they appear as distinct devices with the channel number incremented like: + + - SoapySDR[1:0] LimeSDR... + - SoapySDR[1:1] LimeSDR... + +This works similarly to LimeSDR USB or BladeRF 2.0 micro + +

Binary distributions

+ +The binary distributions provide only the SoapySDR base library. It is your responsibility to install SoapySDR in your system with the SoapySDR plugins suitable for your hardware. + +

SoapySDR API implementation

+ +Not all parts are implemented. Currently the following have been left out: + + - Frequency API tuning arguments. The tuning elements are of course supported. + - Clocking API + - Time API + - Sensor API + - Register API + - GPIO API + - I2C API + - SPI API + - UART API + +

Particular considerations concerning hardware

+ +In general as previously stated you should choose the native plugins if they are available. These are: + + - BladeRF + - HackRF + - LimeSDR + - PlutoSDR + +The following paragraphs list the known issues or oddities. + +

BladeRF

+ +It is very important NOT to use SoapySDR. The default parameters are set to flash the FPGA but as this does not suceeds it results in a FPGA image wipe out and the device returns in "Cypress" mode. It is not too difficult to recover but there is no point risking the hassle. + +

Red Pitaya

+ +When installed the Red Pitaya SoapySDR plugin lists a Red Pitaya device even if there is no Red Pitaya attached. Trying to select and start it when there is no Red Pitaya will result in program crash. + +

Interface

+ +![SoapySDR input plugin GUI](../../../doc/img/SoapySDROutput_plugin1.png) + +The top part described by number tags is common for all devices. The bottom part under the "A" tag depends on the SoapySDR device implementation. The corresponding widgets are stacked vertically inside a scrollable area as there may be many controls depending on how the device interface is implemented in SoapySDR. Move the slider on the right to see all parameters available. + +

1: Start/Stop

+ +Device start / stop button. + + - Blue triangle icon: device is ready and can be started + - Red square icon: device is running and can be stopped + - Magenta (or pink) square icon: an error occurred. In the case the device was accidentally disconnected you may click on the icon, plug back in and start again. + +

2: Stream sample rate

+ +Baseband I/Q sample rate in kS/s. This is the device sample rate (the "SR" SoapySDR control) divided by the interpolation factor (4). + +

3: Frequency

+ +This is the center frequency of transmission in kHz. The center frequency is usually the same for all Tx channels. The GUI of the sibling channel if present is adjusted automatically if necessary. This control corresponds to the first SoapySDR tuning element usually labeled as "RF" and would generally control the main local oscillator (LO). + +Use the wheels to adjust the value. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2. + +

4: Interpolation factor

+ +The I/Q stream from the application is upsampled by a power of two before being sent to the the SoapySDR controlled device. Possible values are increasing powers of two: 1 (no interpolation), 2, 4, 8, 16, 32, 64. + +

5: Transverter mode open dialog

+ +This button opens a dialog to set the transverter mode frequency translation options: + +![Input stream transverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png) + +Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit. + +

5.1: Translating frequency

+ +You can set the translating frequency in Hz with this dial. The manipulation of the dial is described in (3: Frequency). + +The frequency set in the device is the frequency on the main dial (1) minus this frequency. Thus it is positive for down converters and negative for up converters. + +For example a mixer at 120 MHz for HF operation you would set the value to -120,000,000 Hz so that if the main dial frequency is set at 7,130 kHz the PlutoSDR will be set to 127.130 MHz. + +If you use a down converter to receive the 6 cm band narrowband center frequency of 5670 MHz at 432 MHz you would set the translating frequency to 5760 - 432 = 5328 MHz thus dial +5,328,000,000 Hz. + +For bands even higher in the frequency spectrum the GHz digits are not really significant so you can have them set at 1 GHz. Thus to receive the 10368 MHz frequency at 432 MHz you would set the translating frequency to 1368 - 432 = 936 MHz. Note that in this case the frequency of the LO used in the mixer of the transverter is set at 9936 MHz. + +The Hz precision allows a fine tuning of the transverter LO offset + +

5.2: Translating frequency enable/disable

+ +Use this toggle button to activate or deactivate the frequency translation + +

5.3: Confirmation buttons

+ +Use these buttons to confirm ("OK") or dismiss ("Cancel") your changes. + +

6: Software LO ppm correction

+ +Use this slider to adjust SDRangel internal LO correction in ppm. It can be varied from -100.0 to 100.0 in 0.1 steps and is applied in software when calculating the frequency at which the LO should be set. + +

A: SoapySDR variable interface

+ +The form of widgets is closely related to the type of setting defined in the [SoapySDR interface](https://github.com/pothosware/SoapySDR/blob/master/include/SoapySDR/Types.hpp). These are: + + - Ranges + - Continuous range when maximum and minimum are different + - Discrete value when maximum and minimum are equal. Usually this appears in a range list to define a set of values + - List of ranges: more than one range applies to the same setting + - Arguments defined by + - type: boolean, integer, floating point, string + - nature: continuous or discrete + - String list + +

A.1: Continuous range

+ +If the range is all in the positive domain the unsigned variation is used: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_pos.png) + +Note that the same widget is used for single ranges and ranges list. In this case the range selection combo on the right is disabled. The manipulation of the dial is described in (3: Frequency) + +If the range is in both the positive and negative domains the signed variation is used: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_neg.png) + +If the range applies to a gain a slider is used: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_gain.png) + +

A.2: Discrete range

+ +Appears with a combo box to select a discrete value: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_discrete.png) + +

A.3: List of ranges

+ +In this case the range selection combo on the right is enabled: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_range_list1.png) + +

A.4: Boolean argument

+ +A checkbox is used to control boolean values: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool2.png) + +For AGC, Auto DC and Auto IQ corrections the checkbox has its text label on the right: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool1.png) + +

A.5: Int, Float and String arguments

+ +For all these types of values a line editor is used. Numerical values are parsed from string: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_str.png) + +

A.6 String lists

+ +Some parameters like the antenna ports are expressed as a list of possible string values. These are presented in a combo box: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_strlist.png) + + + diff --git a/plugins/samplesource/soapysdrinput/readme.md b/plugins/samplesource/soapysdrinput/readme.md index 55191f7d6..ad4386000 100644 --- a/plugins/samplesource/soapysdrinput/readme.md +++ b/plugins/samplesource/soapysdrinput/readme.md @@ -6,6 +6,18 @@ This input sample source plugin gets its samples from a device interfaced with [ SoapySDR is a [C/C++ API](https://github.com/pothosware/SoapySDR/blob/master/include/SoapySDR/Device.hpp) that interfaces SDR hardware on one side and application software on the other. Due to its very generic nature it was fairly difficult to implement and specific UI widgets were developped to handle specific types of parameters. The level of control depends on how the device API was implemented by the vendors. On application side some parts of the API have not been implemented and can be left as possible enhancements (see next). In any case it is recommended to use the native plugins if they are available. +SoapySDR devices appear in the list of available devices in the order they are listed in the API call to SoapySDR. If more than one device controlled by SoapySDR is listed then its sequence number is incremented like: + + - SoapySDR[0:0] Generic RTL... + - SoapySDR[1:0] Generic RTL... + +If the same device exposes several channels they appear as distinct devices with the channel number incremented like: + + - SoapySDR[1:0] LimeSDR... + - SoapySDR[1:1] LimeSDR... + +This works similarly to LimeSDR USB or BladeRF 2.0 micro +

Binary distributions

The binary distributions provide only the SoapySDR base library. It is your responsibility to install SoapySDR in your system with the SoapySDR plugins suitable for your hardware. @@ -63,7 +75,7 @@ The top part described by number tags is common for all devices. The bottom part

1.1: Frequency

-This is the center frequency of reception in kHz. The center frequency is the same for all Rx channels. The GUI of the sibling channel if present is adjusted automatically. This control corresponds to the first SoapySDR tuning element usually labeled as "RF" and would generally control the main local oscillator (LO). +This is the center frequency of reception in kHz. The center frequency is usually the same for all Rx channels. The GUI of the sibling channel if present is adjusted automatically if necessary. This control corresponds to the first SoapySDR tuning element usually labeled as "RF" and would generally control the main local oscillator (LO). Use the wheels to adjust the value. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2. @@ -188,7 +200,7 @@ A checkbox is used to control boolean values: ![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool2.png) -For AGC, Auto DC and Auto IQ corrections a block with the text on the rihgt: +For AGC, Auto DC and Auto IQ corrections the checkbox has its text label on the right: ![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool1.png) From 26af3014a520c707ab252fe81f3b1ff2ac197dc8 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 22 Nov 2018 17:03:59 +0100 Subject: [PATCH 075/102] SoapySDR support: make checkboxes more visible --- plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp | 3 +++ plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp | 3 +++ sdrgui/soapygui/arginfogui.ui | 4 ++++ sdrgui/soapygui/complexfactorgui.ui | 6 +++++- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp index cdd528ce7..07d67a66a 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputgui.cpp @@ -225,6 +225,7 @@ void SoapySDROutputGui::createGlobalGainControl() { m_autoGain = new QCheckBox(this); m_autoGain->setText(QString("AGC")); + m_autoGain->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}"); layout->addWidget(m_autoGain); connect(m_autoGain, SIGNAL(toggled(bool)), this, SLOT(autoGainChanged(bool))); @@ -280,6 +281,7 @@ void SoapySDROutputGui::createCorrectionsControl() m_autoDCCorrection = new QCheckBox(this); m_autoDCCorrection->setText(QString("Auto DC corr")); m_autoDCCorrection->setToolTip(QString("Automatic hardware DC offset correction")); + m_autoDCCorrection->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}"); layout->addWidget(m_autoDCCorrection); connect(m_autoDCCorrection, SIGNAL(toggled(bool)), this, SLOT(autoDCCorrectionChanged(bool))); @@ -304,6 +306,7 @@ void SoapySDROutputGui::createCorrectionsControl() m_autoIQCorrection = new QCheckBox(this); m_autoIQCorrection->setText(QString("Auto IQ corr")); m_autoIQCorrection->setToolTip(QString("Automatic hardware IQ imbalance correction")); + m_autoIQCorrection->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}"); layout->addWidget(m_autoIQCorrection); connect(m_autoIQCorrection, SIGNAL(toggled(bool)), this, SLOT(autoIQCorrectionChanged(bool))); diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp index b96f3bb71..baac02b5a 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -226,6 +226,7 @@ void SoapySDRInputGui::createGlobalGainControl() { m_autoGain = new QCheckBox(this); m_autoGain->setText(QString("AGC")); + m_autoGain->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}"); layout->addWidget(m_autoGain); connect(m_autoGain, SIGNAL(toggled(bool)), this, SLOT(autoGainChanged(bool))); @@ -282,6 +283,7 @@ void SoapySDRInputGui::createCorrectionsControl() m_autoDCCorrection = new QCheckBox(this); m_autoDCCorrection->setText(QString("Auto DC corr")); m_autoDCCorrection->setToolTip(QString("Automatic hardware DC offset correction")); + m_autoDCCorrection->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}"); layout->addWidget(m_autoDCCorrection); connect(m_autoDCCorrection, SIGNAL(toggled(bool)), this, SLOT(autoDCCorrectionChanged(bool))); @@ -307,6 +309,7 @@ void SoapySDRInputGui::createCorrectionsControl() m_autoIQCorrection = new QCheckBox(this); m_autoIQCorrection->setText(QString("Auto IQ corr")); m_autoIQCorrection->setToolTip(QString("Automatic hardware IQ imbalance correction")); + m_autoIQCorrection->setStyleSheet("QCheckBox::indicator::unchecked {background: rgb(79,79,79);} QCheckBox::indicator::checked {background: rgb(255, 157, 38);}"); layout->addWidget(m_autoIQCorrection); connect(m_autoIQCorrection, SIGNAL(toggled(bool)), this, SLOT(autoIQCorrectionChanged(bool))); diff --git a/sdrgui/soapygui/arginfogui.ui b/sdrgui/soapygui/arginfogui.ui index 62fd6dd1f..523d6e140 100644 --- a/sdrgui/soapygui/arginfogui.ui +++ b/sdrgui/soapygui/arginfogui.ui @@ -50,6 +50,10 @@ + + QCheckBox::indicator::unchecked {background: rgb(79,79,79);} +QCheckBox::indicator::checked {background: rgb(255, 157, 38);} + diff --git a/sdrgui/soapygui/complexfactorgui.ui b/sdrgui/soapygui/complexfactorgui.ui index 37d3d9175..d697b951f 100644 --- a/sdrgui/soapygui/complexfactorgui.ui +++ b/sdrgui/soapygui/complexfactorgui.ui @@ -31,7 +31,7 @@ 0 0 301 - 48 + 58 @@ -56,6 +56,10 @@ Qt::RightToLeft + + QCheckBox::indicator::unchecked {background: rgb(79,79,79);} +QCheckBox::indicator::checked {background: rgb(255, 157, 38);} + Auto From 2e709bdd13c7dc7f018efb403d97958ef0e95e1d Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 23 Nov 2018 00:24:42 +0100 Subject: [PATCH 076/102] Fixed find ffmpeg cmake module --- cmake/Modules/FindFFmpeg.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Modules/FindFFmpeg.cmake b/cmake/Modules/FindFFmpeg.cmake index f97cfbd58..3b0bef249 100644 --- a/cmake/Modules/FindFFmpeg.cmake +++ b/cmake/Modules/FindFFmpeg.cmake @@ -137,7 +137,7 @@ if (NOT FFMPEG_LIBRARIES) endif () # Now set the noncached _FOUND vars for the components. -foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE) +foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROC SWSCALE) set_component_found(${_component}) endforeach () From 8a6ee37ccb1164497f4557a95931d701342a73a9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 23 Nov 2018 00:25:27 +0100 Subject: [PATCH 077/102] SoapySDR support: updated documentation --- doc/img/SoapySDRInput_plugin1.png | Bin 29135 -> 29136 bytes doc/img/SoapySDRInput_plugin1.xcf | Bin 125300 -> 127702 bytes doc/img/SoapySDR_arg_bool1.png | Bin 1456 -> 1440 bytes doc/img/SoapySDR_arg_bool1.xcf | Bin 2921 -> 2840 bytes doc/img/SoapySDR_arg_bool2.png | Bin 1837 -> 1805 bytes doc/img/SoapySDR_arg_bool2.xcf | Bin 3677 -> 3455 bytes doc/img/SoapySDR_arg_bool3.png | Bin 0 -> 1432 bytes doc/img/SoapySDR_arg_bool3.xcf | Bin 0 -> 2822 bytes doc/img/SoapySDR_arg_str.png | Bin 2993 -> 2294 bytes doc/img/SoapySDR_arg_str.xcf | Bin 5461 -> 4858 bytes plugins/samplesink/soapysdroutput/readme.md | 4 ++++ plugins/samplesource/soapysdrinput/readme.md | 4 ++++ sdrgui/soapygui/arginfogui.ui | 3 +++ 13 files changed, 11 insertions(+) create mode 100644 doc/img/SoapySDR_arg_bool3.png create mode 100644 doc/img/SoapySDR_arg_bool3.xcf diff --git a/doc/img/SoapySDRInput_plugin1.png b/doc/img/SoapySDRInput_plugin1.png index 5abf4f7d35374cf99d1c3fd6bb8c28310fafc084..a3f29bdfbd5faee2bbe372fd4dd108a8650063b6 100644 GIT binary patch literal 29136 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 literal 29135 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 z]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 diff --git a/doc/img/SoapySDRInput_plugin1.xcf b/doc/img/SoapySDRInput_plugin1.xcf index 51ace5345285806fd71cf8b4d66a03e52782c5df..1068f3328a469c487283f0dbbc2a0ff406bffbb9 100644 GIT binary patch delta 4218 zcmeI#dr(x@9l-J5VU=AT8f+91EI|-KnOeB`*dPL05&k`%O`fIF8$^aTi;RCtWWoZGDgGi;t3+m86iKKN znY&$N-c6C5k3|+eE|Qll@^pbn(It_RR8j4}6uqb$n`|Gd5Zi&d`Hl>)`6}`aSF=bE z?|~R5VqjWVakm+29kqr(cv-g%w5p>_vx_=Iy%{<_2^m;4wBJ}FV&ocQ1sG?nMH5C6}vXNwDc zaMUAuFJ&yqT<8;yCqk~i>64j>?-cu=vyV`i=k~X{f_>aWd`fAfo4xW^r7E; zfql*0pYaLK4DF9)@5gdY?6Y88><+w%ckpZc4j0jhUXi#FBHAGw$0-n+){Y*Lcs~N4 zc1>j39g*oi7>CJt80lDob$A}HU^m{z2RMnp;2Q1_s1L?rG9E@cmS7#8$1B*4xAg_x z&lkI@&Jh^*x>3K8t}-ZR=K7&+=F^VT<_a%s!9erioXy(KGhi*g3->1U^d~MAN#vTu zQZO!Y4-VltPT@S-(IYbZgh@C{FT3+&^h-+=p&Oo%Bj6MTxD%0X140q1ZPw?*a{ zF&0sniFsIzwRjFM!;XWfMgz{_DsB_J5n~aBnV5&g`ho}Nto+#QCB{ge6t2Q>&%-OV zaA;fVX2<5#$YIuB3^aREqHnXbk9l0~1Ix-`H|xdIpZ*h(bgoH%4~$FyBRjf#tIZ+3w8=+aLURYlQY)&MB4Or%AlMrJUGzgXn4gv&Gz%yb$Q`@k9F;-xjfOjfJT#^jl_P9u{M*$dWa9O(b_0*jl+q!Pd$> zBeJwriRJ4AcSGyB5L@d7lfU!XTUyh8SEIK*E55Pf*e+fVQUUg^FcqXm*+)!JK?ZNF&we>l zg;R0bb0(-TDtGMl<5k!Mxv70MCVhZNt%mr19y$6M=xe)F)MPCU&>ulO^Emd^H>emy zN@MxwwG}(Sk3YS5`b*yv*}~0_?yr!FsGFgpx{u)mn)D0q_p6&-^mpS+ z+(jQ_$ac3kd@&MVLm+~o&lQeIn1ZR$FarrlA`9JfsXPj9Pj@E1jYY`Cay*4KSdT(% z#P?Bx&3F+nVH;k>Yj^_{_$l_|0IKk=z8o^p?_uv~Q|b2JHf7dd#@nY~Q_24X%O5=M delta 3000 zcmZwJ4NR3)9LMqB;et>oQbV&OH1QG%A`y|r704JxC`dX(1c`;zlmMHvEz74Db8VX1 zFe(+SX7(bXcFo!(u`*{#qRvH>85;XT)33bD5d-)-PI&bUM1c8hm^lhnpq%~+#@|) zB~>4nInFiB{CtD=R~o_Za65v)(RYvLM**nm394{s1>_j#T02A=7#S!z_-o#FIp)~q z-r;BsuvYd*%{HF*GS>_p#L&pe$VH)lfAA71n0tcj!MNaEIDlg~gG*9K7^0AXG~{BA zbk*zl6eN9h5N?sI&@w4>p%nHER^tt9#ct`E7ErYa5B`#dg@E}FizT&WWJ=fXM2B>P z12-c_8u>X6<2ZgJ391u$Eyf_pPROGEUNv>uFVj8I?B-j$F=M4$PJ!u;`%nLvUMZSbbOaa|O$yPOn1M1Z#8Rxm zMr_9(9Fd%lg0eVyZcGMVB!SpSDK;K1OhFMU@Dx^HJsQx27PR9OE-=Bth(tVGn1Uiy z;3=%YdNiO3EoisX{r}n>iVg~KvJT$nQ@gm|{bTVC_xZSDhgI4i_O0E7XE_k;kCdz3+rt@b(_e-`^F|7akord8(>xSM}6y-x{4Rbd^~~Y{rg=dl8bv>78vK+fGuc7 zD>`r%ebOY3P1*~11#jacd$|B;t^Y9L%;8`fuIB-4|T5f}Olnyv?U>nUDL&GM{rlnduC) z-t7Z`Q(<*7Ps3#fA(uqHuq$I0>)*32M;)Z_lIBvVx^pir787j#4a4b zF`SWd^QAn_a2`u(<#CAfy3i|43q%CQA{m*Ofif(_Qmny7Y{woPK^J#}>Ua=vQEXg>9tzPUd%5SzZ!?Vg_JuviMa4b;Pa4L-=Sl#GJ? zdxwAjgDhVG_Y|;v1@srNd<8jR`3mMsv*w{zDr9dJvbPG^TZQbcLiX0|E~zM7D(2b6 z6Ohiti}ScBK@}{l!Uk+XGg{Gsv*?rN488g$>w(X0)OMXVFJOL+ymF z)Qj&zg}b7lF2u=q!`pmnRvP0UD@}1Hl%5Q*_`KN7w`OIN`G~VGs=r2?fB#$_J(qV@ z`4HTRxp-N6Adq<@vc1sJV=U}tc86=(Q zk^X!^x>za`&?$5ENSVlFnQ_x)?${ucS}QZTUgrK*nW7HeY@T>erY2tItv6&E82sVi zGQ01R+4rr?;df-d_sASge}3!YkGC#1Z&h2z&)J#yEuHBcF4KLE|GNSZ=GSjJyJb4* z>ly^cb;TeBS(u4(EW$F>ViR^?FWS(Jb229eVYn=FB8H0;WML-Cu?Wjhi%r;py=X%> z&N0D37>*dEAPX~5jzw68T5Q4&>_r>8?Suxl`^VExn+AvVGvE6wo7a$alguyEP=rVQ zE8tln<5`V0cn#}8wLKg0E*h{E+wlo_mS;EiU>{m=5J&JG+Npx)M=rX+@_0_+SM=g9 wTwoH+@0UP?U@*cFff0zrXpBWH;*p4COoR&=$i#h^a=8M1RKe@je|k*&zZsEvKmY&$ diff --git a/doc/img/SoapySDR_arg_bool1.png b/doc/img/SoapySDR_arg_bool1.png index c9acf58168bb226ed2476ea6703da8f067fbc917..813adb017ae942dfa0a091060c6124cb05d9d74d 100644 GIT binary patch delta 1415 zcmV;21$g?f3!n>IiBL{Q4GJ0x0000DNk~Le0001I0000L2nGNE09&i@GXMYp24YJ` zL;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jUAB6%GIqlx1#_ zTP%MBNklEi2xLf%K-8l_2`ybhh=dD*x(II~jbbWub4}>XwfEws!@KN#Yelc}a=x&O z=Q-#3v*-K#p5O2MG@8{jScglNavzgA$P8<#gf*`Q6vcmNAG<|)2B$LVi|H|36Z5zjq9pl!mTeyGS z?jN=j1c8o@j-QTu@7_J?>gsShopg0|Q79CML?YO1HURW`J^lUtSglrkJ|Fe<^>lW2 zVltTshr<{QhW|e~hYlU$_3PI>eE5+4`}bouo0VtRu3f|H^(wN%;XslkbUGc8NCdOl zj3i0y-n|=(#lp>-H<2WXk&zL4dU}5_8jatLpU>xc^X3h`y}dkt{#=RI+S*E4Ss6Z` zkGZ)yWLf6z+qYc4e3?ijf=;K~;7hO9bLrA09zTA}`1m+oU0rCkf0gjSfdkyVdlyNP z7#bSl)TvX7-TnLbIeYdjKgHs)+@E{Wt z6XbHaqIcHU*BKrjCX>l*uy1c~$7Zu}{P=NNT3WE%?RY#MDk>_tapMNza2Qb(@p`?S zIdevdCCf53H8nIhH}mMxBXWPa91RT(_q0r`#W3^hb*=)?r%m6SpHb!%EGa8Mi zBtI1u71Y$!5Q#*TKPyQR4u_*8KbcI1^73-DS}i7%iKV5blI$BA8WmNdepK@Ndu{-!REnyqsv`O8=bN_Y=yW<tvH=dBN7D6FhzT6o6;Xp3&6Qv|-=UYPIzA^kB7GH`phW$)X$tLBL|M zu)Mrnr2kfag+lQa=GXFnN={>ABa4fR%+Jpk=_e*8a5|k-R#uWoB$V#bYPB3adbDWv z8w>{YdOg`}mf6`^+S=LxC@U+&?RFE3#lD+|Mx$Zp&Ykr3_ELXcUCo_4cK{d~8e(;I zmA<|{_U+q;!C;`Os)|r3#NNGoSzKJ);A?Vn61Urp(P+eAFmV0)bs8HRiO1uZOeST_ zS}Ych963@nF}Boqjwp&mqtS16->X-zaJgKJjEoQr1__75q|<5Q@i^7h)d0-R&GG*I zd!o@Oe!rh9SFV3>@!~}!NdjPIW`==*fq#tO*4Bo{<3X#{lF4M4o}T9P>C+?<2>{mC z);M?W9OuuUCm0MWojy4^NgxnFmgNmT2L=WZ1c3(+9w5syQ&Uq64i1vf=kfdf`2Bu- zJ|Fpfp4+!?6OYG#sfHT6-CoFMv+UWkN4;B9uWwY8Jk}%B6`-yh6)HI@IVyfL{sgLX V{uwED$0Gm$002ovPDHLkV1l9cvI77B delta 1431 zcmV;I1!(%93$P1YiBL{Q4GJ0x0000DNk~Le0001E0000H2nGNE0Ljr3UjP6A24YJ` zL;wH)0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jUAA7XmK_!EC#c zTP%MRNklbI3v_{<+J#waZnzumgjg z^ZS3#IXmCO`R#v-s;a88D=RCMmX=bG?UjE&*1vrI{FzK9lNVSJ1a|D$QK;g7O-3e@ zL8sH@1^)8oOQC|BK?Xo^adDv{zY7_gAug8-r_)JSR~IugGrx>$Zf<61XejS^KA(@n zhYz#1wnjRgCK`?M^5skV`uceP{=NE~(P*TjqXVneiYSUKEiExMHAQc4FR@r`TgZP9 zHq&`=aWTh^9pl!mTR0q!U&e`|NPBzxzm9wF-aTq-Yq8mEbar-<&1MM(gIFvU0JK^y zeSLkH&1T$gH+6M&baZrJFc=5~0(p(@Md_>lek_hU2~)w65YuHkaI zRNZQ|BFi!wjfP+_h|y?7mSy(r*@J({Wa8${o5-@v@bEC*-QDQ*`k%&6r_;Q7^M;dv% zP6Xkv@*OyEfV+3^BFi#^gM*wpbxOtEzki>zXU{S=Hb!G(BVMnU3l}ahFfe~WS6A28 zk>PMS7#SHMl}Zr`g|OT0KgFa{DZE}U@pv3bl9-#D5u@+4-nnYOmJ zymFCcncCV~01h5J$oTj;sZ=WGnYFbwhK7bnCX*ZRZEbB>EEbL*KTdOVGgVbpIGs+) z%F4KL;|76107;T?xm=t%b4GuSr6>y3)zvgLHSy@tBT}gp_4W0*-ERDT|JIOUHk+|n zEKE;N128%|N>fu4MMXt<`6(+aqq@49U@)luI9ZmlTCI8cNhXt&mX;z20tSPDg@uK@ z@b&fejE;_?C9EhUGlP6D9n_jP{rluyZi+tzKod7H?EvdFdBB9#zX^vPdMkbRX z9*?tY*RH(q<>lopFE6Y5r%#{M{QjOBKs+9&qM{;4|Mq;#?hK7agWYbYrKJU%&8B|* zem{~Vsq=h&<^n(50IYv^uqcW-|AZD77xT*L#EBC;efkuDXV0F|*x0z?-Vp?W?(S~P zX7dJoEEdbjK@>$yCKHQ`i#hi1<(JK7bI!ljHmL-8!8Ptyas*$_g_xGqkq00#H&?g2Uk;91ef~G>@X9B6jcIO;1k` zm6es;xpN1A!NEb6mzU}7?PcG-edu&LDk>`Q`~B?QyO;U-`3=4%CMIw=9O(6WbUGc^ zuV1I3p@B#wg27-=$EL|-;>eLBITK-9-!mjhA`}XJx4T}wdWGF?XLxuRpU+1i5Fn9A z5Q#*ntgHlJc6NW34<9}d3We}^JY2bQg^L$2BFi!W)6>)R_xJxWerszhPNx$=5J)DI zOifL3`t)g{(I^0`tE-$lcaHPt&*Ss?)J~q5n854xqA1D+pZ)#)h@!}Y2Mm9y}foZnv9sI?e6dw~0g|dDpFIeNp&NqvA71Qdlr<(i^xS2&|Km&!Vs( ln?Ock`?~#7Xzkxf{sbhb2ZApi?dkvk002ovPDHLkV1f!ft8oAT diff --git a/doc/img/SoapySDR_arg_bool1.xcf b/doc/img/SoapySDR_arg_bool1.xcf index 0df4d94c59779550016e99aa16ee4cd4db68954d..7ec5246e9cd1ae1d639723dfb2a4062cd050e271 100644 GIT binary patch literal 2840 zcmeHJPfQed6rNoRqDa(MduW<=PJ#y-{8+jRUBLG7y|j(QrlJr*Y?Y)ka(n0X|$ zRMMIwQ`vk^!0(sp!*nii^3C#~AvN;izXO);3+;A$ zlzLfQW9&u2$Xr1^mcOT735!a-r%np7KH&9+r0`!C$m)NFW+Q)>avyZFoHY=w#(cP= zIo0kEH*}LbA_bYl^I*#)=lLYbvvkaYMLMQMc-Mp%n{c)XFEQa96JAP~>l(I@0Pn|U zel}(!f_0Y;jEg6(^`IbRbA2{FZvBqRzQciaD9zQ7i?x`^-Lhm$!CXrgrkf{aEW%6^ zvXSW4rd|x5uYv{B^MqPr`BI$28sl4812(^h^v@4cqY9 zy+XY_^UIPOfW5Iae`nIxcSz@JKTSQgJRR3$lVDrY4%9tP3qFtIdTUCMfoc1rYP#R? zFMmhZaiBrvE!HMoK%_sdi2j0al5zz$Eh7mgG$ZLbZ}yR zsPvHWh~|en|EB(@-_*v8b;(s&mD?yZW2$51)#%v@ypP1S?T)S8_e<~|X6*dVf7nz; zUz1TsM|`B!2G1RJ;2Yq<(UHi{r~2El6l2GF9nQY5$|i!SjPJt0)nc>{Z^SaZ9B2Sa zi$nLR%8QQEh#dq@|Aytz;y$XVHQnOGv5Sa>DA9&Y%s6>NTW1xeU-s_@DqO(_Oghts zSdd7qL`wXzqhwppT?c>SzQ5%xx%qYJL;$WQ-ZW*Zee~5(3xD6o9qmuX+KW(gdocC| a3`V0cf%!ZC|INH{K_UMv6_WGMknks03@yz7 literal 2921 zcmeHJ-A_|z7(cB{5hR)f^+XLCE$8 zf^JFld)-QPPDZv%c6!}jpO`&8i>pjBJWE191>%%9S zRq62afqv}>N8x%1t)@dQnKnqwMFD28UrF=d#ha*zjuDKl@%Gy|Xq3o+R= zCSx(C8jy)Mo!Z2BFB{_n0J9a`BFqK$SoqhQ;gV_RU2+|;oK z_Fl6LmjaiX0IzBp)YMA*bv1I%h6T__W5jsZRUGZN=ry-IIMbNaK#BsPGqB$NC8hDa zME9?l)uf@nV!({;57#CZVo^!_OJH9(CHf|A?m40tX{RS%7+#EMvQD)%ZUJhZrBnx^ zxYd$UEx@GZX(gS;$oGGt;}lS*@?yntI}q$m$wGhNSkyMVLwee}9(vl5vNs!>uEE@; z!tu(A?q(E*ekK*4-`dR`Q9EprdwNyqIAx!Nj@s|vxqd{&y52FT{clxmEu=8l=Izst zOK|_Vuy80=c6Kg zipkF#N~l2%S=*z7EoL|$sC_>IkB<)qFZ|ZqN-ci)WVhAU^FzsVAIhV<(RZT|Z3ACn z310Wr0qYC>kEjogx1UA$AaM3FvY|V z&i~$uu#fUB)Yv9=6>aVM$IAWkr@OYIJBQal_rgBvN-<(XvHoU$iHum=Mu*!9P<1~N bK7=HpUTDPpbADj;G;ZUsuYB_9FQtD0kIFw% diff --git a/doc/img/SoapySDR_arg_bool2.png b/doc/img/SoapySDR_arg_bool2.png index cefddca78fcab78179a6af62d0515d920910bab2..5ce78c973eac320d469af795030d198059ebd6ab 100644 GIT binary patch delta 1783 zcmVy{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jUAB6&5I_I#tb) zTP%NZNklgu3MwEVfWpE;8X6i91cCbcdJF~wUS3`R7>!2u@89p{M6Fiy^yyO+ z3dK(c;NjsxR#q0*uV1INwG}}SIDPswixw^VA^W^iuwcPY`O@q4w6(SU(gm6~Zyq^0Ij+wplZlFo3Q0LXvMJYSG+e!U zm64GV00ssIIDGgp9v&WUhANecii&>!=iGBPrPkB<+5fq?`C1##-ssb4Pm-#SAzHa2qX*fBCQGg-KBA#%AK zyWP&<;NT=9g+hVJWI_-Gs;hsiCp{Y-DTyv4TyTHn|NR6BEPp z=g(bYnn*)K12&tDS+izQR8+);3m4eDc{4_%k^KC8{QdpEJ2{O;LuzU&TCJ9~YuB=2 z!v+Ax#>R+_jwU4~1*_FcWMm|}ckd=ACx^tuM4FnKFc=ItolcBKBX)ngoz&D+Y&P2@ z{{;mF^z`(QnwrYity>8W4rb@hod7tUPU7R^DJdyo&z?Qh)YOodmp8LYUU6|TCXBK&R75Qc@BvEiHclw70kO>C-2IgM+_2xog+1A&MgJ-o2xxrG@3omjfV*B7z_= zIywqKM@I(<2??%P9z1wJXlUrPzEvs}(b3UVR#v)1YOz>Yvu2HJj7N_iF*Gy;KzDaH z^XJc>StU;tMXXjUR;v|&@bGZ9FsElR9lDtY=-jp_jfBxU$anncsQP(o&Y>~ z@`P>Mwy|T!4kCXeBd6WWe#O_<*Y!=E$is&Z(P%V8L`1kf%gV|kE-sFhD_4@6n~T9< zK&R8OefxHtPUjCz&ezv>QhTC^L{W6LckSB6;>C-}$;m;d(@|Jh_+8&$v)ROX`uX`y z67h^b<>lw+qu1+Q*93lkeq>~1(9zN1+Nj%XHoCjJDJ_33<>bke%$+-TO2^5`$pCnJ zd$W4=>M1v)9UUFqy?Ymv$;7&K>+tsW#^2wc+}vDrIvu^ey#xjZVz=Ar>+3@%lcCe; z09-LnM@mYHtF*?&#qs#@<0<x|-0?Q1p5| zuV24L5Cr=A`lzj~<;s;S^!4>|=gu7p3JTC@G~a)`+xqh53%$L)n9XL)W;4yr&EI_4 zm6er5Mn-bu#tq8K$}pSFyn6MDnwlD3ym-NzH*aWcY-HK8Wp1&DgoI$RSTLK-ynOkR zOP4OqXhF$-_5Y#NYPIVM;qTl_N&J71e#?{i{ZDxkGnfC(G`~&BlbG2^B~L;Ul*I4L ZpNtd7nB_oNeenPQ002ovPDHLkV1gAHRPz7; delta 1815 zcmV+y2k7{X4y_JbiBL{Q4GJ0x0000DNk~Le0001;0000K2nGNE0GF9R#sB~S24YJ` zL;wH)0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jUAA7X}_ObE$=q zTP%N(Nklf8^=GJ|2DPeLq4n*rY~$kDN$OKT0usUO5hWt#5Q}-GAkm8 z0=Ej3LXnwNP=e8eIFnjhVNP&T5>{5=3xysOnv#TClbTbP-v3t(_tUH_`u~5w-~D-Y z#(mCpu5BX=rG`VzE$PUyn|w z!`s^%0KHz%!Gi~<7*Q&fJb(TinM^jTg=S@Car5R)T3cJOSS*}9dzK|jmi*B8y1IWl zVq;_7+P~t@bfl-JyV~E{1Cd#ZuCTC>&!0b&l9EDvd^{SBhOn?OjvYHTqmlmpel~C3 z%-Go2PdlK~=}1marlh2VjT<+To}Nx;XD1aE6)ak`=%;LHwOZQR+J5T>&7VJ?oSYoj zZ-c==MMZ_EoZpp5s8lMhU%!sS;Q)VNU|@iwM~_Y$b`=T*6%`ejOeUI}o2jp_CnhF_ zz`#K2>gp&hEhRQKmcYP3+S}VHE-q$#eB8}OL_`EhNl9$mwvF!YZUBadhbb>F$7;2@ zM7(Cr8V(&gghHV}5Ckq?zD#Xx?G&G`UcE|DQ4w8TT>vB{C85!1P$(2MH8p>^e5k9d z_sMTu9%E~aC&17a~l9rZ+TrS6Evr$x3L}zCwm6etF`}<=unK*p-Fj}n^o6W|# zbLUVhl^j2QoUpJk1VP}%ix-rZmNGm%j9#zD;c(#V>q}5j5W&I0oH=vmx4#sB`$*T= z*vN?!C&1 zR?DhYtJtz-%aqAuVq$pt@})~~lWAyZz-qNJXU-goii)^&=@MJFZbh%xlb@eYKtRBE z7pGFGNKH*etyZ&s{dzWS+62JZ*cj2#(WIoLU^bhHjErRO-o51H_>BtAZ#l9Cek?b}C9 zO$~W@d19FRtLTc0i!m4sEL*mW3l}b6u~;~D>J-7j!ER}CK|ujsU0qzfc=4Nt@7}!& z!06~Gt*xy@M@LWTnh?va-@8WRuCn zx^?SZb3A$SgrT7!0J^)oS+HP%sJOo#uYw?8Hk&b<%>aalhqHfw|9;M&KaX0i1|T^( z8JSE*d3pJahChA!=jVFkC-eC6V^k^?5fKqn zo@Hfa5f>N7>eZ{s&CNxp)1lF5*tv5jPN(yS7U$>Z=hmJqG(iwt?LB+;uypBCa&mIe zXfzZS7Jk?E*Qhvoo&Ns*ZbBFNf#WqlKOe1D>nf4>`}=>Bk&!`1M~5r9uv)EjcXv}- zTFU9ur(Ezx7oQaf_6xT5x7Z=CVr%$Kt7ZemkPfrgHhXXG!FVt!^ z5{U%4T+V-&FJJKV^qf+DvD@vmwY8CvkpX~QE+;K54U5Ghs_I8YH#j&*c6K()moMke zojW{y_>h{K8pg-RIdbI4l!3LiwRCoNqSNW7HT?eld#b9csIIQ&!Gi}hHa1S%@8rpo zR8>`xmzRgxY^J)pn$XZtv|251-@e6SvC!AoM{R#?E!VDHqpz=zd-v{9P*8wMrTS*= zZ(?GC-rin}Mk7X}k>=*+ZwjKavXaQiNN(M_MOj%HMx&88Z{AQ-Q^TuQuXy+F9gU5R ztXQ#Pith^-F2rOqVKf?f{rWXmu3QmS^&KR?`_m?+Qt2w6%%*N9^1op=8knta#J|Br zTvaoP$%)U8j``*6Rpj5xY`zxxzd2q-M1CrJ6%qLp{1^K3rAKikgnR%1002ovPDHLk FV1iyoX@UR% diff --git a/doc/img/SoapySDR_arg_bool2.xcf b/doc/img/SoapySDR_arg_bool2.xcf index c58e325245eb30e1cf9efcd3d658ce458e50ecd8..f8d61b3d9df6a0f190ed342a279dd24058a184d1 100644 GIT binary patch delta 375 zcmcaB^Iu9VJu|mJp&~g=AuTf}l>rE*0I}FcvDu8QVAkYqj5~C}ETA|G0|Qe#0|Re5 z5Ep|K0|8WyX+8r3=M4r1o~@H-GbvAA&&0ZUACnE!etz8~)cb zo}9da>mBQ2BMeqOPzrFm0Ojm2VgLXd{jmA~ diff --git a/doc/img/SoapySDR_arg_bool3.png b/doc/img/SoapySDR_arg_bool3.png new file mode 100644 index 0000000000000000000000000000000000000000..48995034ad5de0974868bd55e886125495be7506 GIT binary patch literal 1432 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 literal 5461 zcmeHLZA?>F7;Y2xETW*bIxAb8!X~oda=vlnP>j0y?RpKQ9OYCJ5WvSETOVo{% zP+fNM%N0i5k-bHgtjS6fFLm`rjk%LGI@|m|$K=Zpu)*ne+w zv^-B` zP0(jg(C19h=T6YQNN0XsWjZOWKUOB@hNDFwN_QyZ!4p<=fYN0tNeGGZdAq2bLLCqY zSXi@*C=ctI{n;Xf;MJ?Ai!d<8jpz?!Iz}Wv4Q$u+Ho+6-sEdyWx+@i^D#aXF2&9E% zgEi|$3=FKj`hbxUYg7UIII?lZ^Umjg zve|-~5+JY575(XQ3fjsZWeRMOc@(l`9lwnD%bNGGr`Yn446Tl?Lu(sx;zvlYjHh=Xp5G#^qRyt;{XUt2}4?kW1R5PUw7=wlq$ed1)>^ z(G_Cag?MucE`1ji(-4mvRr2ur$FQpH%OQe{1vYot8CCjmhApg+eN;5=4do&TGMpa) zlw3wkRFa)hdgkYyWFJevd(=r;085PdgOo>y+y5*kf>rkWZnpaqT!f*-wqU~JUH#h6 zo$&b>j=o2|lGrV9;?A}DiVWlkuI8%-lEr)1?91N48+hE}OOE2~s41?yI8*~Ot#9Hh1wICY9~-l?&%xH6^|!uI-V18!(|AqAL=SXC_l;xIZHE+a-%%Q z#jx0(r@Z9V@_~Zh2|se~$bbUDUV1a!`QXk6cRsk+2eu7NvOd`Nj7nIQyc{!O3*Ux? z<2O5M>84G|?{4oamo?BvA?ZFeV7`sW@7o`hO7ZdC_O3D+opuRQCW+|D+w~CGXq0_X zOG{|EG`L|uZta1*`XhpLDEZYuMWy0t5<9CBB$9t0$Zy2uYe_OXEnCLrtaB z7|#G7^6c!@(+b7$X46?YIq6mMvB3EXs7)CUz%U9vg4(UIE&Cl|lwd{oHc0gPgTRsN z!1Ys*94wSI#Y6Us9kSB4>yPfUwDKRfMFR=_PXeRr^!gvdp?hHHs*=-z-Bx%F@4y<- wnToezJ!brz*3hXW?lE$Y(Z7&K9_j3l+F=q;_D6~e`*X$qezD?BGKDFB0ggb+t^fc4 diff --git a/plugins/samplesink/soapysdroutput/readme.md b/plugins/samplesink/soapysdroutput/readme.md index ac8225971..5eb020cf2 100644 --- a/plugins/samplesink/soapysdroutput/readme.md +++ b/plugins/samplesink/soapysdroutput/readme.md @@ -168,6 +168,10 @@ For AGC, Auto DC and Auto IQ corrections the checkbox has its text label on the ![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool1.png) +When set (true) a checkbox is lit in orange: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool3.png) +

A.5: Int, Float and String arguments

For all these types of values a line editor is used. Numerical values are parsed from string: diff --git a/plugins/samplesource/soapysdrinput/readme.md b/plugins/samplesource/soapysdrinput/readme.md index ad4386000..e84fd2678 100644 --- a/plugins/samplesource/soapysdrinput/readme.md +++ b/plugins/samplesource/soapysdrinput/readme.md @@ -204,6 +204,10 @@ For AGC, Auto DC and Auto IQ corrections the checkbox has its text label on the ![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool1.png) +When set (true) a checkbox is lit in orange: + +![SoapySDR input plugin GUI](../../../doc/img/SoapySDR_arg_bool3.png) +

A.5: Int, Float and String arguments

For all these types of values a line editor is used. Numerical values are parsed from string: diff --git a/sdrgui/soapygui/arginfogui.ui b/sdrgui/soapygui/arginfogui.ui index 523d6e140..c88a86ab9 100644 --- a/sdrgui/soapygui/arginfogui.ui +++ b/sdrgui/soapygui/arginfogui.ui @@ -67,6 +67,9 @@ QCheckBox::indicator::checked {background: rgb(255, 157, 38);} 16777215 + + QLineEdit { background: rgb(50, 50, 50); border: 1px solid rgb(79, 79, 79) } +
From ca36f757e127ada6f5e803c57bba82e033d840ad Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 23 Nov 2018 01:06:56 +0100 Subject: [PATCH 078/102] SoapySDR support: Debian: added internal soapysdr library --- CMakeLists.txt | 1 + debian/rules | 2 +- devices/soapysdr/CMakeLists.txt | 2 +- libsoapysdr/CMakeLists.txt | 27 +++++++++++++++++++ .../samplesink/soapysdroutput/CMakeLists.txt | 6 ++--- .../samplesource/soapysdrinput/CMakeLists.txt | 6 ++--- 6 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 libsoapysdr/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c76bd2be..4de824c0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -346,6 +346,7 @@ if (BUILD_DEBIAN) add_subdirectory(libmirisdr) add_subdirectory(libperseus) add_subdirectory(libiio) + add_subdirectory(libsoapysdr) endif (BUILD_DEBIAN) add_subdirectory(devices) diff --git a/debian/rules b/debian/rules index 800c02c9d..edca0b7d2 100755 --- a/debian/rules +++ b/debian/rules @@ -21,5 +21,5 @@ # dh_make generated override targets # This is example for Cmake (See https://bugs.debian.org/641051 ) override_dh_auto_configure: - dh_auto_configure -- -DCMAKE_INSTALL_PREFIX=/opt/sdrangel -DDEBUG_OUTPUT=ON -DBUILD_TYPE=DEBIAN -DRX_SAMPLE_24BIT=ON -DLIBCM256CCSRC=/z1/development/cm256cc -DLIBDSDCCSRC=/z1/development/dsdcc -DLIBAIRSPYSRC=/z1/development/libairspy -DLIBAIRSPYHFSRC=/z1/softs/airspyhf -DLIBHACKRFSRC=/z1/development/hackrf/host -DLIBRTLSDRSRC=/z1/development/librtlsdr.f4exb -DLIBMBELIBSRC=/z1/development/mbelib -DLIBSERIALDVSRC=/z1/development/serialDV -DLIBBLADERFSRC=/z1/softs/bladeRF -DLIBBLADERFCOMMONSRC=/z1/softs/bladeRF/host/common -DLIBBLADERFLIBSRC=/z1/softs/bladeRF/host/libraries/libbladeRF -DLIBMIRISDRSRC=/z1/development/libmirisdr-4 -DLIBLIMESUITESRC=/z1/softs/LimeSuite -DLIBIIOSRC=/z1/softs/libiio -DLIBPERSEUSSRC=/z1/softs/libperseus-sdr + dh_auto_configure -- -DCMAKE_INSTALL_PREFIX=/opt/sdrangel -DDEBUG_OUTPUT=ON -DBUILD_TYPE=DEBIAN -DRX_SAMPLE_24BIT=ON -DLIBCM256CCSRC=/z1/development/cm256cc -DLIBDSDCCSRC=/z1/development/dsdcc -DLIBAIRSPYSRC=/z1/development/libairspy -DLIBAIRSPYHFSRC=/z1/softs/airspyhf -DLIBHACKRFSRC=/z1/development/hackrf/host -DLIBRTLSDRSRC=/z1/development/librtlsdr.f4exb -DLIBMBELIBSRC=/z1/development/mbelib -DLIBSERIALDVSRC=/z1/development/serialDV -DLIBBLADERFSRC=/z1/softs/bladeRF -DLIBBLADERFCOMMONSRC=/z1/softs/bladeRF/host/common -DLIBBLADERFLIBSRC=/z1/softs/bladeRF/host/libraries/libbladeRF -DLIBMIRISDRSRC=/z1/development/libmirisdr-4 -DLIBLIMESUITESRC=/z1/softs/LimeSuite -DLIBIIOSRC=/z1/softs/libiio -DLIBPERSEUSSRC=/z1/softs/libperseus-sdr -DLIBSOAPYSDRSRC=/z1/softs/SoapySDR diff --git a/devices/soapysdr/CMakeLists.txt b/devices/soapysdr/CMakeLists.txt index 55ef5369b..401f9a18a 100644 --- a/devices/soapysdr/CMakeLists.txt +++ b/devices/soapysdr/CMakeLists.txt @@ -20,7 +20,7 @@ if (BUILD_DEBIAN) include_directories( . ${CMAKE_CURRENT_BINARY_DIR} - ${SOAPYSDRSRC} + ${LIBSOAPYSDRSRC} ) else (BUILD_DEBIAN) include_directories( diff --git a/libsoapysdr/CMakeLists.txt b/libsoapysdr/CMakeLists.txt new file mode 100644 index 000000000..f2a2986d1 --- /dev/null +++ b/libsoapysdr/CMakeLists.txt @@ -0,0 +1,27 @@ +project(soapysdr) + +file(GLOB soapysdr_SOURCES + ${LIBSOAPYSDRSRC}/lib/*.cpp +) + +file(GLOB soapysdr_HEADERS + ${LIBSOAPYSDRSRC}/include/SoapySDR/*.hpp + ${LIBSOAPYSDRSRC}/include/SoapySDR/*.h +) + +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${LIBSOAPYSDRSRC}/include + ${LIBSOAPYSDRSRC}/lib +) + +add_definitions(-DQT_SHARED) + +message( STATUS "soapysdr_SOURCES: ${soapysdr_SOURCES}" ) + +add_library(soapysdr SHARED + ${soapysdr_SOURCES} +) + +install(TARGETS soapysdr DESTINATION lib) diff --git a/plugins/samplesink/soapysdroutput/CMakeLists.txt b/plugins/samplesink/soapysdroutput/CMakeLists.txt index 95011bb52..d621ceb2e 100644 --- a/plugins/samplesink/soapysdroutput/CMakeLists.txt +++ b/plugins/samplesink/soapysdroutput/CMakeLists.txt @@ -28,8 +28,8 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client ${CMAKE_SOURCE_DIR}/devices - ${SOAPYSDRSRC}/include - ${SOAPYSDRSRC}/src + ${LIBSOAPYSDRSRC}/include + ${LIBSOAPYSDRSRC}/src ) else (BUILD_DEBIAN) include_directories( @@ -56,7 +56,7 @@ add_library(outputsoapysdr SHARED if (BUILD_DEBIAN) target_link_libraries(outputsoapysdr ${QT_LIBRARIES} - bladerf + soapysdr sdrbase sdrgui swagger diff --git a/plugins/samplesource/soapysdrinput/CMakeLists.txt b/plugins/samplesource/soapysdrinput/CMakeLists.txt index b87a6567f..da3141fcd 100644 --- a/plugins/samplesource/soapysdrinput/CMakeLists.txt +++ b/plugins/samplesource/soapysdrinput/CMakeLists.txt @@ -28,8 +28,8 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client ${CMAKE_SOURCE_DIR}/devices - ${SOAPYSDRSRC}/include - ${SOAPYSDRSRC}/src + ${LIBSOAPYSDRSRC}/include + ${LIBSOAPYSDRSRC}/src ) else (BUILD_DEBIAN) include_directories( @@ -56,7 +56,7 @@ add_library(inputsoapysdr SHARED if (BUILD_DEBIAN) target_link_libraries(inputsoapysdr ${QT_LIBRARIES} - bladerf + soapysdr sdrbase sdrgui swagger From 4fa3d7cff31c944023ba5fc4c9b4e5fe64e39d64 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 23 Nov 2018 01:17:06 +0100 Subject: [PATCH 079/102] SoapySDR support: created server plugins --- pluginssrv/samplesink/CMakeLists.txt | 6 ++ .../samplesink/soapysdroutput/CMakeLists.txt | 68 +++++++++++++++++++ pluginssrv/samplesource/CMakeLists.txt | 9 +++ .../samplesource/soapysdrinput/CMakeLists.txt | 68 +++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 pluginssrv/samplesink/soapysdroutput/CMakeLists.txt create mode 100644 pluginssrv/samplesource/soapysdrinput/CMakeLists.txt diff --git a/pluginssrv/samplesink/CMakeLists.txt b/pluginssrv/samplesink/CMakeLists.txt index ec27eee6c..97d32a801 100644 --- a/pluginssrv/samplesink/CMakeLists.txt +++ b/pluginssrv/samplesink/CMakeLists.txt @@ -28,6 +28,11 @@ if(CM256CC_FOUND) add_subdirectory(sdrdaemonsink) endif(CM256CC_FOUND) +find_package(SoapySDR) +if(LIBUSB_FOUND AND SOAPYSDR_FOUND) + add_subdirectory(soapysdroutput) +endif() + if (BUILD_DEBIAN) add_subdirectory(bladerf1output) add_subdirectory(bladerf2output) @@ -35,6 +40,7 @@ if (BUILD_DEBIAN) add_subdirectory(limesdroutput) add_subdirectory(plutosdroutput) add_subdirectory(sdrdaemonsink) + add_subdirectory(soapysdroutput) endif (BUILD_DEBIAN) add_subdirectory(filesink) diff --git a/pluginssrv/samplesink/soapysdroutput/CMakeLists.txt b/pluginssrv/samplesink/soapysdroutput/CMakeLists.txt new file mode 100644 index 000000000..0f99beee2 --- /dev/null +++ b/pluginssrv/samplesink/soapysdroutput/CMakeLists.txt @@ -0,0 +1,68 @@ +project(soapysdroutput) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +set(PLUGIN_PREFIX "../../../plugins/samplesink/soapysdroutput") + +set(soapysdroutput_SOURCES + ${PLUGIN_PREFIX}/soapysdroutput.cpp + ${PLUGIN_PREFIX}/soapysdroutputplugin.cpp + ${PLUGIN_PREFIX}/soapysdroutputsettings.cpp + ${PLUGIN_PREFIX}/soapysdroutputthread.cpp +) + +set(soapysdroutput_HEADERS + ${PLUGIN_PREFIX}/soapysdroutput.h + ${PLUGIN_PREFIX}/soapysdroutputplugin.h + ${PLUGIN_PREFIX}/soapysdroutputsettings.h + ${PLUGIN_PREFIX}/soapysdroutputthread.h +) + +if (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${LIBSOAPYSDRSRC}/include + ${LIBSOAPYSDRSRC}/src +) +else (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${SOAPYSDR_INCLUDE_DIR} +) +endif (BUILD_DEBIAN) + +add_definitions(${QT_DEFINITIONS}) +add_definitions(-DQT_PLUGIN) +add_definitions(-DQT_SHARED) + +add_library(outputsoapysdrsrv SHARED + ${soapysdroutput_SOURCES} + ${soapysdroutput_HEADERS_MOC} +) + +if (BUILD_DEBIAN) +target_link_libraries(outputsoapysdrsrv + ${QT_LIBRARIES} + soapysdr + sdrbase + swagger + soapysdrdevice +) +else (BUILD_DEBIAN) +target_link_libraries(outputsoapysdrsrv + ${QT_LIBRARIES} + ${SOAPYSDR_LIBRARY} + sdrbase + swagger + soapysdrdevice +) +endif (BUILD_DEBIAN) + +target_link_libraries(outputsoapysdrsrv Qt5::Core) + +install(TARGETS outputsoapysdrsrv DESTINATION lib/plugins/samplesink) diff --git a/pluginssrv/samplesource/CMakeLists.txt b/pluginssrv/samplesource/CMakeLists.txt index 8e23ea759..3f2883a66 100644 --- a/pluginssrv/samplesource/CMakeLists.txt +++ b/pluginssrv/samplesource/CMakeLists.txt @@ -77,6 +77,14 @@ else(LIBUSB_FOUND AND LIBMIRISDR_FOUND) message(STATUS "LibMiriSDR NOT found") endif(LIBUSB_FOUND AND LIBMIRISDR_FOUND) +find_package(SoapySDR) +if(LIBUSB_FOUND AND SOAPYSDR_FOUND) + add_subdirectory(soapysdrinput) + message(STATUS "SoapySDR found") +else() + message(STATUS "SoapySDR not found") +endif() + if (BUILD_DEBIAN) add_subdirectory(airspy) add_subdirectory(airspyhf) @@ -89,6 +97,7 @@ if (BUILD_DEBIAN) add_subdirectory(rtlsdr) add_subdirectory(sdrdaemonsource) add_subdirectory(sdrplay) + add_subdirectory(soapysdrinput) endif (BUILD_DEBIAN) add_subdirectory(filesource) diff --git a/pluginssrv/samplesource/soapysdrinput/CMakeLists.txt b/pluginssrv/samplesource/soapysdrinput/CMakeLists.txt new file mode 100644 index 000000000..331082b11 --- /dev/null +++ b/pluginssrv/samplesource/soapysdrinput/CMakeLists.txt @@ -0,0 +1,68 @@ +project(soapysdrinput) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +set(PLUGIN_PREFIX "../../../plugins/samplesource/soapysdrinput") + +set(soapysdrinput_SOURCES + ${PLUGIN_PREFIX}/soapysdrinput.cpp + ${PLUGIN_PREFIX}/soapysdrinputplugin.cpp + ${PLUGIN_PREFIX}/soapysdrinputsettings.cpp + ${PLUGIN_PREFIX}/soapysdrinputthread.cpp +) + +set(soapysdrinput_HEADERS + ${PLUGIN_PREFIX}/soapysdrinput.h + ${PLUGIN_PREFIX}/soapysdrinputplugin.h + ${PLUGIN_PREFIX}/soapysdrinputsettings.h + ${PLUGIN_PREFIX}/soapysdrinputthread.h +) + +if (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${LIBSOAPYSDRSRC}/include + ${LIBSOAPYSDRSRC}/src +) +else (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${SOAPYSDR_INCLUDE_DIR} +) +endif (BUILD_DEBIAN) + +add_definitions(${QT_DEFINITIONS}) +add_definitions(-DQT_PLUGIN) +add_definitions(-DQT_SHARED) + +add_library(inputsoapysdrsrv SHARED + ${soapysdrinput_SOURCES} + ${soapysdrinput_HEADERS_MOC} +) + +if (BUILD_DEBIAN) +target_link_libraries(inputsoapysdrsrv + ${QT_LIBRARIES} + soapysdr + sdrbase + swagger + soapysdrdevice +) +else (BUILD_DEBIAN) +target_link_libraries(inputsoapysdrsrv + ${QT_LIBRARIES} + ${SOAPYSDR_LIBRARY} + sdrbase + swagger + soapysdrdevice +) +endif (BUILD_DEBIAN) + +target_link_libraries(inputsoapysdrsrv Qt5::Core) + +install(TARGETS inputsoapysdrsrv DESTINATION lib/plugins/samplesource) From 2e75ed4a2f20b0af195f058e32d58f0c7212fc7d Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 23 Nov 2018 01:26:17 +0100 Subject: [PATCH 080/102] SoapySDR support: fixed Debian build --- devices/soapysdr/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devices/soapysdr/CMakeLists.txt b/devices/soapysdr/CMakeLists.txt index 401f9a18a..f8268c52b 100644 --- a/devices/soapysdr/CMakeLists.txt +++ b/devices/soapysdr/CMakeLists.txt @@ -20,7 +20,8 @@ if (BUILD_DEBIAN) include_directories( . ${CMAKE_CURRENT_BINARY_DIR} - ${LIBSOAPYSDRSRC} + ${LIBSOAPYSDRSRC}/include + ${LIBSOAPYSDRSRC}/src ) else (BUILD_DEBIAN) include_directories( From 5ad4b1f3da7ea1c104e181b4787d2d9414a91f56 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 24 Nov 2018 18:47:56 +0100 Subject: [PATCH 081/102] SoapySDR support: Debian build fixes (1) --- libsoapysdr/CMakeLists.txt | 72 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/libsoapysdr/CMakeLists.txt b/libsoapysdr/CMakeLists.txt index f2a2986d1..fd41345e7 100644 --- a/libsoapysdr/CMakeLists.txt +++ b/libsoapysdr/CMakeLists.txt @@ -1,5 +1,77 @@ project(soapysdr) +######################################################################## +# gather version information +# packagers may specify -DSOAPY_SDR_EXTVER="foo" to replace the git hash +######################################################################## +file(READ "${LIBSOAPYSDRSRC}/Changelog.txt" changelog_txt) +string(REGEX MATCH "Release ([0-9]+\\.[0-9]+\\.[0-9]+) \\(" CHANGELOG_MATCH "${changelog_txt}") +if(NOT CHANGELOG_MATCH) + message(FATAL_ERROR "Failed to extract version number from Changelog.txt") +endif(NOT CHANGELOG_MATCH) +set(SOAPY_SDR_LIBVER "${CMAKE_MATCH_1}") + +if (NOT SOAPY_SDR_EXTVER) + include(${LIBSOAPYSDRSRC}/cmake/Modules/GetGitRevisionDescription.cmake) + get_git_head_revision(GITREFSPEC GITHASH) + if (GITHASH) + string(SUBSTRING "${GITHASH}" 0 8 GITHASH) + set(SOAPY_SDR_EXTVER "g${GITHASH}") + else (GITHASH) + set(SOAPY_SDR_EXTVER "unknown") + endif (GITHASH) +endif() + +set(SOAPY_SDR_VERSION "${SOAPY_SDR_LIBVER}-${SOAPY_SDR_EXTVER}") + +#SOAPY_SDR_ROOT is compiled into the library to locate the install base. +#By default, the SOAPY_SDR_ROOT is set to the CMAKE_INSTALL_PREFIX. +#However users may overload this by specifying -DSOAPY_SDR_ROOT=. +set(SOAPY_SDR_ROOT "${CMAKE_INSTALL_PREFIX}" CACHE PATH + "Installation root for SoapySDR::getRootPath()") +file(TO_CMAKE_PATH "${SOAPY_SDR_ROOT}" SOAPY_SDR_ROOT) + +#SOAPY_SDR_ROOT_ENV is the name of the environment variable +#which tells SoapySDR where to find the root installation. +#By default, the environment variable SOAPY_SDR_ROOT is used. +#Example: set -DSOAPY_SDR_ROOT_ENV=SNAP for snappy packages. +set(SOAPY_SDR_ROOT_ENV "SOAPY_SDR_ROOT" CACHE STRING + "Environment variable for SoapySDR::getRootPath()") + +######################################################################## +# select the release build type by default to get optimization flags +######################################################################## +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") + message(STATUS "Build type not specified: defaulting to release.") +endif(NOT CMAKE_BUILD_TYPE) +set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") + +######################################################################## +# rpath setup - http://www.cmake.org/Wiki/CMake_RPATH_handling +######################################################################## +# use, i.e. don't skip the full RPATH for the build tree +option(CMAKE_SKIP_BUILD_RPATH "skip rpath build" FALSE) + +# when building, don't use the install RPATH already +# (but later on when installing) +option(CMAKE_BUILD_WITH_INSTALL_RPATH "build with install rpath" FALSE) + +# the RPATH to be used when installing, but only if it's not a system directory +option(CMAKE_AUTOSET_INSTALL_RPATH TRUE) +if(CMAKE_AUTOSET_INSTALL_RPATH) +LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" isSystemDir) +IF("${isSystemDir}" STREQUAL "-1") + SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}") +ENDIF("${isSystemDir}" STREQUAL "-1") +endif(CMAKE_AUTOSET_INSTALL_RPATH) + +# add the automatically determined parts of the RPATH +# which point to directories outside the build tree to the install RPATH +option(CMAKE_INSTALL_RPATH_USE_LINK_PATH "build with automatic rpath" TRUE) + +######################################################################## + file(GLOB soapysdr_SOURCES ${LIBSOAPYSDRSRC}/lib/*.cpp ) From e5c4c55d6f5ffaadcf0c6fe752cf7a33500c9e34 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 24 Nov 2018 19:39:40 +0100 Subject: [PATCH 082/102] SoapySDR support: Debian build fixes (2) --- libsoapysdr/CMakeLists.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libsoapysdr/CMakeLists.txt b/libsoapysdr/CMakeLists.txt index fd41345e7..434005e80 100644 --- a/libsoapysdr/CMakeLists.txt +++ b/libsoapysdr/CMakeLists.txt @@ -72,6 +72,20 @@ option(CMAKE_INSTALL_RPATH_USE_LINK_PATH "build with automatic rpath" TRUE) ######################################################################## +list(APPEND SOAPY_SDR_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/Modules.cpp) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/Modules.in.cpp + ${CMAKE_CURRENT_BINARY_DIR}/Modules.cpp +@ONLY) + +list(APPEND SOAPY_SDR_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/Version.cpp) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/Version.in.cpp + ${CMAKE_CURRENT_BINARY_DIR}/Version.cpp +@ONLY) + +######################################################################## + file(GLOB soapysdr_SOURCES ${LIBSOAPYSDRSRC}/lib/*.cpp ) From 9d0bcc7e5cb2a37a34169aac7ae0c04e74289898 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 24 Nov 2018 19:55:37 +0100 Subject: [PATCH 083/102] SoapySDR support: removed from Debian build --- CMakeLists.txt | 1 - devices/CMakeLists.txt | 1 - libsoapysdr/CMakeLists.txt | 4 ++-- plugins/samplesink/CMakeLists.txt | 1 - plugins/samplesource/CMakeLists.txt | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4de824c0e..0c76bd2be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -346,7 +346,6 @@ if (BUILD_DEBIAN) add_subdirectory(libmirisdr) add_subdirectory(libperseus) add_subdirectory(libiio) - add_subdirectory(libsoapysdr) endif (BUILD_DEBIAN) add_subdirectory(devices) diff --git a/devices/CMakeLists.txt b/devices/CMakeLists.txt index 9626e5db9..ad8323e6d 100644 --- a/devices/CMakeLists.txt +++ b/devices/CMakeLists.txt @@ -9,7 +9,6 @@ if (BUILD_DEBIAN) add_subdirectory(limesdr) add_subdirectory(perseus) add_subdirectory(plutosdr) - add_subdirectory(soapysdr) else(BUILD_DEBIAN) find_package(LibBLADERF) if(LIBUSB_FOUND AND LIBBLADERF_FOUND) diff --git a/libsoapysdr/CMakeLists.txt b/libsoapysdr/CMakeLists.txt index 434005e80..47a2e0cc3 100644 --- a/libsoapysdr/CMakeLists.txt +++ b/libsoapysdr/CMakeLists.txt @@ -74,13 +74,13 @@ option(CMAKE_INSTALL_RPATH_USE_LINK_PATH "build with automatic rpath" TRUE) list(APPEND SOAPY_SDR_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/Modules.cpp) configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/Modules.in.cpp + ${LIBSOAPYSDRSRC}/lib/Modules.in.cpp ${CMAKE_CURRENT_BINARY_DIR}/Modules.cpp @ONLY) list(APPEND SOAPY_SDR_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/Version.cpp) configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/Version.in.cpp + ${LIBSOAPYSDRSRC}/lib/Version.in.cpp ${CMAKE_CURRENT_BINARY_DIR}/Version.cpp @ONLY) diff --git a/plugins/samplesink/CMakeLists.txt b/plugins/samplesink/CMakeLists.txt index a57d121a4..f8f4af31c 100644 --- a/plugins/samplesink/CMakeLists.txt +++ b/plugins/samplesink/CMakeLists.txt @@ -40,7 +40,6 @@ if (BUILD_DEBIAN) add_subdirectory(limesdroutput) add_subdirectory(plutosdroutput) add_subdirectory(sdrdaemonsink) - add_subdirectory(soapysdroutput) endif (BUILD_DEBIAN) add_subdirectory(filesink) diff --git a/plugins/samplesource/CMakeLists.txt b/plugins/samplesource/CMakeLists.txt index 9e442fa11..93fc805c7 100644 --- a/plugins/samplesource/CMakeLists.txt +++ b/plugins/samplesource/CMakeLists.txt @@ -97,7 +97,6 @@ if (BUILD_DEBIAN) add_subdirectory(rtlsdr) add_subdirectory(sdrdaemonsource) add_subdirectory(sdrplay) - add_subdirectory(soapysdrinput) endif (BUILD_DEBIAN) add_subdirectory(filesource) From 6dbc07d1c88d1aa3e8d87a1dd680a67c894fac2b Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 24 Nov 2018 20:00:06 +0100 Subject: [PATCH 084/102] SoapySDR support: removed from Debian build (server plugins) --- pluginssrv/samplesink/CMakeLists.txt | 1 - pluginssrv/samplesource/CMakeLists.txt | 1 - 2 files changed, 2 deletions(-) diff --git a/pluginssrv/samplesink/CMakeLists.txt b/pluginssrv/samplesink/CMakeLists.txt index 97d32a801..3fa769ebc 100644 --- a/pluginssrv/samplesink/CMakeLists.txt +++ b/pluginssrv/samplesink/CMakeLists.txt @@ -40,7 +40,6 @@ if (BUILD_DEBIAN) add_subdirectory(limesdroutput) add_subdirectory(plutosdroutput) add_subdirectory(sdrdaemonsink) - add_subdirectory(soapysdroutput) endif (BUILD_DEBIAN) add_subdirectory(filesink) diff --git a/pluginssrv/samplesource/CMakeLists.txt b/pluginssrv/samplesource/CMakeLists.txt index 3f2883a66..5bcb15917 100644 --- a/pluginssrv/samplesource/CMakeLists.txt +++ b/pluginssrv/samplesource/CMakeLists.txt @@ -97,7 +97,6 @@ if (BUILD_DEBIAN) add_subdirectory(rtlsdr) add_subdirectory(sdrdaemonsource) add_subdirectory(sdrplay) - add_subdirectory(soapysdrinput) endif (BUILD_DEBIAN) add_subdirectory(filesource) From bc7ad10f9d9a7694320e8ecebab65eb8b9c1b5e7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 24 Nov 2018 21:21:04 +0100 Subject: [PATCH 085/102] Use C++11 everywhere --- devices/CMakeLists.txt | 2 ++ httpserver/CMakeLists.txt | 2 ++ libairspy/CMakeLists.txt | 2 ++ libairspyhf/CMakeLists.txt | 2 ++ libbladerf/CMakeLists.txt | 2 ++ libhackrf/CMakeLists.txt | 2 ++ libiio/CMakeLists.txt | 2 ++ liblimesuite/CMakeLists.txt | 2 ++ libmirisdr/CMakeLists.txt | 2 ++ libperseus/CMakeLists.txt | 2 ++ librtlsdr/CMakeLists.txt | 2 ++ libsoapysdr/CMakeLists.txt | 2 ++ logging/CMakeLists.txt | 2 ++ mbelib/CMakeLists.txt | 2 ++ plugins/channelrx/chanalyzer/CMakeLists.txt | 2 ++ plugins/channelrx/demodatv/CMakeLists.txt | 2 ++ plugins/channelrx/demoddatv/CMakeLists.txt | 2 ++ plugins/channelrx/demodlora/CMakeLists.txt | 2 ++ qrtplib/CMakeLists.txt | 2 ++ sdrbase/CMakeLists.txt | 1 + sdrgui/CMakeLists.txt | 2 ++ 21 files changed, 41 insertions(+) diff --git a/devices/CMakeLists.txt b/devices/CMakeLists.txt index ad8323e6d..e61097662 100644 --- a/devices/CMakeLists.txt +++ b/devices/CMakeLists.txt @@ -1,5 +1,7 @@ project(devices) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + find_package(LibUSB) if (BUILD_DEBIAN) diff --git a/httpserver/CMakeLists.txt b/httpserver/CMakeLists.txt index 1b8341028..fc1f8e605 100644 --- a/httpserver/CMakeLists.txt +++ b/httpserver/CMakeLists.txt @@ -1,5 +1,7 @@ project(httpserver) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(httpserver_SOURCES httpglobal.cpp httplistener.cpp diff --git a/libairspy/CMakeLists.txt b/libairspy/CMakeLists.txt index e0a8af4c7..bc3a9da48 100644 --- a/libairspy/CMakeLists.txt +++ b/libairspy/CMakeLists.txt @@ -1,5 +1,7 @@ project(airspy) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + find_package(LibUSB) remove_definitions(-DUSE_SSE2) diff --git a/libairspyhf/CMakeLists.txt b/libairspyhf/CMakeLists.txt index 645d76fae..5394c4d44 100644 --- a/libairspyhf/CMakeLists.txt +++ b/libairspyhf/CMakeLists.txt @@ -1,5 +1,7 @@ project(airspyhf) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + find_package(LibUSB) set(airspyhf_SOURCES diff --git a/libbladerf/CMakeLists.txt b/libbladerf/CMakeLists.txt index 990b09984..8b44ba461 100644 --- a/libbladerf/CMakeLists.txt +++ b/libbladerf/CMakeLists.txt @@ -1,5 +1,7 @@ project(bladerf) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + find_package(LibUSB) add_definitions(-DBLADERF_OS_LINUX) diff --git a/libhackrf/CMakeLists.txt b/libhackrf/CMakeLists.txt index 7afa12e96..24473318e 100644 --- a/libhackrf/CMakeLists.txt +++ b/libhackrf/CMakeLists.txt @@ -1,5 +1,7 @@ project(hackrf) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + find_package(LibUSB) set(hackrf_SOURCES diff --git a/libiio/CMakeLists.txt b/libiio/CMakeLists.txt index 5d01b71f4..4ef538a2a 100644 --- a/libiio/CMakeLists.txt +++ b/libiio/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.8.7) project(iio) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(LIBIIO_VERSION_MAJOR 0) set(LIBIIO_VERSION_MINOR 10) set(VERSION "${LIBIIO_VERSION_MAJOR}.${LIBIIO_VERSION_MINOR}") diff --git a/liblimesuite/CMakeLists.txt b/liblimesuite/CMakeLists.txt index 36f6662f9..6c1a3e616 100644 --- a/liblimesuite/CMakeLists.txt +++ b/liblimesuite/CMakeLists.txt @@ -1,5 +1,7 @@ project(limesuite) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + find_package(LibUSB) set(limesuite_SOURCES diff --git a/libmirisdr/CMakeLists.txt b/libmirisdr/CMakeLists.txt index e48d603b5..e2ef09622 100644 --- a/libmirisdr/CMakeLists.txt +++ b/libmirisdr/CMakeLists.txt @@ -1,5 +1,7 @@ project(mirisdr) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + add_definitions(-DDETACH_KERNEL_DRIVER=ON) find_package(LibUSB) diff --git a/libperseus/CMakeLists.txt b/libperseus/CMakeLists.txt index 806153dd2..0e9ddfe50 100644 --- a/libperseus/CMakeLists.txt +++ b/libperseus/CMakeLists.txt @@ -1,5 +1,7 @@ project(perseus) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + find_package(LibUSB) add_definitions(-DHAVE_CONFIG_H) diff --git a/librtlsdr/CMakeLists.txt b/librtlsdr/CMakeLists.txt index dda9bcdd6..7c3d65bd0 100644 --- a/librtlsdr/CMakeLists.txt +++ b/librtlsdr/CMakeLists.txt @@ -1,5 +1,7 @@ project(rtlsdr) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + add_definitions(-DDETACH_KERNEL_DRIVER=ON) find_package(LibUSB) diff --git a/libsoapysdr/CMakeLists.txt b/libsoapysdr/CMakeLists.txt index 47a2e0cc3..7c53f3329 100644 --- a/libsoapysdr/CMakeLists.txt +++ b/libsoapysdr/CMakeLists.txt @@ -1,5 +1,7 @@ project(soapysdr) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + ######################################################################## # gather version information # packagers may specify -DSOAPY_SDR_EXTVER="foo" to replace the git hash diff --git a/logging/CMakeLists.txt b/logging/CMakeLists.txt index 5208d4326..6b0fbf998 100644 --- a/logging/CMakeLists.txt +++ b/logging/CMakeLists.txt @@ -1,5 +1,7 @@ project(logging) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(logging_SOURCES dualfilelogger.cpp loggerwithfile.cpp diff --git a/mbelib/CMakeLists.txt b/mbelib/CMakeLists.txt index a085fa384..2328fec32 100644 --- a/mbelib/CMakeLists.txt +++ b/mbelib/CMakeLists.txt @@ -1,5 +1,7 @@ project(mbelib) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(mbelib_SOURCES ${LIBMBELIBSRC}/ambe3600x2400.c ${LIBMBELIBSRC}/ambe3600x2450.c diff --git a/plugins/channelrx/chanalyzer/CMakeLists.txt b/plugins/channelrx/chanalyzer/CMakeLists.txt index a33c29a51..e286273dd 100644 --- a/plugins/channelrx/chanalyzer/CMakeLists.txt +++ b/plugins/channelrx/chanalyzer/CMakeLists.txt @@ -1,5 +1,7 @@ project(chanalyzer) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(chanalyzer_SOURCES chanalyzer.cpp chanalyzergui.cpp diff --git a/plugins/channelrx/demodatv/CMakeLists.txt b/plugins/channelrx/demodatv/CMakeLists.txt index 7665ee799..30e835539 100644 --- a/plugins/channelrx/demodatv/CMakeLists.txt +++ b/plugins/channelrx/demodatv/CMakeLists.txt @@ -1,5 +1,7 @@ project(atv) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(atv_SOURCES atvdemod.cpp atvdemodsettings.cpp diff --git a/plugins/channelrx/demoddatv/CMakeLists.txt b/plugins/channelrx/demoddatv/CMakeLists.txt index a4bfb1b0e..b1eedcbcb 100644 --- a/plugins/channelrx/demoddatv/CMakeLists.txt +++ b/plugins/channelrx/demoddatv/CMakeLists.txt @@ -1,5 +1,7 @@ project(datv) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(datv_SOURCES datvdemod.cpp datvdemodgui.cpp diff --git a/plugins/channelrx/demodlora/CMakeLists.txt b/plugins/channelrx/demodlora/CMakeLists.txt index a2ced900c..f5d743996 100644 --- a/plugins/channelrx/demodlora/CMakeLists.txt +++ b/plugins/channelrx/demodlora/CMakeLists.txt @@ -1,5 +1,7 @@ project(lora) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(lora_SOURCES lorademod.cpp lorademodgui.cpp diff --git a/qrtplib/CMakeLists.txt b/qrtplib/CMakeLists.txt index 784e7f504..ef57c69c2 100644 --- a/qrtplib/CMakeLists.txt +++ b/qrtplib/CMakeLists.txt @@ -1,5 +1,7 @@ project(qrtplib) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set (qrtplib_HEADERS rtcpapppacket.h rtcpbyepacket.h diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index 1040d5948..13ddb98f6 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -1,5 +1,6 @@ project (sdrbase) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") set(sdrbase_SOURCES diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index 9b2de21ab..ecf762126 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -1,5 +1,7 @@ project (sdrgui) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(sdrgui_SOURCES mainwindow.cpp gui/aboutdialog.cpp From 772a150136a30d70e4efde64a73010d29fb2637c Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 26 Nov 2018 08:54:06 +0100 Subject: [PATCH 086/102] RTLSDR: implemented offset tuning --- plugins/samplesource/rtlsdr/rtlsdrgui.cpp | 7 +++++++ plugins/samplesource/rtlsdr/rtlsdrgui.h | 1 + plugins/samplesource/rtlsdr/rtlsdrgui.ui | 10 +++++++++ plugins/samplesource/rtlsdr/rtlsdrinput.cpp | 21 ++++++++++++++----- .../samplesource/rtlsdr/rtlsdrsettings.cpp | 3 +++ plugins/samplesource/rtlsdr/rtlsdrsettings.h | 1 + 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.cpp b/plugins/samplesource/rtlsdr/rtlsdrgui.cpp index 381a2b053..92cd317f7 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.cpp @@ -261,6 +261,7 @@ void RTLSDRGui::displaySettings() ui->checkBox->setChecked(m_settings.m_noModMode); ui->agc->setChecked(m_settings.m_agc); ui->lowSampleRate->setChecked(m_settings.m_lowSampleRate); + ui->offsetTuning->setChecked(m_settings.m_offsetTuning); } void RTLSDRGui::sendSettings() @@ -441,6 +442,12 @@ void RTLSDRGui::on_sampleRate_changed(quint64 value) sendSettings(); } +void RTLSDRGui::on_offsetTuning_toggled(bool checked) +{ + m_settings.m_offsetTuning = checked; + sendSettings(); +} + void RTLSDRGui::on_rfBW_changed(quint64 value) { m_settings.m_rfBandwidth = value * 1000; diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.h b/plugins/samplesource/rtlsdr/rtlsdrgui.h index f2c838618..69e010f68 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.h +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.h @@ -78,6 +78,7 @@ private slots: void handleInputMessages(); void on_centerFrequency_changed(quint64 value); void on_sampleRate_changed(quint64 value); + void on_offsetTuning_toggled(bool checked); void on_rfBW_changed(quint64 value); void on_lowSampleRate_toggled(bool checked); void on_dcOffset_toggled(bool checked); diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.ui b/plugins/samplesource/rtlsdr/rtlsdrgui.ui index 79b0dd127..0549f25e6 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.ui +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.ui @@ -493,6 +493,16 @@ + + + + Offset tuning + + + Ofs + + + diff --git a/plugins/samplesource/rtlsdr/rtlsdrinput.cpp b/plugins/samplesource/rtlsdr/rtlsdrinput.cpp index f78765cca..394096e59 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrinput.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrinput.cpp @@ -507,17 +507,28 @@ bool RTLSDRInput::applySettings(const RTLSDRSettings& settings, bool force) if (m_dev != 0) { - if (rtlsdr_set_tuner_bandwidth( m_dev, m_settings.m_rfBandwidth) != 0) - { + if (rtlsdr_set_tuner_bandwidth( m_dev, m_settings.m_rfBandwidth) != 0) { qCritical("RTLSDRInput::applySettings: could not set RF bandwidth to %u", m_settings.m_rfBandwidth); - } - else - { + } else { qDebug() << "RTLSDRInput::applySettings: set RF bandwidth to " << m_settings.m_rfBandwidth; } } } + if ((m_settings.m_offsetTuning != settings.m_offsetTuning) || force) + { + m_settings.m_offsetTuning = settings.m_offsetTuning; + + if (m_dev != 0) + { + if (rtlsdr_set_offset_tuning(m_dev, m_settings.m_offsetTuning ? 0 : 1) != 0) { + qCritical("RTLSDRInput::applySettings: could not set offset tuning to %s", m_settings.m_offsetTuning ? "on" : "off"); + } else { + qDebug("RTLSDRInput::applySettings: offset tuning set to %s", m_settings.m_offsetTuning ? "on" : "off"); + } + } + } + if (forwardChange) { int sampleRate = m_settings.m_devSampleRate/(1< Date: Mon, 26 Nov 2018 13:31:51 +0100 Subject: [PATCH 087/102] RTL-SDR: offset tuning support: REST API and version update --- app/main.cpp | 2 +- appbench/main.cpp | 2 +- appsrv/main.cpp | 2 +- debian/changelog | 6 ++++++ plugins/samplesource/rtlsdr/rtlsdrgui.ui | 2 +- plugins/samplesource/rtlsdr/rtlsdrinput.cpp | 4 ++++ sdrbase/resources/webapi/doc/html2/index.html | 5 ++++- .../webapi/doc/swagger/include/RtlSdr.yaml | 4 +++- .../sdrangel/api/swagger/include/RtlSdr.yaml | 4 +++- swagger/sdrangel/code/html2/index.html | 5 ++++- .../code/qt5/client/SWGRtlSdrSettings.cpp | 21 +++++++++++++++++++ .../code/qt5/client/SWGRtlSdrSettings.h | 6 ++++++ 12 files changed, 55 insertions(+), 8 deletions(-) diff --git a/app/main.cpp b/app/main.cpp index 8d1f8de47..101f06656 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -35,7 +35,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo */ QCoreApplication::setOrganizationName("f4exb"); QCoreApplication::setApplicationName("SDRangel"); - QCoreApplication::setApplicationVersion("4.3.0"); + QCoreApplication::setApplicationVersion("4.3.1"); #if QT_VERSION >= 0x050600 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); //HiDPI pixmaps diff --git a/appbench/main.cpp b/appbench/main.cpp index 1bb7f1f5f..49161a862 100644 --- a/appbench/main.cpp +++ b/appbench/main.cpp @@ -57,7 +57,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo QCoreApplication::setOrganizationName("f4exb"); QCoreApplication::setApplicationName("SDRangelBench"); - QCoreApplication::setApplicationVersion("4.3.0"); + QCoreApplication::setApplicationVersion("4.3.1"); int catchSignals[] = {SIGQUIT, SIGINT, SIGTERM, SIGHUP}; std::vector vsig(catchSignals, catchSignals + sizeof(catchSignals) / sizeof(int)); diff --git a/appsrv/main.cpp b/appsrv/main.cpp index e11724111..af308e7a3 100644 --- a/appsrv/main.cpp +++ b/appsrv/main.cpp @@ -56,7 +56,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo QCoreApplication::setOrganizationName("f4exb"); QCoreApplication::setApplicationName("SDRangelSrv"); - QCoreApplication::setApplicationVersion("4.3.0"); + QCoreApplication::setApplicationVersion("4.3.1"); int catchSignals[] = {SIGQUIT, SIGINT, SIGTERM, SIGHUP}; std::vector vsig(catchSignals, catchSignals + sizeof(catchSignals) / sizeof(int)); diff --git a/debian/changelog b/debian/changelog index ef646f6cb..753586486 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +sdrangel (4.3.1-1) unstable; urgency=medium + + * RTL-SDR: offset tuning support + + -- Edouard Griffiths, F4EXB Sun, 02 Dec 2018 21:14:18 +0100 + sdrangel (4.3.0-1) unstable; urgency=medium * SoapySDR support diff --git a/plugins/samplesource/rtlsdr/rtlsdrgui.ui b/plugins/samplesource/rtlsdr/rtlsdrgui.ui index 0549f25e6..dcf3a8a25 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrgui.ui +++ b/plugins/samplesource/rtlsdr/rtlsdrgui.ui @@ -496,7 +496,7 @@ - Offset tuning + Offset tuning (applies to some tuners only incl. E4000) Ofs diff --git a/plugins/samplesource/rtlsdr/rtlsdrinput.cpp b/plugins/samplesource/rtlsdr/rtlsdrinput.cpp index 394096e59..01d3265b9 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrinput.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrinput.cpp @@ -598,6 +598,9 @@ int RTLSDRInput::webapiSettingsPutPatch( if (deviceSettingsKeys.contains("noModMode")) { settings.m_noModMode = response.getRtlSdrSettings()->getNoModMode() != 0; } + if (deviceSettingsKeys.contains("offsetTuning")) { + settings.m_offsetTuning = response.getRtlSdrSettings()->getOffsetTuning() != 0; + } if (deviceSettingsKeys.contains("transverterDeltaFrequency")) { settings.m_transverterDeltaFrequency = response.getRtlSdrSettings()->getTransverterDeltaFrequency(); } @@ -638,6 +641,7 @@ void RTLSDRInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& res response.getRtlSdrSettings()->setLog2Decim(settings.m_log2Decim); response.getRtlSdrSettings()->setLowSampleRate(settings.m_lowSampleRate ? 1 : 0); response.getRtlSdrSettings()->setNoModMode(settings.m_noModMode ? 1 : 0); + response.getRtlSdrSettings()->setOffsetTuning(settings.m_offsetTuning ? 1 : 0); response.getRtlSdrSettings()->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency); response.getRtlSdrSettings()->setTransverterMode(settings.m_transverterMode ? 1 : 0); response.getRtlSdrSettings()->setRfBandwidth(settings.m_rfBandwidth); diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 2eefbe096..5d9f1d1a8 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -3474,6 +3474,9 @@ margin-bottom: 20px; "noModMode" : { "type" : "integer" }, + "offsetTuning" : { + "type" : "integer" + }, "transverterMode" : { "type" : "integer" }, @@ -23614,7 +23617,7 @@ except ApiException as e:
- Generated 2018-11-14T01:13:54.986+01:00 + Generated 2018-11-26T13:24:54.460+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/RtlSdr.yaml b/sdrbase/resources/webapi/doc/swagger/include/RtlSdr.yaml index 566866e1a..8b80ce510 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/RtlSdr.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/RtlSdr.yaml @@ -24,11 +24,13 @@ RtlSdrSettings: type: integer noModMode: type: integer + offsetTuning: + type: integer transverterMode: type: integer transverterDeltaFrequency: type: integer - format: int64 + format: int64 rfBandwidth: type: integer fileRecordName: diff --git a/swagger/sdrangel/api/swagger/include/RtlSdr.yaml b/swagger/sdrangel/api/swagger/include/RtlSdr.yaml index 848b5a61f..1c4c0fde2 100644 --- a/swagger/sdrangel/api/swagger/include/RtlSdr.yaml +++ b/swagger/sdrangel/api/swagger/include/RtlSdr.yaml @@ -24,11 +24,13 @@ RtlSdrSettings: type: integer noModMode: type: integer + offsetTuning: + type: integer transverterMode: type: integer transverterDeltaFrequency: type: integer - format: int64 + format: int64 rfBandwidth: type: integer fileRecordName: diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 2eefbe096..5d9f1d1a8 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -3474,6 +3474,9 @@ margin-bottom: 20px; "noModMode" : { "type" : "integer" }, + "offsetTuning" : { + "type" : "integer" + }, "transverterMode" : { "type" : "integer" }, @@ -23614,7 +23617,7 @@ except ApiException as e:
- Generated 2018-11-14T01:13:54.986+01:00 + Generated 2018-11-26T13:24:54.460+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGRtlSdrSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGRtlSdrSettings.cpp index 297e5ce1b..4300f89d3 100644 --- a/swagger/sdrangel/code/qt5/client/SWGRtlSdrSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGRtlSdrSettings.cpp @@ -50,6 +50,8 @@ SWGRtlSdrSettings::SWGRtlSdrSettings() { m_agc_isSet = false; no_mod_mode = 0; m_no_mod_mode_isSet = false; + offset_tuning = 0; + m_offset_tuning_isSet = false; transverter_mode = 0; m_transverter_mode_isSet = false; transverter_delta_frequency = 0L; @@ -88,6 +90,8 @@ SWGRtlSdrSettings::init() { m_agc_isSet = false; no_mod_mode = 0; m_no_mod_mode_isSet = false; + offset_tuning = 0; + m_offset_tuning_isSet = false; transverter_mode = 0; m_transverter_mode_isSet = false; transverter_delta_frequency = 0L; @@ -114,6 +118,7 @@ SWGRtlSdrSettings::cleanup() { + if(file_record_name != nullptr) { delete file_record_name; } @@ -152,6 +157,8 @@ SWGRtlSdrSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&no_mod_mode, pJson["noModMode"], "qint32", ""); + ::SWGSDRangel::setValue(&offset_tuning, pJson["offsetTuning"], "qint32", ""); + ::SWGSDRangel::setValue(&transverter_mode, pJson["transverterMode"], "qint32", ""); ::SWGSDRangel::setValue(&transverter_delta_frequency, pJson["transverterDeltaFrequency"], "qint64", ""); @@ -209,6 +216,9 @@ SWGRtlSdrSettings::asJsonObject() { if(m_no_mod_mode_isSet){ obj->insert("noModMode", QJsonValue(no_mod_mode)); } + if(m_offset_tuning_isSet){ + obj->insert("offsetTuning", QJsonValue(offset_tuning)); + } if(m_transverter_mode_isSet){ obj->insert("transverterMode", QJsonValue(transverter_mode)); } @@ -335,6 +345,16 @@ SWGRtlSdrSettings::setNoModMode(qint32 no_mod_mode) { this->m_no_mod_mode_isSet = true; } +qint32 +SWGRtlSdrSettings::getOffsetTuning() { + return offset_tuning; +} +void +SWGRtlSdrSettings::setOffsetTuning(qint32 offset_tuning) { + this->offset_tuning = offset_tuning; + this->m_offset_tuning_isSet = true; +} + qint32 SWGRtlSdrSettings::getTransverterMode() { return transverter_mode; @@ -391,6 +411,7 @@ SWGRtlSdrSettings::isSet(){ if(m_iq_imbalance_isSet){ isObjectUpdated = true; break;} if(m_agc_isSet){ isObjectUpdated = true; break;} if(m_no_mod_mode_isSet){ isObjectUpdated = true; break;} + if(m_offset_tuning_isSet){ isObjectUpdated = true; break;} if(m_transverter_mode_isSet){ isObjectUpdated = true; break;} if(m_transverter_delta_frequency_isSet){ isObjectUpdated = true; break;} if(m_rf_bandwidth_isSet){ isObjectUpdated = true; break;} diff --git a/swagger/sdrangel/code/qt5/client/SWGRtlSdrSettings.h b/swagger/sdrangel/code/qt5/client/SWGRtlSdrSettings.h index 4044644ea..16c1dcdff 100644 --- a/swagger/sdrangel/code/qt5/client/SWGRtlSdrSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGRtlSdrSettings.h @@ -75,6 +75,9 @@ public: qint32 getNoModMode(); void setNoModMode(qint32 no_mod_mode); + qint32 getOffsetTuning(); + void setOffsetTuning(qint32 offset_tuning); + qint32 getTransverterMode(); void setTransverterMode(qint32 transverter_mode); @@ -124,6 +127,9 @@ private: qint32 no_mod_mode; bool m_no_mod_mode_isSet; + qint32 offset_tuning; + bool m_offset_tuning_isSet; + qint32 transverter_mode; bool m_transverter_mode_isSet; From a79cfbfb4edc9c53ad0e32136073c186a83b725b Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 27 Nov 2018 00:15:48 +0100 Subject: [PATCH 088/102] RTLSDR: offset tuning documentation --- doc/img/RTLSDR_plugin.png | Bin 27596 -> 28517 bytes doc/img/RTLSDR_plugin.xcf | Bin 163456 -> 168427 bytes plugins/samplesource/rtlsdr/readme.md | 8 ++++++-- plugins/samplesource/rtlsdr/rtlsdrplugin.cpp | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/img/RTLSDR_plugin.png b/doc/img/RTLSDR_plugin.png index d90f96a35be11acd4bd58c6628d7bf3106bc590f..a3db93d9c3a11e0cfc14f885d6e5971caf09df59 100644 GIT binary patch delta 10234 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 ATL1t6 delta 9306 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 KUTs9: RF bandwidth +

9: Offset tuning

+ +This controls the offset tuning. Some RF frontends like the obsolete E4000 implement this feature and it can seriously reduce the central DC peak without digital correction. This does not work for the R820T and R820T2 that are very popular on which it will produce no effect. However these RF frontends exhibit a central DC peak much smaller than on the E4000 and can be easly corrected digitally via control (3). + +

10: RF bandwidth

This controls the tuner filter bandwidth and can be varied from 350 kHz to 8 MHz. In practice depending on the value this appears to be larger and the filter center is slightly offset above the center frequency. This can still be very useful to eliminate or attenuate large signals outside the device to host I/Q stream passband. -

10: RF gain and AGC

+

11: RF gain and AGC

The slider sets RF gain in dB. The values are defined in the RTLSDR device and generally are: 0.0, 0.9, 1.4, 2.7, 3.7, 7.7, 8.7, 12.5, 14.4, 15.7, 16.6, 19.7, 20.7, 22.9, 25.4, 28.0, 29.7, 32.8, 33.8, 36.4, 37.2, 38.6, 40.2, 42.1, 43.4, 43.9, 44.5, 48.0, 49.6 diff --git a/plugins/samplesource/rtlsdr/rtlsdrplugin.cpp b/plugins/samplesource/rtlsdr/rtlsdrplugin.cpp index e4d4c5959..ebde7cd55 100644 --- a/plugins/samplesource/rtlsdr/rtlsdrplugin.cpp +++ b/plugins/samplesource/rtlsdr/rtlsdrplugin.cpp @@ -14,7 +14,7 @@ const PluginDescriptor RTLSDRPlugin::m_pluginDescriptor = { QString("RTL-SDR Input"), - QString("4.0.6"), + QString("4.3.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, From 468fab5c5e626bbba305eefe7c72b94e003d3bfb Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 27 Nov 2018 23:44:11 +0100 Subject: [PATCH 089/102] SoapySDR support: set a minimum read or write timeout of 250ms --- plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp | 6 ++++-- plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp b/plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp index 3b2cc4175..50df22745 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputthread.cpp @@ -124,9 +124,11 @@ void SoapySDROutputThread::run() int flags(0); long long timeNs(0); float blockTime = ((float) numElems) / (m_sampleRate <= 0 ? 1024000 : m_sampleRate); - long timeoutUs = 10000000 * blockTime; // 10 times the block time + long initialTtimeoutUs = 10000000 * blockTime; // 10 times the block time + long timeoutUs = initialTtimeoutUs < 250000 ? 250000 : initialTtimeoutUs; // 250ms minimum - qDebug("SoapySDROutputThread::run: numElems: %u elemSize: %u timeoutUs: %ld", numElems, elemSize, timeoutUs); + qDebug("SoapySDROutputThread::run: numElems: %u elemSize: %u initialTtimeoutUs: %ld timeoutUs: %ld", + numElems, elemSize, initialTtimeoutUs, timeoutUs); qDebug("SoapySDROutputThread::run: start running loop"); while (m_running) diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp index 97ab36586..e01164aaf 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputthread.cpp @@ -129,9 +129,11 @@ void SoapySDRInputThread::run() int flags(0); long long timeNs(0); float blockTime = ((float) numElems) / (m_sampleRate <= 0 ? 1024000 : m_sampleRate); - long timeoutUs = 10000000 * blockTime; // 10 times the block time + long initialTtimeoutUs = 10000000 * blockTime; // 10 times the block time + long timeoutUs = initialTtimeoutUs < 250000 ? 250000 : initialTtimeoutUs; // 250ms minimum - qDebug("SoapySDRInputThread::run: numElems: %u elemSize: %u timeoutUs: %ld", numElems, elemSize, timeoutUs); + qDebug("SoapySDRInputThread::run: numElems: %u elemSize: %u initialTtimeoutUs: %ld timeoutUs: %ld", + numElems, elemSize, initialTtimeoutUs, timeoutUs); qDebug("SoapySDRInputThread::run: start running loop"); while (m_running) From c8480a58fe9cf5b26e0d2e48045d8c448a184579 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 27 Nov 2018 23:47:04 +0100 Subject: [PATCH 090/102] SoapySDR support: increment version --- debian/changelog | 1 + plugins/samplesink/soapysdroutput/soapysdroutputplugin.cpp | 2 +- plugins/samplesource/soapysdrinput/soapysdrinputplugin.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 753586486..ed647bf77 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ sdrangel (4.3.1-1) unstable; urgency=medium * RTL-SDR: offset tuning support + * SoapySDR support: 250 ms minimum timeout -- Edouard Griffiths, F4EXB Sun, 02 Dec 2018 21:14:18 +0100 diff --git a/plugins/samplesink/soapysdroutput/soapysdroutputplugin.cpp b/plugins/samplesink/soapysdroutput/soapysdroutputplugin.cpp index cdb6def6d..87a641ed3 100644 --- a/plugins/samplesink/soapysdroutput/soapysdroutputplugin.cpp +++ b/plugins/samplesink/soapysdroutput/soapysdroutputplugin.cpp @@ -31,7 +31,7 @@ const PluginDescriptor SoapySDROutputPlugin::m_pluginDescriptor = { QString("SoapySDR Output"), - QString("4.3.0"), + QString("4.3.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputplugin.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputplugin.cpp index f0e6ed867..d103760d2 100644 --- a/plugins/samplesource/soapysdrinput/soapysdrinputplugin.cpp +++ b/plugins/samplesource/soapysdrinput/soapysdrinputplugin.cpp @@ -30,7 +30,7 @@ const PluginDescriptor SoapySDRInputPlugin::m_pluginDescriptor = { QString("SoapySDR Input"), - QString("4.3.0"), + QString("4.3.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, From 788ffa7c8684331a6d785770b4e6ed438d911af7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 28 Nov 2018 08:51:55 +0100 Subject: [PATCH 091/102] DATV demod: adapt to MSVC --- .../channelrx/demoddatv/datvconstellation.h | 1 - .../channelrx/demoddatv/datvideostream.cpp | 2 -- plugins/channelrx/demoddatv/leansdr/dvb.h | 21 ++++++++------- plugins/channelrx/demoddatv/leansdr/generic.h | 26 +++++++++++++++++++ 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/plugins/channelrx/demoddatv/datvconstellation.h b/plugins/channelrx/demoddatv/datvconstellation.h index dc97744e8..091bed139 100644 --- a/plugins/channelrx/demoddatv/datvconstellation.h +++ b/plugins/channelrx/demoddatv/datvconstellation.h @@ -19,7 +19,6 @@ #ifndef DATVCONSTELLATION_H #define DATVCONSTELLATION_H -#include #include #include "leansdr/framework.h" diff --git a/plugins/channelrx/demoddatv/datvideostream.cpp b/plugins/channelrx/demoddatv/datvideostream.cpp index fc89f6d1c..fbe644ed5 100644 --- a/plugins/channelrx/demoddatv/datvideostream.cpp +++ b/plugins/channelrx/demoddatv/datvideostream.cpp @@ -49,8 +49,6 @@ void DATVideostream::cleanUp() m_objeventLoop.exit(); } - m_objMutex.unlock(); - m_intBytesAvailable=0; m_intBytesWaiting=0; m_intQueueWaiting=0; diff --git a/plugins/channelrx/demoddatv/leansdr/dvb.h b/plugins/channelrx/demoddatv/leansdr/dvb.h index 3bd9a624a..474eab072 100644 --- a/plugins/channelrx/demoddatv/leansdr/dvb.h +++ b/plugins/channelrx/demoddatv/leansdr/dvb.h @@ -668,16 +668,17 @@ static struct fec_spec int bits_in; // Entering the convolutional coder int bits_out; // Exiting the convolutional coder const uint16_t *polys; // [bits_out] -} fec_specs[FEC_MAX] = -{ [FEC12] = -{ 1, 2, polys_fec12 }, [FEC23] = -{ 2, 3, polys_fec23 }, [FEC46] = -{ 4, 6, polys_fec46 }, [FEC34] = -{ 3, 4, polys_fec34 }, [FEC56] = -{ 5, 6, polys_fec56 }, [FEC78] = -{ 7, 8, polys_fec78 }, [FEC45] = -{ 4, 5, polys_fec45 }, // Non-standard - }; +} + +fec_specs[FEC_MAX] = { + [FEC12] = { 1, 2, polys_fec12 }, + [FEC23] = { 2, 3, polys_fec23 }, + [FEC46] = { 4, 6, polys_fec46 }, + [FEC34] = { 3, 4, polys_fec34 }, + [FEC56] = { 5, 6, polys_fec56 }, + [FEC78] = { 7, 8, polys_fec78 }, + [FEC45] = { 4, 5, polys_fec45 }, // Non-standard +}; struct dvb_convol: runnable { diff --git a/plugins/channelrx/demoddatv/leansdr/generic.h b/plugins/channelrx/demoddatv/leansdr/generic.h index 206b15473..d7e541d28 100644 --- a/plugins/channelrx/demoddatv/leansdr/generic.h +++ b/plugins/channelrx/demoddatv/leansdr/generic.h @@ -2,7 +2,13 @@ #define LEANSDR_GENERIC_H #include + +#ifdef _MSC_VER +#include +#include +#else #include +#endif #include "leansdr/math.h" @@ -29,7 +35,11 @@ struct file_reader: runnable if (!size) return; +#ifdef _MSC_VER + again: ssize_t nr = _read(fdin, out.wr(), size); +#else again: ssize_t nr = read(fdin, out.wr(), size); +#endif if (nr < 0) { fatal("leansdr::file_reader::run: read"); @@ -41,7 +51,11 @@ struct file_reader: runnable return; if (sch->debug) fprintf(stderr, "leansdr::file_reader::run: %s looping\n", name); +#ifdef _MSC_VER + off_t res = _lseek(fdin, 0, SEEK_SET); +#else off_t res = lseek(fdin, 0, SEEK_SET); +#endif if (res == (off_t) -1) { fatal("leansdr::file_reader::run: lseek"); @@ -57,7 +71,11 @@ struct file_reader: runnable { if (sch->debug) fprintf(stderr, "+"); +#ifdef _MSC_VER + ssize_t nr2 = _read(fdin, (char*) out.wr() + nr, remain); +#else ssize_t nr2 = read(fdin, (char*) out.wr() + nr, remain); +#endif if (nr2 <= 0) { fatal("leansdr::file_reader::run: partial read"); @@ -89,7 +107,11 @@ struct file_writer: runnable int size = in.readable() * sizeof(T); if (!size) return; +#ifdef _MSC_VER + int nw = _write(fdout, in.rd(), size); +#else int nw = write(fdout, in.rd(), size); +#endif if (!nw) { fatal("leansdr::file_writer::run: pipe"); @@ -138,7 +160,11 @@ struct file_printer: runnable fatal("leansdr::file_printer::run: obsolete glibc"); return; } +#ifdef _MSC_VER + int nw = _write(fdout, buf, len); +#else int nw = write(fdout, buf, len); +#endif if (nw != len) { fatal("leansdr::file_printer::run: partial write"); From 6f4969f4170866483d1a6d2c30bd269223306127 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 28 Nov 2018 10:57:03 +0100 Subject: [PATCH 092/102] Windows MSVC2017: include DATV Demod --- plugins/channelrx/demoddatv/demoddatv.pro | 18 ++++++++++-------- plugins/channelrx/demoddatv/leansdr/dvb.h | 14 +++++++------- plugins/channelrx/demoddatv/leansdr/math.h | 1 + sdrangel.windows.pro | 1 + windowsms.install.bat | 5 +++++ 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/plugins/channelrx/demoddatv/demoddatv.pro b/plugins/channelrx/demoddatv/demoddatv.pro index c02e89ad5..46c0404d9 100644 --- a/plugins/channelrx/demoddatv/demoddatv.pro +++ b/plugins/channelrx/demoddatv/demoddatv.pro @@ -7,7 +7,7 @@ TEMPLATE = lib CONFIG += plugin -QT += core gui multimedia multimediawidgets widgets opengl +QT += core gui multimedia multimediawidgets widgets opengl qml TARGET = demoddatv @@ -18,25 +18,26 @@ QMAKE_CXXFLAGS += -msse4.1 QMAKE_CXXFLAGS += -std=c++11 INCLUDEPATH += $$PWD +INCLUDEPATH += ../../../exports INCLUDEPATH += ../../../sdrbase INCLUDEPATH += ../../../sdrgui CONFIG(Release):build_subdir = release CONFIG(Debug):build_subdir = debug -CONFIG(MINGW32):INCLUDEPATH += "D:\boost_1_58_0" -CONFIG(MINGW64):INCLUDEPATH += "D:\boost_1_58_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\ffmpeg-20181127-1035206-win64-dev\include" CONFIG(macx):INCLUDEPATH += "../../../../../boost_1_64_0" SOURCES += datvdemod.cpp\ - datvdemodgui.cpp\ - datvdemodplugin.cpp\ + datvdemodgui.cpp\ + datvdemodplugin.cpp\ datvideostream.cpp \ datvideorender.cpp HEADERS += datvdemod.h\ - datvdemodgui.h\ - datvdemodplugin.h\ + datvdemodgui.h\ + datvdemodplugin.h\ leansdr/convolutional.h \ leansdr/dsp.h \ leansdr/dvb.h \ @@ -58,6 +59,7 @@ FORMS += datvdemodgui.ui LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui -LIBS += -lavutil -lswscale -lavdevice -lavformat -lavcodec -lswresample +#LIBS += -lavutil -lswscale -lavdevice -lavformat -lavcodec -lswresample +LIBS += -L"C:\softs\ffmpeg-20181127-1035206-win64-dev\lib" -lavutil -lswscale -lavdevice -lavformat -lavcodec -lswresample RESOURCES = ../../../sdrbase/resources/res.qrc diff --git a/plugins/channelrx/demoddatv/leansdr/dvb.h b/plugins/channelrx/demoddatv/leansdr/dvb.h index 474eab072..8cde82b79 100644 --- a/plugins/channelrx/demoddatv/leansdr/dvb.h +++ b/plugins/channelrx/demoddatv/leansdr/dvb.h @@ -671,13 +671,13 @@ static struct fec_spec } fec_specs[FEC_MAX] = { - [FEC12] = { 1, 2, polys_fec12 }, - [FEC23] = { 2, 3, polys_fec23 }, - [FEC46] = { 4, 6, polys_fec46 }, - [FEC34] = { 3, 4, polys_fec34 }, - [FEC56] = { 5, 6, polys_fec56 }, - [FEC78] = { 7, 8, polys_fec78 }, - [FEC45] = { 4, 5, polys_fec45 }, // Non-standard + { 1, 2, polys_fec12 }, + { 2, 3, polys_fec23 }, + { 4, 6, polys_fec46 }, + { 3, 4, polys_fec34 }, + { 5, 6, polys_fec56 }, + { 7, 8, polys_fec78 }, + { 4, 5, polys_fec45 }, // Non-standard }; struct dvb_convol: runnable diff --git a/plugins/channelrx/demoddatv/leansdr/math.h b/plugins/channelrx/demoddatv/leansdr/math.h index 26a94b250..ada707f17 100644 --- a/plugins/channelrx/demoddatv/leansdr/math.h +++ b/plugins/channelrx/demoddatv/leansdr/math.h @@ -1,6 +1,7 @@ #ifndef LEANSDR_MATH_H #define LEANSDR_MATH_H +#define _USE_MATH_DEFINES #include #include diff --git a/sdrangel.windows.pro b/sdrangel.windows.pro index 3b6221a55..0cec85c84 100644 --- a/sdrangel.windows.pro +++ b/sdrangel.windows.pro @@ -53,6 +53,7 @@ SUBDIRS += plugins/channelrx/chanalyzer SUBDIRS += plugins/channelrx/demodam SUBDIRS += plugins/channelrx/demodatv SUBDIRS += plugins/channelrx/demodbfm +CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demoddatv CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demoddsd CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demodlora SUBDIRS += plugins/channelrx/demodnfm diff --git a/windowsms.install.bat b/windowsms.install.bat index ee5c32671..e7022b617 100644 --- a/windowsms.install.bat +++ b/windowsms.install.bat @@ -5,6 +5,8 @@ SET libiconvdir="C:\softs\iconv-1.9.2.win32" SET libzlib1dir="C:\softs\zlib-1.2.5" SET pothosdir="C:\Program Files\PothosSDR" SET pthreadsdir="C:\softs\pthreads-w32" +SET ffmpegdir="C:\softs\ffmpeg-20181127-1035206-win64-shared\bin" +SET qt5dir="C:\Qt\5.11.1\msvc2017_64\bin" copy app\%1\sdrangel.exe %2 copy sdrbase\%1\sdrbase.dll %2 @@ -39,6 +41,8 @@ REM copy %opencvdir%\opencv_ffmpeg2413.dll %2 REM copy %opencvdir%\libopencv_imgproc2413.dll %2 REM copy %opencvdir%\libopencv_highgui2413.dll %2 REM copy %opencvdir%\libopencv_core2413.dll %2 +copy %ffmpegdir%\*.dll %2 +copy %qt5dir%\Qt5Qml.dll %2 mkdir %2\plugins mkdir %2\plugins\channelrx @@ -50,6 +54,7 @@ copy plugins\channelrx\chanalyzer\%1\chanalyzer.dll %2\plugins\channelrx copy plugins\channelrx\demodam\%1\demodam.dll %2\plugins\channelrx copy plugins\channelrx\demodatv\%1\demodatv.dll %2\plugins\channelrx copy plugins\channelrx\demodbfm\%1\demodbfm.dll %2\plugins\channelrx +copy plugins\channelrx\demoddatv\%1\demoddatv.dll %2\plugins\channelrx REM copy plugins\channelrx\demoddsd\%1\demoddsd.dll %2\plugins\channelrx REM copy plugins\channelrx\demodlora\%1\demodlora.dll %2\plugins\channelrx copy plugins\channelrx\demodnfm\%1\demodnfm.dll %2\plugins\channelrx From 98544d9dd97f7f86bb5bdb1c22c301ea670ec8a3 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 28 Nov 2018 11:13:27 +0100 Subject: [PATCH 093/102] Windows MSVC2017: include DATV Demod: fixed main .pro file --- sdrangel.windows.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdrangel.windows.pro b/sdrangel.windows.pro index 0cec85c84..e3d5885f6 100644 --- a/sdrangel.windows.pro +++ b/sdrangel.windows.pro @@ -53,7 +53,7 @@ SUBDIRS += plugins/channelrx/chanalyzer SUBDIRS += plugins/channelrx/demodam SUBDIRS += plugins/channelrx/demodatv SUBDIRS += plugins/channelrx/demodbfm -CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demoddatv +CONFIG(MSVC):SUBDIRS += plugins/channelrx/demoddatv CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demoddsd CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demodlora SUBDIRS += plugins/channelrx/demodnfm From 35e787f89b82fe915a6f83951c0211a6c02b3aa0 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 28 Nov 2018 14:23:25 +0100 Subject: [PATCH 094/102] Windows MSVC2017: added DSD demodulator --- dsdcc/dsdcc.pro | 9 +++++++-- mbelib/mbelib.pro | 3 +++ plugins/channelrx/demoddatv/datvdemodplugin.cpp | 2 +- plugins/channelrx/demoddsd/demoddsd.pro | 3 +++ plugins/channelrx/demoddsd/dsddemodplugin.cpp | 2 +- sdrangel.windows.pro | 4 ++-- windowsms.install.bat | 4 ++-- 7 files changed, 19 insertions(+), 8 deletions(-) diff --git a/dsdcc/dsdcc.pro b/dsdcc/dsdcc.pro index e89ae3230..89dc3b67a 100644 --- a/dsdcc/dsdcc.pro +++ b/dsdcc/dsdcc.pro @@ -9,6 +9,8 @@ QT += core TEMPLATE = lib TARGET = dsdcc +CONFIG(MSVC):DEFINES += dsdcc_EXPORTS + CONFIG(MINGW32):LIBDSDCCSRC = "C:\softs\dsdcc" CONFIG(MINGW64):LIBDSDCCSRC = "C:\softs\dsdcc" CONFIG(MSVC):LIBDSDCCSRC = "C:\softs\dsdcc" @@ -52,7 +54,8 @@ $$LIBDSDCCSRC/viterbi5.cpp\ $$LIBDSDCCSRC/pn.cpp\ $$LIBDSDCCSRC/mbefec.cpp\ $$LIBDSDCCSRC/phaselock.cpp\ -$$LIBDSDCCSRC/locator.cpp +$$LIBDSDCCSRC/locator.cpp\ +$$LIBDSDCCSRC/timeutil.cpp HEADERS = $$LIBDSDCCSRC/descramble.h\ $$LIBDSDCCSRC/dmr.h\ @@ -82,6 +85,8 @@ $$LIBDSDCCSRC/viterbi5.h\ $$LIBDSDCCSRC/pn.h\ $$LIBDSDCCSRC/mbefec.h\ $$LIBDSDCCSRC/phaselock.h\ -$$LIBDSDCCSRC/locator.h +$$LIBDSDCCSRC/locator.h\ +$$LIBDSDCCSRC/timeutil.h\ +$$LIBDSDCCSRC/export.h LIBS += -L../mbelib/$${build_subdir} -lmbelib diff --git a/mbelib/mbelib.pro b/mbelib/mbelib.pro index 9fa45a02b..57cb623f2 100644 --- a/mbelib/mbelib.pro +++ b/mbelib/mbelib.pro @@ -9,6 +9,8 @@ QT += core TEMPLATE = lib TARGET = mbelib +CONFIG(MSVC):DEFINES += mbelib_EXPORTS + CONFIG(MINGW32):LIBMBELIBSRC = "C:\softs\mbelib" CONFIG(MINGW64):LIBMBELIBSRC = "C:\softs\mbelib" CONFIG(MSVC):LIBMBELIBSRC = "C:\softs\mbelib" @@ -28,4 +30,5 @@ $$LIBMBELIBSRC/ambe3600x2450_const.h\ $$LIBMBELIBSRC/ecc_const.h\ $$LIBMBELIBSRC/imbe7200x4400_const.h\ $$LIBMBELIBSRC/mbelib.h\ +$$LIBMBELIBSRC/export.h\ $$LIBMBELIBSRC/mbelib_const.h diff --git a/plugins/channelrx/demoddatv/datvdemodplugin.cpp b/plugins/channelrx/demoddatv/datvdemodplugin.cpp index 346a898ff..0fe293803 100644 --- a/plugins/channelrx/demoddatv/datvdemodplugin.cpp +++ b/plugins/channelrx/demoddatv/datvdemodplugin.cpp @@ -27,7 +27,7 @@ const PluginDescriptor DATVDemodPlugin::m_ptrPluginDescriptor = { QString("DATV Demodulator"), - QString("4.0.1"), + QString("4.3.1"), QString("(c) F4HKW for SDRAngel using LeanSDR framework (c) F4DAV"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/channelrx/demoddsd/demoddsd.pro b/plugins/channelrx/demoddsd/demoddsd.pro index 8b8c96bc7..d9e085168 100644 --- a/plugins/channelrx/demoddsd/demoddsd.pro +++ b/plugins/channelrx/demoddsd/demoddsd.pro @@ -19,14 +19,17 @@ QMAKE_CXXFLAGS += -std=c++11 CONFIG(MINGW32):LIBDSDCCSRC = "C:\softs\dsdcc" CONFIG(MINGW64):LIBDSDCCSRC = "C:\softs\dsdcc" +CONFIG(MSVC):LIBDSDCCSRC = "C:\softs\dsdcc" CONFIG(macx):LIBDSDCCSRC = "../../../../deps/dsdcc" CONFIG(MINGW32):LIBMBELIBSRC = "C:\softs\mbelib" CONFIG(MINGW64):LIBMBELIBSRC = "C:\softs\mbelib" +CONFIG(MSVC):LIBMBELIBSRC = "C:\softs\mbelib" CONFIG(macx):LIBMBELIBSRC = "../../../../deps/mbelib" CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(MINGW64):INCLUDEPATH += "C:\softs\boost_1_66_0" +CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0" CONFIG(macx):INCLUDEPATH += "../../../../../boost_1_64_0" INCLUDEPATH += $$PWD diff --git a/plugins/channelrx/demoddsd/dsddemodplugin.cpp b/plugins/channelrx/demoddsd/dsddemodplugin.cpp index 0d14131da..4f8835841 100644 --- a/plugins/channelrx/demoddsd/dsddemodplugin.cpp +++ b/plugins/channelrx/demoddsd/dsddemodplugin.cpp @@ -27,7 +27,7 @@ const PluginDescriptor DSDDemodPlugin::m_pluginDescriptor = { QString("DSD Demodulator"), - QString("4.2.4"), + QString("4.3.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/sdrangel.windows.pro b/sdrangel.windows.pro index e3d5885f6..a85891506 100644 --- a/sdrangel.windows.pro +++ b/sdrangel.windows.pro @@ -27,7 +27,7 @@ CONFIG(!MSVC):SUBDIRS += libperseus SUBDIRS += librtlsdr SUBDIRS += devices SUBDIRS += mbelib -CONFIG(!MSVC):SUBDIRS += dsdcc +SUBDIRS += dsdcc CONFIG(MSVC):SUBDIRS += cm256cc SUBDIRS += plugins/samplesource/airspy SUBDIRS += plugins/samplesource/airspyhf @@ -54,7 +54,7 @@ SUBDIRS += plugins/channelrx/demodam SUBDIRS += plugins/channelrx/demodatv SUBDIRS += plugins/channelrx/demodbfm CONFIG(MSVC):SUBDIRS += plugins/channelrx/demoddatv -CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demoddsd +SUBDIRS += plugins/channelrx/demoddsd CONFIG(!MSVC):SUBDIRS += plugins/channelrx/demodlora SUBDIRS += plugins/channelrx/demodnfm SUBDIRS += plugins/channelrx/demodssb diff --git a/windowsms.install.bat b/windowsms.install.bat index e7022b617..6453a7233 100644 --- a/windowsms.install.bat +++ b/windowsms.install.bat @@ -14,7 +14,7 @@ copy sdrbase\res.qrb %2\sdrbase.rcc copy sdrgui\%1\sdrgui.dll %2 copy devices\%1\devices.dll %2 copy mbelib\%1\mbelib.dll %2 -REM copy dsdcc\%1\dsdcc.dll %2 +copy dsdcc\%1\dsdcc.dll %2 copy serialdv\%1\serialdv.dll %2 copy httpserver\%1\httpserver.dll %2 copy qrtplib\%1\qrtplib.dll %2 @@ -55,7 +55,7 @@ copy plugins\channelrx\demodam\%1\demodam.dll %2\plugins\channelrx copy plugins\channelrx\demodatv\%1\demodatv.dll %2\plugins\channelrx copy plugins\channelrx\demodbfm\%1\demodbfm.dll %2\plugins\channelrx copy plugins\channelrx\demoddatv\%1\demoddatv.dll %2\plugins\channelrx -REM copy plugins\channelrx\demoddsd\%1\demoddsd.dll %2\plugins\channelrx +copy plugins\channelrx\demoddsd\%1\demoddsd.dll %2\plugins\channelrx REM copy plugins\channelrx\demodlora\%1\demodlora.dll %2\plugins\channelrx copy plugins\channelrx\demodnfm\%1\demodnfm.dll %2\plugins\channelrx copy plugins\channelrx\demodssb\%1\demodssb.dll %2\plugins\channelrx From f96978d1960b9c56996fc3e2db69730eea4ebbc9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 28 Nov 2018 18:30:11 +0100 Subject: [PATCH 095/102] Windows MSVC2017: PlutoSDR support --- devices/devices.pro | 13 ++++++++++ devices/plutosdr/deviceplutosdrbox.h | 5 ++++ devices/plutosdr/deviceplutosdrparams.h | 2 +- devices/plutosdr/deviceplutosdrshared.h | 2 +- .../plutosdroutput/plutosdroutput.pro | 24 ++++++++++++++----- .../plutosdroutput/plutosdroutputthread.cpp | 2 -- .../plutosdrinput/plutosdrinput.pro | 24 ++++++++++++++----- .../plutosdrinput/plutosdrinputthread.cpp | 2 -- windowsms.install.bat | 6 ++--- 9 files changed, 59 insertions(+), 21 deletions(-) diff --git a/devices/devices.pro b/devices/devices.pro index 4d34d5297..c06a7188e 100644 --- a/devices/devices.pro +++ b/devices/devices.pro @@ -156,6 +156,12 @@ MSVC { soapysdr/devicesoapysdrscan.cpp\ soapysdr/devicesoapysdrshared.cpp + SOURCES += plutosdr/deviceplutosdr.cpp\ + plutosdr/deviceplutosdrbox.cpp\ + plutosdr/deviceplutosdrparams.cpp\ + plutosdr/deviceplutosdrscan.cpp\ + plutosdr/deviceplutosdrshared.cpp + HEADERS += bladerf1/devicebladerf1.h\ bladerf1/devicebladerf1param.h\ bladerf1/devicebladerf1values.h\ @@ -177,6 +183,12 @@ MSVC { soapysdr/devicesoapysdrparams.h\ soapysdr/devicesoapysdrscan.h\ soapysdr/devicesoapysdrshared.h + + HEADERS += plutosdr/deviceplutosdr.h\ + plutosdr/deviceplutosdrbox.h\ + plutosdr/deviceplutosdrparams.h\ + plutosdr/deviceplutosdrscan.h\ + plutosdr/deviceplutosdrshared.h } LIBS += -L../sdrbase/$${build_subdir} -lsdrbase @@ -199,4 +211,5 @@ MSVC { LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lbladeRF LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lLimeSuite LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -lSoapySDR + LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -llibiio } diff --git a/devices/plutosdr/deviceplutosdrbox.h b/devices/plutosdr/deviceplutosdrbox.h index 4941ff30b..c3487c833 100644 --- a/devices/plutosdr/deviceplutosdrbox.h +++ b/devices/plutosdr/deviceplutosdrbox.h @@ -24,6 +24,11 @@ #include "export.h" +#if defined(_MSC_VER) +#include +typedef SSIZE_T ssize_t; +#endif + class DEVICES_API DevicePlutoSDRBox { public: diff --git a/devices/plutosdr/deviceplutosdrparams.h b/devices/plutosdr/deviceplutosdrparams.h index 113b05752..4ff154cb6 100644 --- a/devices/plutosdr/deviceplutosdrparams.h +++ b/devices/plutosdr/deviceplutosdrparams.h @@ -30,7 +30,7 @@ class DEVICES_API DevicePlutoSDRBox; * There is only one copy that is constructed by the first participant and destroyed by the last. * A participant knows it is the first or last by checking the lists of buddies (Rx + Tx). */ -class DevicePlutoSDRParams +class DEVICES_API DevicePlutoSDRParams { public: DevicePlutoSDRParams(); diff --git a/devices/plutosdr/deviceplutosdrshared.h b/devices/plutosdr/deviceplutosdrshared.h index 9d98c66a0..78657b369 100644 --- a/devices/plutosdr/deviceplutosdrshared.h +++ b/devices/plutosdr/deviceplutosdrshared.h @@ -42,7 +42,7 @@ public: virtual bool isRunning() = 0; }; - class MsgCrossReportToBuddy : public Message { + class DEVICES_API MsgCrossReportToBuddy : public Message { MESSAGE_CLASS_DECLARATION public: uint64_t getDevSampleRate() const { return m_devSampleRate; } diff --git a/plugins/samplesink/plutosdroutput/plutosdroutput.pro b/plugins/samplesink/plutosdroutput/plutosdroutput.pro index 2d1fd03e4..1cee810e4 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutput.pro +++ b/plugins/samplesink/plutosdroutput/plutosdroutput.pro @@ -17,17 +17,22 @@ DEFINES += USE_SSE4_1=1 QMAKE_CXXFLAGS += -msse4.1 QMAKE_CXXFLAGS += -std=c++11 -CONFIG(MINGW32):LIBIIOSRC = "C:\softs\libiio" -CONFIG(MINGW64):LIBIIOSRC = "C:\softs\libiio" - INCLUDEPATH += $$PWD INCLUDEPATH += ../../../exports INCLUDEPATH += ../../../sdrbase INCLUDEPATH += ../../../sdrgui INCLUDEPATH += ../../../swagger/sdrangel/code/qt5/client INCLUDEPATH += ../../../devices -INCLUDEPATH += ../../../libiio/includemw -INCLUDEPATH += $$LIBIIOSRC + +MINGW32 || MINGW64 { + LIBIIOSRC = "C:\softs\libiio" + INCLUDEPATH += ../../../libiio/includemw + INCLUDEPATH += $$LIBIIOSRC +} + +MSVC { + INCLUDEPATH += "C:\Program Files\PothosSDR\include" +} CONFIG(Release):build_subdir = release CONFIG(Debug):build_subdir = debug @@ -49,7 +54,14 @@ FORMS += plutosdroutputgui.ui LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui LIBS += -L../../../swagger/$${build_subdir} -lswagger -LIBS += -L../../../libiio/$${build_subdir} -llibiio LIBS += -L../../../devices/$${build_subdir} -ldevices +MINGW32 || MINGW64 { + LIBS += -L../../../libiio/$${build_subdir} -llibiio +} + +MSVC { + LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -llibiio +} + RESOURCES = ../../../sdrgui/resources/res.qrc diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp index 88a10bc7a..fd51f6b07 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp @@ -14,8 +14,6 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include - #include "plutosdr/deviceplutosdrbox.h" #include "plutosdroutputsettings.h" #include "iio.h" diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.pro b/plugins/samplesource/plutosdrinput/plutosdrinput.pro index f18fe1bb4..74999834f 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.pro +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.pro @@ -17,17 +17,22 @@ DEFINES += USE_SSE4_1=1 QMAKE_CXXFLAGS += -msse4.1 QMAKE_CXXFLAGS += -std=c++11 -CONFIG(MINGW32):LIBIIOSRC = "C:\softs\libiio" -CONFIG(MINGW64):LIBIIOSRC = "C:\softs\libiio" - INCLUDEPATH += $$PWD INCLUDEPATH += ../../../exports INCLUDEPATH += ../../../sdrbase INCLUDEPATH += ../../../sdrgui INCLUDEPATH += ../../../swagger/sdrangel/code/qt5/client INCLUDEPATH += ../../../devices -INCLUDEPATH += ../../../libiio/includemw -INCLUDEPATH += $$LIBIIOSRC + +MINGW32 || MINGW64 { + LIBIIOSRC = "C:\softs\libiio" + INCLUDEPATH += ../../../libiio/includemw + INCLUDEPATH += $$LIBIIOSRC +} + +MSVC { + INCLUDEPATH += "C:\Program Files\PothosSDR\include" +} CONFIG(Release):build_subdir = release CONFIG(Debug):build_subdir = debug @@ -49,7 +54,14 @@ FORMS += plutosdrinputgui.ui LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui LIBS += -L../../../swagger/$${build_subdir} -lswagger -LIBS += -L../../../libiio/$${build_subdir} -llibiio LIBS += -L../../../devices/$${build_subdir} -ldevices +MINGW32 || MINGW64 { + LIBS += -L../../../libiio/$${build_subdir} -llibiio +} + +MSVC { + LIBS += -L"C:\Program Files\PothosSDR\bin" -L"C:\Program Files\PothosSDR\lib" -llibiio +} + RESOURCES = ../../../sdrgui/resources/res.qrc diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputthread.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputthread.cpp index a85a078a3..5c0f90c28 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputthread.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputthread.cpp @@ -14,8 +14,6 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include - #include "plutosdr/deviceplutosdrbox.h" #include "plutosdrinputsettings.h" #include "plutosdrinputthread.h" diff --git a/windowsms.install.bat b/windowsms.install.bat index 6453a7233..ea21ba9a5 100644 --- a/windowsms.install.bat +++ b/windowsms.install.bat @@ -27,7 +27,7 @@ copy librtlsdr\%1\librtlsdr.dll %2 copy libairspy\%1\libairspy.dll %2 copy libairspyhf\%1\libairspyhf.dll %2 copy %pothosdir%\bin\bladeRF.dll %2 -REM copy libiio\%1\libiio.dll %2 +copy %pothosdir%\bin\libiio.dll %2 copy %pothosdir%\bin\LimeSuite.dll %2 copy %pothosdir%\bin\SoapySDR.dll %2 @@ -78,7 +78,7 @@ copy plugins\samplesource\airspyhf\%1\inputairspyhf.dll %2\plugins\samplesource copy plugins\samplesource\bladerf1input\%1\inputbladerf1.dll %2\plugins\samplesource copy plugins\samplesource\bladerf2input\%1\inputbladerf2.dll %2\plugins\samplesource copy plugins\samplesource\limesdrinput\%1\inputlimesdr.dll %2\plugins\samplesource -REM copy plugins\samplesource\plutosdrinput\%1\inputplutosdr.dll %2\plugins\samplesource +copy plugins\samplesource\plutosdrinput\%1\inputplutosdr.dll %2\plugins\samplesource copy plugins\samplesource\sdrdaemonsource\%1\inputsdrdaemonsource.dll %2\plugins\samplesource copy plugins\samplesource\soapysdrinput\%1\inputsoapysdr.dll %2\plugins\samplesource @@ -87,6 +87,6 @@ copy plugins\samplesink\bladerf1output\%1\outputbladerf1.dll %2\plugins\samplesi copy plugins\samplesink\bladerf2output\%1\outputbladerf2.dll %2\plugins\samplesink copy plugins\samplesink\hackrfoutput\%1\outputhackrf.dll %2\plugins\samplesink copy plugins\samplesink\limesdroutput\%1\outputlimesdr.dll %2\plugins\samplesink -REM copy plugins\samplesink\plutosdroutput\%1\outputplutosdr.dll %2\plugins\samplesink +copy plugins\samplesink\plutosdroutput\%1\outputplutosdr.dll %2\plugins\samplesink copy plugins\samplesink\sdrdaemonsink\%1\outputsdrdaemonsink.dll %2\plugins\samplesink copy plugins\samplesink\soapysdroutput\%1\outputsoapysdr.dll %2\plugins\samplesink From 5319eac2ff35485d577771bc18ad3c0b03f93045 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 29 Nov 2018 01:21:44 +0100 Subject: [PATCH 096/102] LimeSDR REST API: support GPIO --- debian/changelog | 1 + devices/limesdr/devicelimesdrshared.cpp | 1 + devices/limesdr/devicelimesdrshared.h | 22 +++++ .../limesdroutput/limesdroutput.cpp | 81 +++++++++++++++++- .../limesdroutput/limesdroutputplugin.cpp | 2 +- .../limesdroutput/limesdroutputsettings.cpp | 9 ++ .../limesdroutput/limesdroutputsettings.h | 2 + .../plutosdroutput/plutosdroutputplugin.cpp | 2 +- .../limesdrinput/limesdrinput.cpp | 83 ++++++++++++++++++- .../limesdrinput/limesdrinputplugin.cpp | 2 +- .../limesdrinput/limesdrinputsettings.cpp | 9 ++ .../limesdrinput/limesdrinputsettings.h | 2 + .../plutosdrinput/plutosdrinputplugin.cpp | 2 +- sdrbase/resources/webapi/doc/html2/index.html | 34 +++++++- .../webapi/doc/swagger/include/LimeSdr.yaml | 28 ++++++- .../sdrangel/api/swagger/include/LimeSdr.yaml | 28 ++++++- swagger/sdrangel/code/html2/index.html | 34 +++++++- .../code/qt5/client/SWGLimeSdrInputReport.cpp | 42 ++++++++++ .../code/qt5/client/SWGLimeSdrInputReport.h | 12 +++ .../qt5/client/SWGLimeSdrInputSettings.cpp | 42 ++++++++++ .../code/qt5/client/SWGLimeSdrInputSettings.h | 12 +++ .../qt5/client/SWGLimeSdrOutputReport.cpp | 42 ++++++++++ .../code/qt5/client/SWGLimeSdrOutputReport.h | 12 +++ .../qt5/client/SWGLimeSdrOutputSettings.cpp | 42 ++++++++++ .../qt5/client/SWGLimeSdrOutputSettings.h | 12 +++ 25 files changed, 546 insertions(+), 12 deletions(-) diff --git a/debian/changelog b/debian/changelog index ed647bf77..8c08cd6b8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,7 @@ sdrangel (4.3.1-1) unstable; urgency=medium * RTL-SDR: offset tuning support * SoapySDR support: 250 ms minimum timeout + * LimeSDR REST API: support GPIO -- Edouard Griffiths, F4EXB Sun, 02 Dec 2018 21:14:18 +0100 diff --git a/devices/limesdr/devicelimesdrshared.cpp b/devices/limesdr/devicelimesdrshared.cpp index ba9f4d6f0..c380ea689 100644 --- a/devices/limesdr/devicelimesdrshared.cpp +++ b/devices/limesdr/devicelimesdrshared.cpp @@ -18,6 +18,7 @@ MESSAGE_CLASS_DEFINITION(DeviceLimeSDRShared::MsgReportBuddyChange, Message) MESSAGE_CLASS_DEFINITION(DeviceLimeSDRShared::MsgReportClockSourceChange, Message) +MESSAGE_CLASS_DEFINITION(DeviceLimeSDRShared::MsgReportGPIOChange, Message) MESSAGE_CLASS_DEFINITION(DeviceLimeSDRShared::MsgReportDeviceInfo, Message) const float DeviceLimeSDRShared::m_sampleFifoLengthInSeconds = 0.25; diff --git a/devices/limesdr/devicelimesdrshared.h b/devices/limesdr/devicelimesdrshared.h index 3d98d0923..8e2478008 100644 --- a/devices/limesdr/devicelimesdrshared.h +++ b/devices/limesdr/devicelimesdrshared.h @@ -118,6 +118,28 @@ public: { } }; + class DEVICES_API MsgReportGPIOChange : public Message { + MESSAGE_CLASS_DECLARATION + + public: + uint8_t getGPIODir() const { return m_gpioDir; } + uint8_t getGPIOPins() const { return m_gpioPins; } + + static MsgReportGPIOChange* create(uint8_t gpioDir, uint8_t gpioPins) + { + return new MsgReportGPIOChange(gpioDir, gpioPins); + } + + private: + uint8_t m_gpioDir; + uint8_t m_gpioPins; + + MsgReportGPIOChange(uint8_t gpioDir, uint8_t gpioPins) : + m_gpioDir(gpioDir), + m_gpioPins(gpioPins) + {} + }; + class DEVICES_API ThreadInterface { public: diff --git a/plugins/samplesink/limesdroutput/limesdroutput.cpp b/plugins/samplesink/limesdroutput/limesdroutput.cpp index 1cffadf56..c9bf756a6 100644 --- a/plugins/samplesink/limesdroutput/limesdroutput.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutput.cpp @@ -599,6 +599,17 @@ bool LimeSDROutput::handleMessage(const Message& message) return true; } + else if (DeviceLimeSDRShared::MsgReportGPIOChange::match(message)) + { + DeviceLimeSDRShared::MsgReportGPIOChange& report = (DeviceLimeSDRShared::MsgReportGPIOChange&) message; + + m_settings.m_gpioDir = report.getGPIODir(); + m_settings.m_gpioPins = report.getGPIOPins(); + + // no GUI for the moment only REST API + + return true; + } else if (MsgGetStreamInfo::match(message)) { // qDebug() << "LimeSDROutput::handleMessage: MsgGetStreamInfo"; @@ -700,6 +711,7 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo bool forwardChangeTxDSP = false; bool forwardChangeAllDSP = false; bool forwardClockSource = false; + bool forwardGPIOChange = false; bool ownThreadWasRunning = false; bool doCalibration = false; bool doLPCalibration = false; @@ -916,6 +928,32 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo } } + if ((m_settings.m_gpioDir != settings.m_gpioDir) || force) + { + if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) < 0) + { + qCritical("LimeSDROutput::applySettings: could not set GPIO directions to %u", settings.m_gpioDir); + } + else + { + forwardGPIOChange = true; + qDebug("LimeSDROutput::applySettings: GPIO directions set to %u", settings.m_gpioDir); + } + } + + if ((m_settings.m_gpioPins != settings.m_gpioPins) || force) + { + if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) < 0) + { + qCritical("LimeSDROutput::applySettings: could not set GPIO pins to %u", settings.m_gpioPins); + } + else + { + forwardGPIOChange = true; + qDebug("LimeSDROutput::applySettings: GPIO pins set to %u", settings.m_gpioPins); + } + } + m_settings = settings; double clockGenFreqAfter; @@ -1072,6 +1110,30 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo } } + if (forwardGPIOChange) + { + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); + + for (; itSource != sourceBuddies.end(); ++itSource) + { + DeviceLimeSDRShared::MsgReportGPIOChange *report = DeviceLimeSDRShared::MsgReportGPIOChange::create( + m_settings.m_gpioDir, m_settings.m_gpioPins); + (*itSource)->getSampleSourceInputMessageQueue()->push(report); + } + + // send to sink buddies + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceLimeSDRShared::MsgReportGPIOChange *report = DeviceLimeSDRShared::MsgReportGPIOChange::create( + m_settings.m_gpioDir, m_settings.m_gpioPins); + (*itSink)->getSampleSinkInputMessageQueue()->push(report); + } + } + QLocale loc; qDebug().noquote() << "LimeSDROutput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz" @@ -1092,6 +1154,8 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo << " m_antennaPath: " << m_settings.m_antennaPath << " m_extClock: " << m_settings.m_extClock << " m_extClockFreq: " << loc.toString(m_settings.m_extClockFreq) + << " m_gpioDir: " << m_settings.m_gpioDir + << " m_gpioPins: " << m_settings.m_gpioPins << " force: " << force << " forceNCOFrequency: " << forceNCOFrequency << " doCalibration: " << doCalibration @@ -1165,6 +1229,12 @@ int LimeSDROutput::webapiSettingsPutPatch( if (deviceSettingsKeys.contains("transverterMode")) { settings.m_transverterMode = response.getLimeSdrOutputSettings()->getTransverterMode() != 0; } + if (deviceSettingsKeys.contains("gpioDir")) { + settings.m_gpioDir = response.getLimeSdrOutputSettings()->getGpioDir() & 0xFF; + } + if (deviceSettingsKeys.contains("gpioPins")) { + settings.m_gpioPins = response.getLimeSdrOutputSettings()->getGpioPins() & 0xFF; + } MsgConfigureLimeSDR *msg = MsgConfigureLimeSDR::create(settings, force); m_inputMessageQueue.push(msg); @@ -1206,6 +1276,8 @@ void LimeSDROutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& r response.getLimeSdrOutputSettings()->setNcoFrequency(settings.m_ncoFrequency); response.getLimeSdrOutputSettings()->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency); response.getLimeSdrOutputSettings()->setTransverterMode(settings.m_transverterMode ? 1 : 0); + response.getLimeSdrOutputSettings()->setGpioDir(settings.m_gpioDir); + response.getLimeSdrOutputSettings()->setGpioPins(settings.m_gpioPins); } int LimeSDROutput::webapiRunGet( @@ -1240,6 +1312,8 @@ void LimeSDROutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respo { bool success = false; double temp = 0.0; + uint8_t gpioDir = 0; + uint8_t gpioPins = 0; lms_stream_status_t status; status.active = false; status.fifoFilledCount = 0; @@ -1262,9 +1336,14 @@ void LimeSDROutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respo response.getLimeSdrOutputReport()->setLinkRate(status.linkRate); response.getLimeSdrOutputReport()->setHwTimestamp(status.timestamp); - if (m_deviceShared.m_deviceParams->getDevice()) { + if (m_deviceShared.m_deviceParams->getDevice()) + { LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp); + LMS_GPIODirRead(m_deviceShared.m_deviceParams->getDevice(), &gpioDir, 1); + LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1); } response.getLimeSdrOutputReport()->setTemperature(temp); + response.getLimeSdrOutputReport()->setGpioDir(gpioDir); + response.getLimeSdrOutputReport()->setGpioPins(gpioPins); } diff --git a/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp b/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp index 1c4d765e9..4764834d6 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutputplugin.cpp @@ -34,7 +34,7 @@ const PluginDescriptor LimeSDROutputPlugin::m_pluginDescriptor = { QString("LimeSDR Output"), - QString("4.2.4"), + QString("4.3.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesink/limesdroutput/limesdroutputsettings.cpp b/plugins/samplesink/limesdroutput/limesdroutputsettings.cpp index 96270d375..3983126af 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputsettings.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutputsettings.cpp @@ -40,6 +40,8 @@ void LimeSDROutputSettings::resetToDefaults() m_extClockFreq = 10000000; // 10 MHz m_transverterMode = false; m_transverterDeltaFrequency = 0; + m_gpioDir = 0; + m_gpioPins = 0; } QByteArray LimeSDROutputSettings::serialize() const @@ -60,6 +62,8 @@ QByteArray LimeSDROutputSettings::serialize() const s.writeU32(15, m_extClockFreq); s.writeBool(16, m_transverterMode); s.writeS64(17, m_transverterDeltaFrequency); + s.writeU32(18, m_gpioDir); + s.writeU32(19, m_gpioPins); return s.final(); } @@ -77,6 +81,7 @@ bool LimeSDROutputSettings::deserialize(const QByteArray& data) if (d.getVersion() == 1) { int intval; + uint32_t uintval; d.readS32(1, &m_devSampleRate, 5000000); d.readU32(2, &m_log2HardInterp, 2); @@ -93,6 +98,10 @@ bool LimeSDROutputSettings::deserialize(const QByteArray& data) d.readU32(15, &m_extClockFreq, 10000000); d.readBool(16, &m_transverterMode, false); d.readS64(17, &m_transverterDeltaFrequency, 0); + d.readU32(18, &uintval, 0); + m_gpioDir = uintval & 0xFF; + d.readU32(19, &uintval, 0); + m_gpioPins = uintval & 0xFF; return true; } diff --git a/plugins/samplesink/limesdroutput/limesdroutputsettings.h b/plugins/samplesink/limesdroutput/limesdroutputsettings.h index 2fe21b054..f29ac63ba 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputsettings.h +++ b/plugins/samplesink/limesdroutput/limesdroutputsettings.h @@ -56,6 +56,8 @@ struct LimeSDROutputSettings uint32_t m_extClockFreq; //!< Frequency (Hz) of external clock source bool m_transverterMode; qint64 m_transverterDeltaFrequency; + uint8_t m_gpioDir; //!< GPIO pin direction LSB first; 0 input, 1 output + uint8_t m_gpioPins; //!< GPIO pins to write; LSB first LimeSDROutputSettings(); void resetToDefaults(); diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp index fd5469c99..99d3b4259 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp @@ -30,7 +30,7 @@ class DeviceSourceAPI; const PluginDescriptor PlutoSDROutputPlugin::m_pluginDescriptor = { QString("PlutoSDR Output"), - QString("4.0.4"), + QString("4.3.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index bcd8dee34..16538553d 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -615,6 +615,17 @@ bool LimeSDRInput::handleMessage(const Message& message) return true; } + else if (DeviceLimeSDRShared::MsgReportGPIOChange::match(message)) + { + DeviceLimeSDRShared::MsgReportGPIOChange& report = (DeviceLimeSDRShared::MsgReportGPIOChange&) message; + + m_settings.m_gpioDir = report.getGPIODir(); + m_settings.m_gpioPins = report.getGPIOPins(); + + // no GUI for the moment only REST API + + return true; + } else if (MsgGetStreamInfo::match(message)) { // qDebug() << "LimeSDRInput::handleMessage: MsgGetStreamInfo"; @@ -757,6 +768,7 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc bool forwardChangeRxDSP = false; bool forwardChangeAllDSP = false; bool forwardClockSource = false; + bool forwardGPIOChange = false; bool ownThreadWasRunning = false; bool doCalibration = false; bool doLPCalibration = false; @@ -1093,6 +1105,32 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc } } + if ((m_settings.m_gpioDir != settings.m_gpioDir) || force) + { + if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) < 0) + { + qCritical("LimeSDROutput::applySettings: could not set GPIO directions to %u", settings.m_gpioDir); + } + else + { + forwardGPIOChange = true; + qDebug("LimeSDROutput::applySettings: GPIO directions set to %u", settings.m_gpioDir); + } + } + + if ((m_settings.m_gpioPins != settings.m_gpioPins) || force) + { + if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) < 0) + { + qCritical("LimeSDROutput::applySettings: could not set GPIO pins to %u", settings.m_gpioPins); + } + else + { + forwardGPIOChange = true; + qDebug("LimeSDROutput::applySettings: GPIO pins set to %u", settings.m_gpioPins); + } + } + m_settings = settings; double clockGenFreqAfter; @@ -1250,6 +1288,31 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc } } + if (forwardGPIOChange) + { + // send to source buddies + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); + + for (; itSource != sourceBuddies.end(); ++itSource) + { + DeviceLimeSDRShared::MsgReportClockSourceChange *report = DeviceLimeSDRShared::MsgReportClockSourceChange::create( + m_settings.m_extClock, m_settings.m_extClockFreq); + (*itSource)->getSampleSourceInputMessageQueue()->push(report); + } + + // send to sink buddies + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceLimeSDRShared::MsgReportClockSourceChange *report = DeviceLimeSDRShared::MsgReportClockSourceChange::create( + m_settings.m_extClock, m_settings.m_extClockFreq); + (*itSink)->getSampleSinkInputMessageQueue()->push(report); + } + } + QLocale loc; qDebug().noquote() << "LimeSDRInput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz" @@ -1270,6 +1333,8 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc << " m_antennaPath: " << m_settings.m_antennaPath << " m_extClock: " << m_settings.m_extClock << " m_extClockFreq: " << loc.toString(m_settings.m_extClockFreq) + << " m_gpioDir: " << m_settings.m_gpioDir + << " m_gpioPins: " << m_settings.m_gpioPins << " force: " << force << " forceNCOFrequency: " << forceNCOFrequency << " doCalibration: " << doCalibration @@ -1364,6 +1429,12 @@ int LimeSDRInput::webapiSettingsPutPatch( if (deviceSettingsKeys.contains("fileRecordName")) { settings.m_fileRecordName = *response.getLimeSdrInputSettings()->getFileRecordName(); } + if (deviceSettingsKeys.contains("gpioDir")) { + settings.m_gpioDir = response.getLimeSdrInputSettings()->getGpioDir() & 0xFF; + } + if (deviceSettingsKeys.contains("gpioPins")) { + settings.m_gpioPins = response.getLimeSdrInputSettings()->getGpioPins() & 0xFF; + } MsgConfigureLimeSDR *msg = MsgConfigureLimeSDR::create(settings, force); m_inputMessageQueue.push(msg); @@ -1407,6 +1478,9 @@ void LimeSDRInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& re } else { response.getLimeSdrInputSettings()->setFileRecordName(new QString(settings.m_fileRecordName)); } + + response.getLimeSdrInputSettings()->setGpioDir(settings.m_gpioDir); + response.getLimeSdrInputSettings()->setGpioPins(settings.m_gpioPins); } int LimeSDRInput::webapiReportGet( @@ -1452,6 +1526,8 @@ void LimeSDRInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respon { bool success = false; double temp = 0.0; + uint8_t gpioDir = 0; + uint8_t gpioPins = 0; lms_stream_status_t status; status.active = false; status.fifoFilledCount = 0; @@ -1474,9 +1550,14 @@ void LimeSDRInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respon response.getLimeSdrInputReport()->setLinkRate(status.linkRate); response.getLimeSdrInputReport()->setHwTimestamp(status.timestamp); - if (m_deviceShared.m_deviceParams->getDevice()) { + if (m_deviceShared.m_deviceParams->getDevice()) + { LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp); + LMS_GPIODirRead(m_deviceShared.m_deviceParams->getDevice(), &gpioDir, 1); + LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1); } response.getLimeSdrInputReport()->setTemperature(temp); + response.getLimeSdrInputReport()->setGpioDir(gpioDir); + response.getLimeSdrInputReport()->setGpioPins(gpioPins); } diff --git a/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp b/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp index a61ed225c..b1abed6d4 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp @@ -33,7 +33,7 @@ const PluginDescriptor LimeSDRInputPlugin::m_pluginDescriptor = { QString("LimeSDR Input"), - QString("4.2.4"), + QString("4.3.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp b/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp index 88383e328..736069ea0 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp @@ -46,6 +46,8 @@ void LimeSDRInputSettings::resetToDefaults() m_transverterMode = false; m_transverterDeltaFrequency = 0; m_fileRecordName = ""; + m_gpioDir = 0; + m_gpioPins = 0; } QByteArray LimeSDRInputSettings::serialize() const @@ -72,6 +74,8 @@ QByteArray LimeSDRInputSettings::serialize() const s.writeU32(19, m_extClockFreq); s.writeBool(20, m_transverterMode); s.writeS64(21, m_transverterDeltaFrequency); + s.writeU32(22, m_gpioDir); + s.writeU32(23, m_gpioPins); return s.final(); } @@ -89,6 +93,7 @@ bool LimeSDRInputSettings::deserialize(const QByteArray& data) if (d.getVersion() == 1) { int intval; + uint32_t uintval; d.readS32(1, &m_devSampleRate, 5000000); d.readU32(2, &m_log2HardDecim, 2); @@ -112,6 +117,10 @@ bool LimeSDRInputSettings::deserialize(const QByteArray& data) d.readU32(19, &m_extClockFreq, 10000000); d.readBool(20, &m_transverterMode, false); d.readS64(21, &m_transverterDeltaFrequency, 0); + d.readU32(22, &uintval, 0); + m_gpioDir = uintval & 0xFF; + d.readU32(23, &uintval, 0); + m_gpioPins = uintval & 0xFF; return true; } diff --git a/plugins/samplesource/limesdrinput/limesdrinputsettings.h b/plugins/samplesource/limesdrinput/limesdrinputsettings.h index 9287589a2..cade58966 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputsettings.h +++ b/plugins/samplesource/limesdrinput/limesdrinputsettings.h @@ -66,6 +66,8 @@ struct LimeSDRInputSettings bool m_transverterMode; qint64 m_transverterDeltaFrequency; QString m_fileRecordName; + uint8_t m_gpioDir; //!< GPIO pin direction LSB first; 0 input, 1 output + uint8_t m_gpioPins; //!< GPIO pins to write; LSB first LimeSDRInputSettings(); void resetToDefaults(); diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp index 1fb15bfc6..e840a6db1 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp @@ -30,7 +30,7 @@ class DeviceSourceAPI; const PluginDescriptor PlutoSDRInputPlugin::m_pluginDescriptor = { QString("PlutoSDR Input"), - QString("4.0.0"), + QString("4.3.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 5d9f1d1a8..54b9dc825 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -2626,6 +2626,14 @@ margin-bottom: 20px; "temperature" : { "type" : "number", "format" : "float" + }, + "gpioDir" : { + "type" : "integer", + "format" : "int8" + }, + "gpioPins" : { + "type" : "integer", + "format" : "int8" } }, "description" : "LimeSDR" @@ -2699,6 +2707,14 @@ margin-bottom: 20px; }, "fileRecordName" : { "type" : "string" + }, + "gpioDir" : { + "type" : "integer", + "format" : "int8" + }, + "gpioPins" : { + "type" : "integer", + "format" : "int8" } }, "description" : "LimeSDR" @@ -2740,6 +2756,14 @@ margin-bottom: 20px; "temperature" : { "type" : "number", "format" : "float" + }, + "gpioDir" : { + "type" : "integer", + "format" : "int8" + }, + "gpioPins" : { + "type" : "integer", + "format" : "int8" } }, "description" : "LimeSDR" @@ -2792,6 +2816,14 @@ margin-bottom: 20px; "transverterDeltaFrequency" : { "type" : "integer", "format" : "int64" + }, + "gpioDir" : { + "type" : "integer", + "format" : "int8" + }, + "gpioPins" : { + "type" : "integer", + "format" : "int8" } }, "description" : "LimeSDR" @@ -23617,7 +23649,7 @@ except ApiException as e:
- Generated 2018-11-26T13:24:54.460+01:00 + Generated 2018-11-29T00:50:52.609+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/LimeSdr.yaml b/sdrbase/resources/webapi/doc/swagger/include/LimeSdr.yaml index 48225a4a2..bc4b90408 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/LimeSdr.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/LimeSdr.yaml @@ -47,6 +47,12 @@ LimeSdrInputSettings: format: int64 fileRecordName: type: string + gpioDir: + type: integer + format: int8 + gpioPins: + type: integer + format: int8 LimeSdrOutputSettings: description: LimeSDR @@ -83,6 +89,12 @@ LimeSdrOutputSettings: transverterDeltaFrequency: type: integer format: int64 + gpioDir: + type: integer + format: int8 + gpioPins: + type: integer + format: int8 LimeSdrInputReport: description: LimeSDR @@ -112,7 +124,13 @@ LimeSdrInputReport: format: uint64 temperature: type: number - format: float + format: float + gpioDir: + type: integer + format: int8 + gpioPins: + type: integer + format: int8 LimeSdrOutputReport: description: LimeSDR @@ -142,5 +160,11 @@ LimeSdrOutputReport: format: uint64 temperature: type: number - format: float + format: float + gpioDir: + type: integer + format: int8 + gpioPins: + type: integer + format: int8 \ No newline at end of file diff --git a/swagger/sdrangel/api/swagger/include/LimeSdr.yaml b/swagger/sdrangel/api/swagger/include/LimeSdr.yaml index 48225a4a2..bc4b90408 100644 --- a/swagger/sdrangel/api/swagger/include/LimeSdr.yaml +++ b/swagger/sdrangel/api/swagger/include/LimeSdr.yaml @@ -47,6 +47,12 @@ LimeSdrInputSettings: format: int64 fileRecordName: type: string + gpioDir: + type: integer + format: int8 + gpioPins: + type: integer + format: int8 LimeSdrOutputSettings: description: LimeSDR @@ -83,6 +89,12 @@ LimeSdrOutputSettings: transverterDeltaFrequency: type: integer format: int64 + gpioDir: + type: integer + format: int8 + gpioPins: + type: integer + format: int8 LimeSdrInputReport: description: LimeSDR @@ -112,7 +124,13 @@ LimeSdrInputReport: format: uint64 temperature: type: number - format: float + format: float + gpioDir: + type: integer + format: int8 + gpioPins: + type: integer + format: int8 LimeSdrOutputReport: description: LimeSDR @@ -142,5 +160,11 @@ LimeSdrOutputReport: format: uint64 temperature: type: number - format: float + format: float + gpioDir: + type: integer + format: int8 + gpioPins: + type: integer + format: int8 \ No newline at end of file diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 5d9f1d1a8..54b9dc825 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -2626,6 +2626,14 @@ margin-bottom: 20px; "temperature" : { "type" : "number", "format" : "float" + }, + "gpioDir" : { + "type" : "integer", + "format" : "int8" + }, + "gpioPins" : { + "type" : "integer", + "format" : "int8" } }, "description" : "LimeSDR" @@ -2699,6 +2707,14 @@ margin-bottom: 20px; }, "fileRecordName" : { "type" : "string" + }, + "gpioDir" : { + "type" : "integer", + "format" : "int8" + }, + "gpioPins" : { + "type" : "integer", + "format" : "int8" } }, "description" : "LimeSDR" @@ -2740,6 +2756,14 @@ margin-bottom: 20px; "temperature" : { "type" : "number", "format" : "float" + }, + "gpioDir" : { + "type" : "integer", + "format" : "int8" + }, + "gpioPins" : { + "type" : "integer", + "format" : "int8" } }, "description" : "LimeSDR" @@ -2792,6 +2816,14 @@ margin-bottom: 20px; "transverterDeltaFrequency" : { "type" : "integer", "format" : "int64" + }, + "gpioDir" : { + "type" : "integer", + "format" : "int8" + }, + "gpioPins" : { + "type" : "integer", + "format" : "int8" } }, "description" : "LimeSDR" @@ -23617,7 +23649,7 @@ except ApiException as e:
- Generated 2018-11-26T13:24:54.460+01:00 + Generated 2018-11-29T00:50:52.609+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputReport.cpp b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputReport.cpp index 7ee9046a1..4b7340144 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputReport.cpp @@ -48,6 +48,10 @@ SWGLimeSdrInputReport::SWGLimeSdrInputReport() { m_hw_timestamp_isSet = false; temperature = 0.0f; m_temperature_isSet = false; + gpio_dir = 0; + m_gpio_dir_isSet = false; + gpio_pins = 0; + m_gpio_pins_isSet = false; } SWGLimeSdrInputReport::~SWGLimeSdrInputReport() { @@ -76,6 +80,10 @@ SWGLimeSdrInputReport::init() { m_hw_timestamp_isSet = false; temperature = 0.0f; m_temperature_isSet = false; + gpio_dir = 0; + m_gpio_dir_isSet = false; + gpio_pins = 0; + m_gpio_pins_isSet = false; } void @@ -90,6 +98,8 @@ SWGLimeSdrInputReport::cleanup() { + + } SWGLimeSdrInputReport* @@ -123,6 +133,10 @@ SWGLimeSdrInputReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&temperature, pJson["temperature"], "float", ""); + ::SWGSDRangel::setValue(&gpio_dir, pJson["gpioDir"], "qint32", ""); + + ::SWGSDRangel::setValue(&gpio_pins, pJson["gpioPins"], "qint32", ""); + } QString @@ -169,6 +183,12 @@ SWGLimeSdrInputReport::asJsonObject() { if(m_temperature_isSet){ obj->insert("temperature", QJsonValue(temperature)); } + if(m_gpio_dir_isSet){ + obj->insert("gpioDir", QJsonValue(gpio_dir)); + } + if(m_gpio_pins_isSet){ + obj->insert("gpioPins", QJsonValue(gpio_pins)); + } return obj; } @@ -273,6 +293,26 @@ SWGLimeSdrInputReport::setTemperature(float temperature) { this->m_temperature_isSet = true; } +qint32 +SWGLimeSdrInputReport::getGpioDir() { + return gpio_dir; +} +void +SWGLimeSdrInputReport::setGpioDir(qint32 gpio_dir) { + this->gpio_dir = gpio_dir; + this->m_gpio_dir_isSet = true; +} + +qint32 +SWGLimeSdrInputReport::getGpioPins() { + return gpio_pins; +} +void +SWGLimeSdrInputReport::setGpioPins(qint32 gpio_pins) { + this->gpio_pins = gpio_pins; + this->m_gpio_pins_isSet = true; +} + bool SWGLimeSdrInputReport::isSet(){ @@ -288,6 +328,8 @@ SWGLimeSdrInputReport::isSet(){ if(m_link_rate_isSet){ isObjectUpdated = true; break;} if(m_hw_timestamp_isSet){ isObjectUpdated = true; break;} if(m_temperature_isSet){ isObjectUpdated = true; break;} + if(m_gpio_dir_isSet){ isObjectUpdated = true; break;} + if(m_gpio_pins_isSet){ isObjectUpdated = true; break;} }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputReport.h b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputReport.h index 979cc2fa4..e83a96213 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputReport.h @@ -71,6 +71,12 @@ public: float getTemperature(); void setTemperature(float temperature); + qint32 getGpioDir(); + void setGpioDir(qint32 gpio_dir); + + qint32 getGpioPins(); + void setGpioPins(qint32 gpio_pins); + virtual bool isSet() override; @@ -105,6 +111,12 @@ private: float temperature; bool m_temperature_isSet; + qint32 gpio_dir; + bool m_gpio_dir_isSet; + + qint32 gpio_pins; + bool m_gpio_pins_isSet; + }; } diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp index a14905cec..2fe4db37c 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.cpp @@ -72,6 +72,10 @@ SWGLimeSdrInputSettings::SWGLimeSdrInputSettings() { m_transverter_delta_frequency_isSet = false; file_record_name = nullptr; m_file_record_name_isSet = false; + gpio_dir = 0; + m_gpio_dir_isSet = false; + gpio_pins = 0; + m_gpio_pins_isSet = false; } SWGLimeSdrInputSettings::~SWGLimeSdrInputSettings() { @@ -124,6 +128,10 @@ SWGLimeSdrInputSettings::init() { m_transverter_delta_frequency_isSet = false; file_record_name = new QString(""); m_file_record_name_isSet = false; + gpio_dir = 0; + m_gpio_dir_isSet = false; + gpio_pins = 0; + m_gpio_pins_isSet = false; } void @@ -152,6 +160,8 @@ SWGLimeSdrInputSettings::cleanup() { if(file_record_name != nullptr) { delete file_record_name; } + + } SWGLimeSdrInputSettings* @@ -209,6 +219,10 @@ SWGLimeSdrInputSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&file_record_name, pJson["fileRecordName"], "QString", "QString"); + ::SWGSDRangel::setValue(&gpio_dir, pJson["gpioDir"], "qint32", ""); + + ::SWGSDRangel::setValue(&gpio_pins, pJson["gpioPins"], "qint32", ""); + } QString @@ -291,6 +305,12 @@ SWGLimeSdrInputSettings::asJsonObject() { if(file_record_name != nullptr && *file_record_name != QString("")){ toJsonValue(QString("fileRecordName"), file_record_name, obj, QString("QString")); } + if(m_gpio_dir_isSet){ + obj->insert("gpioDir", QJsonValue(gpio_dir)); + } + if(m_gpio_pins_isSet){ + obj->insert("gpioPins", QJsonValue(gpio_pins)); + } return obj; } @@ -515,6 +535,26 @@ SWGLimeSdrInputSettings::setFileRecordName(QString* file_record_name) { this->m_file_record_name_isSet = true; } +qint32 +SWGLimeSdrInputSettings::getGpioDir() { + return gpio_dir; +} +void +SWGLimeSdrInputSettings::setGpioDir(qint32 gpio_dir) { + this->gpio_dir = gpio_dir; + this->m_gpio_dir_isSet = true; +} + +qint32 +SWGLimeSdrInputSettings::getGpioPins() { + return gpio_pins; +} +void +SWGLimeSdrInputSettings::setGpioPins(qint32 gpio_pins) { + this->gpio_pins = gpio_pins; + this->m_gpio_pins_isSet = true; +} + bool SWGLimeSdrInputSettings::isSet(){ @@ -542,6 +582,8 @@ SWGLimeSdrInputSettings::isSet(){ if(m_transverter_mode_isSet){ isObjectUpdated = true; break;} if(m_transverter_delta_frequency_isSet){ isObjectUpdated = true; break;} if(file_record_name != nullptr && *file_record_name != QString("")){ isObjectUpdated = true; break;} + if(m_gpio_dir_isSet){ isObjectUpdated = true; break;} + if(m_gpio_pins_isSet){ isObjectUpdated = true; break;} }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h index 60ba94de5..4672f90b2 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrInputSettings.h @@ -108,6 +108,12 @@ public: QString* getFileRecordName(); void setFileRecordName(QString* file_record_name); + qint32 getGpioDir(); + void setGpioDir(qint32 gpio_dir); + + qint32 getGpioPins(); + void setGpioPins(qint32 gpio_pins); + virtual bool isSet() override; @@ -178,6 +184,12 @@ private: QString* file_record_name; bool m_file_record_name_isSet; + qint32 gpio_dir; + bool m_gpio_dir_isSet; + + qint32 gpio_pins; + bool m_gpio_pins_isSet; + }; } diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputReport.cpp b/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputReport.cpp index fdf025207..0fd466d6d 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputReport.cpp @@ -48,6 +48,10 @@ SWGLimeSdrOutputReport::SWGLimeSdrOutputReport() { m_hw_timestamp_isSet = false; temperature = 0.0f; m_temperature_isSet = false; + gpio_dir = 0; + m_gpio_dir_isSet = false; + gpio_pins = 0; + m_gpio_pins_isSet = false; } SWGLimeSdrOutputReport::~SWGLimeSdrOutputReport() { @@ -76,6 +80,10 @@ SWGLimeSdrOutputReport::init() { m_hw_timestamp_isSet = false; temperature = 0.0f; m_temperature_isSet = false; + gpio_dir = 0; + m_gpio_dir_isSet = false; + gpio_pins = 0; + m_gpio_pins_isSet = false; } void @@ -90,6 +98,8 @@ SWGLimeSdrOutputReport::cleanup() { + + } SWGLimeSdrOutputReport* @@ -123,6 +133,10 @@ SWGLimeSdrOutputReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&temperature, pJson["temperature"], "float", ""); + ::SWGSDRangel::setValue(&gpio_dir, pJson["gpioDir"], "qint32", ""); + + ::SWGSDRangel::setValue(&gpio_pins, pJson["gpioPins"], "qint32", ""); + } QString @@ -169,6 +183,12 @@ SWGLimeSdrOutputReport::asJsonObject() { if(m_temperature_isSet){ obj->insert("temperature", QJsonValue(temperature)); } + if(m_gpio_dir_isSet){ + obj->insert("gpioDir", QJsonValue(gpio_dir)); + } + if(m_gpio_pins_isSet){ + obj->insert("gpioPins", QJsonValue(gpio_pins)); + } return obj; } @@ -273,6 +293,26 @@ SWGLimeSdrOutputReport::setTemperature(float temperature) { this->m_temperature_isSet = true; } +qint32 +SWGLimeSdrOutputReport::getGpioDir() { + return gpio_dir; +} +void +SWGLimeSdrOutputReport::setGpioDir(qint32 gpio_dir) { + this->gpio_dir = gpio_dir; + this->m_gpio_dir_isSet = true; +} + +qint32 +SWGLimeSdrOutputReport::getGpioPins() { + return gpio_pins; +} +void +SWGLimeSdrOutputReport::setGpioPins(qint32 gpio_pins) { + this->gpio_pins = gpio_pins; + this->m_gpio_pins_isSet = true; +} + bool SWGLimeSdrOutputReport::isSet(){ @@ -288,6 +328,8 @@ SWGLimeSdrOutputReport::isSet(){ if(m_link_rate_isSet){ isObjectUpdated = true; break;} if(m_hw_timestamp_isSet){ isObjectUpdated = true; break;} if(m_temperature_isSet){ isObjectUpdated = true; break;} + if(m_gpio_dir_isSet){ isObjectUpdated = true; break;} + if(m_gpio_pins_isSet){ isObjectUpdated = true; break;} }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputReport.h b/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputReport.h index 8f23843d3..658309318 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputReport.h @@ -71,6 +71,12 @@ public: float getTemperature(); void setTemperature(float temperature); + qint32 getGpioDir(); + void setGpioDir(qint32 gpio_dir); + + qint32 getGpioPins(); + void setGpioPins(qint32 gpio_pins); + virtual bool isSet() override; @@ -105,6 +111,12 @@ private: float temperature; bool m_temperature_isSet; + qint32 gpio_dir; + bool m_gpio_dir_isSet; + + qint32 gpio_pins; + bool m_gpio_pins_isSet; + }; } diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputSettings.cpp index 162de8246..f808a8d9b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputSettings.cpp @@ -58,6 +58,10 @@ SWGLimeSdrOutputSettings::SWGLimeSdrOutputSettings() { m_transverter_mode_isSet = false; transverter_delta_frequency = 0L; m_transverter_delta_frequency_isSet = false; + gpio_dir = 0; + m_gpio_dir_isSet = false; + gpio_pins = 0; + m_gpio_pins_isSet = false; } SWGLimeSdrOutputSettings::~SWGLimeSdrOutputSettings() { @@ -96,6 +100,10 @@ SWGLimeSdrOutputSettings::init() { m_transverter_mode_isSet = false; transverter_delta_frequency = 0L; m_transverter_delta_frequency_isSet = false; + gpio_dir = 0; + m_gpio_dir_isSet = false; + gpio_pins = 0; + m_gpio_pins_isSet = false; } void @@ -115,6 +123,8 @@ SWGLimeSdrOutputSettings::cleanup() { + + } SWGLimeSdrOutputSettings* @@ -158,6 +168,10 @@ SWGLimeSdrOutputSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&transverter_delta_frequency, pJson["transverterDeltaFrequency"], "qint64", ""); + ::SWGSDRangel::setValue(&gpio_dir, pJson["gpioDir"], "qint32", ""); + + ::SWGSDRangel::setValue(&gpio_pins, pJson["gpioPins"], "qint32", ""); + } QString @@ -219,6 +233,12 @@ SWGLimeSdrOutputSettings::asJsonObject() { if(m_transverter_delta_frequency_isSet){ obj->insert("transverterDeltaFrequency", QJsonValue(transverter_delta_frequency)); } + if(m_gpio_dir_isSet){ + obj->insert("gpioDir", QJsonValue(gpio_dir)); + } + if(m_gpio_pins_isSet){ + obj->insert("gpioPins", QJsonValue(gpio_pins)); + } return obj; } @@ -373,6 +393,26 @@ SWGLimeSdrOutputSettings::setTransverterDeltaFrequency(qint64 transverter_delta_ this->m_transverter_delta_frequency_isSet = true; } +qint32 +SWGLimeSdrOutputSettings::getGpioDir() { + return gpio_dir; +} +void +SWGLimeSdrOutputSettings::setGpioDir(qint32 gpio_dir) { + this->gpio_dir = gpio_dir; + this->m_gpio_dir_isSet = true; +} + +qint32 +SWGLimeSdrOutputSettings::getGpioPins() { + return gpio_pins; +} +void +SWGLimeSdrOutputSettings::setGpioPins(qint32 gpio_pins) { + this->gpio_pins = gpio_pins; + this->m_gpio_pins_isSet = true; +} + bool SWGLimeSdrOutputSettings::isSet(){ @@ -393,6 +433,8 @@ SWGLimeSdrOutputSettings::isSet(){ if(m_ext_clock_freq_isSet){ isObjectUpdated = true; break;} if(m_transverter_mode_isSet){ isObjectUpdated = true; break;} if(m_transverter_delta_frequency_isSet){ isObjectUpdated = true; break;} + if(m_gpio_dir_isSet){ isObjectUpdated = true; break;} + if(m_gpio_pins_isSet){ isObjectUpdated = true; break;} }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputSettings.h b/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputSettings.h index 897971ad5..5eeff69eb 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGLimeSdrOutputSettings.h @@ -86,6 +86,12 @@ public: qint64 getTransverterDeltaFrequency(); void setTransverterDeltaFrequency(qint64 transverter_delta_frequency); + qint32 getGpioDir(); + void setGpioDir(qint32 gpio_dir); + + qint32 getGpioPins(); + void setGpioPins(qint32 gpio_pins); + virtual bool isSet() override; @@ -135,6 +141,12 @@ private: qint64 transverter_delta_frequency; bool m_transverter_delta_frequency_isSet; + qint32 gpio_dir; + bool m_gpio_dir_isSet; + + qint32 gpio_pins; + bool m_gpio_pins_isSet; + }; } From 83b66eb6f13bbaf23a7fb99c19f1f2e6adbbe527 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 29 Nov 2018 13:57:04 +0100 Subject: [PATCH 097/102] LimeSDR: report GPIO pins values in the GUI --- devices/limesdr/devicelimesdrshared.h | 11 ++-- .../limesdroutput/limesdroutput.cpp | 25 +++++----- .../limesdroutput/limesdroutputgui.cpp | 1 + .../limesdroutput/limesdroutputgui.ui | 50 +++++++++++++++++++ .../limesdrinput/limesdrinput.cpp | 25 +++++----- .../limesdrinput/limesdrinputgui.cpp | 1 + .../limesdrinput/limesdrinputgui.ui | 50 +++++++++++++++++++ 7 files changed, 135 insertions(+), 28 deletions(-) diff --git a/devices/limesdr/devicelimesdrshared.h b/devices/limesdr/devicelimesdrshared.h index 8e2478008..b4e90fd88 100644 --- a/devices/limesdr/devicelimesdrshared.h +++ b/devices/limesdr/devicelimesdrshared.h @@ -103,18 +103,21 @@ public: public: float getTemperature() const { return m_temperature; } + uint8_t getGPIOPins() const { return m_gpioPins; } - static MsgReportDeviceInfo* create(float temperature) + static MsgReportDeviceInfo* create(float temperature, uint8_t gpioPins) { - return new MsgReportDeviceInfo(temperature); + return new MsgReportDeviceInfo(temperature, gpioPins); } private: float m_temperature; + uint8_t m_gpioPins; - MsgReportDeviceInfo(float temperature) : + MsgReportDeviceInfo(float temperature, uint8_t gpioPins) : Message(), - m_temperature(temperature) + m_temperature(temperature), + m_gpioPins(gpioPins) { } }; diff --git a/plugins/samplesink/limesdroutput/limesdroutput.cpp b/plugins/samplesink/limesdroutput/limesdroutput.cpp index c9bf756a6..6ca3facf4 100644 --- a/plugins/samplesink/limesdroutput/limesdroutput.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutput.cpp @@ -655,19 +655,20 @@ bool LimeSDROutput::handleMessage(const Message& message) else if (MsgGetDeviceInfo::match(message)) { double temp = 0.0; + uint8_t gpioPins = 0; - if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp) == 0)) - { - //qDebug("LimeSDROutput::handleMessage: MsgGetDeviceInfo: temperature: %f", temp); + if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp) != 0)) { + qWarning("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get temperature"); } - else - { - qDebug("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get temperature"); + + if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1) != 0)) { + qWarning("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get GPIO pins values"); } // send to oneself - if (getMessageQueueToGUI()) { - DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp); + if (getMessageQueueToGUI()) + { + DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp, gpioPins); getMessageQueueToGUI()->push(report); } @@ -679,7 +680,7 @@ bool LimeSDROutput::handleMessage(const Message& message) { if ((*itSource)->getSampleSourceGUIMessageQueue()) { - DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp); + DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp, gpioPins); (*itSource)->getSampleSourceGUIMessageQueue()->push(report); } } @@ -692,7 +693,7 @@ bool LimeSDROutput::handleMessage(const Message& message) { if ((*itSink)->getSampleSinkGUIMessageQueue()) { - DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp); + DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp, gpioPins); (*itSink)->getSampleSinkGUIMessageQueue()->push(report); } } @@ -930,7 +931,7 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo if ((m_settings.m_gpioDir != settings.m_gpioDir) || force) { - if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) < 0) + if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) != 0) { qCritical("LimeSDROutput::applySettings: could not set GPIO directions to %u", settings.m_gpioDir); } @@ -943,7 +944,7 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo if ((m_settings.m_gpioPins != settings.m_gpioPins) || force) { - if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) < 0) + if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) != 0) { qCritical("LimeSDROutput::applySettings: could not set GPIO pins to %u", settings.m_gpioPins); } diff --git a/plugins/samplesink/limesdroutput/limesdroutputgui.cpp b/plugins/samplesink/limesdroutput/limesdroutputgui.cpp index f904360d9..1ca300685 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputgui.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutputgui.cpp @@ -244,6 +244,7 @@ bool LimeSDROutputGUI::handleMessage(const Message& message) { DeviceLimeSDRShared::MsgReportDeviceInfo& report = (DeviceLimeSDRShared::MsgReportDeviceInfo&) message; ui->temperatureText->setText(tr("%1C").arg(QString::number(report.getTemperature(), 'f', 0))); + ui->gpioText->setText(tr("%1").arg(report.getGPIOPins(), 2, 16, QChar('0'))); return true; } diff --git a/plugins/samplesink/limesdroutput/limesdroutputgui.ui b/plugins/samplesink/limesdroutput/limesdroutputgui.ui index 19d8d00e4..3e7197e9a 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputgui.ui +++ b/plugins/samplesink/limesdroutput/limesdroutputgui.ui @@ -880,6 +880,23 @@ QToolTip{background-color: white; color: black;}
+ + + + Qt::Vertical + + + + + + + GPIO bits as hex value (LSB first) + + + 00 + + + @@ -952,6 +969,39 @@ QToolTip{background-color: white; color: black;} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index 16538553d..403243c3a 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -671,19 +671,20 @@ bool LimeSDRInput::handleMessage(const Message& message) else if (MsgGetDeviceInfo::match(message)) { double temp = 0.0; + uint8_t gpioPins = 0; - if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp) == 0)) - { - //qDebug("LimeSDRInput::handleMessage: MsgGetDeviceInfo: temperature: %f", temp); + if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp) != 0)) { + qWarning("LimeSDRInput::handleMessage: MsgGetDeviceInfo: cannot get temperature"); } - else - { - qDebug("LimeSDRInput::handleMessage: MsgGetDeviceInfo: cannot get temperature"); + + if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1) != 0)) { + qWarning("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get GPIO pins values"); } // send to oneself - if (m_deviceAPI->getSampleSourceGUIMessageQueue()) { - DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp); + if (m_deviceAPI->getSampleSourceGUIMessageQueue()) + { + DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp, gpioPins); m_deviceAPI->getSampleSourceGUIMessageQueue()->push(report); } @@ -695,7 +696,7 @@ bool LimeSDRInput::handleMessage(const Message& message) { if ((*itSource)->getSampleSourceGUIMessageQueue()) { - DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp); + DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp, gpioPins); (*itSource)->getSampleSourceGUIMessageQueue()->push(report); } } @@ -708,7 +709,7 @@ bool LimeSDRInput::handleMessage(const Message& message) { if ((*itSink)->getSampleSinkGUIMessageQueue()) { - DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp); + DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp, gpioPins); (*itSink)->getSampleSinkGUIMessageQueue()->push(report); } } @@ -1107,7 +1108,7 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc if ((m_settings.m_gpioDir != settings.m_gpioDir) || force) { - if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) < 0) + if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) != 0) { qCritical("LimeSDROutput::applySettings: could not set GPIO directions to %u", settings.m_gpioDir); } @@ -1120,7 +1121,7 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc if ((m_settings.m_gpioPins != settings.m_gpioPins) || force) { - if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) < 0) + if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) != 0) { qCritical("LimeSDROutput::applySettings: could not set GPIO pins to %u", settings.m_gpioPins); } diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp index 8693eb7e1..d31a66642 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp @@ -226,6 +226,7 @@ bool LimeSDRInputGUI::handleMessage(const Message& message) { DeviceLimeSDRShared::MsgReportDeviceInfo& report = (DeviceLimeSDRShared::MsgReportDeviceInfo&) message; ui->temperatureText->setText(tr("%1C").arg(QString::number(report.getTemperature(), 'f', 0))); + ui->gpioText->setText(tr("%1").arg(report.getGPIOPins(), 2, 16, QChar('0'))); return true; } else if (LimeSDRInput::MsgStartStop::match(message)) diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.ui b/plugins/samplesource/limesdrinput/limesdrinputgui.ui index a41f0c50e..669475c97 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.ui +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.ui @@ -1121,6 +1121,23 @@ QToolTip{background-color: white; color: black;}
+ + + + Qt::Vertical + + + + + + + GPIO bits as hex value (LSB first) + + + 00 + + + @@ -1193,6 +1210,39 @@ QToolTip{background-color: white; color: black;} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f3b75ead00bb76f799920864d7ab286419563b82 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 29 Nov 2018 23:37:34 +0100 Subject: [PATCH 098/102] LimeSDR: detect Lime hardware type. Interface with GPIO only for SPI and USB type --- debian/changelog | 2 +- devices/limesdr/devicelimesdrparam.cpp | 19 ++++++- devices/limesdr/devicelimesdrparam.h | 15 +++++- .../limesdroutput/limesdroutput.cpp | 52 ++++++++++-------- .../limesdroutput/limesdroutputgui.cpp | 2 +- .../limesdrinput/limesdrinput.cpp | 54 +++++++++++-------- .../limesdrinput/limesdrinputgui.cpp | 2 +- 7 files changed, 96 insertions(+), 50 deletions(-) diff --git a/debian/changelog b/debian/changelog index 8c08cd6b8..7bee4db1d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,7 +4,7 @@ sdrangel (4.3.1-1) unstable; urgency=medium * SoapySDR support: 250 ms minimum timeout * LimeSDR REST API: support GPIO - -- Edouard Griffiths, F4EXB Sun, 02 Dec 2018 21:14:18 +0100 + -- Edouard Griffiths, F4EXB Fri, 30 Nov 2018 21:14:18 +0100 sdrangel (4.3.0-1) unstable; urgency=medium diff --git a/devices/limesdr/devicelimesdrparam.cpp b/devices/limesdr/devicelimesdrparam.cpp index 954eee9fa..dd819dfc2 100644 --- a/devices/limesdr/devicelimesdrparam.cpp +++ b/devices/limesdr/devicelimesdrparam.cpp @@ -19,7 +19,9 @@ bool DeviceLimeSDRParams::open(lms_info_str_t deviceStr) { - qDebug("DeviceLimeSDRParams::open: serial: %s", (const char *) deviceStr); + getHardwareType((const char *) deviceStr); + + qDebug("DeviceLimeSDRParams::open: serial: %s type: %d", (const char *) deviceStr, (int) m_type); if (LMS_Open(&m_dev, deviceStr, 0) < 0) { @@ -105,3 +107,18 @@ void DeviceLimeSDRParams::close() } } +void DeviceLimeSDRParams::getHardwareType(const char *device_str) +{ + QString deviceStr(device_str); + + if (deviceStr.contains(QString("LimeSDR Mini"))) { + m_type = LimeMini; + } else if (deviceStr.contains(QString("LimeSDR-USB"))) { + m_type = LimeUSB; + } else if (deviceStr.contains(QString("media=SPI"))) { + m_type = LimeSPI; + } else { + m_type = LimeUndefined; + } +} + diff --git a/devices/limesdr/devicelimesdrparam.h b/devices/limesdr/devicelimesdrparam.h index 353b256e0..3178f21fb 100644 --- a/devices/limesdr/devicelimesdrparam.h +++ b/devices/limesdr/devicelimesdrparam.h @@ -30,6 +30,14 @@ */ struct DEVICES_API DeviceLimeSDRParams { + enum LimeType + { + LimeSPI, + LimeMini, + LimeUSB, + LimeUndefined + }; + lms_device_t *m_dev; //!< device handle uint32_t m_nbRxChannels; //!< number of Rx channels (normally 2, we'll see if we really use it...) uint32_t m_nbTxChannels; //!< number of Tx channels (normally 2, we'll see if we really use it...) @@ -44,6 +52,7 @@ struct DEVICES_API DeviceLimeSDRParams int m_log2OvSRTx; //!< log2 of Tx oversampling (0..5) float m_rxFrequency; //!< Rx frequency float m_txFrequency; //!< Tx frequency + LimeType m_type; //!< Hardware type DeviceLimeSDRParams() : m_dev(0), @@ -53,7 +62,8 @@ struct DEVICES_API DeviceLimeSDRParams m_log2OvSRRx(0), m_log2OvSRTx(0), m_rxFrequency(1e6), - m_txFrequency(1e6) + m_txFrequency(1e6), + m_type(LimeUndefined) { m_lpfRangeRx.max = 0.0f; m_lpfRangeRx.min = 0.0f; @@ -90,6 +100,9 @@ struct DEVICES_API DeviceLimeSDRParams ~DeviceLimeSDRParams() { } + +private: + void getHardwareType(const char *device_str); }; #endif /* DEVICES_LIMESDR_DEVICELIMESDRPARAM_H_ */ diff --git a/plugins/samplesink/limesdroutput/limesdroutput.cpp b/plugins/samplesink/limesdroutput/limesdroutput.cpp index 6ca3facf4..d0b82ee5d 100644 --- a/plugins/samplesink/limesdroutput/limesdroutput.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutput.cpp @@ -658,15 +658,19 @@ bool LimeSDROutput::handleMessage(const Message& message) uint8_t gpioPins = 0; if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp) != 0)) { - qWarning("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get temperature"); + qDebug("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get temperature"); } - if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1) != 0)) { - qWarning("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get GPIO pins values"); + if ((m_deviceShared.m_deviceParams->m_type != DeviceLimeSDRParams::LimeMini) + && (m_deviceShared.m_deviceParams->m_type != DeviceLimeSDRParams::LimeUndefined)) + { + if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1) != 0)) { + qDebug("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get GPIO pins values"); + } } // send to oneself - if (getMessageQueueToGUI()) + if (getMessageQueueToGUI()) { DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp, gpioPins); getMessageQueueToGUI()->push(report); @@ -929,29 +933,33 @@ bool LimeSDROutput::applySettings(const LimeSDROutputSettings& settings, bool fo } } - if ((m_settings.m_gpioDir != settings.m_gpioDir) || force) + if ((m_deviceShared.m_deviceParams->m_type != DeviceLimeSDRParams::LimeMini) + && (m_deviceShared.m_deviceParams->m_type != DeviceLimeSDRParams::LimeUndefined)) { - if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) != 0) + if ((m_settings.m_gpioDir != settings.m_gpioDir) || force) { - qCritical("LimeSDROutput::applySettings: could not set GPIO directions to %u", settings.m_gpioDir); + if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) != 0) + { + qCritical("LimeSDROutput::applySettings: could not set GPIO directions to %u", settings.m_gpioDir); + } + else + { + forwardGPIOChange = true; + qDebug("LimeSDROutput::applySettings: GPIO directions set to %u", settings.m_gpioDir); + } } - else - { - forwardGPIOChange = true; - qDebug("LimeSDROutput::applySettings: GPIO directions set to %u", settings.m_gpioDir); - } - } - if ((m_settings.m_gpioPins != settings.m_gpioPins) || force) - { - if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) != 0) + if ((m_settings.m_gpioPins != settings.m_gpioPins) || force) { - qCritical("LimeSDROutput::applySettings: could not set GPIO pins to %u", settings.m_gpioPins); - } - else - { - forwardGPIOChange = true; - qDebug("LimeSDROutput::applySettings: GPIO pins set to %u", settings.m_gpioPins); + if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) != 0) + { + qCritical("LimeSDROutput::applySettings: could not set GPIO pins to %u", settings.m_gpioPins); + } + else + { + forwardGPIOChange = true; + qDebug("LimeSDROutput::applySettings: GPIO pins set to %u", settings.m_gpioPins); + } } } diff --git a/plugins/samplesink/limesdroutput/limesdroutputgui.cpp b/plugins/samplesink/limesdroutput/limesdroutputgui.cpp index 1ca300685..f5aa0b9c6 100644 --- a/plugins/samplesink/limesdroutput/limesdroutputgui.cpp +++ b/plugins/samplesink/limesdroutput/limesdroutputgui.cpp @@ -244,7 +244,7 @@ bool LimeSDROutputGUI::handleMessage(const Message& message) { DeviceLimeSDRShared::MsgReportDeviceInfo& report = (DeviceLimeSDRShared::MsgReportDeviceInfo&) message; ui->temperatureText->setText(tr("%1C").arg(QString::number(report.getTemperature(), 'f', 0))); - ui->gpioText->setText(tr("%1").arg(report.getGPIOPins(), 2, 16, QChar('0'))); + ui->gpioText->setText(tr("%1").arg(report.getGPIOPins(), 2, 16, QChar('0')).toUpper()); return true; } diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index 403243c3a..ab08e7c3e 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -671,18 +671,22 @@ bool LimeSDRInput::handleMessage(const Message& message) else if (MsgGetDeviceInfo::match(message)) { double temp = 0.0; - uint8_t gpioPins = 0; + uint8_t gpioPins = 0; if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GetChipTemperature(m_deviceShared.m_deviceParams->getDevice(), 0, &temp) != 0)) { - qWarning("LimeSDRInput::handleMessage: MsgGetDeviceInfo: cannot get temperature"); + qDebug("LimeSDRInput::handleMessage: MsgGetDeviceInfo: cannot get temperature"); } - if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1) != 0)) { - qWarning("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get GPIO pins values"); + if ((m_deviceShared.m_deviceParams->m_type != DeviceLimeSDRParams::LimeMini) + && (m_deviceShared.m_deviceParams->m_type != DeviceLimeSDRParams::LimeUndefined)) + { + if (m_deviceShared.m_deviceParams->getDevice() && (LMS_GPIORead(m_deviceShared.m_deviceParams->getDevice(), &gpioPins, 1) != 0)) { + qDebug("LimeSDROutput::handleMessage: MsgGetDeviceInfo: cannot get GPIO pins values"); + } } // send to oneself - if (m_deviceAPI->getSampleSourceGUIMessageQueue()) + if (m_deviceAPI->getSampleSourceGUIMessageQueue()) { DeviceLimeSDRShared::MsgReportDeviceInfo *report = DeviceLimeSDRShared::MsgReportDeviceInfo::create(temp, gpioPins); m_deviceAPI->getSampleSourceGUIMessageQueue()->push(report); @@ -1106,29 +1110,33 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, bool forc } } - if ((m_settings.m_gpioDir != settings.m_gpioDir) || force) + if ((m_deviceShared.m_deviceParams->m_type != DeviceLimeSDRParams::LimeMini) + && (m_deviceShared.m_deviceParams->m_type != DeviceLimeSDRParams::LimeUndefined)) { - if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) != 0) + if ((m_settings.m_gpioDir != settings.m_gpioDir) || force) { - qCritical("LimeSDROutput::applySettings: could not set GPIO directions to %u", settings.m_gpioDir); + if (LMS_GPIODirWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioDir, 1) != 0) + { + qCritical("LimeSDROutput::applySettings: could not set GPIO directions to %u", settings.m_gpioDir); + } + else + { + forwardGPIOChange = true; + qDebug("LimeSDROutput::applySettings: GPIO directions set to %u", settings.m_gpioDir); + } } - else - { - forwardGPIOChange = true; - qDebug("LimeSDROutput::applySettings: GPIO directions set to %u", settings.m_gpioDir); - } - } - if ((m_settings.m_gpioPins != settings.m_gpioPins) || force) - { - if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) != 0) + if ((m_settings.m_gpioPins != settings.m_gpioPins) || force) { - qCritical("LimeSDROutput::applySettings: could not set GPIO pins to %u", settings.m_gpioPins); - } - else - { - forwardGPIOChange = true; - qDebug("LimeSDROutput::applySettings: GPIO pins set to %u", settings.m_gpioPins); + if (LMS_GPIOWrite(m_deviceShared.m_deviceParams->getDevice(), &settings.m_gpioPins, 1) != 0) + { + qCritical("LimeSDROutput::applySettings: could not set GPIO pins to %u", settings.m_gpioPins); + } + else + { + forwardGPIOChange = true; + qDebug("LimeSDROutput::applySettings: GPIO pins set to %u", settings.m_gpioPins); + } } } diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp index d31a66642..ff0f60ea9 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp @@ -226,7 +226,7 @@ bool LimeSDRInputGUI::handleMessage(const Message& message) { DeviceLimeSDRShared::MsgReportDeviceInfo& report = (DeviceLimeSDRShared::MsgReportDeviceInfo&) message; ui->temperatureText->setText(tr("%1C").arg(QString::number(report.getTemperature(), 'f', 0))); - ui->gpioText->setText(tr("%1").arg(report.getGPIOPins(), 2, 16, QChar('0'))); + ui->gpioText->setText(tr("%1").arg(report.getGPIOPins(), 2, 16, QChar('0')).toUpper()); return true; } else if (LimeSDRInput::MsgStartStop::match(message)) From 781eb0d97b9c1523138855b94c91398557d7cc67 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 30 Nov 2018 08:38:22 +0100 Subject: [PATCH 099/102] SoapySDR support: new attempt for Debian build --- CMakeLists.txt | 1 + debian/rules | 2 +- libsoapysdr/CMakeLists.txt | 120 +++++++++++++++++++++++++------------ 3 files changed, 85 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c76bd2be..03b3e3a10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -346,6 +346,7 @@ if (BUILD_DEBIAN) add_subdirectory(libmirisdr) add_subdirectory(libperseus) add_subdirectory(libiio) + add_subdirectory(libsoapysdr) endif (BUILD_DEBIAN) add_subdirectory(devices) diff --git a/debian/rules b/debian/rules index edca0b7d2..b78931773 100755 --- a/debian/rules +++ b/debian/rules @@ -21,5 +21,5 @@ # dh_make generated override targets # This is example for Cmake (See https://bugs.debian.org/641051 ) override_dh_auto_configure: - dh_auto_configure -- -DCMAKE_INSTALL_PREFIX=/opt/sdrangel -DDEBUG_OUTPUT=ON -DBUILD_TYPE=DEBIAN -DRX_SAMPLE_24BIT=ON -DLIBCM256CCSRC=/z1/development/cm256cc -DLIBDSDCCSRC=/z1/development/dsdcc -DLIBAIRSPYSRC=/z1/development/libairspy -DLIBAIRSPYHFSRC=/z1/softs/airspyhf -DLIBHACKRFSRC=/z1/development/hackrf/host -DLIBRTLSDRSRC=/z1/development/librtlsdr.f4exb -DLIBMBELIBSRC=/z1/development/mbelib -DLIBSERIALDVSRC=/z1/development/serialDV -DLIBBLADERFSRC=/z1/softs/bladeRF -DLIBBLADERFCOMMONSRC=/z1/softs/bladeRF/host/common -DLIBBLADERFLIBSRC=/z1/softs/bladeRF/host/libraries/libbladeRF -DLIBMIRISDRSRC=/z1/development/libmirisdr-4 -DLIBLIMESUITESRC=/z1/softs/LimeSuite -DLIBIIOSRC=/z1/softs/libiio -DLIBPERSEUSSRC=/z1/softs/libperseus-sdr -DLIBSOAPYSDRSRC=/z1/softs/SoapySDR + dh_auto_configure -- -DCMAKE_INSTALL_PREFIX=/opt/sdrangel -DDEBUG_OUTPUT=ON -DBUILD_TYPE=DEBIAN -DRX_SAMPLE_24BIT=ON -DLIBCM256CCSRC=/z1/development/cm256cc -DLIBDSDCCSRC=/z1/development/dsdcc -DLIBAIRSPYSRC=/z1/development/libairspy -DLIBAIRSPYHFSRC=/z1/softs/airspyhf -DLIBHACKRFSRC=/z1/development/hackrf/host -DLIBRTLSDRSRC=/z1/development/librtlsdr.f4exb -DLIBMBELIBSRC=/z1/development/mbelib -DLIBSERIALDVSRC=/z1/development/serialDV -DLIBBLADERFSRC=/z1/softs/bladeRF -DLIBBLADERFCOMMONSRC=/z1/softs/bladeRF/host/common -DLIBBLADERFLIBSRC=/z1/softs/bladeRF/host/libraries/libbladeRF -DLIBMIRISDRSRC=/z1/development/libmirisdr-4 -DLIBLIMESUITESRC=/z1/softs/LimeSuite -DLIBIIOSRC=/z1/softs/libiio -DLIBPERSEUSSRC=/z1/softs/libperseus-sdr -DSOAPYSDR_SOURCE_DIR=/z1/softs/SoapySDR diff --git a/libsoapysdr/CMakeLists.txt b/libsoapysdr/CMakeLists.txt index 7c53f3329..a10a0f957 100644 --- a/libsoapysdr/CMakeLists.txt +++ b/libsoapysdr/CMakeLists.txt @@ -1,12 +1,17 @@ -project(soapysdr) - +######################################################################## +# Project setup +######################################################################## +cmake_minimum_required(VERSION 2.8.7) +project(SoapySDR) +enable_language(CXX) +enable_testing() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - +#set(SOAPYSDR_SOURCE_DIR "/opt/build/SoapySDR") ######################################################################## # gather version information # packagers may specify -DSOAPY_SDR_EXTVER="foo" to replace the git hash ######################################################################## -file(READ "${LIBSOAPYSDRSRC}/Changelog.txt" changelog_txt) +file(READ "${SOAPYSDR_SOURCE_DIR}/Changelog.txt" changelog_txt) string(REGEX MATCH "Release ([0-9]+\\.[0-9]+\\.[0-9]+) \\(" CHANGELOG_MATCH "${changelog_txt}") if(NOT CHANGELOG_MATCH) message(FATAL_ERROR "Failed to extract version number from Changelog.txt") @@ -14,7 +19,7 @@ endif(NOT CHANGELOG_MATCH) set(SOAPY_SDR_LIBVER "${CMAKE_MATCH_1}") if (NOT SOAPY_SDR_EXTVER) - include(${LIBSOAPYSDRSRC}/cmake/Modules/GetGitRevisionDescription.cmake) + include(${SOAPYSDR_SOURCE_DIR}/cmake/Modules/GetGitRevisionDescription.cmake) get_git_head_revision(GITREFSPEC GITHASH) if (GITHASH) string(SUBSTRING "${GITHASH}" 0 8 GITHASH) @@ -72,44 +77,85 @@ endif(CMAKE_AUTOSET_INSTALL_RPATH) # which point to directories outside the build tree to the install RPATH option(CMAKE_INSTALL_RPATH_USE_LINK_PATH "build with automatic rpath" TRUE) -######################################################################## - -list(APPEND SOAPY_SDR_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/Modules.cpp) -configure_file( - ${LIBSOAPYSDRSRC}/lib/Modules.in.cpp - ${CMAKE_CURRENT_BINARY_DIR}/Modules.cpp -@ONLY) - -list(APPEND SOAPY_SDR_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/Version.cpp) -configure_file( - ${LIBSOAPYSDRSRC}/lib/Version.in.cpp - ${CMAKE_CURRENT_BINARY_DIR}/Version.cpp -@ONLY) +if(APPLE) + set(CMAKE_MACOSX_RPATH ON) +endif() ######################################################################## +# Allows in-tree module util +######################################################################## +set(SoapySDR_DIR ${SOAPYSDR_SOURCE_DIR}/cmake/Modules) +set(SOAPY_SDR_IN_TREE_SOURCE_DIR ${SOAPYSDR_SOURCE_DIR}) +find_package(SoapySDR NO_MODULE REQUIRED) +include_directories(${SoapySDR_INCLUDE_DIRS}) #local include precedence -file(GLOB soapysdr_SOURCES - ${LIBSOAPYSDRSRC}/lib/*.cpp -) +######################################################################## +# Install cmake helper modules +######################################################################## +configure_file( + ${SOAPYSDR_SOURCE_DIR}/cmake/Modules/SoapySDRConfigVersion.in.cmake + ${PROJECT_BINARY_DIR}/SoapySDRConfigVersion.cmake +@ONLY) +set(cmake_files + ${SOAPYSDR_SOURCE_DIR}/cmake/Modules/SoapySDRConfig.cmake + ${SOAPYSDR_SOURCE_DIR}/cmake/Modules/SoapySDRUtil.cmake + ${PROJECT_BINARY_DIR}/SoapySDRConfigVersion.cmake) +if (UNIX) + install(FILES ${cmake_files} DESTINATION share/cmake/${PROJECT_NAME}) +elseif (WIN32) + install(FILES ${cmake_files} DESTINATION cmake) +endif () -file(GLOB soapysdr_HEADERS - ${LIBSOAPYSDRSRC}/include/SoapySDR/*.hpp - ${LIBSOAPYSDRSRC}/include/SoapySDR/*.h -) +######################################################################## +# Install headers +######################################################################## +#install(DIRECTORY include/SoapySDR DESTINATION include) -include_directories( - . - ${CMAKE_CURRENT_BINARY_DIR} - ${LIBSOAPYSDRSRC}/include - ${LIBSOAPYSDRSRC}/lib -) +######################################################################## +# Build subdirs +######################################################################## +add_subdirectory(${SOAPYSDR_SOURCE_DIR}/lib ${PROJECT_BINARY_DIR}/lib) +#add_subdirectory(apps) +#add_subdirectory(tests) +#add_subdirectory(docs) -add_definitions(-DQT_SHARED) +######################################################################## +# uninstall target +######################################################################## +configure_file( + "${SOAPYSDR_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${SOAPYSDR_SOURCE_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) -message( STATUS "soapysdr_SOURCES: ${soapysdr_SOURCES}" ) +#only add uninstall target if this is the top project +if(${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +endif() -add_library(soapysdr SHARED - ${soapysdr_SOURCES} -) +######################################################################### +# summary +######################################################################### +include(FeatureSummary) +message(STATUS "") +message(STATUS "######################################################") +message(STATUS "## ${PROJECT_NAME} enabled features") +message(STATUS "######################################################") +feature_summary(WHAT ENABLED_FEATURES) +message(STATUS "######################################################") +message(STATUS "## ${PROJECT_NAME} disabled features") +message(STATUS "######################################################") +feature_summary(WHAT DISABLED_FEATURES) +message(STATUS "SoapySDR version: v${SOAPY_SDR_VERSION}") +message(STATUS "ABI/so version: v${SOAPY_SDR_ABI_VERSION}") +message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}") -install(TARGETS soapysdr DESTINATION lib) +#add_definitions(-DQT_SHARED) +# +#message( STATUS "soapysdr_SOURCES: ${soapysdr_SOURCES}" ) +# +#add_library(soapysdr SHARED +# ${soapysdr_SOURCES} +#) +# +#install(TARGETS soapysdr DESTINATION lib) From d225bf937824c866d82b487dc6f2f1b5be0346eb Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 1 Dec 2018 10:09:10 +0100 Subject: [PATCH 100/102] SoapySDR support: new attempt for Debian build (2) --- devices/CMakeLists.txt | 1 + devices/soapysdr/CMakeLists.txt | 4 ++-- plugins/samplesink/CMakeLists.txt | 1 + plugins/samplesink/soapysdroutput/CMakeLists.txt | 4 ++-- plugins/samplesource/CMakeLists.txt | 1 + plugins/samplesource/soapysdrinput/CMakeLists.txt | 4 ++-- pluginssrv/samplesink/soapysdroutput/CMakeLists.txt | 4 ++-- pluginssrv/samplesource/soapysdrinput/CMakeLists.txt | 4 ++-- 8 files changed, 13 insertions(+), 10 deletions(-) diff --git a/devices/CMakeLists.txt b/devices/CMakeLists.txt index e61097662..65439fb0d 100644 --- a/devices/CMakeLists.txt +++ b/devices/CMakeLists.txt @@ -11,6 +11,7 @@ if (BUILD_DEBIAN) add_subdirectory(limesdr) add_subdirectory(perseus) add_subdirectory(plutosdr) + add_subdirectory(soapysdr) else(BUILD_DEBIAN) find_package(LibBLADERF) if(LIBUSB_FOUND AND LIBBLADERF_FOUND) diff --git a/devices/soapysdr/CMakeLists.txt b/devices/soapysdr/CMakeLists.txt index f8268c52b..2f6c3dfea 100644 --- a/devices/soapysdr/CMakeLists.txt +++ b/devices/soapysdr/CMakeLists.txt @@ -20,8 +20,8 @@ if (BUILD_DEBIAN) include_directories( . ${CMAKE_CURRENT_BINARY_DIR} - ${LIBSOAPYSDRSRC}/include - ${LIBSOAPYSDRSRC}/src + ${SOAPYSDR_SOURCE_DIR}/include + ${SOAPYSDR_SOURCE_DIR}/src ) else (BUILD_DEBIAN) include_directories( diff --git a/plugins/samplesink/CMakeLists.txt b/plugins/samplesink/CMakeLists.txt index f8f4af31c..a57d121a4 100644 --- a/plugins/samplesink/CMakeLists.txt +++ b/plugins/samplesink/CMakeLists.txt @@ -40,6 +40,7 @@ if (BUILD_DEBIAN) add_subdirectory(limesdroutput) add_subdirectory(plutosdroutput) add_subdirectory(sdrdaemonsink) + add_subdirectory(soapysdroutput) endif (BUILD_DEBIAN) add_subdirectory(filesink) diff --git a/plugins/samplesink/soapysdroutput/CMakeLists.txt b/plugins/samplesink/soapysdroutput/CMakeLists.txt index d621ceb2e..a0aafc3ae 100644 --- a/plugins/samplesink/soapysdroutput/CMakeLists.txt +++ b/plugins/samplesink/soapysdroutput/CMakeLists.txt @@ -28,8 +28,8 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client ${CMAKE_SOURCE_DIR}/devices - ${LIBSOAPYSDRSRC}/include - ${LIBSOAPYSDRSRC}/src + ${SOAPYSDR_SOURCE_DIR}/include + ${SOAPYSDR_SOURCE_DIR}/src ) else (BUILD_DEBIAN) include_directories( diff --git a/plugins/samplesource/CMakeLists.txt b/plugins/samplesource/CMakeLists.txt index 93fc805c7..9e442fa11 100644 --- a/plugins/samplesource/CMakeLists.txt +++ b/plugins/samplesource/CMakeLists.txt @@ -97,6 +97,7 @@ if (BUILD_DEBIAN) add_subdirectory(rtlsdr) add_subdirectory(sdrdaemonsource) add_subdirectory(sdrplay) + add_subdirectory(soapysdrinput) endif (BUILD_DEBIAN) add_subdirectory(filesource) diff --git a/plugins/samplesource/soapysdrinput/CMakeLists.txt b/plugins/samplesource/soapysdrinput/CMakeLists.txt index da3141fcd..bc46d685e 100644 --- a/plugins/samplesource/soapysdrinput/CMakeLists.txt +++ b/plugins/samplesource/soapysdrinput/CMakeLists.txt @@ -28,8 +28,8 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client ${CMAKE_SOURCE_DIR}/devices - ${LIBSOAPYSDRSRC}/include - ${LIBSOAPYSDRSRC}/src + ${SOAPYSDR_SOURCE_DIR}/include + ${SOAPYSDR_SOURCE_DIR}/src ) else (BUILD_DEBIAN) include_directories( diff --git a/pluginssrv/samplesink/soapysdroutput/CMakeLists.txt b/pluginssrv/samplesink/soapysdroutput/CMakeLists.txt index 0f99beee2..b84de7a4a 100644 --- a/pluginssrv/samplesink/soapysdroutput/CMakeLists.txt +++ b/pluginssrv/samplesink/soapysdroutput/CMakeLists.txt @@ -23,8 +23,8 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client ${CMAKE_SOURCE_DIR}/devices - ${LIBSOAPYSDRSRC}/include - ${LIBSOAPYSDRSRC}/src + ${SOAPYSDR_SOURCE_DIR}/include + ${SOAPYSDR_SOURCE_DIR}/src ) else (BUILD_DEBIAN) include_directories( diff --git a/pluginssrv/samplesource/soapysdrinput/CMakeLists.txt b/pluginssrv/samplesource/soapysdrinput/CMakeLists.txt index 331082b11..ceccc4ff2 100644 --- a/pluginssrv/samplesource/soapysdrinput/CMakeLists.txt +++ b/pluginssrv/samplesource/soapysdrinput/CMakeLists.txt @@ -23,8 +23,8 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client ${CMAKE_SOURCE_DIR}/devices - ${LIBSOAPYSDRSRC}/include - ${LIBSOAPYSDRSRC}/src + ${SOAPYSDR_SOURCE_DIR}/include + ${SOAPYSDR_SOURCE_DIR}/src ) else (BUILD_DEBIAN) include_directories( From fe0f506f5081a15e98f4723220c3b28641987d82 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 1 Dec 2018 10:12:15 +0000 Subject: [PATCH 101/102] SoapySDR support: new attempt for Debian build (3) --- devices/soapysdr/CMakeLists.txt | 2 +- plugins/samplesink/soapysdroutput/CMakeLists.txt | 2 +- plugins/samplesource/soapysdrinput/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/devices/soapysdr/CMakeLists.txt b/devices/soapysdr/CMakeLists.txt index 2f6c3dfea..c7902bdde 100644 --- a/devices/soapysdr/CMakeLists.txt +++ b/devices/soapysdr/CMakeLists.txt @@ -40,7 +40,7 @@ add_library(soapysdrdevice SHARED if (BUILD_DEBIAN) target_link_libraries(soapysdrdevice - soapysdr + SoapySDR sdrbase ) else (BUILD_DEBIAN) diff --git a/plugins/samplesink/soapysdroutput/CMakeLists.txt b/plugins/samplesink/soapysdroutput/CMakeLists.txt index a0aafc3ae..b1b1db381 100644 --- a/plugins/samplesink/soapysdroutput/CMakeLists.txt +++ b/plugins/samplesink/soapysdroutput/CMakeLists.txt @@ -56,7 +56,7 @@ add_library(outputsoapysdr SHARED if (BUILD_DEBIAN) target_link_libraries(outputsoapysdr ${QT_LIBRARIES} - soapysdr + SoapySDR sdrbase sdrgui swagger diff --git a/plugins/samplesource/soapysdrinput/CMakeLists.txt b/plugins/samplesource/soapysdrinput/CMakeLists.txt index bc46d685e..4bc9a72cf 100644 --- a/plugins/samplesource/soapysdrinput/CMakeLists.txt +++ b/plugins/samplesource/soapysdrinput/CMakeLists.txt @@ -56,7 +56,7 @@ add_library(inputsoapysdr SHARED if (BUILD_DEBIAN) target_link_libraries(inputsoapysdr ${QT_LIBRARIES} - soapysdr + SoapySDR sdrbase sdrgui swagger From f520ad60724e94e6b392029b41c15f25f98be348 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 2 Dec 2018 00:04:41 +0100 Subject: [PATCH 102/102] Debian dsdcc build with C++11 option --- dsdcc/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dsdcc/CMakeLists.txt b/dsdcc/CMakeLists.txt index 5f5611cae..152efc73e 100644 --- a/dsdcc/CMakeLists.txt +++ b/dsdcc/CMakeLists.txt @@ -1,5 +1,7 @@ project(dsdcc) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(dsdcc_SOURCES ${LIBDSDCCSRC}/descramble.cpp ${LIBDSDCCSRC}/dmr.cpp