diff --git a/plugins/channelrx/demodbfm/bfmdemod.cpp b/plugins/channelrx/demodbfm/bfmdemod.cpp index 8cbef582e..a19bc71df 100644 --- a/plugins/channelrx/demodbfm/bfmdemod.cpp +++ b/plugins/channelrx/demodbfm/bfmdemod.cpp @@ -33,6 +33,7 @@ MESSAGE_CLASS_DEFINITION(BFMDemod::MsgConfigureBFMDemod, Message) const Real BFMDemod::default_deemphasis = 50.0; // 50 us +const int BFMDemod::m_udpBlockSize = 512; BFMDemod::BFMDemod(BasebandSampleSink* sampleSink, RDSParser *rdsParser) : m_sampleSink(sampleSink), @@ -70,6 +71,7 @@ BFMDemod::BFMDemod(BasebandSampleSink* sampleSink, RDSParser *rdsParser) : m_magsqCount = 0; DSPEngine::instance()->addAudioSink(&m_audioFifo); + m_udpBufferAudio = new UDPSink(this, m_udpBlockSize, m_config.m_udpPort); } BFMDemod::~BFMDemod() @@ -90,7 +92,11 @@ void BFMDemod::configure(MessageQueue* messageQueue, bool audioStereo, bool lsbStereo, bool showPilot, - bool rdsActive) + bool rdsActive, + bool copyAudioToUDP, + const QString& udpAddress, + quint16 udpPort, + bool force) { Message* cmd = MsgConfigureBFMDemod::create(rfBandwidth, afBandwidth, @@ -99,7 +105,11 @@ void BFMDemod::configure(MessageQueue* messageQueue, audioStereo, lsbStereo, showPilot, - rdsActive); + rdsActive, + copyAudioToUDP, + udpAddress, + udpPort, + force); messageQueue->push(cmd); } @@ -231,11 +241,13 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto { m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_running.m_volume); m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_running.m_volume); + if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]); } else { m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_running.m_volume); m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_running.m_volume); + if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]); } } else @@ -245,6 +257,7 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto quint16 sample = (qint16)(deemph * (1<<12) * m_running.m_volume); m_audioBuffer[m_audioBufferFill].l = sample; m_audioBuffer[m_audioBufferFill].r = sample; + if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]); } ++m_audioBufferFill; @@ -327,8 +340,11 @@ bool BFMDemod::handleMessage(const Message& cmd) m_config.m_lsbStereo = cfg.getLsbStereo(); m_config.m_showPilot = cfg.getShowPilot(); m_config.m_rdsActive = cfg.getRDSActive(); + m_config.m_copyAudioToUDP= cfg.getCopyAudioToUDP(); + m_config.m_udpAddress = cfg.getUDPAddress(); + m_config.m_udpPort = cfg.getUDPPort(); - apply(); + apply(cfg.getForce()); qDebug() << "BFMDemod::handleMessage: MsgConfigureBFMDemod: m_rfBandwidth: " << m_config.m_rfBandwidth << " m_afBandwidth: " << m_config.m_afBandwidth @@ -337,7 +353,10 @@ bool BFMDemod::handleMessage(const Message& cmd) << " m_audioStereo: " << m_config.m_audioStereo << " m_lsbStereo: " << m_config.m_lsbStereo << " m_showPilot: " << m_config.m_showPilot - << " m_rdsActive: " << m_config.m_rdsActive; + << " m_rdsActive: " << m_config.m_rdsActive + << " m_copyAudioToUDP: " << m_config.m_copyAudioToUDP + << " m_udpAddress: " << m_config.m_udpAddress + << " m_udpPort: " << m_config.m_udpPort; return true; } @@ -356,23 +375,23 @@ bool BFMDemod::handleMessage(const Message& cmd) } } -void BFMDemod::apply() +void BFMDemod::apply(bool force) { if ((m_config.m_inputSampleRate != m_running.m_inputSampleRate) - || (m_config.m_audioStereo && (m_config.m_audioStereo != m_running.m_audioStereo))) + || (m_config.m_audioStereo && (m_config.m_audioStereo != m_running.m_audioStereo)) || force) { m_pilotPLL.configure(19000.0/m_config.m_inputSampleRate, 50.0/m_config.m_inputSampleRate, 0.01); } if((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || - (m_config.m_inputSampleRate != m_running.m_inputSampleRate)) + (m_config.m_inputSampleRate != m_running.m_inputSampleRate) || force) { qDebug() << "BFMDemod::handleMessage: m_nco.setFreq"; m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate); } if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) || - (m_config.m_afBandwidth != m_running.m_afBandwidth)) + (m_config.m_afBandwidth != m_running.m_afBandwidth) || force) { m_settingsMutex.lock(); qDebug() << "BFMDemod::handleMessage: m_interpolator.create"; @@ -394,7 +413,7 @@ void BFMDemod::apply() if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) || (m_config.m_rfBandwidth != m_running.m_rfBandwidth) || - (m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset)) + (m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || force) { m_settingsMutex.lock(); Real lowCut = -(m_config.m_rfBandwidth / 2.0) / m_config.m_inputSampleRate; @@ -409,8 +428,8 @@ void BFMDemod::apply() << " hiCut: " << hiCut * m_config.m_inputSampleRate; } - if((m_config.m_afBandwidth != m_running.m_afBandwidth) || - (m_config.m_audioSampleRate != m_running.m_audioSampleRate)) + if ((m_config.m_afBandwidth != m_running.m_afBandwidth) || + (m_config.m_audioSampleRate != m_running.m_audioSampleRate) || force) { m_settingsMutex.lock(); qDebug() << "BFMDemod::handleMessage: m_lowpass.create"; @@ -418,27 +437,25 @@ void BFMDemod::apply() m_settingsMutex.unlock(); } - if(m_config.m_squelch != m_running.m_squelch) { + if ((m_config.m_squelch != m_running.m_squelch) || force) + { qDebug() << "BFMDemod::handleMessage: set m_squelchLevel"; m_squelchLevel = std::pow(10.0, m_config.m_squelch / 20.0); m_squelchLevel *= m_squelchLevel; } - if (m_config.m_audioSampleRate != m_running.m_audioSampleRate) + if ((m_config.m_audioSampleRate != m_running.m_audioSampleRate) || force) { m_deemphasisFilterX.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6); m_deemphasisFilterY.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6); } - m_running.m_inputSampleRate = m_config.m_inputSampleRate; - m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset; - m_running.m_rfBandwidth = m_config.m_rfBandwidth; - m_running.m_afBandwidth = m_config.m_afBandwidth; - m_running.m_squelch = m_config.m_squelch; - m_running.m_volume = m_config.m_volume; - m_running.m_audioSampleRate = m_config.m_audioSampleRate; - m_running.m_audioStereo = m_config.m_audioStereo; - m_running.m_lsbStereo = m_config.m_lsbStereo; - m_running.m_showPilot = m_config.m_showPilot; - m_running.m_rdsActive = m_config.m_rdsActive; + if ((m_config.m_udpAddress != m_running.m_udpAddress) + || (m_config.m_udpPort != m_running.m_udpPort) || force) + { + m_udpBufferAudio->setAddress(m_config.m_udpAddress); + m_udpBufferAudio->setPort(m_config.m_udpPort); + } + + m_running = m_config; } diff --git a/plugins/channelrx/demodbfm/bfmdemod.h b/plugins/channelrx/demodbfm/bfmdemod.h index 5ff600f18..5c6dc813c 100644 --- a/plugins/channelrx/demodbfm/bfmdemod.h +++ b/plugins/channelrx/demodbfm/bfmdemod.h @@ -31,9 +31,10 @@ #include "dsp/phasediscri.h" #include "audio/audiofifo.h" #include "util/message.h" +#include "util/udpsink.h" -#include "../../channelrx/demodbfm/rdsdecoder.h" -#include "../../channelrx/demodbfm/rdsdemod.h" +#include "rdsdecoder.h" +#include "rdsdemod.h" class RDSParser; @@ -50,7 +51,11 @@ public: bool audioStereo, bool lsbStereo, bool showPilot, - bool rdsActive); + bool rdsActive, + bool copyAudioUDP, + const QString& m_udpAddress, + quint16 udpPort, + bool force = false); int getSampleRate() const { return m_config.m_inputSampleRate; } virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); @@ -93,6 +98,10 @@ private: bool getLsbStereo() const { return m_lsbStereo; } bool getShowPilot() const { return m_showPilot; } bool getRDSActive() const { return m_rdsActive; } + bool getCopyAudioToUDP() const { return m_copyAudioToUDP; } + const QString& getUDPAddress() const { return m_udpAddress; } + quint16 getUDPPort() const { return m_udpPort; } + bool getForce() const { return m_force; } static MsgConfigureBFMDemod* create(Real rfBandwidth, Real afBandwidth, @@ -101,7 +110,11 @@ private: bool audioStereo, bool lsbStereo, bool showPilot, - bool rdsActive) + bool rdsActive, + bool copyAudioToUDP, + const QString& udpAddress, + quint16 udpPort, + bool force) { return new MsgConfigureBFMDemod(rfBandwidth, afBandwidth, @@ -110,7 +123,11 @@ private: audioStereo, lsbStereo, showPilot, - rdsActive); + rdsActive, + copyAudioToUDP, + udpAddress, + udpPort, + force); } private: @@ -122,6 +139,10 @@ private: bool m_lsbStereo; bool m_showPilot; bool m_rdsActive; + bool m_copyAudioToUDP; + QString m_udpAddress; + quint16 m_udpPort; + bool m_force; MsgConfigureBFMDemod(Real rfBandwidth, Real afBandwidth, @@ -130,7 +151,11 @@ private: bool audioStereo, bool lsbStereo, bool showPilot, - bool rdsActive) : + bool rdsActive, + bool copyAudioToUDP, + const QString& udpAddress, + quint16 udpPort, + bool force) : Message(), m_rfBandwidth(rfBandwidth), m_afBandwidth(afBandwidth), @@ -139,7 +164,11 @@ private: m_audioStereo(audioStereo), m_lsbStereo(lsbStereo), m_showPilot(showPilot), - m_rdsActive(rdsActive) + m_rdsActive(rdsActive), + m_copyAudioToUDP(copyAudioToUDP), + m_udpAddress(udpAddress), + m_udpPort(udpPort), + m_force(force) { } }; @@ -160,6 +189,9 @@ private: bool m_lsbStereo; bool m_showPilot; bool m_rdsActive; + bool m_copyAudioToUDP; + QString m_udpAddress; + quint16 m_udpPort; Config() : m_inputSampleRate(-1), @@ -172,7 +204,10 @@ private: m_audioStereo(false), m_lsbStereo(false), m_showPilot(false), - m_rdsActive(false) + m_rdsActive(false), + m_copyAudioToUDP(false), + m_udpAddress("127.0.0.1"), + m_udpPort(9999) { } }; @@ -229,8 +264,11 @@ private: static const int default_excursion = 750000; // +/- 75 kHz PhaseDiscriminators m_phaseDiscri; + UDPSink *m_udpBufferAudio; - void apply(); + static const int m_udpBlockSize; + + void apply(bool force = false); }; #endif // INCLUDE_BFMDEMOD_H diff --git a/plugins/channelrx/demodbfm/bfmdemodgui.cpp b/plugins/channelrx/demodbfm/bfmdemodgui.cpp index 797a87ad0..e7477977c 100644 --- a/plugins/channelrx/demodbfm/bfmdemodgui.cpp +++ b/plugins/channelrx/demodbfm/bfmdemodgui.cpp @@ -34,7 +34,7 @@ #include "plugin/pluginapi.h" #include "util/simpleserializer.h" #include "util/db.h" -#include "gui/basicchannelsettingswidget.h" +#include "gui/basicchannelsettingsdialog.h" #include "mainwindow.h" #include "bfmdemod.h" @@ -169,10 +169,12 @@ bool BFMDemodGUI::deserialize(const QByteArray& data) d.readBool(10, &booltmp, false); ui->lsbStereo->setChecked(booltmp); + displayUDPAddress(); + blockApplySettings(false); m_channelMarker.blockSignals(false); - applySettings(); + applySettings(true); return true; } else @@ -187,9 +189,10 @@ bool BFMDemodGUI::handleMessage(const Message& message __attribute__((unused))) return false; } -void BFMDemodGUI::viewChanged() +void BFMDemodGUI::channelMarkerChanged() { - applySettings(); + this->setWindowTitle(m_channelMarker.getTitle()); + applySettings(); } void BFMDemodGUI::on_deltaFrequency_changed(qint64 value) @@ -237,6 +240,11 @@ void BFMDemodGUI::on_lsbStereo_toggled(bool lsb __attribute__((unused))) applySettings(); } +void BFMDemodGUI::on_copyAudioToUDP_toggled(bool copy __attribute__((unused))) +{ + applySettings(); +} + void BFMDemodGUI::on_showPilot_clicked() { applySettings(); @@ -333,14 +341,11 @@ void BFMDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool r { } -void BFMDemodGUI::onMenuDoubleClicked() +void BFMDemodGUI::onMenuDialogCalled(const QPoint &p) { - if(!m_basicSettingsShown) - { - m_basicSettingsShown = true; - BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(&m_channelMarker, this); - bcsw->show(); - } + BasicChannelSettingsDialog dialog(&m_channelMarker, this); + dialog.move(p); + dialog.exec(); } BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget* parent) : @@ -349,7 +354,6 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg m_pluginAPI(pluginAPI), m_deviceAPI(deviceAPI), m_channelMarker(this), - m_basicSettingsShown(false), m_rdsTimerCount(0), m_channelPowerDbAvg(20,0), m_rate(625000) @@ -362,7 +366,7 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg setAttribute(Qt::WA_DeleteOnClose, true); connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); - connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked())); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); m_spectrumVis = new SpectrumVis(ui->glSpectrum); m_bfmDemod = new BFMDemod(m_spectrumVis, &m_rdsParser); @@ -380,14 +384,17 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); //m_channelMarker = new ChannelMarker(this); - //m_channelMarker.setColor(Qt::blue); + m_channelMarker.setTitle("Broadcast FM Demod"); + m_channelMarker.setColor(Qt::blue); m_channelMarker.setColor(QColor(80, 120, 228)); m_channelMarker.setBandwidth(12500); m_channelMarker.setCenterFrequency(0); + m_channelMarker.setUDPAddress("127.0.0.1"); + m_channelMarker.setUDPSendPort(9999); m_channelMarker.setVisible(true); setTitleColor(m_channelMarker.getColor()); - connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); + connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); m_deviceAPI->registerChannelInstance(m_channelID, this); m_deviceAPI->addChannelMarker(&m_channelMarker); @@ -401,8 +408,8 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg rdsUpdateFixedFields(); rdsUpdate(true); - - applySettings(); + displayUDPAddress(); + applySettings(true); } BFMDemodGUI::~BFMDemodGUI() @@ -416,12 +423,17 @@ BFMDemodGUI::~BFMDemodGUI() delete ui; } +void BFMDemodGUI::displayUDPAddress() +{ + ui->copyAudioToUDP->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort())); +} + void BFMDemodGUI::blockApplySettings(bool block) { m_doApplySettings = !block; } -void BFMDemodGUI::applySettings() +void BFMDemodGUI::applySettings(bool force) { if (m_doApplySettings) { @@ -439,7 +451,11 @@ void BFMDemodGUI::applySettings() ui->audioStereo->isChecked(), ui->lsbStereo->isChecked(), ui->showPilot->isChecked(), - ui->rds->isChecked()); + ui->rds->isChecked(), + ui->copyAudioToUDP->isChecked(), + m_channelMarker.getUDPAddress(), + m_channelMarker.getUDPSendPort(), + force); } } diff --git a/plugins/channelrx/demodbfm/bfmdemodgui.h b/plugins/channelrx/demodbfm/bfmdemodgui.h index a73fafcbf..0409496a9 100644 --- a/plugins/channelrx/demodbfm/bfmdemodgui.h +++ b/plugins/channelrx/demodbfm/bfmdemodgui.h @@ -58,7 +58,7 @@ public: static const QString m_channelID; private slots: - void viewChanged(); + void channelMarkerChanged(); void channelSampleRateChanged(); void on_deltaFrequency_changed(qint64 value); void on_rfBW_valueChanged(int value); @@ -69,13 +69,14 @@ private slots: void on_lsbStereo_toggled(bool lsb); void on_showPilot_clicked(); void on_rds_clicked(); + void on_copyAudioToUDP_toggled(bool copy); void on_g14ProgServiceNames_currentIndexChanged(int index); void on_clearData_clicked(bool checked); void on_g00AltFrequenciesBox_activated(int index); void on_g14MappedFrequencies_activated(int index); void on_g14AltFrequencies_activated(int index); void onWidgetRolled(QWidget* widget, bool rollDown); - void onMenuDoubleClicked(); + void onMenuDialogCalled(const QPoint& p); void tick(); private: @@ -83,7 +84,6 @@ private: PluginAPI* m_pluginAPI; DeviceSourceAPI* m_deviceAPI; ChannelMarker m_channelMarker; - bool m_basicSettingsShown; bool m_doApplySettings; int m_rdsTimerCount; @@ -103,7 +103,8 @@ private: virtual ~BFMDemodGUI(); void blockApplySettings(bool block); - void applySettings(); + void applySettings(bool force = false); + void displayUDPAddress(); void rdsUpdate(bool force); void rdsUpdateFixedFields(); diff --git a/plugins/channelrx/demodbfm/bfmdemodgui.ui b/plugins/channelrx/demodbfm/bfmdemodgui.ui index e8b87a433..926858447 100644 --- a/plugins/channelrx/demodbfm/bfmdemodgui.ui +++ b/plugins/channelrx/demodbfm/bfmdemodgui.ui @@ -28,12 +28,18 @@ 9 + + Qt::WheelFocus + Broadcast FM Demod + + Broadcast FM Demod + @@ -299,6 +305,19 @@ + + + + Copy audio to UDP + + + U + + + true + + + @@ -413,6 +432,9 @@ 100 + + 1 + 20 @@ -459,6 +481,9 @@ 0 + + 1 + -40 diff --git a/plugins/channelrx/demodbfm/bfmplugin.cpp b/plugins/channelrx/demodbfm/bfmplugin.cpp index a6edc1bda..fec48c649 100644 --- a/plugins/channelrx/demodbfm/bfmplugin.cpp +++ b/plugins/channelrx/demodbfm/bfmplugin.cpp @@ -24,7 +24,7 @@ const PluginDescriptor BFMPlugin::m_pluginDescriptor = { QString("Broadcast FM Demodulator"), - QString("3.5.0"), + QString("3.6.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true,