Deep redesign: phase #2

This commit is contained in:
f4exb 2015-08-14 05:00:28 +02:00
parent 1799cd816f
commit f5c5e19571
27 changed files with 592 additions and 550 deletions

View File

@ -111,6 +111,7 @@ set(sdrbase_SOURCES
sdrbase/util/message.cpp
sdrbase/util/messagequeue.cpp
sdrbase/util/syncmessenger.cpp
#sdrbase/util/miniz.cpp
sdrbase/util/simpleserializer.cpp
sdrbase/util/spinlock.cpp
@ -185,6 +186,7 @@ set(sdrbase_HEADERS
include/util/export.h
include/util/message.h
include/util/messagequeue.h
include/util/syncmessenger.h
#include/util/miniz.h
include/util/simpleserializer.h
include/util/spinlock.h

View File

@ -131,6 +131,7 @@ Done since the fork
- File sample source plugin (recording reader) not working
- Make the DSP engine global static
- Fixed startup initialization sequence. New initialization phase in DSP engine and new ready state
- Message queuing and handling redesign
=====
To Do

View File

@ -12,15 +12,16 @@ class SDRANGELOVE_API Channelizer : public SampleSink {
Q_OBJECT
public:
Channelizer(SampleSink* sampleSink);
~Channelizer();
virtual ~Channelizer();
void configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency);
int getInputSampleRate() const { return m_inputSampleRate; }
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
void start();
void stop();
bool handleMessage(Message* cmd);
virtual bool init(const Message& cmd);
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
virtual void start();
virtual void stop();
virtual bool handleMessage(const Message& cmd);
protected:
struct FilterStage {

View File

@ -133,144 +133,115 @@ class SDRANGELOVE_API DSPConfigureSpectrumVis : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getFFTSize() const { return m_fftSize; }
int getOverlapPercent() const { return m_overlapPercent; }
FFTWindow::Function getWindow() const { return m_window; }
static DSPConfigureSpectrumVis* create(int fftSize, int overlapPercent, FFTWindow::Function window)
{
return new DSPConfigureSpectrumVis(fftSize, overlapPercent, window);
}
private:
int m_fftSize;
int m_overlapPercent;
FFTWindow::Function m_window;
DSPConfigureSpectrumVis(int fftSize, int overlapPercent, FFTWindow::Function window) :
Message(),
m_fftSize(fftSize),
m_overlapPercent(overlapPercent),
m_window(window)
{ }
int getFFTSize() const { return m_fftSize; }
int getOverlapPercent() const { return m_overlapPercent; }
FFTWindow::Function getWindow() const { return m_window; }
private:
int m_fftSize;
int m_overlapPercent;
FFTWindow::Function m_window;
};
class SDRANGELOVE_API DSPConfigureCorrection : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool getDCOffsetCorrection() const { return m_dcOffsetCorrection; }
bool getIQImbalanceCorrection() const { return m_iqImbalanceCorrection; }
static DSPConfigureCorrection* create(bool dcOffsetCorrection, bool iqImbalanceCorrection)
{
return new DSPConfigureCorrection(dcOffsetCorrection, iqImbalanceCorrection);
}
private:
bool m_dcOffsetCorrection;
bool m_iqImbalanceCorrection;
DSPConfigureCorrection(bool dcOffsetCorrection, bool iqImbalanceCorrection) :
Message(),
m_dcOffsetCorrection(dcOffsetCorrection),
m_iqImbalanceCorrection(iqImbalanceCorrection)
{ }
bool getDCOffsetCorrection() const { return m_dcOffsetCorrection; }
bool getIQImbalanceCorrection() const { return m_iqImbalanceCorrection; }
private:
bool m_dcOffsetCorrection;
bool m_iqImbalanceCorrection;
};
class SDRANGELOVE_API DSPEngineReport : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getSampleRate() const { return m_sampleRate; }
quint64 getCenterFrequency() const { return m_centerFrequency; }
static DSPEngineReport* create(int sampleRate, quint64 centerFrequency)
{
return new DSPEngineReport(sampleRate, centerFrequency);
}
private:
int m_sampleRate;
quint64 m_centerFrequency;
DSPEngineReport(int sampleRate, quint64 centerFrequency) :
Message(),
m_sampleRate(sampleRate),
m_centerFrequency(centerFrequency)
{ }
int getSampleRate() const { return m_sampleRate; }
quint64 getCenterFrequency() const { return m_centerFrequency; }
private:
int m_sampleRate;
quint64 m_centerFrequency;
};
class SDRANGELOVE_API DSPConfigureScopeVis : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getTriggerChannel() const { return m_triggerChannel; }
Real getTriggerLevelHigh() const { return m_triggerLevelHigh; }
Real getTriggerLevelLow() const { return m_triggerLevelLow; }
static DSPConfigureScopeVis* create(int triggerChannel, Real triggerLevelHigh, Real triggerLevelLow)
{
return new DSPConfigureScopeVis(triggerChannel, triggerLevelHigh, triggerLevelLow);
}
private:
int m_triggerChannel;
Real m_triggerLevelHigh;
Real m_triggerLevelLow;
DSPConfigureScopeVis(int triggerChannel, Real triggerLevelHigh, Real triggerLevelLow) :
Message(),
m_triggerChannel(triggerChannel),
m_triggerLevelHigh(triggerLevelHigh),
m_triggerLevelLow(triggerLevelLow)
{ }
int getTriggerChannel() const { return m_triggerChannel; }
Real getTriggerLevelHigh() const { return m_triggerLevelHigh; }
Real getTriggerLevelLow() const { return m_triggerLevelLow; }
private:
int m_triggerChannel;
Real m_triggerLevelHigh;
Real m_triggerLevelLow;
};
class SDRANGELOVE_API DSPSignalNotification : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getSampleRate() const { return m_sampleRate; }
qint64 getFrequencyOffset() const { return m_frequencyOffset; }
static DSPSignalNotification* create(int sampleRate, quint64 frequencyOffset)
{
return new DSPSignalNotification(sampleRate, frequencyOffset);
}
private:
int m_sampleRate;
qint64 m_frequencyOffset;
DSPSignalNotification(int samplerate, qint64 frequencyOffset) :
Message(),
m_sampleRate(samplerate),
m_frequencyOffset(frequencyOffset)
{ }
int getSampleRate() const { return m_sampleRate; }
qint64 getFrequencyOffset() const { return m_frequencyOffset; }
private:
int m_sampleRate;
qint64 m_frequencyOffset;
};
class SDRANGELOVE_API DSPConfigureChannelizer : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getSampleRate() const { return m_sampleRate; }
int getCenterFrequency() const { return m_centerFrequency; }
static DSPConfigureChannelizer* create(int sampleRate, int centerFrequency)
{
return new DSPConfigureChannelizer(sampleRate, centerFrequency);
}
private:
int m_sampleRate;
int m_centerFrequency;
DSPConfigureChannelizer(int sampleRate, int centerFrequency) :
Message(),
m_sampleRate(sampleRate),
m_centerFrequency(centerFrequency)
{ }
int getSampleRate() const { return m_sampleRate; }
int getCenterFrequency() const { return m_centerFrequency; }
private:
int m_sampleRate;
int m_centerFrequency;
};
#endif // INCLUDE_DSPCOMMANDS_H

