From 81c8a8eef882e2e2151cabc9bbd39aa2d5f472bc Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 24 Dec 2018 00:51:29 +0100 Subject: [PATCH] Reverse API: SSB demod --- plugins/channelrx/demodssb/ssbdemod.cpp | 165 +++++++++++++++++- plugins/channelrx/demodssb/ssbdemod.h | 14 +- plugins/channelrx/demodssb/ssbdemodgui.cpp | 11 ++ .../channelrx/demodssb/ssbdemodsettings.cpp | 25 +++ plugins/channelrx/demodssb/ssbdemodsettings.h | 5 + 5 files changed, 218 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/demodssb/ssbdemod.cpp b/plugins/channelrx/demodssb/ssbdemod.cpp index 311cca888..6d14d3843 100644 --- a/plugins/channelrx/demodssb/ssbdemod.cpp +++ b/plugins/channelrx/demodssb/ssbdemod.cpp @@ -17,9 +17,13 @@ /////////////////////////////////////////////////////////////////////////////////// +#include + #include #include -#include +#include +#include +#include #include "SWGChannelSettings.h" #include "SWGSSBDemodSettings.h" @@ -98,10 +102,15 @@ SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) : m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this); m_deviceAPI->addThreadedSink(m_threadedChannelizer); m_deviceAPI->addChannelAPI(this); + + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); } SSBDemod::~SSBDemod() { + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; DSPEngine::instance()->getAudioDeviceManager()->removeAudioSink(&m_audioFifo); m_deviceAPI->removeChannelAPI(this); @@ -455,6 +464,18 @@ void SSBDemod::applySettings(const SSBDemodSettings& settings, bool force) << " m_audioDeviceName: " << settings.m_audioDeviceName << " force: " << force; + QList reverseAPIKeys; + + if((m_settings.m_inputFrequencyOffset != settings.m_inputFrequencyOffset) || force) { + reverseAPIKeys.append("inputFrequencyOffset"); + } + if((m_settings.m_rfBandwidth != settings.m_rfBandwidth) || force) { + reverseAPIKeys.append("rfBandwidth"); + } + if((m_settings.m_lowCutoff != settings.m_lowCutoff) || force) { + reverseAPIKeys.append("lowCutoff"); + } + if((m_settings.m_rfBandwidth != settings.m_rfBandwidth) || (m_settings.m_lowCutoff != settings.m_lowCutoff) || force) { @@ -491,10 +512,24 @@ void SSBDemod::applySettings(const SSBDemodSettings& settings, bool force) if ((m_settings.m_volume != settings.m_volume) || force) { + reverseAPIKeys.append("volume"); m_volume = settings.m_volume; m_volume /= 4.0; // for 3276.8 } + if ((m_settings.m_agcTimeLog2 != settings.m_agcTimeLog2) || force) { + reverseAPIKeys.append("agcTimeLog2"); + } + if ((m_settings.m_agcPowerThreshold != settings.m_agcPowerThreshold) || force) { + reverseAPIKeys.append("agcPowerThreshold"); + } + if ((m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) || force) { + reverseAPIKeys.append("agcThresholdGate"); + } + if ((m_settings.m_agcClamping != settings.m_agcClamping) || force) { + reverseAPIKeys.append("agcClamping"); + } + if ((m_settings.m_agcTimeLog2 != settings.m_agcTimeLog2) || (m_settings.m_agcPowerThreshold != settings.m_agcPowerThreshold) || (m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) || @@ -542,6 +577,7 @@ void SSBDemod::applySettings(const SSBDemodSettings& settings, bool force) if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force) { + reverseAPIKeys.append("audioDeviceName"); AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_audioDeviceName); audioDeviceManager->addAudioSink(&m_audioFifo, getInputMessageQueue(), audioDeviceIndex); @@ -552,6 +588,25 @@ void SSBDemod::applySettings(const SSBDemodSettings& settings, bool force) } } + if ((m_settings.m_spanLog2 != settings.m_spanLog2) || force) { + reverseAPIKeys.append("spanLog2"); + } + if ((m_settings.m_audioBinaural != settings.m_audioBinaural) || force) { + reverseAPIKeys.append("audioBinaural"); + } + if ((m_settings.m_audioFlipChannels != settings.m_audioFlipChannels) || force) { + reverseAPIKeys.append("audioFlipChannels"); + } + if ((m_settings.m_dsb != settings.m_dsb) || force) { + reverseAPIKeys.append("dsb"); + } + if ((m_settings.m_audioMute != settings.m_audioMute) || force) { + reverseAPIKeys.append("audioMute"); + } + if ((m_settings.m_agc != settings.m_agc) || force) { + reverseAPIKeys.append("agc"); + } + m_spanLog2 = settings.m_spanLog2; m_audioBinaual = settings.m_audioBinaural; m_audioFlipChannels = settings.m_audioFlipChannels; @@ -559,6 +614,16 @@ void SSBDemod::applySettings(const SSBDemodSettings& settings, bool force) m_audioMute = settings.m_audioMute; m_agcActive = settings.m_agc; + if (settings.m_useReverseAPI) + { + bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || + (m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) || + (m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) || + (m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex) || + (m_settings.m_reverseAPIChannelIndex != settings.m_reverseAPIChannelIndex); + webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); + } + m_settings = settings; } @@ -736,3 +801,101 @@ void SSBDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response response.getSsbDemodReport()->setChannelSampleRate(m_inputSampleRate); } +void SSBDemod::webapiReverseSendSettings(QList& channelSettingsKeys, const SSBDemodSettings& settings, bool force) +{ + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + swgChannelSettings->setTx(0); + swgChannelSettings->setChannelType(new QString("SSBDemod")); + swgChannelSettings->setSsbDemodSettings(new SWGSDRangel::SWGSSBDemodSettings()); + SWGSDRangel::SWGSSBDemodSettings *swgSSBDemodSettings = swgChannelSettings->getSsbDemodSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { + swgSSBDemodSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); + } + if (channelSettingsKeys.contains("rfBandwidth") || force) { + swgSSBDemodSettings->setRfBandwidth(settings.m_rfBandwidth); + } + if (channelSettingsKeys.contains("lowCutoff") || force) { + swgSSBDemodSettings->setLowCutoff(settings.m_lowCutoff); + } + if (channelSettingsKeys.contains("volume") || force) { + swgSSBDemodSettings->setVolume(settings.m_volume); + } + if (channelSettingsKeys.contains("spanLog2") || force) { + swgSSBDemodSettings->setSpanLog2(settings.m_spanLog2); + } + if (channelSettingsKeys.contains("audioBinaural") || force) { + swgSSBDemodSettings->setAudioBinaural(settings.m_audioBinaural ? 1 : 0); + } + if (channelSettingsKeys.contains("audioFlipChannels") || force) { + swgSSBDemodSettings->setAudioFlipChannels(settings.m_audioFlipChannels ? 1 : 0); + } + if (channelSettingsKeys.contains("dsb") || force) { + swgSSBDemodSettings->setDsb(settings.m_dsb ? 1 : 0); + } + if (channelSettingsKeys.contains("audioMute") || force) { + swgSSBDemodSettings->setAudioMute(settings.m_audioMute ? 1 : 0); + } + if (channelSettingsKeys.contains("agc") || force) { + swgSSBDemodSettings->setAgc(settings.m_agc ? 1 : 0); + } + if (channelSettingsKeys.contains("agcClamping") || force) { + swgSSBDemodSettings->setAgcClamping(settings.m_agcClamping ? 1 : 0); + } + if (channelSettingsKeys.contains("agcTimeLog2") || force) { + swgSSBDemodSettings->setAgcTimeLog2(settings.m_agcTimeLog2); + } + if (channelSettingsKeys.contains("agcPowerThreshold") || force) { + swgSSBDemodSettings->setAgcPowerThreshold(settings.m_agcPowerThreshold); + } + if (channelSettingsKeys.contains("agcThresholdGate") || force) { + swgSSBDemodSettings->setAgcThresholdGate(settings.m_agcThresholdGate); + } + if (channelSettingsKeys.contains("rgbColor") || force) { + swgSSBDemodSettings->setRgbColor(settings.m_rgbColor); + } + if (channelSettingsKeys.contains("title") || force) { + swgSSBDemodSettings->setTitle(new QString(settings.m_title)); + } + if (channelSettingsKeys.contains("audioDeviceName") || force) { + swgSSBDemodSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName)); + } + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer=new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->asJson().toUtf8()); + buffer->seek(0); + + // Always use PATCH to avoid passing reverse API settings + m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + + delete swgChannelSettings; +} + +void SSBDemod::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "SSBDemod::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + return; + } + + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("SSBDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); +} diff --git a/plugins/channelrx/demodssb/ssbdemod.h b/plugins/channelrx/demodssb/ssbdemod.h index 27521aa01..da30d0470 100644 --- a/plugins/channelrx/demodssb/ssbdemod.h +++ b/plugins/channelrx/demodssb/ssbdemod.h @@ -18,9 +18,11 @@ #ifndef INCLUDE_SSBDEMOD_H #define INCLUDE_SSBDEMOD_H -#include #include +#include +#include + #include "dsp/basebandsamplesink.h" #include "channel/channelsinkapi.h" #include "dsp/ncof.h" @@ -36,11 +38,14 @@ #define ssbFftLen 1024 #define agcTarget 3276.8 // -10 dB amplitude => -20 dB power: center of normal signal +class QNetworkAccessManager; +class QNetworkReply; class DeviceSourceAPI; class ThreadedBasebandSampleSink; class DownChannelizer; class SSBDemod : public BasebandSampleSink, public ChannelSinkAPI { + Q_OBJECT public: class MsgConfigureSSBDemod : public Message { MESSAGE_CLASS_DECLARATION @@ -310,6 +315,9 @@ private: AudioFifo m_audioFifo; quint32 m_audioSampleRate; + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + QMutex m_settingsMutex; void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force = false); @@ -317,6 +325,10 @@ private: void applyAudioSampleRate(int sampleRate); void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const SSBDemodSettings& settings); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); + void webapiReverseSendSettings(QList& channelSettingsKeys, const SSBDemodSettings& settings, bool force); + +private slots: + void networkManagerFinished(QNetworkReply *reply); }; #endif // INCLUDE_SSBDEMOD_H diff --git a/plugins/channelrx/demodssb/ssbdemodgui.cpp b/plugins/channelrx/demodssb/ssbdemodgui.cpp index f9763b65d..ca4702b0b 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.cpp +++ b/plugins/channelrx/demodssb/ssbdemodgui.cpp @@ -238,12 +238,23 @@ void SSBDemodGUI::on_flipSidebands_clicked(bool checked) void SSBDemodGUI::onMenuDialogCalled(const QPoint &p) { BasicChannelSettingsDialog dialog(&m_channelMarker, this); + dialog.setUseReverseAPI(m_settings.m_useReverseAPI); + dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); + dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); + dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex); + dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex); + dialog.move(p); dialog.exec(); m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); m_settings.m_rgbColor = m_channelMarker.getColor().rgb(); m_settings.m_title = m_channelMarker.getTitle(); + m_settings.m_useReverseAPI = dialog.useReverseAPI(); + m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); + m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); + m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex(); + m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex(); setWindowTitle(m_settings.m_title); setTitleColor(m_settings.m_rgbColor); diff --git a/plugins/channelrx/demodssb/ssbdemodsettings.cpp b/plugins/channelrx/demodssb/ssbdemodsettings.cpp index fbc4b7689..1b7fe8149 100644 --- a/plugins/channelrx/demodssb/ssbdemodsettings.cpp +++ b/plugins/channelrx/demodssb/ssbdemodsettings.cpp @@ -55,6 +55,11 @@ void SSBDemodSettings::resetToDefaults() m_rgbColor = QColor(0, 255, 0).rgb(); m_title = "SSB Demodulator"; m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; + m_reverseAPIChannelIndex = 0; } QByteArray SSBDemodSettings::serialize() const @@ -81,6 +86,11 @@ QByteArray SSBDemodSettings::serialize() const s.writeBool(15, m_agcClamping); s.writeString(16, m_title); s.writeString(17, m_audioDeviceName); + s.writeBool(18, m_useReverseAPI); + s.writeString(19, m_reverseAPIAddress); + s.writeU32(20, m_reverseAPIPort); + s.writeU32(21, m_reverseAPIDeviceIndex); + s.writeU32(22, m_reverseAPIChannelIndex); return s.final(); } @@ -99,6 +109,7 @@ bool SSBDemodSettings::deserialize(const QByteArray& data) { QByteArray bytetmp; qint32 tmp; + uint32_t utmp; QString strtmp; d.readS32(1, &m_inputFrequencyOffset, 0); @@ -126,6 +137,20 @@ bool SSBDemodSettings::deserialize(const QByteArray& data) d.readBool(15, &m_agcClamping, false); d.readString(16, &m_title, "SSB Demodulator"); d.readString(17, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName); + d.readBool(18, &m_useReverseAPI, false); + d.readString(19, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(20, &utmp, 0); + + if ((utmp > 1023) && (utmp < 65535)) { + m_reverseAPIPort = utmp; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(21, &utmp, 0); + m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp; + d.readU32(22, &utmp, 0); + m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp; return true; } diff --git a/plugins/channelrx/demodssb/ssbdemodsettings.h b/plugins/channelrx/demodssb/ssbdemodsettings.h index 7b6ac2035..33632fbc5 100644 --- a/plugins/channelrx/demodssb/ssbdemodsettings.h +++ b/plugins/channelrx/demodssb/ssbdemodsettings.h @@ -40,6 +40,11 @@ struct SSBDemodSettings quint32 m_rgbColor; QString m_title; QString m_audioDeviceName; + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; + uint16_t m_reverseAPIChannelIndex; Serializable *m_channelMarker; Serializable *m_spectrumGUI;