1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-25 01:18:38 -05:00

Compare commits

...

6 Commits

Author SHA1 Message Date
f4exb
113aff6e57 Data pipes redesign: renaming. Part of #1154 2022-02-21 03:06:16 +01:00
f4exb
adfaac1545 Data pipes redesign (2) 2022-02-21 02:18:51 +01:00
f4exb
c678b40988 NCOF: fix null sample rate condition 2022-02-21 02:18:44 +01:00
f4exb
4c2ca8fa20 Data pipes redesign 2022-02-20 23:18:29 +01:00
f4exb
22604244a3 ValueDialZ: fixed compilation warning. Fixes #1155 2022-02-20 23:02:42 +01:00
f4exb
308ffcad54 Updated versions and changelogs 2022-02-20 22:37:25 +01:00
45 changed files with 852 additions and 280 deletions

View File

@ -1,3 +1,20 @@
sdrangel (6.19.1-1) unstable; urgency=medium
* Fix stereo sound in DAB demod. PR #1150.
* Make Channel API inherit from QObject. Issue #1147
* Channel Analyzer: fixed reverse API handling and a few other things. Fixes #1144
* Metis MISO: set spectrum sink input back in GUI. Fixes #1145
* DATV Demod - Increase max RF bandwidth in GUI to 50MHz. PR #1142. Issue #1136.
* DATV Mod - Increase RF bandwidth slider to 50M. PR #1137. Issue #1136
* Spectrum markers update. PR #1141
* Pager demod: fixed typo in POCSAG. Fixes #1138
* Metis MISO: save stream and spectrum stream indices in settings. Fixes #1126
* Map feature, ADSB and AIS demods updates. PR #1135
* Do not write tail audio samples and write to sample buffer only if necessary. Issue #1132
* ValueDialZ: fixed compilation warning, Fixes #1155
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 20 Feb 2022 21:31:55 +0100
sdrangel (6.19.0-1) unstable; urgency=medium
* Map: added 3D to map feature. PR #1127

View File

@ -16,7 +16,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# configure version
set(sdrangel_VERSION_MAJOR "6")
set(sdrangel_VERSION_MINOR "19")
set(sdrangel_VERSION_PATCH "0")
set(sdrangel_VERSION_PATCH "1")
set(sdrangel_VERSION_SUFFIX "")
# SDRAngel cmake options

17
debian/changelog vendored
View File

@ -1,3 +1,20 @@
sdrangel (6.19.1-1) unstable; urgency=medium
* Fix stereo sound in DAB demod. PR #1150.
* Make Channel API inherit from QObject. Issue #1147
* Channel Analyzer: fixed reverse API handling and a few other things. Fixes #1144
* Metis MISO: set spectrum sink input back in GUI. Fixes #1145
* DATV Demod - Increase max RF bandwidth in GUI to 50MHz. PR #1142. Issue #1136.
* DATV Mod - Increase RF bandwidth slider to 50M. PR #1137. Issue #1136
* Spectrum markers update. PR #1141
* Pager demod: fixed typo in POCSAG. Fixes #1138
* Metis MISO: save stream and spectrum stream indices in settings. Fixes #1126
* Map feature, ADSB and AIS demods updates. PR #1135
* Do not write tail audio samples and write to sample buffer only if necessary. Issue #1132
* ValueDialZ: fixed compilation warning, Fixes #1155
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 20 Feb 2022 21:31:55 +0100
sdrangel (6.19.0-1) unstable; urgency=medium
* Map: added 3D to map feature. PR #1127

View File

@ -26,7 +26,7 @@
const PluginDescriptor ChannelAnalyzerPlugin::m_pluginDescriptor = {
ChannelAnalyzer::m_channelId,
QStringLiteral("Channel Analyzer"),
QStringLiteral("6.18.0"),
QStringLiteral("6.19.1"),
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -30,7 +30,7 @@
const PluginDescriptor ADSBPlugin::m_pluginDescriptor = {
ADSBDemod::m_channelId,
QStringLiteral("ADS-B Demodulator"),
QStringLiteral("6.19.0"),
QStringLiteral("6.19.1"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -29,7 +29,7 @@
const PluginDescriptor AISDemodPlugin::m_pluginDescriptor = {
AISDemod::m_channelId,
QStringLiteral("AIS Demodulator"),
QStringLiteral("6.19.0"),
QStringLiteral("6.19.1"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -383,14 +383,20 @@ void AISDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -219,14 +219,20 @@ void AMDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -29,7 +29,7 @@
const PluginDescriptor DABDemodPlugin::m_pluginDescriptor = {
DABDemod::m_channelId,
QStringLiteral("DAB Demodulator"),
QStringLiteral("6.18.0"),
QStringLiteral("6.19.1"),
QStringLiteral("(c) Jon Beniston, M7RCE. DAB library by Jvan Katwijk"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -447,14 +447,20 @@ void DABDemodSink::processOneAudioSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeCI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeCI16);
}
}
}

View File

@ -30,7 +30,7 @@ const PluginDescriptor DATVDemodPlugin::m_ptrPluginDescriptor =
{
DATVDemod::m_channelId,
QString("DATV Demodulator"),
QString("6.19.0"),
QString("6.19.1"),
QString("(c) F4HKW for SDRAngel using LeanSDR framework (c) F4DAV"),
QString("https://github.com/f4exb/sdrangel"),
true,

View File

@ -180,14 +180,20 @@ void DSDDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -256,14 +256,20 @@ void NFMDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -249,14 +249,20 @@ void PacketDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -29,7 +29,7 @@
const PluginDescriptor PagerDemodPlugin::m_pluginDescriptor = {
PagerDemod::m_channelId,
QStringLiteral("Pager Demodulator"),
QStringLiteral("6.18.0"),
QStringLiteral("6.19.1"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -594,14 +594,20 @@ void PagerDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -207,21 +207,27 @@ void SSBDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it)
for (; it != dataPipes.end(); ++it)
{
(*it)->write(
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo)
{
fifo->write(
(quint8*) &m_demodBuffer[0],
m_demodBuffer.size() * sizeof(qint16),
m_audioBinaual ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
);
}
}
}
m_demodBufferFill = 0;
}

View File

@ -141,14 +141,20 @@ void WFMDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -272,14 +272,20 @@ void AISModSource::modulateSample()
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -112,14 +112,20 @@ void AMModSource::pullOne(Sample& sample)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -29,7 +29,7 @@
const PluginDescriptor DATVModPlugin::m_pluginDescriptor = {
DATVMod::m_channelId,
QStringLiteral("DATV Modulator"),
QStringLiteral("6.18.0"),
QStringLiteral("6.19.1"),
QStringLiteral("(c) Jon Beniston, M7RCE, Edouard Griffiths, F4EXB. DVB-S2 by G4GUO"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -173,14 +173,20 @@ void NFMModSource::modulateSample()
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -280,14 +280,20 @@ void PacketModSource::modulateSample()
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -184,21 +184,27 @@ void SSBModSource::modulateSample()
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it)
for (; it != dataPipes.end(); ++it)
{
(*it)->write(
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo)
{
fifo->write(
(quint8*) &m_demodBuffer[0],
m_demodBuffer.size() * sizeof(qint16),
m_settings.m_audioBinaural ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
);
}
}
}
m_demodBufferFill = 0;
}

View File

@ -152,14 +152,20 @@ void WFMModSource::pullOne(Sample& sample)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -50,7 +50,7 @@ DemodAnalyzer::DemodAnalyzer(WebAPIAdapterInterface *webAPIAdapterInterface) :
Feature(m_featureIdURI, webAPIAdapterInterface),
m_spectrumVis(SDR_RX_SCALEF),
m_selectedChannel(nullptr),
m_dataFifo(nullptr)
m_dataPipe(nullptr)
{
qDebug("DemodAnalyzer::DemodAnalyzer: webAPIAdapterInterface: %p", webAPIAdapterInterface);
setObjectName(m_featureId);
@ -88,22 +88,32 @@ void DemodAnalyzer::start()
= DemodAnalyzerWorker::MsgConfigureDemodAnalyzerWorker::create(m_settings, true);
m_worker->getInputMessageQueue()->push(msg);
if (m_dataFifo)
if (m_dataPipe)
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(m_dataFifo, true);
DataFifo *fifo = qobject_cast<DataFifo*>(m_dataPipe->m_element);
if (fifo)
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(fifo, true);
m_worker->getInputMessageQueue()->push(msg);
}
}
}
void DemodAnalyzer::stop()
{
qDebug("DemodAnalyzer::stop");
if (m_dataFifo)
if (m_dataPipe)
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(m_dataFifo, false);
DataFifo *fifo = qobject_cast<DataFifo*>(m_dataPipe->m_element);
if (fifo)
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(fifo, false);
m_worker->getInputMessageQueue()->push(msg);
}
}
m_worker->stopWork();
m_state = StIdle;
@ -169,8 +179,13 @@ bool DemodAnalyzer::handleMessage(const Message& cmd)
DSPSignalNotification *msg = new DSPSignalNotification(0, m_sampleRate);
m_spectrumVis.getInputMessageQueue()->push(msg);
if (m_dataFifo) {
m_dataFifo->setSize(2*m_sampleRate);
if (m_dataPipe)
{
DataFifo *fifo = qobject_cast<DataFifo*>(m_dataPipe->m_element);
if (fifo) {
fifo->setSize(2*m_sampleRate);
}
}
if (getMessageQueueToGUI())
@ -319,7 +334,8 @@ void DemodAnalyzer::setChannel(ChannelAPI *selectedChannel)
if (m_selectedChannel)
{
DataFifo *fifo = mainCore->getDataPipes().unregisterChannelToFeature(m_selectedChannel, this, "demod");
ObjectPipe *pipe = mainCore->getDataPipes().unregisterProducerToConsumer(m_selectedChannel, this, "demod");
DataFifo *fifo = qobject_cast<DataFifo*>(pipe->m_element);
if ((fifo) && m_worker->isRunning())
{
@ -331,14 +347,20 @@ void DemodAnalyzer::setChannel(ChannelAPI *selectedChannel)
disconnect(messageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleChannelMessageQueue(MessageQueue*)));
}
m_dataFifo = mainCore->getDataPipes().registerChannelToFeature(selectedChannel, this, "demod");
m_dataFifo->setSize(96000);
m_dataPipe = mainCore->getDataPipes().registerProducerToConsumer(selectedChannel, this, "demod");
connect(m_dataPipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleDataPipeToBeDeleted(int, QObject*)));
DataFifo *fifo = qobject_cast<DataFifo*>(m_dataPipe->m_element);
if (fifo)
{
fifo->setSize(96000);
if (m_worker->isRunning())
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(m_dataFifo, true);
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(fifo, true);
m_worker->getInputMessageQueue()->push(msg);
}
}
MessageQueue *messageQueue = mainCore->getMessagePipes().registerChannelToFeature(selectedChannel, this, "reportdemod");
@ -580,3 +602,22 @@ void DemodAnalyzer::handleChannelMessageQueue(MessageQueue* messageQueue)
}
}
}
void DemodAnalyzer::handleDataPipeToBeDeleted(int reason, QObject *object)
{
qDebug("DemodAnalyzer::handleDataPipeToBeDeleted: %d %p", reason, object);
if ((reason == 0) && (m_selectedChannel == object))
{
DataFifo *fifo = qobject_cast<DataFifo*>(m_dataPipe->m_element);
if (fifo && m_worker->isRunning())
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(fifo, false);
m_worker->getInputMessageQueue()->push(msg);
}
updateChannels();
m_selectedChannel = nullptr;
}
}

View File

@ -33,7 +33,7 @@ class WebAPIAdapterInterface;
class DemodAnalyzerWorker;
class QNetworkAccessManager;
class QNetworkReply;
class DataFifo;
class ObjectPipe;
namespace SWGSDRangel {
class SWGDeviceState;
@ -201,7 +201,7 @@ private:
ScopeVis m_scopeVis;
QHash<ChannelAPI*, DemodAnalyzerSettings::AvailableChannel> m_availableChannels;
ChannelAPI *m_selectedChannel;
DataFifo *m_dataFifo;
ObjectPipe *m_dataPipe;
int m_sampleRate;
QNetworkAccessManager *m_networkManager;
@ -217,6 +217,7 @@ private:
private slots:
void networkManagerFinished(QNetworkReply *reply);
void handleChannelMessageQueue(MessageQueue *messageQueues);
void handleDataPipeToBeDeleted(int reason, QObject *object);
};
#endif // INCLUDE_FEATURE_DEMODANALYZER_H_

View File

@ -156,11 +156,11 @@ bool DemodAnalyzerWorker::handleMessage(const Message& cmd)
}
else if (MsgConnectFifo::match(cmd))
{
qDebug("DemodAnalyzerWorker::handleMessage: MsgConnectFifo");
QMutexLocker mutexLocker(&m_mutex);
MsgConnectFifo& msg = (MsgConnectFifo&) cmd;
m_dataFifo = msg.getFifo();
bool doConnect = msg.getConnect();
qDebug("DemodAnalyzerWorker::handleMessage: MsgConnectFifo: %s", (doConnect ? "connect" : "disconnect"));
if (doConnect) {
QObject::connect(
@ -170,7 +170,9 @@ bool DemodAnalyzerWorker::handleMessage(const Message& cmd)
&DemodAnalyzerWorker::handleData,
Qt::QueuedConnection
);
} else {
}
else
{
QObject::disconnect(
m_dataFifo,
&DataFifo::dataReady,

View File

@ -30,7 +30,7 @@
const PluginDescriptor MapPlugin::m_pluginDescriptor = {
Map::m_featureId,
QStringLiteral("Map"),
QStringLiteral("6.19.0"),
QStringLiteral("6.19.1"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -32,7 +32,7 @@
const PluginDescriptor MetisMISOPlugin::m_pluginDescriptor = {
QStringLiteral("MetisMISO"),
QStringLiteral("Metis MISO"),
QStringLiteral("6.18.1"),
QStringLiteral("6.19.1"),
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -167,13 +167,15 @@ set(sdrbase_SOURCES
limerfe/limerfeusbcalib.cpp
pipes/datafifostore.cpp
pipes/datapipes.cpp
pipes/datapipescommon.cpp
pipes/datapipesgcworker.cpp
pipes/messagepipes.cpp
pipes/messagepipescommon.cpp
pipes/messagepipesgcworker.cpp
pipes/pipeendpoint.cpp
pipes/objectpipe.cpp
pipes/objectpipesregistrations.cpp
settings/featuresetpreset.cpp
settings/preferences.cpp
@ -371,8 +373,8 @@ set(sdrbase_HEADERS
limerfe/limerfeusbcalib.h
pipes/datafifostore.h
pipes/datapipes.h
pipes/datapipescommon.h
pipes/datapipesgcworker.h
pipes/elementpipescommon.h
pipes/elementpipesgc.h
@ -380,6 +382,8 @@ set(sdrbase_HEADERS
pipes/messagepipescommon.h
pipes/messagepipesgcworker.h
pipes/pipeendpoint.h
pipes/objectpipe.h
pipes/objectpipesregistrations.h
plugin/plugininterface.h
plugin/pluginapi.h

View File

@ -46,8 +46,8 @@ NCOF::NCOF()
void NCOF::setFreq(Real freq, Real sampleRate)
{
m_phaseIncrement = (freq * TableSize) / sampleRate;
qDebug("NCOF::setFreq: freq: %f m_phaseIncrement: %f", freq, m_phaseIncrement);
m_phaseIncrement = sampleRate == 0 ? 0 : (freq * TableSize) / sampleRate;
qDebug("NCOF::setFreq: freq: %f sr: %f m_phaseIncrement: %f", freq, sampleRate, m_phaseIncrement);
}
float NCOF::next()

View File

@ -0,0 +1,56 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "dsp/datafifo.h"
#include "datafifostore.h"
DataFifoStore::DataFifoStore()
{}
DataFifoStore::~DataFifoStore()
{
deleteAllElements();
}
QObject *DataFifoStore::createElement()
{
DataFifo *fifo = new DataFifo();
m_dataFifos.push_back(fifo);
qDebug("DataFifoStore::createElement: %d added", m_dataFifos.size() - 1);
return fifo;
}
void DataFifoStore::deleteElement(QObject *element)
{
int i = m_dataFifos.indexOf((DataFifo*) element);
if (i >= 0)
{
qDebug("DataFifoStore::deleteElement: delte element at %d", i);
delete m_dataFifos[i];
m_dataFifos.removeAt(i);
}
}
void DataFifoStore::deleteAllElements()
{
for (auto& fifo : m_dataFifos) {
delete fifo;
}
m_dataFifos.clear();
}

View File

@ -0,0 +1,42 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_PIPES_DATAFIFOSTORE_H_
#define SDRBASE_PIPES_DATAFIFOSTORE_H_
#include <QList>
#include "export.h"
#include "objectpipeelementsstore.h"
class DataFifo;
class SDRBASE_API DataFifoStore : public ObjectPipeElementsStore
{
public:
DataFifoStore();
virtual ~DataFifoStore();
virtual QObject *createElement();
virtual void deleteElement(QObject*);
private:
void deleteAllElements();
QList<DataFifo*> m_dataFifos;
};
#endif // SDRBASE_PIPES_DATAFIFOSTORE_H_

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 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 //
@ -16,18 +16,13 @@
///////////////////////////////////////////////////////////////////////////////////
#include "dsp/datafifo.h"
#include "datapipesgcworker.h"
#include "datapipes.h"
#include "datapipesgcworker.h"
DataPipes::DataPipes()
DataPipes::DataPipes() :
m_registrations(&m_dataFifoStore)
{
m_gcWorker = new DataPipesGCWorker();
m_gcWorker->setC2FRegistrations(
m_registrations.getMutex(),
m_registrations.getElements(),
m_registrations.getConsumers()
);
m_gcWorker = new DataPipesGCWorker(m_registrations);
m_gcWorker->moveToThread(&m_gcThread);
startGC();
}
@ -37,23 +32,23 @@ DataPipes::~DataPipes()
if (m_gcWorker->isRunning()) {
stopGC();
}
m_gcWorker->deleteLater();
}
DataFifo *DataPipes::registerChannelToFeature(const ChannelAPI *source, Feature *feature, const QString& type)
ObjectPipe *DataPipes::registerProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type)
{
return m_registrations.registerProducerToConsumer(source, feature, type);
return m_registrations.registerProducerToConsumer(producer, consumer, type);
}
DataFifo *DataPipes::unregisterChannelToFeature(const ChannelAPI *source, Feature *feature, const QString& type)
ObjectPipe *DataPipes::unregisterProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type)
{
DataFifo *dataFifo = m_registrations.unregisterProducerToConsumer(source, feature, type);
m_gcWorker->addDataFifoToDelete(dataFifo);
return dataFifo;
return m_registrations.unregisterProducerToConsumer(producer, consumer, type);
}
QList<DataFifo*>* DataPipes::getFifos(const ChannelAPI *source, const QString& type)
void DataPipes::getDataPipes(const QObject *producer, const QString& type, QList<ObjectPipe*>& pipes)
{
return m_registrations.getElements(source, type);
return m_registrations.getPipes(producer, type, pipes);
}
void DataPipes::startGC()

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 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,24 +15,18 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_PIPES_DATAPIPES_H_
#define SDRBASE_PIPES_DATAPIPES_H_
#ifndef SDRBASE_PIPES_DATAPIPES2_H_
#define SDRBASE_PIPES_DATAPIPES2_H_
#include <QObject>
#include <QHash>
#include <QMap>
#include <QMutex>
#include <QThread>
#include "export.h"
#include "objectpipesregistrations.h"
#include "datafifostore.h"
#include "datapipescommon.h"
#include "elementpipesregistrations.h"
class ChannelAPI;
class Feature;
class DataPipesGCWorker;
class DataFifo;
class DataPipesGCWorker;
class SDRBASE_API DataPipes : public QObject
{
@ -43,12 +37,13 @@ public:
DataPipes& operator=(const DataPipes&) = delete;
~DataPipes();
DataFifo *registerChannelToFeature(const ChannelAPI *source, Feature *feature, const QString& type);
DataFifo *unregisterChannelToFeature(const ChannelAPI *source, Feature *feature, const QString& type);
QList<DataFifo*>* getFifos(const ChannelAPI *source, const QString& type);
ObjectPipe *registerProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type);
ObjectPipe *unregisterProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type);
void getDataPipes(const QObject *producer, const QString& type, QList<ObjectPipe*>& pipes);
private:
ElementPipesRegistrations<ChannelAPI, Feature, DataFifo> m_registrations;
DataFifoStore m_dataFifoStore;
ObjectPipesRegistrations m_registrations;
QThread m_gcThread; //!< Garbage collector thread
DataPipesGCWorker *m_gcWorker; //!< Garbage collector
@ -56,4 +51,5 @@ private:
void stopGC(); //!< Stop garbage collector
};
#endif // SDRBASE_PIPES_DATAPIPES_H_
#endif // SDRBASE_PIPES_DATAPIPES2_H_

View File

@ -1,63 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 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 //
// (at your option) any later version. //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_PIPES_DATAPIPESCOMON_H_
#define SDRBASE_PIPES_DATAPIPESCOMON_H_
#include <QHash>
#include <QMap>
#include <QMutex>
#include "export.h"
#include "util/message.h"
#include "elementpipescommon.h"
class ChannelAPI;
class Feature;
class DataFifo;
class SDRBASE_API DataPipesCommon
{
public:
typedef ElementPipesCommon::RegistrationKey<ChannelAPI> ChannelRegistrationKey;
/** Send this message to stakeholders when the garbage collector finds that a channel was deleted */
class SDRBASE_API MsgReportChannelDeleted : public Message {
MESSAGE_CLASS_DECLARATION
public:
const DataFifo *getFifo() const { return m_fifo; }
const ChannelRegistrationKey& getChannelRegistrationKey() const { return m_channelRegistrationKey; }
static MsgReportChannelDeleted* create(const DataFifo *fifo, const ChannelRegistrationKey& channelRegistrationKey) {
return new MsgReportChannelDeleted(fifo, channelRegistrationKey);
}
private:
const DataFifo *m_fifo;
ChannelRegistrationKey m_channelRegistrationKey;
MsgReportChannelDeleted(const DataFifo *fifo, const ChannelRegistrationKey& channelRegistrationKey) :
Message(),
m_fifo(fifo),
m_channelRegistrationKey(channelRegistrationKey)
{ }
};
};
#endif // SDRBASE_PIPES_DATAPIPESCOMON_H_

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 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,31 +15,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "feature/feature.h"
#include "dsp/datafifo.h"
#include "maincore.h"
#include "datapipescommon.h"
#include "datapipesgcworker.h"
bool DataPipesGCWorker::DataPipesGC::existsProducer(const ChannelAPI *channel)
{
return MainCore::instance()->existsChannel(channel);
}
bool DataPipesGCWorker::DataPipesGC::existsConsumer(const Feature *feature)
{
return MainCore::instance()->existsFeature(feature);
}
void DataPipesGCWorker::DataPipesGC::sendMessageToConsumer(const DataFifo *fifo, DataPipesCommon::ChannelRegistrationKey channelKey, Feature *feature)
{
DataPipesCommon::MsgReportChannelDeleted *msg = DataPipesCommon::MsgReportChannelDeleted::create(
fifo, channelKey);
feature->getInputMessageQueue()->push(msg);
}
DataPipesGCWorker::DataPipesGCWorker() :
m_running(false)
DataPipesGCWorker::DataPipesGCWorker(ObjectPipesRegistrations& objectPipesRegistrations) :
m_running(false),
m_objectPipesRegistrations(objectPipesRegistrations)
{}
DataPipesGCWorker::~DataPipesGCWorker()
@ -59,17 +40,7 @@ void DataPipesGCWorker::stopWork()
disconnect(&m_gcTimer, SIGNAL(timeout()), this, SLOT(processGC()));
}
void DataPipesGCWorker::addDataFifoToDelete(DataFifo *dataFifo)
{
if (dataFifo)
{
m_gcTimer.start(10000); // restart GC to make sure deletion is postponed
m_dataPipesGC.addElementToDelete(dataFifo);
}
}
void DataPipesGCWorker::processGC()
{
// qDebug("MessagePipesGCWorker::processGC");
m_dataPipesGC.processGC();
m_objectPipesRegistrations.processGC();
}

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 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,56 +15,35 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_PIPES_DATAPIPESGCWORKER_H_
#define SDRBASE_PIPES_DATAPIPESGCWORKER_H_
#ifndef SDRBASE_PIPES_DATAPIPES2GCWORKER_H_
#define SDRBASE_PIPES_DATAPIPES2GCWORKER_H_
#include <QObject>
#include <QTimer>
#include "export.h"
#include "objectpipesregistrations.h"
#include "elementpipesgc.h"
#include "datapipescommon.h"
class QMutex;
class DataFifo;
class SDRBASE_API DataPipesGCWorker : public QObject
{
Q_OBJECT
public:
DataPipesGCWorker();
DataPipesGCWorker(ObjectPipesRegistrations& objectPipesRegistrations);
~DataPipesGCWorker();
void setC2FRegistrations(
QMutex *c2fMutex,
QMap<DataPipesCommon::ChannelRegistrationKey, QList<DataFifo*>> *c2fFifos,
QMap<DataPipesCommon::ChannelRegistrationKey, QList<Feature*>> *c2fFeatures
)
{
m_dataPipesGC.setRegistrations(c2fMutex, c2fFifos, c2fFeatures);
}
void startWork();
void stopWork();
void addDataFifoToDelete(DataFifo *dataFifo);
bool isRunning() const { return m_running; }
private:
class DataPipesGC : public ElementPipesGC<ChannelAPI, Feature, DataFifo>
{
private:
virtual bool existsProducer(const ChannelAPI *channelAPI);
virtual bool existsConsumer(const Feature *feature);
virtual void sendMessageToConsumer(const DataFifo *fifo, DataPipesCommon::ChannelRegistrationKey key, Feature *feature);
};
DataPipesGC m_dataPipesGC;
bool m_running;
QTimer m_gcTimer;
ObjectPipesRegistrations& m_objectPipesRegistrations;
private slots:
void processGC(); //!< Collect garbage
};
#endif // SDRBASE_PIPES_DATAPIPESGCWORKER_H_
#endif // SDRBASE_PIPES_DATAPIPES2GCWORKER_H_

View File

@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "objectpipe.h"
ObjectPipe::ObjectPipe() :
m_pipeId(0),
m_typeId(0),
m_producer(nullptr),
m_consumer(nullptr),
m_element(nullptr),
m_gcCount(0)
{}
void ObjectPipe::setToBeDeleted(int reason, QObject *object)
{
m_gcCount = 2; // will defer actual deletion by one GC pass
emit toBeDeleted(reason, object);
}
int ObjectPipe::getGCCount() const {
return m_gcCount;
}
int ObjectPipe::decreaseGCCount()
{
if (m_gcCount > 0) {
return m_gcCount--;
} else {
return m_gcCount;
}
}

View File

@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_PIPES_OBJECTPIPE_H_
#define SDRBASE_PIPES_OBJECTPIPE_H_
#include <QObject>
#include "export.h"
class SDRBASE_API ObjectPipe : public QObject
{
Q_OBJECT
public:
ObjectPipe();
ObjectPipe(const ObjectPipe&) = default;
ObjectPipe& operator=(const ObjectPipe&) = default;
void setToBeDeleted(int reason, QObject *object);
int getGCCount() const;
int decreaseGCCount();
unsigned int m_pipeId;
int m_typeId;
const QObject *m_producer;
const QObject *m_consumer;
QObject *m_element;
signals:
void toBeDeleted(int reason, QObject *object);
private:
int m_gcCount;
};
#endif // SDRBASE_PIPES_OBJECTPIPE_H_

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 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,6 +15,16 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "datapipescommon.h"
#ifndef SDRBASE_PIPES_OBJECTPIPESELEMENT_H_
#define SDRBASE_PIPES_OBJECTPIPESELEMENT_H_
MESSAGE_CLASS_DEFINITION(DataPipesCommon::MsgReportChannelDeleted, Message)
class QObject;
class ObjectPipeElementsStore
{
public:
virtual QObject *createElement() = 0;
virtual void deleteElement(QObject*) = 0;
};
#endif // SDRBASE_PIPES_OBJECTPIPESELEMENT_H_

View File

@ -0,0 +1,241 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "objectpipesregistrations.h"
ObjectPipesRegistrations::ObjectPipesRegistrations(ObjectPipeElementsStore *objectPipeElementsStore) :
m_typeCount(0),
m_pipeId(0),
m_objectPipeElementsStore(objectPipeElementsStore),
m_mutex(QMutex::Recursive)
{}
ObjectPipesRegistrations::~ObjectPipesRegistrations()
{}
ObjectPipe *ObjectPipesRegistrations::registerProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type)
{
qDebug("ObjectPipesRegistrations::registerProducerToConsumer: %p %p %s", producer, consumer, qPrintable("type"));
int typeId;
QMutexLocker mlock(&m_mutex);
if (m_typeIds.contains(type))
{
typeId = m_typeIds.value(type);
}
else
{
typeId = m_typeCount++;
m_typeIds.insert(type, typeId);
m_types.insert(typeId, type);
}
for (auto& pipe : m_pipes) // check if pipe exists already - there is a unique pipe per producer, consumer and type
{
if ((producer == pipe->m_producer) && (consumer == pipe->m_consumer) && (typeId == pipe->m_typeId)) {
return pipe;
}
}
QObject *element = m_objectPipeElementsStore->createElement();
m_pipes.push_back(new ObjectPipe());
m_pipes.back()->m_pipeId = ++m_pipeId;
m_pipes.back()->m_typeId = typeId;
m_pipes.back()->m_producer = producer;
m_pipes.back()->m_consumer = consumer;
m_pipes.back()->m_element = element;
m_producerPipes[producer].push_back(m_pipes.back());
m_consumerPipes[consumer].push_back(m_pipes.back());
m_typeIdPipes[typeId].push_back(m_pipes.back());
m_producerAndTypeIdPipes[std::make_tuple(producer, typeId)].push_back(m_pipes.back());
m_pipeMap[std::make_tuple(producer, consumer, typeId)] = m_pipes.back();
connect(producer, SIGNAL(destroyed(QObject*)), this, SLOT(removeProducer(QObject*)));
connect(consumer, SIGNAL(destroyed(QObject*)), this, SLOT(removeConsumer(QObject*)));
return m_pipes.back();
}
ObjectPipe *ObjectPipesRegistrations::unregisterProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type)
{
qDebug("ObjectPipesRegistrations::unregisterProducerToConsumer: %p %p %s", producer, consumer, qPrintable("type"));
ObjectPipe *pipe = nullptr;
if (m_typeIds.contains(type))
{
int typeId = m_typeIds.value(type);
if (m_pipeMap.contains(std::make_tuple(producer, consumer, typeId)))
{
pipe = m_pipeMap[std::make_tuple(producer, consumer, typeId)];
m_producerPipes[producer].removeAll(pipe);
m_consumerPipes[consumer].removeAll(pipe);
m_typeIdPipes[typeId].removeAll(pipe);
m_producerAndTypeIdPipes[std::make_tuple(producer, typeId)].removeAll(pipe);
if (m_producerPipes[producer].size() == 0) {
m_producerPipes.remove(producer);
}
if (m_consumerPipes[consumer].size() == 0) {
m_consumerPipes.remove(consumer);
}
if (m_typeIdPipes[typeId].size() == 0) {
m_typeIdPipes.remove(typeId);
}
if (m_producerAndTypeIdPipes[std::make_tuple(producer, typeId)].size() == 0) {
m_producerAndTypeIdPipes.remove(std::make_tuple(producer, typeId));
}
pipe->setToBeDeleted(PipeDeletionReason::PipeDeleted, pipe);
}
}
return pipe;
}
void ObjectPipesRegistrations::getPipes(const QObject *producer, const QString& type, QList<ObjectPipe*>& pipes)
{
QMutexLocker mlock(&m_mutex);
if (m_typeIds.contains(type))
{
if (m_producerAndTypeIdPipes.contains(std::make_tuple(producer, m_typeIds[type]))) {
pipes = m_producerAndTypeIdPipes[std::make_tuple(producer, m_typeIds[type])];
}
}
}
void ObjectPipesRegistrations::processGC()
{
QMutexLocker mlock(&m_mutex);
typename QList<ObjectPipe*>::iterator itPipe = m_pipes.begin();
while (itPipe != m_pipes.end())
{
if ((*itPipe)->getGCCount() > 0) // scheduled for deletion
{
if ((*itPipe)->decreaseGCCount() == 0) // delete on this pass
{
m_objectPipeElementsStore->deleteElement((*itPipe)->m_element);
delete *itPipe;
itPipe = m_pipes.erase(itPipe);
}
else
{
++itPipe;
}
}
else
{
++itPipe;
}
}
}
void ObjectPipesRegistrations::removeProducer(QObject *producer)
{
qDebug("ObjectPipesRegistrations::removeProducer: %p", producer);
QMutexLocker mlock(&m_mutex);
if (m_producerPipes.contains(producer) && (m_producerPipes[producer].size() != 0))
{
const QList<ObjectPipe*>& pipeList = m_producerPipes[producer];
for (auto& pipe : pipeList)
{
for (const auto& consumer : m_consumerPipes.keys()) {
m_consumerPipes[consumer].removeAll(pipe);
}
for (const auto& typeId : m_typeIdPipes.keys()) {
m_typeIdPipes[typeId].removeAll(pipe);
}
pipe->setToBeDeleted(PipeDeletionReason::PipeProducerDeleted, producer);
}
m_producerPipes.remove(producer);
}
typename QMap<std::tuple<const QObject*, const QObject*, int>, ObjectPipe*>::iterator itP = m_pipeMap.begin();
while (itP != m_pipeMap.end())
{
if (std::get<0>(itP.key())) {
itP = m_pipeMap.erase(itP);
} else {
++itP;
}
}
typename QMap<std::tuple<const QObject*, int>, QList<ObjectPipe*>>::iterator itPT = m_producerAndTypeIdPipes.begin();
while (itPT != m_producerAndTypeIdPipes.end())
{
if (std::get<0>(itPT.key()) == producer) {
itPT = m_producerAndTypeIdPipes.erase(itPT);
} else {
++itPT;
}
}
}
void ObjectPipesRegistrations::removeConsumer(QObject *consumer)
{
qDebug("ObjectPipesRegistrations::removeConsumer: %p", consumer);
QMutexLocker mlock(&m_mutex);
if (m_consumerPipes.contains(consumer) && (m_consumerPipes[consumer].size() != 0))
{
QList<ObjectPipe*>& pipeList = m_consumerPipes[consumer];
for (auto& pipe : pipeList)
{
for (const auto& producer : m_producerPipes.keys()) {
m_producerPipes[producer].removeAll(pipe);
}
for (const auto& typeId : m_typeIdPipes.keys()) {
m_typeIdPipes[typeId].removeAll(pipe);
}
for (const auto& producerAndTypeId : m_producerAndTypeIdPipes.keys()) {
m_producerAndTypeIdPipes[producerAndTypeId].removeAll(pipe);
}
pipe->setToBeDeleted(PipeDeletionReason::PipeConsumerDeleted, consumer);
}
m_consumerPipes.remove(consumer);
}
typename QMap<std::tuple<const QObject*, const QObject*, int>, ObjectPipe*>::iterator it = m_pipeMap.begin();
while (it != m_pipeMap.end())
{
if (std::get<1>(it.key()) == consumer) {
it = m_pipeMap.erase(it);
} else {
++it;
}
}
}

View File

@ -0,0 +1,75 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_PIPES_OBJECTPIPESREGISTRATION_H_
#define SDRBASE_PIPES_OBJECTPIPESREGISTRATION_H_
#include <QObject>
#include <QHash>
#include <QMap>
#include <QPair>
#include <QSet>
#include <QString>
#include <QMutex>
#include <tuple>
#include "export.h"
#include "objectpipe.h"
#include "objectpipeelementsstore.h"
class SDRBASE_API ObjectPipesRegistrations : public QObject
{
Q_OBJECT
public:
enum PipeDeletionReason
{
PipeProducerDeleted,
PipeConsumerDeleted,
PipeDeleted
};
ObjectPipesRegistrations(ObjectPipeElementsStore *objectPipeElementsStore);
~ObjectPipesRegistrations();
ObjectPipe *registerProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type);
ObjectPipe *unregisterProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type);
void getPipes(const QObject *producer, const QString& type, QList<ObjectPipe*>& pipes);
void processGC();
private slots:
void removeProducer(QObject *producer);
void removeConsumer(QObject *consumer);
private:
QHash<QString, int> m_typeIds;
QMap<int, QString> m_types;
int m_typeCount;
unsigned int m_pipeId;
ObjectPipeElementsStore *m_objectPipeElementsStore;
QList<ObjectPipe*> m_pipes;
QMap<const QObject*, QList<ObjectPipe*>> m_producerPipes;
QMap<const QObject*, QList<ObjectPipe*>> m_consumerPipes;
QMap<int, QList<ObjectPipe*>> m_typeIdPipes;
QMap<std::tuple<const QObject*, int>, QList<ObjectPipe*>> m_producerAndTypeIdPipes;
QMap<std::tuple<const QObject*, const QObject*, int>, ObjectPipe*> m_pipeMap;
QMutex m_mutex;
};
#endif // SDRBASE_PIPES_OBJECTPIPESREGISTRATION_H_

View File

@ -136,7 +136,7 @@ void ValueDialZ::setValue(qint64 value)
void ValueDialZ::setValueRange(bool positiveOnly, uint numDigits, qint64 min, qint64 max, int decimalPos)
{
m_positiveOnly = positiveOnly;
m_decimalPos = decimalPos < 0 ? 0 : decimalPos > numDigits ? numDigits : decimalPos;
m_decimalPos = decimalPos < 0 ? 0 : decimalPos > (int) numDigits ? numDigits : decimalPos;
m_numDigits = numDigits;
m_numThousandPoints = m_numDigits < 3 ? 0 : (m_numDigits%3) == 0 ? (m_numDigits/3)-1 : m_numDigits/3;