View File

@ -27,6 +27,7 @@
#include "dsp/samplefifo.h"
#include "audio/audiooutput.h"
#include "util/messagequeue.h"
#include "util/syncmessenger.h"
#include "util/export.h"
class SampleSource;
@ -78,6 +79,7 @@ public:
private:
MessageQueue m_inputMessageQueue; //<! Input message queue. Post here.
MessageQueue m_outputMessageQueue; //<! Output message queue. Listen here.
SyncMessenger m_syncMessenger; //!< Used to process messages synchronously with the thread
State m_state;
@ -113,11 +115,11 @@ private:
State gotoError(const QString& errorMsg); //!< Go to an error state
void handleSetSource(SampleSource* source); //!< Manage source setting
bool distributeMessage(Message* message); // FIXME: remove ?
private slots:
void handleData(); //!< Handle data when samples from source FIFO are ready to be processed
void handleInputMessages(); //!< Handle input message queue
void handleSynchronousMessages(Message *message); //!< Handle synchronous messages with the thread
};
#endif // INCLUDE_DSPENGINE_H

View File

@ -26,19 +26,17 @@ public:
quint64 getByteCount() const { return m_byteCount; }
void configure(MessageQueue* msgQueue, const std::string& filename, int sampleRate, quint64 centerFrequency);
void configure(MessageQueue* msgQueue, const std::string& filename);
virtual bool init(Message* cmd);
virtual bool init(const Message& cmd);
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
virtual void start();
virtual void stop();
virtual bool handleMessage(Message* message);
virtual bool handleMessage(const Message& message);
void startRecording();
void stopRecording();
static void readHeader(std::ifstream& samplefile, Header& header);
MessageQueue *getMessageQueue() { return m_messageQueue; }
private:
class MsgConfigureFileSink : public Message {
MESSAGE_CLASS_DECLARATION
@ -67,9 +65,8 @@ private:
bool m_recordStart;
std::ofstream m_sampleFile;
quint64 m_byteCount;
MessageQueue m_messageQueue;
void handleConfigure(const std::string& fileName, int sampleRate, quint64 centerFrequency);
void handleConfigure(const std::string& fileName);
void writeHeader();
};

View File

@ -4,17 +4,19 @@
#include "dsp/samplesink.h"
#include "util/export.h"
class MessageQueue;
class Message;
class SDRANGELOVE_API NullSink : public SampleSink {
public:
NullSink();
virtual ~NullSink();
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
void start();
void stop();
bool handleMessage(Message* message);
virtual bool init(const Message& cmd);
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
virtual void start();
virtual void stop();
virtual bool handleMessage(const Message& message);
};
#endif // INCLUDE_NULLSINK_H

View File

@ -23,6 +23,7 @@ public:
static const uint m_traceChunkSize;
ScopeVis(GLScope* glScope = NULL);
virtual ~ScopeVis();
void configure(MessageQueue* msgQueue,
TriggerChannel triggerChannel,
@ -34,11 +35,11 @@ public:
uint traceSize);
void setOneShot(bool oneShot);
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
void start();
void stop();
bool handleMessageKeep(Message* message);
bool handleMessage(Message* message);
virtual bool init(const Message& cmd);
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
virtual void start();
virtual void stop();
virtual bool handleMessage(const Message& message);
void setSampleRate(int sampleRate);
int getSampleRate() const { return m_sampleRate; }

View File

@ -6,17 +6,19 @@
#include "dsp/scopevis.h"
#include "util/export.h"
class MessageQueue;
class Message;
class SDRANGELOVE_API SpectrumScopeComboVis : public SampleSink {
public:
SpectrumScopeComboVis(SpectrumVis* spectrumVis, ScopeVis* scopeVis);
virtual ~SpectrumScopeComboVis();
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
void start();
void stop();
bool handleMessage(Message* message);
virtual bool init(const Message& cmd);
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
virtual void start();
virtual void stop();
virtual bool handleMessage(const Message& message);
private:
SpectrumVis* m_spectrumVis;

View File

@ -12,16 +12,16 @@ class MessageQueue;
class SDRANGELOVE_API SpectrumVis : public SampleSink {
public:
SpectrumVis(GLSpectrum* glSpectrum = NULL);
~SpectrumVis();
virtual ~SpectrumVis();
void configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, FFTWindow::Function window);
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
virtual bool init(const Message& cmd);
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
void feedTriggered(SampleVector::const_iterator triggerPoint, SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
void start();
void stop();
bool handleMessageKeep(Message* message);
bool handleMessage(Message* message);
virtual void start();
virtual void stop();
virtual bool handleMessage(const Message& message);
private:
FFTEngine* m_fft;
@ -30,11 +30,11 @@ private:
std::vector<Complex> m_fftBuffer;
std::vector<Real> m_logPowerSpectrum;
size_t m_fftSize;
size_t m_overlapPercent;
size_t m_overlapSize;
size_t m_refillSize;
size_t m_fftBufferFill;
std::size_t m_fftSize;
std::size_t m_overlapPercent;
std::size_t m_overlapSize;
std::size_t m_refillSize;
std::size_t m_fftBufferFill;
bool m_needMoreSamples;
GLSpectrum* m_glSpectrum;

View File

@ -4,6 +4,7 @@
#include <QObject>
#include "dsptypes.h"
#include "util/export.h"
#include "util/messagequeue.h"
class Message;
@ -12,11 +13,18 @@ public:
SampleSink();
virtual ~SampleSink();
virtual bool init(Message* cmd) = 0;
virtual bool init(const Message& cmd) = 0;
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly) = 0;
virtual void start() = 0;
virtual void stop() = 0;
virtual bool handleMessage(Message* cmd) = 0; //!< Handle message immediately or submit it to a queue
virtual bool handleMessage(const Message& cmd) = 0; //!< Processing of a message. Returns true if message has actually been processed
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
MessageQueue *getOutputMessageQueue() { return &m_outputMessageQueue; }
protected:
MessageQueue m_inputMessageQueue;
MessageQueue m_outputMessageQueue;
};
#endif // INCLUDE_SAMPLESINK_H

