From abf0f2f2e76fb71d3dbe3b1506d81482c22e5d1d Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 13 Oct 2022 00:14:00 +0200 Subject: [PATCH] VOR demod: updated threading model. Part of #1346 --- plugins/channelrx/demodvor/vordemod.cpp | 82 +++++++++++++------ plugins/channelrx/demodvor/vordemod.h | 21 +++-- .../channelrx/demodvor/vordemodbaseband.cpp | 27 +++--- plugins/channelrx/demodvor/vordemodbaseband.h | 5 +- 4 files changed, 83 insertions(+), 52 deletions(-) diff --git a/plugins/channelrx/demodvor/vordemod.cpp b/plugins/channelrx/demodvor/vordemod.cpp index 1ac469377..39d58656b 100644 --- a/plugins/channelrx/demodvor/vordemod.cpp +++ b/plugins/channelrx/demodvor/vordemod.cpp @@ -51,14 +51,12 @@ const char * const VORDemod::m_channelId = "VORDemod"; VORDemod::VORDemod(DeviceAPI *deviceAPI) : ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink), m_deviceAPI(deviceAPI), + m_thread(nullptr), + m_basebandSink(nullptr), + m_running(false), m_basebandSampleRate(0) { setObjectName(m_channelId); - - m_basebandSink = new VORDemodBaseband(); - m_basebandSink->setMessageQueueToChannel(getInputMessageQueue()); - m_basebandSink->moveToThread(&m_thread); - applySettings(m_settings, true); m_deviceAPI->addChannelSink(this); @@ -77,6 +75,8 @@ VORDemod::VORDemod(DeviceAPI *deviceAPI) : this, &VORDemod::handleIndexInDeviceSetChanged ); + + start(); } VORDemod::~VORDemod() @@ -91,12 +91,7 @@ VORDemod::~VORDemod() delete m_networkManager; m_deviceAPI->removeChannelSinkAPI(this); m_deviceAPI->removeChannelSink(this); - - if (m_basebandSink->isRunning()) { - stop(); - } - - delete m_basebandSink; + stop(); } void VORDemod::setDeviceAPI(DeviceAPI *deviceAPI) @@ -119,30 +114,51 @@ uint32_t VORDemod::getNumberOfDeviceStreams() const void VORDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) { (void) firstOfBurst; - m_basebandSink->feed(begin, end); + + if (m_running) { + m_basebandSink->feed(begin, end); + } } void VORDemod::start() { + if (m_running) { + return; + } + qDebug("VORDemod::start"); + m_thread = new QThread(); + m_basebandSink = new VORDemodBaseband(); + m_basebandSink->setMessageQueueToChannel(getInputMessageQueue()); + m_basebandSink->moveToThread(m_thread); + + QObject::connect(m_thread, &QThread::finished, m_basebandSink, &QObject::deleteLater); + QObject::connect(m_thread, &QThread::finished, m_thread, &QThread::deleteLater); m_basebandSink->reset(); m_basebandSink->startWork(); - m_thread.start(); + m_thread->start(); DSPSignalNotification *dspMsg = new DSPSignalNotification(m_basebandSampleRate, m_centerFrequency); m_basebandSink->getInputMessageQueue()->push(dspMsg); VORDemodBaseband::MsgConfigureVORDemodBaseband *msg = VORDemodBaseband::MsgConfigureVORDemodBaseband::create(m_settings, true); m_basebandSink->getInputMessageQueue()->push(msg); + + m_running = true; } void VORDemod::stop() { + if (!m_running) { + return; + } + qDebug("VORDemod::stop"); + m_running = false; m_basebandSink->stopWork(); - m_thread.quit(); - m_thread.wait(); + m_thread->quit(); + m_thread->wait(); } bool VORDemod::handleMessage(const Message& cmd) @@ -160,10 +176,15 @@ bool VORDemod::handleMessage(const Message& cmd) DSPSignalNotification& notif = (DSPSignalNotification&) cmd; m_basebandSampleRate = notif.getSampleRate(); m_centerFrequency = notif.getCenterFrequency(); - // Forward to the sink - DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy qDebug() << "VORDemod::handleMessage: DSPSignalNotification"; - m_basebandSink->getInputMessageQueue()->push(rep); + + // Forward to the sink + if (m_running) + { + DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy + m_basebandSink->getInputMessageQueue()->push(rep); + } + // Forward to GUI if any if (m_guiMessageQueue) { m_guiMessageQueue->push(new DSPSignalNotification(notif)); @@ -297,8 +318,11 @@ void VORDemod::applySettings(const VORDemodSettings& settings, bool force) reverseAPIKeys.append("identThreshold"); } - VORDemodBaseband::MsgConfigureVORDemodBaseband *msg = VORDemodBaseband::MsgConfigureVORDemodBaseband::create(settings, force); - m_basebandSink->getInputMessageQueue()->push(msg); + if (m_running) + { + VORDemodBaseband::MsgConfigureVORDemodBaseband *msg = VORDemodBaseband::MsgConfigureVORDemodBaseband::create(settings, force); + m_basebandSink->getInputMessageQueue()->push(msg); + } if (settings.m_useReverseAPI) { @@ -522,12 +546,16 @@ void VORDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& resp void VORDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) { - double magsqAvg, magsqPeak; - int nbMagsqSamples; - getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples); - response.getVorDemodReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg)); - response.getVorDemodReport()->setSquelch(m_basebandSink->getSquelchOpen() ? 1 : 0); - response.getVorDemodReport()->setAudioSampleRate(m_basebandSink->getAudioSampleRate()); + if (m_running) + { + double magsqAvg, magsqPeak; + int nbMagsqSamples; + getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples); + response.getVorDemodReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg)); + response.getVorDemodReport()->setSquelch(m_basebandSink->getSquelchOpen() ? 1 : 0); + response.getVorDemodReport()->setAudioSampleRate(m_basebandSink->getAudioSampleRate()); + } + response.getVorDemodReport()->setNavId(m_settings.m_navId); response.getVorDemodReport()->setRadial(m_radial); response.getVorDemodReport()->setRefMag(m_refMag); @@ -701,7 +729,7 @@ void VORDemod::networkManagerFinished(QNetworkReply *reply) void VORDemod::handleIndexInDeviceSetChanged(int index) { - if (index < 0) { + if (!m_running || (index < 0)) { return; } diff --git a/plugins/channelrx/demodvor/vordemod.h b/plugins/channelrx/demodvor/vordemod.h index ec4e51a61..c23847a60 100644 --- a/plugins/channelrx/demodvor/vordemod.h +++ b/plugins/channelrx/demodvor/vordemod.h @@ -22,7 +22,6 @@ #include #include -#include #include "dsp/basebandsamplesink.h" #include "channel/channelapi.h" @@ -122,12 +121,17 @@ public: const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response); - uint32_t getAudioSampleRate() const { return m_basebandSink->getAudioSampleRate(); } - double getMagSq() const { return m_basebandSink->getMagSq(); } - bool getSquelchOpen() const { return m_basebandSink->getSquelchOpen(); } + uint32_t getAudioSampleRate() const { return m_running ? m_basebandSink->getAudioSampleRate() : 0; } + double getMagSq() const { return m_running ? m_basebandSink->getMagSq() : 0.0; } + bool getSquelchOpen() const { return m_running ? m_basebandSink->getSquelchOpen() : false; } - void getMagSqLevels(double& avg, double& peak, int& nbSamples) { - m_basebandSink->getMagSqLevels(avg, peak, nbSamples); + void getMagSqLevels(double& avg, double& peak, int& nbSamples) + { + if (m_running) { + m_basebandSink->getMagSqLevels(avg, peak, nbSamples); + } else { + avg = 0.0; peak = 0.0; nbSamples = 1; + } } uint32_t getNumberOfDeviceStreams() const; @@ -137,8 +141,9 @@ public: private: DeviceAPI *m_deviceAPI; - QThread m_thread; - VORDemodBaseband* m_basebandSink; + QThread *m_thread; + VORDemodBaseband *m_basebandSink; + bool m_running; VORDemodSettings m_settings; int m_basebandSampleRate; //!< stored from device message used when starting baseband sink qint64 m_centerFrequency; diff --git a/plugins/channelrx/demodvor/vordemodbaseband.cpp b/plugins/channelrx/demodvor/vordemodbaseband.cpp index 6b3593ce8..a90ad0185 100644 --- a/plugins/channelrx/demodvor/vordemodbaseband.cpp +++ b/plugins/channelrx/demodvor/vordemodbaseband.cpp @@ -28,12 +28,12 @@ MESSAGE_CLASS_DEFINITION(VORDemodBaseband::MsgConfigureVORDemodBaseband, Message) VORDemodBaseband::VORDemodBaseband() : + m_channelizer(&m_sink), m_messageQueueToGUI(nullptr), m_running(false) { qDebug("VORDemodBaseband::VORDemodBaseband"); m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(48000)); - m_channelizer = new DownChannelizer(&m_sink); DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(m_sink.getAudioFifo(), getInputMessageQueue()); m_sink.applyAudioSampleRate(DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate()); @@ -44,7 +44,6 @@ VORDemodBaseband::~VORDemodBaseband() { m_inputMessageQueue.clear(); DSPEngine::instance()->getAudioDeviceManager()->removeAudioSink(m_sink.getAudioFifo()); - delete m_channelizer; } void VORDemodBaseband::reset() @@ -102,12 +101,12 @@ void VORDemodBaseband::handleData() // first part of FIFO data if (part1begin != part1end) { - m_channelizer->feed(part1begin, part1end); + m_channelizer.feed(part1begin, part1end); } // second part of FIFO data (used when block wraps around) if(part2begin != part2end) { - m_channelizer->feed(part2begin, part2end); + m_channelizer.feed(part2begin, part2end); } m_sampleFifo.readCommit((unsigned int) count); @@ -144,13 +143,13 @@ bool VORDemodBaseband::handleMessage(const Message& cmd) DSPSignalNotification& notif = (DSPSignalNotification&) cmd; qDebug() << "VORDemodBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate() << " centerFrequency: " << notif.getCenterFrequency(); m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(notif.getSampleRate())); - m_channelizer->setBasebandSampleRate(notif.getSampleRate()); - m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset()); + m_channelizer.setBasebandSampleRate(notif.getSampleRate()); + m_sink.applyChannelSettings(m_channelizer.getChannelSampleRate(), m_channelizer.getChannelFrequencyOffset()); - if (m_channelSampleRate != m_channelizer->getChannelSampleRate()) + if (m_channelSampleRate != m_channelizer.getChannelSampleRate()) { m_sink.applyAudioSampleRate(m_sink.getAudioSampleRate()); // reapply when channel sample rate changes - m_channelSampleRate = m_channelizer->getChannelSampleRate(); + m_channelSampleRate = m_channelizer.getChannelSampleRate(); } return true; @@ -165,13 +164,13 @@ void VORDemodBaseband::applySettings(const VORDemodSettings& settings, bool forc { if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) { - m_channelizer->setChannelization(m_sink.getAudioSampleRate(), settings.m_inputFrequencyOffset); - m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset()); + m_channelizer.setChannelization(m_sink.getAudioSampleRate(), settings.m_inputFrequencyOffset); + m_sink.applyChannelSettings(m_channelizer.getChannelSampleRate(), m_channelizer.getChannelFrequencyOffset()); - if (m_channelSampleRate != m_channelizer->getChannelSampleRate()) + if (m_channelSampleRate != m_channelizer.getChannelSampleRate()) { m_sink.applyAudioSampleRate(m_sink.getAudioSampleRate()); // reapply when channel sample rate changes - m_channelSampleRate = m_channelizer->getChannelSampleRate(); + m_channelSampleRate = m_channelizer.getChannelSampleRate(); } } @@ -186,8 +185,8 @@ void VORDemodBaseband::applySettings(const VORDemodSettings& settings, bool forc if (m_sink.getAudioSampleRate() != audioSampleRate) { - m_channelizer->setChannelization(audioSampleRate, settings.m_inputFrequencyOffset); - m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset()); + m_channelizer.setChannelization(audioSampleRate, settings.m_inputFrequencyOffset); + m_sink.applyChannelSettings(m_channelizer.getChannelSampleRate(), m_channelizer.getChannelFrequencyOffset()); m_sink.applyAudioSampleRate(audioSampleRate); } } diff --git a/plugins/channelrx/demodvor/vordemodbaseband.h b/plugins/channelrx/demodvor/vordemodbaseband.h index 557b1b181..ddadd0448 100644 --- a/plugins/channelrx/demodvor/vordemodbaseband.h +++ b/plugins/channelrx/demodvor/vordemodbaseband.h @@ -23,13 +23,12 @@ #include #include "dsp/samplesinkfifo.h" +#include "dsp/downchannelizer.h" #include "util/message.h" #include "util/messagequeue.h" #include "vordemodsink.h" -class DownChannelizer; - class VORDemodBaseband : public QObject { Q_OBJECT @@ -75,7 +74,7 @@ public: private: SampleSinkFifo m_sampleFifo; - DownChannelizer * m_channelizer; + DownChannelizer m_channelizer; int m_channelSampleRate; VORDemodSCSink m_sink; MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication