diff --git a/plugins/channeltx/modam/ammod.cpp b/plugins/channeltx/modam/ammod.cpp index b947d4f76..39430c63b 100644 --- a/plugins/channeltx/modam/ammod.cpp +++ b/plugins/channeltx/modam/ammod.cpp @@ -56,18 +56,13 @@ const char* const AMMod::m_channelId ="AMMod"; AMMod::AMMod(DeviceAPI *deviceAPI) : ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource), m_deviceAPI(deviceAPI), + m_running(false), m_fileSize(0), m_recordLength(0), - m_sampleRate(48000) + m_sampleRate(48000), + m_levelMeter(nullptr) { setObjectName(m_channelId); - - m_thread = new QThread(this); - m_basebandSource = new AMModBaseband(); - m_basebandSource->setInputFileStream(&m_ifstream); - m_basebandSource->setChannel(this); - m_basebandSource->moveToThread(m_thread); - applySettings(m_settings, true); m_deviceAPI->addChannelSource(this); @@ -93,8 +88,8 @@ AMMod::~AMMod() delete m_networkManager; m_deviceAPI->removeChannelSourceAPI(this); m_deviceAPI->removeChannelSource(this); - delete m_basebandSource; - delete m_thread; + + stop(); } void AMMod::setDeviceAPI(DeviceAPI *deviceAPI) @@ -116,21 +111,61 @@ uint32_t AMMod::getNumberOfDeviceStreams() const void AMMod::start() { + if (m_running) { + return; + } + qDebug("AMMod::start"); + m_thread = new QThread(this); + m_basebandSource = new AMModBaseband(); + m_basebandSource->setInputFileStream(&m_ifstream); + m_basebandSource->setChannel(this); m_basebandSource->reset(); + m_basebandSource->setCWKeyer(&m_cwKeyer); + m_basebandSource->moveToThread(m_thread); + + QObject::connect( + m_thread, + &QThread::finished, + m_basebandSource, + &QObject::deleteLater + ); + QObject::connect( + m_thread, + &QThread::finished, + m_thread, + &QThread::deleteLater + ); + m_thread->start(); + + AMModBaseband::MsgConfigureAMModBaseband *msg = AMModBaseband::MsgConfigureAMModBaseband::create(m_settings, true); + m_basebandSource->getInputMessageQueue()->push(msg); + + if (m_levelMeter) { + connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), m_levelMeter, SLOT(levelChanged(qreal, qreal, int))); + } + + m_running = true; } void AMMod::stop() { + if (!m_running) { + return; + } + qDebug("AMMod::stop"); + m_running = false; m_thread->exit(); m_thread->wait(); } void AMMod::pull(SampleVector::iterator& begin, unsigned int nbSamples) { - m_basebandSource->pull(begin, nbSamples); + if (m_running) { + m_basebandSource->pull(begin, nbSamples); + } } void AMMod::setCenterFrequency(qint64 frequency) @@ -203,11 +238,13 @@ bool AMMod::handleMessage(const Message& cmd) } else if (DSPSignalNotification::match(cmd)) { + qDebug() << "AMMod::handleMessage: DSPSignalNotification"; // Forward to the source DSPSignalNotification& notif = (DSPSignalNotification&) cmd; - DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy - qDebug() << "AMMod::handleMessage: DSPSignalNotification"; - m_basebandSource->getInputMessageQueue()->push(rep); + + if (m_running) { + m_basebandSource->getInputMessageQueue()->push(new DSPSignalNotification(notif)); + } // Forward to GUI if any if (getMessageQueueToGUI()) { getMessageQueueToGUI()->push(new DSPSignalNotification(notif)); @@ -338,8 +375,11 @@ void AMMod::applySettings(const AMModSettings& settings, bool force) reverseAPIKeys.append("streamIndex"); } - AMModBaseband::MsgConfigureAMModBaseband *msg = AMModBaseband::MsgConfigureAMModBaseband::create(settings, force); - m_basebandSource->getInputMessageQueue()->push(msg); + if (m_running) + { + AMModBaseband::MsgConfigureAMModBaseband *msg = AMModBaseband::MsgConfigureAMModBaseband::create(settings, force); + m_basebandSource->getInputMessageQueue()->push(msg); + } if (settings.m_useReverseAPI) { @@ -412,7 +452,7 @@ int AMMod::webapiSettingsGet( webapiFormatChannelSettings(response, m_settings); SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getAmModSettings()->getCwKeyer(); - const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings(); + const CWKeyerSettings& cwKeyerSettings = getCWKeyer()->getSettings(); CWKeyer::webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); return 200; @@ -440,11 +480,11 @@ int AMMod::webapiSettingsPutPatch( if (channelSettingsKeys.contains("cwKeyer")) { SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getAmModSettings()->getCwKeyer(); - CWKeyerSettings cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings(); + CWKeyerSettings cwKeyerSettings = getCWKeyer()->getSettings(); CWKeyer::webapiSettingsPutPatch(channelSettingsKeys, cwKeyerSettings, apiCwKeyerSettings); CWKeyer::MsgConfigureCWKeyer *msgCwKeyer = CWKeyer::MsgConfigureCWKeyer::create(cwKeyerSettings, force); - m_basebandSource->getCWKeyer().getInputMessageQueue()->push(msgCwKeyer); + getCWKeyer()->getInputMessageQueue()->push(msgCwKeyer); if (m_guiMessageQueue) // forward to GUI if any { @@ -615,8 +655,12 @@ void AMMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respons void AMMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) { response.getAmModReport()->setChannelPowerDb(CalcDb::dbPower(getMagSq())); - response.getAmModReport()->setAudioSampleRate(m_basebandSource->getAudioSampleRate()); - response.getAmModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate()); + + if (m_running) + { + response.getAmModReport()->setAudioSampleRate(m_basebandSource->getAudioSampleRate()); + response.getAmModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate()); + } } void AMMod::webapiReverseSendSettings(QList& channelSettingsKeys, const AMModSettings& settings, bool force) @@ -654,7 +698,7 @@ void AMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings) swgAMModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgAMModSettings->getCwKeyer(); - m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); + getCWKeyer()->webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") .arg(m_settings.m_reverseAPIAddress) @@ -756,10 +800,10 @@ void AMMod::webapiFormatChannelSettings( if (force) { - const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings(); + const CWKeyerSettings& cwKeyerSettings = getCWKeyer()->getSettings(); swgAMModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgAMModSettings->getCwKeyer(); - m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); + getCWKeyer()->webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); } if (settings.m_channelMarker && (channelSettingsKeys.contains("channelMarker") || force)) @@ -800,25 +844,32 @@ void AMMod::networkManagerFinished(QNetworkReply *reply) double AMMod::getMagSq() const { - return m_basebandSource->getMagSq(); + if (m_running) { + return m_basebandSource->getMagSq(); + } + + return 0; } CWKeyer *AMMod::getCWKeyer() { - return &m_basebandSource->getCWKeyer(); -} - -void AMMod::setLevelMeter(QObject *levelMeter) -{ - connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int))); + return &m_cwKeyer; } int AMMod::getAudioSampleRate() const { - return m_basebandSource->getAudioSampleRate(); + if (m_running) { + return m_basebandSource->getAudioSampleRate(); + } + + return 0; } int AMMod::getFeedbackAudioSampleRate() const { - return m_basebandSource->getFeedbackAudioSampleRate(); + if (m_running) { + return m_basebandSource->getFeedbackAudioSampleRate(); + } + + return 0; } diff --git a/plugins/channeltx/modam/ammod.h b/plugins/channeltx/modam/ammod.h index 61f427a53..28fdc6553 100644 --- a/plugins/channeltx/modam/ammod.h +++ b/plugins/channeltx/modam/ammod.h @@ -28,6 +28,7 @@ #include #include "dsp/basebandsamplesource.h" +#include "dsp/cwkeyer.h" #include "channel/channelapi.h" #include "util/message.h" @@ -235,7 +236,7 @@ public: uint32_t getNumberOfDeviceStreams() const; double getMagSq() const; CWKeyer *getCWKeyer(); - void setLevelMeter(QObject *levelMeter); + void setLevelMeter(QObject *levelMeter) { m_levelMeter = levelMeter; } int getAudioSampleRate() const; int getFeedbackAudioSampleRate() const; @@ -250,6 +251,7 @@ private: DeviceAPI* m_deviceAPI; QThread *m_thread; + bool m_running; AMModBaseband* m_basebandSource; AMModSettings m_settings; @@ -264,6 +266,8 @@ private: QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; + CWKeyer m_cwKeyer; + QObject *m_levelMeter; virtual bool handleMessage(const Message& cmd); void applySettings(const AMModSettings& settings, bool force = false); diff --git a/plugins/channeltx/modam/ammodbaseband.cpp b/plugins/channeltx/modam/ammodbaseband.cpp index 605b2f09e..df3726894 100644 --- a/plugins/channeltx/modam/ammodbaseband.cpp +++ b/plugins/channeltx/modam/ammodbaseband.cpp @@ -21,6 +21,7 @@ #include "dsp/upchannelizer.h" #include "dsp/dspengine.h" #include "dsp/dspcommands.h" +#include "dsp/cwkeyer.h" #include "ammodbaseband.h" @@ -171,8 +172,8 @@ bool AMModBaseband::handleMessage(const Message& cmd) qDebug() << "AMModBaseband::handleMessage: MsgConfigureCWKeyer"; const CWKeyer::MsgConfigureCWKeyer& cfg = (CWKeyer::MsgConfigureCWKeyer&) cmd; CWKeyer::MsgConfigureCWKeyer *notif = new CWKeyer::MsgConfigureCWKeyer(cfg); - CWKeyer& cwKeyer = m_source.getCWKeyer(); - cwKeyer.getInputMessageQueue()->push(notif); + CWKeyer *cwKeyer = m_source.getCWKeyer(); + cwKeyer->getInputMessageQueue()->push(notif); return true; } diff --git a/plugins/channeltx/modam/ammodbaseband.h b/plugins/channeltx/modam/ammodbaseband.h index ef2bde946..c0926c610 100644 --- a/plugins/channeltx/modam/ammodbaseband.h +++ b/plugins/channeltx/modam/ammodbaseband.h @@ -63,7 +63,7 @@ public: void reset(); void pull(const SampleVector::iterator& begin, unsigned int nbSamples); MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication - CWKeyer& getCWKeyer() { return m_source.getCWKeyer(); } + void setCWKeyer(CWKeyer *cwKeyer) { m_source.setCWKeyer(cwKeyer); } double getMagSq() const { return m_source.getMagSq(); } int getAudioSampleRate() const { return m_source.getAudioSampleRate(); } int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); } diff --git a/plugins/channeltx/modam/ammodsource.cpp b/plugins/channeltx/modam/ammodsource.cpp index b25e5e343..01921618c 100644 --- a/plugins/channeltx/modam/ammodsource.cpp +++ b/plugins/channeltx/modam/ammodsource.cpp @@ -19,6 +19,7 @@ #include #include "dsp/datafifo.h" +#include "dsp/cwkeyer.h" #include "util/messagequeue.h" #include "maincore.h" @@ -35,7 +36,8 @@ AMModSource::AMModSource() : m_levelCalcCount(0), m_peakLevel(0.0f), m_levelSum(0.0f), - m_ifstream(nullptr) + m_ifstream(nullptr), + m_cwKeyer(nullptr) { m_audioFifo.setLabel("AMModSource.m_audioFifo"); m_feedbackAudioFifo.setLabel("AMModSource.m_feedbackAudioFifo"); @@ -218,14 +220,18 @@ void AMModSource::pullAF(Real& sample) case AMModSettings::AMModInputCWTone: Real fadeFactor; - if (m_cwKeyer.getSample()) + if (!m_cwKeyer) { + break; + } + + if (m_cwKeyer->getSample()) { - m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor); + m_cwKeyer->getCWSmoother().getFadeSample(true, fadeFactor); sample = m_toneNco.next() * fadeFactor; } else { - if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor)) + if (m_cwKeyer->getCWSmoother().getFadeSample(false, fadeFactor)) { sample = m_toneNco.next() * fadeFactor; } @@ -320,8 +326,12 @@ void AMModSource::applyAudioSampleRate(int sampleRate) m_interpolatorDistance = (Real) sampleRate / (Real) m_channelSampleRate; m_interpolator.create(48, sampleRate, m_settings.m_rfBandwidth / 2.2, 3.0); m_toneNco.setFreq(m_settings.m_toneFrequency, sampleRate); - m_cwKeyer.setSampleRate(sampleRate); - m_cwKeyer.reset(); + + if (m_cwKeyer) + { + m_cwKeyer->setSampleRate(sampleRate); + m_cwKeyer->reset(); + } QList pipes; MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes); diff --git a/plugins/channeltx/modam/ammodsource.h b/plugins/channeltx/modam/ammodsource.h index f10ef226e..a032ff774 100644 --- a/plugins/channeltx/modam/ammodsource.h +++ b/plugins/channeltx/modam/ammodsource.h @@ -31,12 +31,12 @@ #include "dsp/ncof.h" #include "dsp/interpolator.h" #include "util/movingaverage.h" -#include "dsp/cwkeyer.h" #include "audio/audiofifo.h" #include "ammodsettings.h" class ChannelAPI; +class CWKeyer; class AMModSource : public QObject, public ChannelSampleSource { @@ -57,7 +57,8 @@ public: void applyFeedbackAudioSampleRate(int sampleRate); int getAudioSampleRate() const { return m_audioSampleRate; } int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; } - CWKeyer& getCWKeyer() { return m_cwKeyer; } + void setCWKeyer(CWKeyer *cwKeyer) { m_cwKeyer = cwKeyer; } + CWKeyer* getCWKeyer() { return m_cwKeyer; } double getMagSq() const { return m_magsq; } void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const { @@ -112,7 +113,7 @@ private: Real m_levelSum; std::ifstream *m_ifstream; - CWKeyer m_cwKeyer; + CWKeyer *m_cwKeyer; QRecursiveMutex m_mutex;