View File

@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
// written by Christian Daniel //
// Copyright (C) 2015 F4EXB //
// written by Edouard Griffiths //
// //
// 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 //
@ -21,42 +21,32 @@
#include <QtGlobal>
#include "dsp/samplefifo.h"
#include "util/message.h"
#include "util/messagequeue.h"
#include "util/export.h"
class PluginGUI;
class MessageQueue;
class SDRANGELOVE_API SampleSource {
public:
struct SDRANGELOVE_API GeneralSettings {
quint64 m_centerFrequency;
GeneralSettings();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
SampleSource(MessageQueue* guiMessageQueue);
SampleSource();
virtual ~SampleSource();
virtual void init(Message* cmd) = 0;
virtual bool startInput(int device) = 0;
virtual void stopInput() = 0;
virtual void init(const Message& cmd) = 0;
virtual bool start(int device) = 0;
virtual void stop() = 0;
virtual const QString& getDeviceDescription() const = 0;
virtual int getSampleRate() const = 0;
virtual quint64 getCenterFrequency() const = 0;
virtual bool handleMessage(Message* message) = 0;
SampleFifo* getSampleFifo() { return &m_sampleFifo; }
virtual bool handleMessage(const Message& message) = 0;
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
MessageQueue *getOutputMessageQueue() { return &m_outputMessageQueue; }
SampleFifo* getSampleFifo() { return &m_sampleFifo; }
protected:
SampleFifo m_sampleFifo;
MessageQueue* m_guiMessageQueue;
GeneralSettings m_generalSettings;
SampleFifo m_sampleFifo;
MessageQueue m_inputMessageQueue;
MessageQueue m_outputMessageQueue;
};
#endif // INCLUDE_SAMPLESOURCE_H

View File

@ -1,14 +1,26 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 F4EXB //
// written by Edouard Griffiths //
// //
// 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 //
// //
// 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 INCLUDE_MESSAGE_H
#define INCLUDE_MESSAGE_H
#include <stdlib.h>
#include <QAtomicInt>
#include "util/export.h"
class MessageQueue;
class QWaitCondition;
class QMutex;
class SDRANGELOVE_API Message {
public:
Message();
@ -16,33 +28,22 @@ public:
virtual const char* getIdentifier() const;
virtual bool matchIdentifier(const char* identifier) const;
static bool match(Message* message);
static bool match(const Message* message);
void* getDestination() const { return m_destination; }
void submit(MessageQueue* queue, void* destination = NULL);
int execute(MessageQueue* queue, void* destination = NULL);
void completed(int result = 0);
void setDestination(void *destination) { m_destination = destination; }
protected:
// addressing
static const char* m_identifier;
void* m_destination;
// stuff for synchronous messages
bool m_synchronous;
QWaitCondition* m_waitCondition;
QMutex* m_mutex;
QAtomicInt m_complete;
int m_result;
};
#define MESSAGE_CLASS_DECLARATION \
public: \
const char* getIdentifier() const; \
bool matchIdentifier(const char* identifier) const; \
static bool match(Message* message); \
static bool match(const Message* message); \
protected: \
static const char* m_identifier; \
private:
@ -53,6 +54,6 @@ protected:
bool Name::matchIdentifier(const char* identifier) const {\
return (m_identifier == identifier) ? true : BaseClass::matchIdentifier(identifier); \
} \
bool Name::match(Message* message) { return message->matchIdentifier(m_identifier); }
bool Name::match(const Message* message) { return message->matchIdentifier(m_identifier); }
#endif // INCLUDE_MESSAGE_H

View File

@ -1,3 +1,20 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 F4EXB //
// written by Edouard Griffiths //
// //
// 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 //
// //
// 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 INCLUDE_MESSAGEQUEUE_H
#define INCLUDE_MESSAGEQUEUE_H
@ -15,11 +32,11 @@ public:
MessageQueue(QObject* parent = NULL);
~MessageQueue();
void submit(Message* message);
Message* accept();
void push(Message* message, bool emitSignal = true); //!< Push message onto queue
Message* pop(); //!< Pop message from queue
int countPending();
void clear();
int size(); //!< Returns queue size
void clear(); //!< Empty queue
signals:
void messageEnqueued();

View File

@ -0,0 +1,54 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 F4EXB //
// written by Edouard Griffiths //
// //
// 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 //
// //
// 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 INCLUDE_UTIL_SYNCMESSENGER_H_
#define INCLUDE_UTIL_SYNCMESSENGER_H_
#include <QObject>
#include <QWaitCondition>
#include <QMutex>
#include <QAtomicInt>
#include "util/export.h"
class Message;
/**
* This class is responsible of managing the synchronous processing of a message across threads
*/
class SDRANGELOVE_API SyncMessenger : public QObject {
Q_OBJECT
public:
SyncMessenger();
~SyncMessenger();
int sendWait(Message *message, unsigned long msPollTime = 100); //!< Send message and waits for its process completion
void done(int result = 0); //!< Processing of the message is complete
signals:
void messageSent(Message *message);
protected:
QWaitCondition m_waitCondition;
QMutex m_mutex;
QAtomicInt m_complete;
int m_result;
};
#endif /* INCLUDE_UTIL_SYNCMESSENGER_H_ */

View File

@ -20,10 +20,26 @@ Channelizer::~Channelizer()
freeFilterChain();
}
bool Channelizer::init(const Message& cmd)
{
if (DSPSignalNotification::match(&cmd))
{
DSPSignalNotification* notif = (DSPSignalNotification*) &cmd;
m_inputSampleRate = notif->getSampleRate();
qDebug() << "FileSink::init: DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate;
emit inputSampleRateChanged();
return true;
}
else
{
return false;
}
}
void Channelizer::configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency)
{
Message* cmd = DSPConfigureChannelizer::create(sampleRate, centerFrequency);
cmd->submit(messageQueue, this);
Message* cmd = new DSPConfigureChannelizer(sampleRate, centerFrequency);
messageQueue->push(cmd);
}
void Channelizer::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
@ -64,52 +80,58 @@ void Channelizer::stop()
m_sampleSink->stop();
}
bool Channelizer::handleMessage(Message* cmd)
bool Channelizer::handleMessage(const Message& cmd)
{
qDebug() << "Channelizer::handleMessage: " << cmd->getIdentifier();
qDebug() << "Channelizer::handleMessage: " << cmd.getIdentifier();
if (DSPSignalNotification::match(cmd))
/*
if (DSPSignalNotification::match(&cmd))
{
DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
m_inputSampleRate = signal->getSampleRate();
DSPSignalNotification* notif = (DSPSignalNotification*) &cmd;
m_inputSampleRate = notif->getSampleRate();
qDebug() << "Channelizer::handleMessage: DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate;
applyConfiguration();
cmd->completed();
if(m_sampleSink != NULL)
delete cmd;
if (m_sampleSink != NULL)
{
signal = DSPSignalNotification::create(m_currentOutputSampleRate, m_currentCenterFrequency);
if(!m_sampleSink->handleMessage(signal)) {
signal->completed();
}
DSPSignalNotification notif(m_currentOutputSampleRate, m_currentCenterFrequency);
m_sampleSink->handleMessage(notif))
}
emit inputSampleRateChanged();
return true;
}
else if (DSPConfigureChannelizer::match(cmd))
else*/
if (DSPConfigureChannelizer::match(&cmd))
{
DSPConfigureChannelizer* chan = (DSPConfigureChannelizer*)cmd;
DSPConfigureChannelizer* chan = (DSPConfigureChannelizer*) &cmd;
m_requestedOutputSampleRate = chan->getSampleRate();
m_requestedCenterFrequency = chan->getCenterFrequency();
qDebug() << "Channelizer::handleMessage: DSPConfigureChannelizer:"
<< " m_requestedOutputSampleRate: " << m_requestedOutputSampleRate
<< " m_requestedCenterFrequency: " << m_requestedCenterFrequency;
applyConfiguration();
cmd->completed();
if(m_sampleSink != NULL)
if (m_sampleSink != NULL)
{
DSPSignalNotification* signal = DSPSignalNotification::create(m_currentOutputSampleRate, m_currentCenterFrequency);
if(!m_sampleSink->handleMessage(signal)) {
signal->completed();
}
DSPSignalNotification notif(m_currentOutputSampleRate, m_currentCenterFrequency);
m_sampleSink->handleMessage(notif);
}
return true;
}
else
{
if(m_sampleSink != NULL) {
if (m_sampleSink != NULL)
{
return m_sampleSink->handleMessage(cmd);
} else {
}
else
{
return false;
}
}

View File

@ -58,6 +58,7 @@ void DSPEngine::run()
qDebug() << "DSPEngine::run";
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
connect(&m_syncMessenger, SIGNAL(messageSent(Message*)), this, SLOT(handleSynchronousMessages(Message*)), Qt::QueuedConnection);
m_state = StIdle;
@ -70,34 +71,34 @@ void DSPEngine::start()
qDebug() << "DSPEngine::start";
DSPPing cmd;
QThread::start();
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
}
void DSPEngine::stop()
{
qDebug() << "DSPEngine::stop";
DSPExit cmd;
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
}
bool DSPEngine::initAcquisition()
{
DSPAcquisitionInit cmd;
return cmd.execute(&m_inputMessageQueue) == StReady;
return m_syncMessenger.sendWait(&cmd) == StReady;
}
bool DSPEngine::startAcquisition()
{
DSPAcquisitionStart cmd;
return cmd.execute(&m_inputMessageQueue) == StRunning;
return m_syncMessenger.sendWait(&cmd) == StRunning;
}
void DSPEngine::stopAcquistion()
{
DSPAcquisitionStop cmd;
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
if(m_dcOffsetCorrection)
{
@ -108,51 +109,51 @@ void DSPEngine::stopAcquistion()
void DSPEngine::setSource(SampleSource* source)
{
DSPSetSource cmd(source);
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
}
void DSPEngine::addSink(SampleSink* sink)
{
qDebug() << "DSPEngine::addSink: " << sink->objectName().toStdString().c_str();
DSPAddSink cmd(sink);
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
}
void DSPEngine::removeSink(SampleSink* sink)
{
DSPRemoveSink cmd(sink);
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
}
void DSPEngine::addAudioSink(AudioFifo* audioFifo)
{
DSPAddAudioSink cmd(audioFifo);
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
}
void DSPEngine::removeAudioSink(AudioFifo* audioFifo)
{
DSPRemoveAudioSink cmd(audioFifo);
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
}
void DSPEngine::configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection)
{
Message* cmd = DSPConfigureCorrection::create(dcOffsetCorrection, iqImbalanceCorrection);
cmd->submit(&m_inputMessageQueue);
DSPConfigureCorrection* cmd = new DSPConfigureCorrection(dcOffsetCorrection, iqImbalanceCorrection);
m_inputMessageQueue.push(cmd);
}
QString DSPEngine::errorMessage()
{
DSPGetErrorMessage cmd;
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
return cmd.getErrorMessage();
}
QString DSPEngine::sourceDeviceDescription()
{
DSPGetSourceDeviceDescription cmd;
cmd.execute(&m_inputMessageQueue);
m_syncMessenger.sendWait(&cmd);
return cmd.getDeviceDescription();
}
@ -229,17 +230,17 @@ void DSPEngine::imbalance(SampleVector::iterator begin, SampleVector::iterator e
void DSPEngine::work()
{
SampleFifo* sampleFifo = m_sampleSource->getSampleFifo();
size_t samplesDone = 0;
std::size_t samplesDone = 0;
bool positiveOnly = false;
while ((sampleFifo->fill() > 0) && (m_inputMessageQueue.countPending() == 0) && (samplesDone < m_sampleRate))
while ((sampleFifo->fill() > 0) && (m_inputMessageQueue.size() == 0) && (samplesDone < m_sampleRate))
{
SampleVector::iterator part1begin;
SampleVector::iterator part1end;
SampleVector::iterator part2begin;
SampleVector::iterator part2end;
size_t count = sampleFifo->readBegin(sampleFifo->fill(), &part1begin, &part1end, &part2begin, &part2end);
std::size_t count = sampleFifo->readBegin(sampleFifo->fill(), &part1begin, &part1end, &part2begin, &part2end);
// first part of FIFO data
if (part1begin != part1end)
@ -278,7 +279,7 @@ void DSPEngine::work()
}
// adjust FIFO pointers
sampleFifo->readCommit(count);
sampleFifo->readCommit((unsigned int) count);
samplesDone += count;
}
}
@ -314,7 +315,7 @@ DSPEngine::State DSPEngine::gotoIdle()
(*it)->stop();
}
m_sampleSource->stopInput();
m_sampleSource->stop();
m_deviceDescription.clear();
m_audioSink.stop();
m_sampleRate = 0;
@ -362,14 +363,14 @@ DSPEngine::State DSPEngine::gotoInit()
for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
{
qDebug() << " - initializing " << (*it)->objectName().toStdString().c_str();
DSPSignalNotification* notif = DSPSignalNotification::create(m_sampleRate, m_centerFrequency);
DSPSignalNotification notif(m_sampleRate, m_centerFrequency);
(*it)->init(notif);
}
// pass sample rate to main window
Message* rep = DSPEngineReport::create(m_sampleRate, m_centerFrequency);
rep->submit(&m_outputMessageQueue);
DSPEngineReport* rep = new DSPEngineReport(m_sampleRate, m_centerFrequency);
m_outputMessageQueue.push(rep);
return StReady;
}
@ -402,7 +403,7 @@ DSPEngine::State DSPEngine::gotoRunning()
// Start everything
if(!m_sampleSource->startInput(0))
if(!m_sampleSource->start(0))
{
return gotoError("Could not start sample source");
}
@ -415,7 +416,7 @@ DSPEngine::State DSPEngine::gotoRunning()
(*it)->start();
}
qDebug() << " - input message queue pending: " << m_inputMessageQueue.countPending();
qDebug() << " - input message queue pending: " << m_inputMessageQueue.size();
return StRunning;
}
@ -448,33 +449,6 @@ void DSPEngine::handleSetSource(SampleSource* source)
}
}
bool DSPEngine::distributeMessage(Message* message)
{
if (m_sampleSource != 0)
{
if ((message->getDestination() == 0) || (message->getDestination() == m_sampleSource))
{
if (m_sampleSource->handleMessage(message))
{
return true;
}
}
}
for (SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
{
if ((message->getDestination() == NULL) || (message->getDestination() == *it))
{
if ((*it)->handleMessage(message))
{
return true;
}
}
}
return false;
}
void DSPEngine::handleData()
{
if(m_state == StRunning)
@ -483,90 +457,92 @@ void DSPEngine::handleData()
}
}
void DSPEngine::handleSynchronousMessages(Message *message)
{
if (DSPExit::match(message))
{
gotoIdle();
m_state = StNotStarted;
exit();
m_syncMessenger.done(m_state);
}
else if (DSPAcquisitionInit::match(message))
{
m_state = gotoIdle();
if(m_state == StIdle) {
m_state = gotoInit(); // State goes ready if init is performed
}
m_syncMessenger.done(m_state);
}
else if (DSPAcquisitionStart::match(message))
{
if(m_state == StReady) {
m_state = gotoRunning();
}
m_syncMessenger.done(m_state);
}
else if (DSPAcquisitionStop::match(message))
{
m_state = gotoIdle();
m_syncMessenger.done(m_state);
}
else if (DSPGetSourceDeviceDescription::match(message))
{
((DSPGetSourceDeviceDescription*)message)->setDeviceDescription(m_deviceDescription);
m_syncMessenger.done(m_state);
}
else if (DSPGetErrorMessage::match(message))
{
((DSPGetErrorMessage*)message)->setErrorMessage(m_errorMessage);
m_syncMessenger.done(m_state);
}
else if (DSPSetSource::match(message)) {
handleSetSource(((DSPSetSource*)message)->getSampleSource());
m_syncMessenger.done(m_state);
}
else if (DSPAddSink::match(message))
{
SampleSink* sink = ((DSPAddSink*)message)->getSampleSink();
m_sampleSinks.push_back(sink);
m_syncMessenger.done(m_state);
}
else if (DSPRemoveSink::match(message))
{
SampleSink* sink = ((DSPRemoveSink*)message)->getSampleSink();
if(m_state == StRunning) {
sink->stop();
}
m_sampleSinks.remove(sink);
m_syncMessenger.done(m_state);
}
else if (DSPAddAudioSink::match(message))
{
m_audioSink.addFifo(((DSPAddAudioSink*)message)->getAudioFifo());
m_syncMessenger.done(m_state);
}
else if (DSPRemoveAudioSink::match(message))
{
m_audioSink.removeFifo(((DSPRemoveAudioSink*)message)->getAudioFifo());
m_syncMessenger.done(m_state);
}
m_syncMessenger.done(m_state);
}
void DSPEngine::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.accept()) != NULL)
while ((message = m_inputMessageQueue.pop()) != 0)
{
qDebug("DSPEngine::handleInputMessages: Message: %s", message->getIdentifier());
if (DSPPing::match(message))
{
message->completed(m_state);
}
else if (DSPExit::match(message))
{
gotoIdle();
m_state = StNotStarted;
exit();
message->completed(m_state);
}
else if (DSPAcquisitionInit::match(message))
{
m_state = gotoIdle();
if(m_state == StIdle) {
m_state = gotoInit(); // State goes ready if init is performed
}
message->completed(m_state);
}
else if (DSPAcquisitionStart::match(message))
{
if(m_state == StReady) {
m_state = gotoRunning();
}
message->completed(m_state);
}
else if (DSPAcquisitionStop::match(message))
{
m_state = gotoIdle();
message->completed(m_state);
}
else if (DSPGetSourceDeviceDescription::match(message))
{
((DSPGetSourceDeviceDescription*)message)->setDeviceDescription(m_deviceDescription);
message->completed();
}
else if (DSPGetErrorMessage::match(message))
{
((DSPGetErrorMessage*)message)->setErrorMessage(m_errorMessage);
message->completed();
}
else if (DSPSetSource::match(message)) {
handleSetSource(((DSPSetSource*)message)->getSampleSource());
message->completed();
}
else if (DSPAddSink::match(message))
{
SampleSink* sink = ((DSPAddSink*)message)->getSampleSink();
m_sampleSinks.push_back(sink);
message->completed();
}
else if (DSPRemoveSink::match(message))
{
SampleSink* sink = ((DSPAddSink*)message)->getSampleSink();
if(m_state == StRunning) {
sink->stop();
}
m_sampleSinks.remove(sink);
message->completed();
}
else if (DSPAddAudioSink::match(message))
{
m_audioSink.addFifo(((DSPAddAudioSink*)message)->getAudioFifo());
message->completed();
}
else if (DSPRemoveAudioSink::match(message))
{
m_audioSink.removeFifo(((DSPAddAudioSink*)message)->getAudioFifo());
message->completed();
}
else if (DSPConfigureCorrection::match(message))
if (DSPConfigureCorrection::match(message))
{
DSPConfigureCorrection* conf = (DSPConfigureCorrection*)message;
m_iqImbalanceCorrection = conf->getIQImbalanceCorrection();
@ -585,20 +561,8 @@ void DSPEngine::handleInputMessages()
m_qRange = 1 << 16;
m_imbalance = 65536;
}
}
message->completed();
}
else
{
if (DSPSignalNotification::match(message))
{
DSPSignalNotification *conf = (DSPSignalNotification*)message;
qDebug() << " (" << conf->getSampleRate() << "," << conf->getFrequencyOffset() << ")";
}
if (!distributeMessage(message))
{
message->completed();
}
}
delete message;
}
}

View File

@ -1,4 +1,5 @@
#include "dsp/filesink.h"
#include "dsp/dspcommands.h"
#include "util/simpleserializer.h"
#include "util/messagequeue.h"
@ -23,23 +24,26 @@ FileSink::~FileSink()
stopRecording();
}
void FileSink::configure(MessageQueue* msgQueue, const std::string& filename, int sampleRate, quint64 centerFrequency)
void FileSink::configure(MessageQueue* msgQueue, const std::string& filename)
{
Message* cmd = MsgConfigureFileSink::create(filename, sampleRate, centerFrequency);
cmd->submit(msgQueue, this);
Message* cmd = MsgConfigureFileSink::create(filename);
msgQueue->push(cmd);
}
bool FileSink::init(Message* cmd)
bool FileSink::init(const Message& cmd)
{
if (DSPSignalNotification::match(cmd))
if (DSPSignalNotification::match(&cmd))
{
DSPSignalNotification* notif = (DSPSignalNotification*) cmd;
DSPSignalNotification* notif = (DSPSignalNotification*) &cmd;
m_sampleRate = notif->getSampleRate();
m_centerFrequency = notif->getFrequencyOffset();
qDebug() << "FileSink::init: DSPSignalNotification: m_inputSampleRate: " << m_sampleRate;
cmd->completed();
return true;
}
else
{
return false;
}
}
void FileSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
@ -93,17 +97,14 @@ void FileSink::stopRecording()
}
}
bool FileSink::handleMessage(Message* message)
bool FileSink::handleMessage(const Message& message)
{
if (MsgConfigureFileSink::match(message))
if (MsgConfigureFileSink::match(&message))
{
MsgConfigureFileSink* conf = (MsgConfigureFileSink*) message;
handleConfigure(conf->getFileName(), conf->getSampleRate(), conf->getCenterFrequency());
MsgConfigureFileSink* conf = (MsgConfigureFileSink*) &message;
handleConfigure(conf->getFileName());
qDebug() << "FileSink::handleMessage:"
<< " fileName: " << m_fileName.c_str()
<< " sampleRate: " << m_sampleRate
<< " centerFrequency: " << m_centerFrequency;
message->completed();
<< " fileName: " << m_fileName.c_str();
return true;
}
else
@ -112,16 +113,14 @@ bool FileSink::handleMessage(Message* message)
}
}
void FileSink::handleConfigure(const std::string& fileName, int sampleRate, quint64 centerFrequency)
void FileSink::handleConfigure(const std::string& fileName)
{
if ((fileName != m_fileName) || (m_sampleRate != sampleRate) || (m_centerFrequency != centerFrequency))
if (fileName != m_fileName)
{
stopRecording();
}
m_fileName = fileName;
m_sampleRate = sampleRate;
m_centerFrequency = centerFrequency;
}
void FileSink::writeHeader()

View File

@ -7,6 +7,15 @@ NullSink::NullSink()
setObjectName("NullSink");
}
NullSink::~NullSink()
{
}
bool NullSink::init(const Message& message)
{
return false;
}
void NullSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
{
}
@ -19,8 +28,7 @@ void NullSink::stop()
{
}
bool NullSink::handleMessage(Message* message)
bool NullSink::handleMessage(const Message& message)
{
message->completed();
return true;
return false;
}

View File

@ -7,65 +7,3 @@ SampleSink::SampleSink()
SampleSink::~SampleSink()
{
}
bool SampleSink::executeMessage(Message *cmd)
{
return handleMessage(cmd);
}
#if 0
#include "samplesink.h"
SampleSink::SampleSink() :
m_sinkBuffer(),
m_sinkBufferFill(0)
{
}
void SampleSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end)
{
size_t wus = workUnitSize();
// make sure our buffer is big enough for at least one work unit
if(m_sinkBuffer.size() < wus)
m_sinkBuffer.resize(wus);
while(begin < end) {
// if the buffer contains something, keep filling it until it contains one complete work unit
if((m_sinkBufferFill > 0) && (m_sinkBufferFill < wus)) {
// check number if missing samples, but don't copy more than we have
size_t len = wus - m_sinkBufferFill;
if(len > (size_t)(end - begin))
len = end - begin;
// copy
std::copy(begin, begin + len, m_sinkBuffer.begin() + m_sinkBufferFill);
// adjust pointers
m_sinkBufferFill += len;
begin += len;
}
// if one complete work unit is in the buffer, feed it to the worker
if(m_sinkBufferFill >= wus) {
size_t done = 0;
while(m_sinkBufferFill - done >= wus)
done += work(m_sinkBuffer.begin() + done, m_sinkBuffer.begin() + done + wus);
// now copy the remaining data to the front of the buffer (should be zero)
if(m_sinkBufferFill - done > 0) {
qDebug("error in SampleSink buffer management");
std::copy(m_sinkBuffer.begin() + done, m_sinkBuffer.begin() + m_sinkBufferFill, m_sinkBuffer.begin());
}
m_sinkBufferFill -= done;
}
// if no remainder from last run is buffered and we have at least one work unit left, feed the data to the worker
if(m_sinkBufferFill == 0) {
while((size_t)(end - begin) > wus)
begin += work(begin, begin + wus);
// copy any remaining data to the buffer
std::copy(begin, end, m_sinkBuffer.begin());
m_sinkBufferFill = end - begin;
begin += m_sinkBufferFill;
}
}
}
#endif

View File

@ -32,6 +32,10 @@ ScopeVis::ScopeVis(GLScope* glScope) :
m_traceback.resize(20*m_traceChunkSize);
}
ScopeVis::~ScopeVis()
{
}
void ScopeVis::configure(MessageQueue* msgQueue,
TriggerChannel triggerChannel,
Real triggerLevel,
@ -48,7 +52,21 @@ void ScopeVis::configure(MessageQueue* msgQueue,
triggerPre,
triggerDelay,
traceSize);
cmd->submit(msgQueue, this);
msgQueue->push(cmd);
}
bool ScopeVis::init(const Message& cmd)
{
if (DSPSignalNotification::match(&cmd))
{
DSPSignalNotification* signal = (DSPSignalNotification*) &cmd;
m_sampleRate = signal->getSampleRate();
return true;
}
else
{
return false;
}
}
void ScopeVis::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
@ -200,18 +218,11 @@ void ScopeVis::stop()
{
}
bool ScopeVis::handleMessageKeep(Message* message)
bool ScopeVis::handleMessage(const Message& message)
{
if(DSPSignalNotification::match(message)) {
DSPSignalNotification* signal = (DSPSignalNotification*)message;
m_sampleRate = signal->getSampleRate();
/*fprintf(stderr, "ScopeVis::handleMessage : %d samples/sec, %lld Hz offset, traceSize: \n",
m_sampleRate,
signal->getFrequencyOffset(),
m_trace.size());*/
return true;
} else if(MsgConfigureScopeVis::match(message)) {
MsgConfigureScopeVis* conf = (MsgConfigureScopeVis*)message;
if (MsgConfigureScopeVis::match(&message))
{
MsgConfigureScopeVis* conf = (MsgConfigureScopeVis*) &message;
m_tracebackCount = 0;
m_triggerState = Config;
m_triggerChannel = (TriggerChannel) conf->getTriggerChannel();
@ -230,7 +241,7 @@ bool ScopeVis::handleMessageKeep(Message* message)
if (newSize > m_traceback.size()) { // fitting the exact required space is not a requirement for the back trace
m_traceback.resize(newSize);
}
qDebug() << "ScopeVis::handleMessageKeep:"
qDebug() << "ScopeVis::handleMessage:"
<< " m_triggerChannel: " << m_triggerChannel
<< " m_triggerLevel: " << m_triggerLevel
<< " m_triggerPositiveEdge: " << (m_triggerPositiveEdge ? "edge+" : "edge-")
@ -239,31 +250,13 @@ bool ScopeVis::handleMessageKeep(Message* message)
<< " m_triggerDelay: " << m_triggerDelay
<< " m_traceSize: " << m_trace.size();
return true;
/*
} else if(DSPConfigureScopeVis::match(message)) {
DSPConfigureScopeVis* conf = (DSPConfigureScopeVis*)message;
m_triggerState = Untriggered;
m_triggerChannel = (TriggerChannel)conf->getTriggerChannel();
m_triggerLevelHigh = conf->getTriggerLevelHigh() * 32767;
m_triggerLevelLow = conf->getTriggerLevelLow() * 32767;
return true;*/
} else {
}
else
{
return false;
}
}
bool ScopeVis::handleMessage(Message* message)
{
bool done = handleMessageKeep(message);
if (done)
{
message->completed();
}
return done;
}
void ScopeVis::setSampleRate(int sampleRate)
{
m_sampleRate = sampleRate;

View File

@ -9,6 +9,18 @@ SpectrumScopeComboVis::SpectrumScopeComboVis(SpectrumVis* spectrumVis, ScopeVis*
setObjectName("SpectrumScopeComboVis");
}
SpectrumScopeComboVis::~SpectrumScopeComboVis()
{
}
bool SpectrumScopeComboVis::init(const Message& cmd)
{
bool spectDone = m_spectrumVis->init(cmd);
bool scopeDone = m_scopeVis->init(cmd);
return (spectDone || scopeDone);
}
void SpectrumScopeComboVis::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
{
m_scopeVis->feed(begin, end, false);
@ -28,15 +40,10 @@ void SpectrumScopeComboVis::stop()
m_scopeVis->stop();
}
bool SpectrumScopeComboVis::handleMessage(Message* message)
bool SpectrumScopeComboVis::handleMessage(const Message& message)
{
bool spectDone = m_spectrumVis->handleMessageKeep(message);
bool scopeDone = m_scopeVis->handleMessageKeep(message);
if (spectDone || scopeDone)
{
message->completed();
}
bool spectDone = m_spectrumVis->handleMessage(message);
bool scopeDone = m_scopeVis->handleMessage(message);
return (spectDone || scopeDone);
}

View File

@ -30,10 +30,15 @@ SpectrumVis::~SpectrumVis()
delete m_fft;
}
bool SpectrumVis::init(const Message& cmd)
{
return false;
}
void SpectrumVis::configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, FFTWindow::Function window)
{
Message* cmd = DSPConfigureSpectrumVis::create(fftSize, overlapPercent, window);
cmd->submit(msgQueue, this);
DSPConfigureSpectrumVis* cmd = new DSPConfigureSpectrumVis(fftSize, overlapPercent, window);
msgQueue->push(cmd);
}
void SpectrumVis::feedTriggered(SampleVector::const_iterator triggerPoint, SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
@ -136,39 +141,39 @@ void SpectrumVis::stop()
{
}
bool SpectrumVis::handleMessageKeep(Message* message)
bool SpectrumVis::handleMessage(const Message& message)
{
if(DSPConfigureSpectrumVis::match(message)) {
DSPConfigureSpectrumVis* conf = (DSPConfigureSpectrumVis*)message;
if(DSPConfigureSpectrumVis::match(&message))
{
DSPConfigureSpectrumVis* conf = (DSPConfigureSpectrumVis*) &message;
handleConfigure(conf->getFFTSize(), conf->getOverlapPercent(), conf->getWindow());
return true;
} else {
}
else
{
return false;
}
}
bool SpectrumVis::handleMessage(Message* message)
{
bool done = handleMessageKeep(message);
if (done)
{
message->completed();
}
return done;
}
void SpectrumVis::handleConfigure(int fftSize, int overlapPercent, FFTWindow::Function window)
{
if(fftSize > MAX_FFT_SIZE)
if (fftSize > MAX_FFT_SIZE)
{
fftSize = MAX_FFT_SIZE;
else if(fftSize < 64)
}
else if (fftSize < 64)
{
fftSize = 64;
if(overlapPercent > 100)
}
if (overlapPercent > 100)
{
m_overlapPercent = 100;
else if(overlapPercent < 0)
}
else if (overlapPercent < 0)
{
m_overlapPercent = 0;
}
m_fftSize = fftSize;
m_overlapPercent = overlapPercent;

View File

@ -319,7 +319,7 @@ void MainWindow::handleDSPMessages()
{
Message* message;
while ((message = m_dspEngine->getOutputMessageQueue()->accept()) != 0)
while ((message = m_dspEngine->getOutputMessageQueue()->pop()) != 0)
{
qDebug("Message: %s", message->getIdentifier());
@ -333,10 +333,11 @@ void MainWindow::handleDSPMessages()
qDebug("SampleRate:%d, CenterFrequency:%llu", rep->getSampleRate(), rep->getCenterFrequency());
updateCenterFreqDisplay();
updateSampleRate();
message->completed();
qDebug() << "MainWindow::handleMessages: m_fileSink->configure";
m_fileSink->configure(m_fileSink->getMessageQueue(), m_sampleFileName, m_sampleRate, m_centerFrequency);
m_fileSink->configure(m_fileSink->getInputMessageQueue(), m_sampleFileName);
}
delete message;
}
}
@ -344,14 +345,14 @@ void MainWindow::handleMessages()
{
Message* message;
while ((message = m_messageQueue->accept()) != 0)
while ((message = m_messageQueue->pop()) != 0)
{
qDebug("Message: %s", message->getIdentifier());
std::cerr << "MainWindow::handleMessages: " << message->getIdentifier() << std::endl;
if (!m_pluginManager->handleMessage(message)) {
message->completed();
if (!m_pluginManager->handleMessage(message))
{
delete message;
}
}
}

View File

@ -1,3 +1,20 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 F4EXB //
// written by Edouard Griffiths //
// //
// 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 //
// //
// 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 <QWaitCondition>
#include <QMutex>
#include "util/message.h"
@ -6,20 +23,12 @@
const char* Message::m_identifier = "Message";
Message::Message() :
m_destination(NULL),
m_synchronous(false),
m_waitCondition(NULL),
m_mutex(NULL),
m_complete(0)
m_destination(0)
{
}
Message::~Message()
{
if(m_waitCondition != NULL)
delete m_waitCondition;
if(m_mutex != NULL)
delete m_mutex;
}
const char* Message::getIdentifier() const
@ -32,48 +41,7 @@ bool Message::matchIdentifier(const char* identifier) const
return m_identifier == identifier;
}
bool Message::match(Message* message)
bool Message::match(const Message* message)
{
return message->matchIdentifier(m_identifier);
}
void Message::submit(MessageQueue* queue, void* destination)
{
m_destination = destination;
m_synchronous = false;
queue->submit(this);
}
int Message::execute(MessageQueue* queue, void* destination)
{
m_destination = destination;
m_synchronous = true;
if(m_waitCondition == NULL)
m_waitCondition = new QWaitCondition;
if(m_mutex == NULL)
m_mutex = new QMutex;
m_mutex->lock();
m_complete.testAndSetAcquire(0, 1);
queue->submit(this);
while(!m_complete.testAndSetAcquire(0, 1))
((QWaitCondition*)m_waitCondition)->wait(m_mutex, 100);
m_complete = 0;
int result = m_result;
m_mutex->unlock();
return result;
}
void Message::completed(int result)
{
if(m_synchronous) {
m_result = result;
m_complete = 0;
if(m_waitCondition == NULL)
qFatal("wait condition is NULL");
m_waitCondition->wakeAll();
} else {
delete this;
}
}

View File

@ -1,3 +1,20 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 F4EXB //
// written by Edouard Griffiths //
// //
// 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 //
// //
// 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 "util/messagequeue.h"
#include "util/message.h"
@ -10,29 +27,44 @@ MessageQueue::MessageQueue(QObject* parent) :
MessageQueue::~MessageQueue()
{
Message* cmd;
while((cmd = accept()) != NULL)
cmd->completed();
Message* message;
while ((message = pop()) != 0)
{
delete message;
}
}
void MessageQueue::submit(Message* message)
void MessageQueue::push(Message* message, bool emitSignal)
{
m_lock.lock();
m_queue.append(message);
m_lock.unlock();
emit messageEnqueued();
if (message)
{
m_lock.lock();
m_queue.append(message);
m_lock.unlock();
}
if (emitSignal)
{
emit messageEnqueued();
}
}
Message* MessageQueue::accept()
Message* MessageQueue::pop()
{
SpinlockHolder spinlockHolder(&m_lock);
if(m_queue.isEmpty())
return NULL;
else return m_queue.takeFirst();
if (m_queue.isEmpty())
{
return 0;
}
else
{
return m_queue.takeFirst();
}
}
int MessageQueue::countPending()
int MessageQueue::size()
{
SpinlockHolder spinlockHolder(&m_lock);

View File

@ -0,0 +1,56 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 F4EXB //
// written by Edouard Griffiths //
// //
// 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 //
// //
// 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 "util/syncmessenger.h"
#include "util/message.h"
SyncMessenger::SyncMessenger() :
m_complete(0),
m_result(0)
{}
SyncMessenger::~SyncMessenger()
{}
int SyncMessenger::sendWait(Message *message, unsigned long msPollTime)
{
m_mutex.lock();
m_complete.testAndSetAcquire(0, 1);
emit messageSent(message);
while (!m_complete.testAndSetAcquire(0, 1))
{
m_waitCondition.wait(&m_mutex, msPollTime);
}
m_complete = 0;
int result = m_result;
m_mutex.unlock();
return result;
}
void SyncMessenger::done(int result)
{
m_result = result;
m_complete = 0;
m_waitCondition.wakeAll();
}