mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-05-24 11:12:27 -04:00
Deep redesign: phase #2
This commit is contained in:
parent
1799cd816f
commit
f5c5e19571
@ -111,6 +111,7 @@ set(sdrbase_SOURCES
|
|||||||
|
|
||||||
sdrbase/util/message.cpp
|
sdrbase/util/message.cpp
|
||||||
sdrbase/util/messagequeue.cpp
|
sdrbase/util/messagequeue.cpp
|
||||||
|
sdrbase/util/syncmessenger.cpp
|
||||||
#sdrbase/util/miniz.cpp
|
#sdrbase/util/miniz.cpp
|
||||||
sdrbase/util/simpleserializer.cpp
|
sdrbase/util/simpleserializer.cpp
|
||||||
sdrbase/util/spinlock.cpp
|
sdrbase/util/spinlock.cpp
|
||||||
@ -185,6 +186,7 @@ set(sdrbase_HEADERS
|
|||||||
include/util/export.h
|
include/util/export.h
|
||||||
include/util/message.h
|
include/util/message.h
|
||||||
include/util/messagequeue.h
|
include/util/messagequeue.h
|
||||||
|
include/util/syncmessenger.h
|
||||||
#include/util/miniz.h
|
#include/util/miniz.h
|
||||||
include/util/simpleserializer.h
|
include/util/simpleserializer.h
|
||||||
include/util/spinlock.h
|
include/util/spinlock.h
|
||||||
|
@ -131,6 +131,7 @@ Done since the fork
|
|||||||
- File sample source plugin (recording reader) not working
|
- File sample source plugin (recording reader) not working
|
||||||
- Make the DSP engine global static
|
- Make the DSP engine global static
|
||||||
- Fixed startup initialization sequence. New initialization phase in DSP engine and new ready state
|
- Fixed startup initialization sequence. New initialization phase in DSP engine and new ready state
|
||||||
|
- Message queuing and handling redesign
|
||||||
|
|
||||||
=====
|
=====
|
||||||
To Do
|
To Do
|
||||||
|
@ -12,15 +12,16 @@ class SDRANGELOVE_API Channelizer : public SampleSink {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
Channelizer(SampleSink* sampleSink);
|
Channelizer(SampleSink* sampleSink);
|
||||||
~Channelizer();
|
virtual ~Channelizer();
|
||||||
|
|
||||||
void configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency);
|
void configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency);
|
||||||
int getInputSampleRate() const { return m_inputSampleRate; }
|
int getInputSampleRate() const { return m_inputSampleRate; }
|
||||||
|
|
||||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
virtual bool init(const Message& cmd);
|
||||||
void start();
|
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||||
void stop();
|
virtual void start();
|
||||||
bool handleMessage(Message* cmd);
|
virtual void stop();
|
||||||
|
virtual bool handleMessage(const Message& cmd);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct FilterStage {
|
struct FilterStage {
|
||||||
|
@ -133,144 +133,115 @@ class SDRANGELOVE_API DSPConfigureSpectrumVis : public Message {
|
|||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
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) :
|
DSPConfigureSpectrumVis(int fftSize, int overlapPercent, FFTWindow::Function window) :
|
||||||
Message(),
|
Message(),
|
||||||
m_fftSize(fftSize),
|
m_fftSize(fftSize),
|
||||||
m_overlapPercent(overlapPercent),
|
m_overlapPercent(overlapPercent),
|
||||||
m_window(window)
|
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 {
|
class SDRANGELOVE_API DSPConfigureCorrection : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
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) :
|
DSPConfigureCorrection(bool dcOffsetCorrection, bool iqImbalanceCorrection) :
|
||||||
Message(),
|
Message(),
|
||||||
m_dcOffsetCorrection(dcOffsetCorrection),
|
m_dcOffsetCorrection(dcOffsetCorrection),
|
||||||
m_iqImbalanceCorrection(iqImbalanceCorrection)
|
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 {
|
class SDRANGELOVE_API DSPEngineReport : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
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) :
|
DSPEngineReport(int sampleRate, quint64 centerFrequency) :
|
||||||
Message(),
|
Message(),
|
||||||
m_sampleRate(sampleRate),
|
m_sampleRate(sampleRate),
|
||||||
m_centerFrequency(centerFrequency)
|
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 {
|
class SDRANGELOVE_API DSPConfigureScopeVis : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
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) :
|
DSPConfigureScopeVis(int triggerChannel, Real triggerLevelHigh, Real triggerLevelLow) :
|
||||||
Message(),
|
Message(),
|
||||||
m_triggerChannel(triggerChannel),
|
m_triggerChannel(triggerChannel),
|
||||||
m_triggerLevelHigh(triggerLevelHigh),
|
m_triggerLevelHigh(triggerLevelHigh),
|
||||||
m_triggerLevelLow(triggerLevelLow)
|
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 {
|
class SDRANGELOVE_API DSPSignalNotification : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
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) :
|
DSPSignalNotification(int samplerate, qint64 frequencyOffset) :
|
||||||
Message(),
|
Message(),
|
||||||
m_sampleRate(samplerate),
|
m_sampleRate(samplerate),
|
||||||
m_frequencyOffset(frequencyOffset)
|
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 {
|
class SDRANGELOVE_API DSPConfigureChannelizer : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
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) :
|
DSPConfigureChannelizer(int sampleRate, int centerFrequency) :
|
||||||
Message(),
|
Message(),
|
||||||
m_sampleRate(sampleRate),
|
m_sampleRate(sampleRate),
|
||||||
m_centerFrequency(centerFrequency)
|
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
|
#endif // INCLUDE_DSPCOMMANDS_H
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "dsp/samplefifo.h"
|
#include "dsp/samplefifo.h"
|
||||||
#include "audio/audiooutput.h"
|
#include "audio/audiooutput.h"
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
|
#include "util/syncmessenger.h"
|
||||||
#include "util/export.h"
|
#include "util/export.h"
|
||||||
|
|
||||||
class SampleSource;
|
class SampleSource;
|
||||||
@ -78,6 +79,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
MessageQueue m_inputMessageQueue; //<! Input message queue. Post here.
|
MessageQueue m_inputMessageQueue; //<! Input message queue. Post here.
|
||||||
MessageQueue m_outputMessageQueue; //<! Output message queue. Listen here.
|
MessageQueue m_outputMessageQueue; //<! Output message queue. Listen here.
|
||||||
|
SyncMessenger m_syncMessenger; //!< Used to process messages synchronously with the thread
|
||||||
|
|
||||||
State m_state;
|
State m_state;
|
||||||
|
|
||||||
@ -113,11 +115,11 @@ private:
|
|||||||
State gotoError(const QString& errorMsg); //!< Go to an error state
|
State gotoError(const QString& errorMsg); //!< Go to an error state
|
||||||
|
|
||||||
void handleSetSource(SampleSource* source); //!< Manage source setting
|
void handleSetSource(SampleSource* source); //!< Manage source setting
|
||||||
bool distributeMessage(Message* message); // FIXME: remove ?
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleData(); //!< Handle data when samples from source FIFO are ready to be processed
|
void handleData(); //!< Handle data when samples from source FIFO are ready to be processed
|
||||||
void handleInputMessages(); //!< Handle input message queue
|
void handleInputMessages(); //!< Handle input message queue
|
||||||
|
void handleSynchronousMessages(Message *message); //!< Handle synchronous messages with the thread
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_DSPENGINE_H
|
#endif // INCLUDE_DSPENGINE_H
|
||||||
|
@ -26,19 +26,17 @@ public:
|
|||||||
|
|
||||||
quint64 getByteCount() const { return m_byteCount; }
|
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 feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||||
virtual void start();
|
virtual void start();
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual bool handleMessage(Message* message);
|
virtual bool handleMessage(const Message& message);
|
||||||
void startRecording();
|
void startRecording();
|
||||||
void stopRecording();
|
void stopRecording();
|
||||||
static void readHeader(std::ifstream& samplefile, Header& header);
|
static void readHeader(std::ifstream& samplefile, Header& header);
|
||||||
|
|
||||||
MessageQueue *getMessageQueue() { return m_messageQueue; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class MsgConfigureFileSink : public Message {
|
class MsgConfigureFileSink : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
@ -67,9 +65,8 @@ private:
|
|||||||
bool m_recordStart;
|
bool m_recordStart;
|
||||||
std::ofstream m_sampleFile;
|
std::ofstream m_sampleFile;
|
||||||
quint64 m_byteCount;
|
quint64 m_byteCount;
|
||||||
MessageQueue m_messageQueue;
|
|
||||||
|
|
||||||
void handleConfigure(const std::string& fileName, int sampleRate, quint64 centerFrequency);
|
void handleConfigure(const std::string& fileName);
|
||||||
void writeHeader();
|
void writeHeader();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,17 +4,19 @@
|
|||||||
#include "dsp/samplesink.h"
|
#include "dsp/samplesink.h"
|
||||||
#include "util/export.h"
|
#include "util/export.h"
|
||||||
|
|
||||||
class MessageQueue;
|
class Message;
|
||||||
|
|
||||||
class SDRANGELOVE_API NullSink : public SampleSink {
|
class SDRANGELOVE_API NullSink : public SampleSink {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NullSink();
|
NullSink();
|
||||||
|
virtual ~NullSink();
|
||||||
|
|
||||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
virtual bool init(const Message& cmd);
|
||||||
void start();
|
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||||
void stop();
|
virtual void start();
|
||||||
bool handleMessage(Message* message);
|
virtual void stop();
|
||||||
|
virtual bool handleMessage(const Message& message);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_NULLSINK_H
|
#endif // INCLUDE_NULLSINK_H
|
||||||
|
@ -23,6 +23,7 @@ public:
|
|||||||
static const uint m_traceChunkSize;
|
static const uint m_traceChunkSize;
|
||||||
|
|
||||||
ScopeVis(GLScope* glScope = NULL);
|
ScopeVis(GLScope* glScope = NULL);
|
||||||
|
virtual ~ScopeVis();
|
||||||
|
|
||||||
void configure(MessageQueue* msgQueue,
|
void configure(MessageQueue* msgQueue,
|
||||||
TriggerChannel triggerChannel,
|
TriggerChannel triggerChannel,
|
||||||
@ -34,11 +35,11 @@ public:
|
|||||||
uint traceSize);
|
uint traceSize);
|
||||||
void setOneShot(bool oneShot);
|
void setOneShot(bool oneShot);
|
||||||
|
|
||||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
virtual bool init(const Message& cmd);
|
||||||
void start();
|
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||||
void stop();
|
virtual void start();
|
||||||
bool handleMessageKeep(Message* message);
|
virtual void stop();
|
||||||
bool handleMessage(Message* message);
|
virtual bool handleMessage(const Message& message);
|
||||||
|
|
||||||
void setSampleRate(int sampleRate);
|
void setSampleRate(int sampleRate);
|
||||||
int getSampleRate() const { return m_sampleRate; }
|
int getSampleRate() const { return m_sampleRate; }
|
||||||
|
@ -6,17 +6,19 @@
|
|||||||
#include "dsp/scopevis.h"
|
#include "dsp/scopevis.h"
|
||||||
#include "util/export.h"
|
#include "util/export.h"
|
||||||
|
|
||||||
class MessageQueue;
|
class Message;
|
||||||
|
|
||||||
class SDRANGELOVE_API SpectrumScopeComboVis : public SampleSink {
|
class SDRANGELOVE_API SpectrumScopeComboVis : public SampleSink {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SpectrumScopeComboVis(SpectrumVis* spectrumVis, ScopeVis* scopeVis);
|
SpectrumScopeComboVis(SpectrumVis* spectrumVis, ScopeVis* scopeVis);
|
||||||
|
virtual ~SpectrumScopeComboVis();
|
||||||
|
|
||||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
virtual bool init(const Message& cmd);
|
||||||
void start();
|
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||||
void stop();
|
virtual void start();
|
||||||
bool handleMessage(Message* message);
|
virtual void stop();
|
||||||
|
virtual bool handleMessage(const Message& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpectrumVis* m_spectrumVis;
|
SpectrumVis* m_spectrumVis;
|
||||||
|
@ -12,16 +12,16 @@ class MessageQueue;
|
|||||||
class SDRANGELOVE_API SpectrumVis : public SampleSink {
|
class SDRANGELOVE_API SpectrumVis : public SampleSink {
|
||||||
public:
|
public:
|
||||||
SpectrumVis(GLSpectrum* glSpectrum = NULL);
|
SpectrumVis(GLSpectrum* glSpectrum = NULL);
|
||||||
~SpectrumVis();
|
virtual ~SpectrumVis();
|
||||||
|
|
||||||
void configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, FFTWindow::Function window);
|
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 feedTriggered(SampleVector::const_iterator triggerPoint, SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||||
void start();
|
virtual void start();
|
||||||
void stop();
|
virtual void stop();
|
||||||
bool handleMessageKeep(Message* message);
|
virtual bool handleMessage(const Message& message);
|
||||||
bool handleMessage(Message* message);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FFTEngine* m_fft;
|
FFTEngine* m_fft;
|
||||||
@ -30,11 +30,11 @@ private:
|
|||||||
std::vector<Complex> m_fftBuffer;
|
std::vector<Complex> m_fftBuffer;
|
||||||
std::vector<Real> m_logPowerSpectrum;
|
std::vector<Real> m_logPowerSpectrum;
|
||||||
|
|
||||||
size_t m_fftSize;
|
std::size_t m_fftSize;
|
||||||
size_t m_overlapPercent;
|
std::size_t m_overlapPercent;
|
||||||
size_t m_overlapSize;
|
std::size_t m_overlapSize;
|
||||||
size_t m_refillSize;
|
std::size_t m_refillSize;
|
||||||
size_t m_fftBufferFill;
|
std::size_t m_fftBufferFill;
|
||||||
bool m_needMoreSamples;
|
bool m_needMoreSamples;
|
||||||
|
|
||||||
GLSpectrum* m_glSpectrum;
|
GLSpectrum* m_glSpectrum;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "dsptypes.h"
|
#include "dsptypes.h"
|
||||||
#include "util/export.h"
|
#include "util/export.h"
|
||||||
|
#include "util/messagequeue.h"
|
||||||
|
|
||||||
class Message;
|
class Message;
|
||||||
|
|
||||||
@ -12,11 +13,18 @@ public:
|
|||||||
SampleSink();
|
SampleSink();
|
||||||
virtual ~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 feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly) = 0;
|
||||||
virtual void start() = 0;
|
virtual void start() = 0;
|
||||||
virtual void stop() = 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
|
#endif // INCLUDE_SAMPLESINK_H
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
// Copyright (C) 2015 F4EXB //
|
||||||
// written by Christian Daniel //
|
// written by Edouard Griffiths //
|
||||||
// //
|
// //
|
||||||
// This program is free software; you can redistribute it and/or modify //
|
// 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 //
|
// it under the terms of the GNU General Public License as published by //
|
||||||
@ -21,42 +21,32 @@
|
|||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include "dsp/samplefifo.h"
|
#include "dsp/samplefifo.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
|
#include "util/messagequeue.h"
|
||||||
#include "util/export.h"
|
#include "util/export.h"
|
||||||
|
|
||||||
class PluginGUI;
|
|
||||||
class MessageQueue;
|
|
||||||
|
|
||||||
class SDRANGELOVE_API SampleSource {
|
class SDRANGELOVE_API SampleSource {
|
||||||
public:
|
public:
|
||||||
struct SDRANGELOVE_API GeneralSettings {
|
SampleSource();
|
||||||
quint64 m_centerFrequency;
|
|
||||||
|
|
||||||
GeneralSettings();
|
|
||||||
void resetToDefaults();
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
};
|
|
||||||
|
|
||||||
SampleSource(MessageQueue* guiMessageQueue);
|
|
||||||
virtual ~SampleSource();
|
virtual ~SampleSource();
|
||||||
|
|
||||||
virtual void init(Message* cmd) = 0;
|
virtual void init(const Message& cmd) = 0;
|
||||||
virtual bool startInput(int device) = 0;
|
virtual bool start(int device) = 0;
|
||||||
virtual void stopInput() = 0;
|
virtual void stop() = 0;
|
||||||
|
|
||||||
virtual const QString& getDeviceDescription() const = 0;
|
virtual const QString& getDeviceDescription() const = 0;
|
||||||
virtual int getSampleRate() const = 0;
|
virtual int getSampleRate() const = 0;
|
||||||
virtual quint64 getCenterFrequency() const = 0;
|
virtual quint64 getCenterFrequency() const = 0;
|
||||||
|
|
||||||
virtual bool handleMessage(Message* message) = 0;
|
virtual bool handleMessage(const Message& message) = 0;
|
||||||
|
|
||||||
|
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||||
|
MessageQueue *getOutputMessageQueue() { return &m_outputMessageQueue; }
|
||||||
SampleFifo* getSampleFifo() { return &m_sampleFifo; }
|
SampleFifo* getSampleFifo() { return &m_sampleFifo; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SampleFifo m_sampleFifo;
|
SampleFifo m_sampleFifo;
|
||||||
MessageQueue* m_guiMessageQueue;
|
MessageQueue m_inputMessageQueue;
|
||||||
|
MessageQueue m_outputMessageQueue;
|
||||||
GeneralSettings m_generalSettings;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_SAMPLESOURCE_H
|
#endif // INCLUDE_SAMPLESOURCE_H
|
||||||
|
@ -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
|
#ifndef INCLUDE_MESSAGE_H
|
||||||
#define INCLUDE_MESSAGE_H
|
#define INCLUDE_MESSAGE_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <QAtomicInt>
|
|
||||||
#include "util/export.h"
|
#include "util/export.h"
|
||||||
|
|
||||||
class MessageQueue;
|
|
||||||
class QWaitCondition;
|
|
||||||
class QMutex;
|
|
||||||
|
|
||||||
class SDRANGELOVE_API Message {
|
class SDRANGELOVE_API Message {
|
||||||
public:
|
public:
|
||||||
Message();
|
Message();
|
||||||
@ -16,33 +28,22 @@ public:
|
|||||||
|
|
||||||
virtual const char* getIdentifier() const;
|
virtual const char* getIdentifier() const;
|
||||||
virtual bool matchIdentifier(const char* identifier) 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* getDestination() const { return m_destination; }
|
||||||
|
void setDestination(void *destination) { m_destination = destination; }
|
||||||
void submit(MessageQueue* queue, void* destination = NULL);
|
|
||||||
int execute(MessageQueue* queue, void* destination = NULL);
|
|
||||||
|
|
||||||
void completed(int result = 0);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// addressing
|
// addressing
|
||||||
static const char* m_identifier;
|
static const char* m_identifier;
|
||||||
void* m_destination;
|
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 \
|
#define MESSAGE_CLASS_DECLARATION \
|
||||||
public: \
|
public: \
|
||||||
const char* getIdentifier() const; \
|
const char* getIdentifier() const; \
|
||||||
bool matchIdentifier(const char* identifier) const; \
|
bool matchIdentifier(const char* identifier) const; \
|
||||||
static bool match(Message* message); \
|
static bool match(const Message* message); \
|
||||||
protected: \
|
protected: \
|
||||||
static const char* m_identifier; \
|
static const char* m_identifier; \
|
||||||
private:
|
private:
|
||||||
@ -53,6 +54,6 @@ protected:
|
|||||||
bool Name::matchIdentifier(const char* identifier) const {\
|
bool Name::matchIdentifier(const char* identifier) const {\
|
||||||
return (m_identifier == identifier) ? true : BaseClass::matchIdentifier(identifier); \
|
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
|
#endif // INCLUDE_MESSAGE_H
|
||||||
|
@ -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
|
#ifndef INCLUDE_MESSAGEQUEUE_H
|
||||||
#define INCLUDE_MESSAGEQUEUE_H
|
#define INCLUDE_MESSAGEQUEUE_H
|
||||||
|
|
||||||
@ -15,11 +32,11 @@ public:
|
|||||||
MessageQueue(QObject* parent = NULL);
|
MessageQueue(QObject* parent = NULL);
|
||||||
~MessageQueue();
|
~MessageQueue();
|
||||||
|
|
||||||
void submit(Message* message);
|
void push(Message* message, bool emitSignal = true); //!< Push message onto queue
|
||||||
Message* accept();
|
Message* pop(); //!< Pop message from queue
|
||||||
|
|
||||||
int countPending();
|
int size(); //!< Returns queue size
|
||||||
void clear();
|
void clear(); //!< Empty queue
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void messageEnqueued();
|
void messageEnqueued();
|
||||||
|
54
include/util/syncmessenger.h
Normal file
54
include/util/syncmessenger.h
Normal 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_ */
|
@ -20,10 +20,26 @@ Channelizer::~Channelizer()
|
|||||||
freeFilterChain();
|
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)
|
void Channelizer::configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency)
|
||||||
{
|
{
|
||||||
Message* cmd = DSPConfigureChannelizer::create(sampleRate, centerFrequency);
|
Message* cmd = new DSPConfigureChannelizer(sampleRate, centerFrequency);
|
||||||
cmd->submit(messageQueue, this);
|
messageQueue->push(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channelizer::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
void Channelizer::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||||
@ -64,52 +80,58 @@ void Channelizer::stop()
|
|||||||
m_sampleSink->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;
|
DSPSignalNotification* notif = (DSPSignalNotification*) &cmd;
|
||||||
m_inputSampleRate = signal->getSampleRate();
|
m_inputSampleRate = notif->getSampleRate();
|
||||||
qDebug() << "Channelizer::handleMessage: DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate;
|
qDebug() << "Channelizer::handleMessage: DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate;
|
||||||
applyConfiguration();
|
applyConfiguration();
|
||||||
cmd->completed();
|
|
||||||
if(m_sampleSink != NULL)
|
delete cmd;
|
||||||
|
|
||||||
|
if (m_sampleSink != NULL)
|
||||||
{
|
{
|
||||||
signal = DSPSignalNotification::create(m_currentOutputSampleRate, m_currentCenterFrequency);
|
DSPSignalNotification notif(m_currentOutputSampleRate, m_currentCenterFrequency);
|
||||||
if(!m_sampleSink->handleMessage(signal)) {
|
m_sampleSink->handleMessage(notif))
|
||||||
signal->completed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit inputSampleRateChanged();
|
emit inputSampleRateChanged();
|
||||||
return true;
|
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_requestedOutputSampleRate = chan->getSampleRate();
|
||||||
m_requestedCenterFrequency = chan->getCenterFrequency();
|
m_requestedCenterFrequency = chan->getCenterFrequency();
|
||||||
|
|
||||||
qDebug() << "Channelizer::handleMessage: DSPConfigureChannelizer:"
|
qDebug() << "Channelizer::handleMessage: DSPConfigureChannelizer:"
|
||||||
<< " m_requestedOutputSampleRate: " << m_requestedOutputSampleRate
|
<< " m_requestedOutputSampleRate: " << m_requestedOutputSampleRate
|
||||||
<< " m_requestedCenterFrequency: " << m_requestedCenterFrequency;
|
<< " m_requestedCenterFrequency: " << m_requestedCenterFrequency;
|
||||||
|
|
||||||
applyConfiguration();
|
applyConfiguration();
|
||||||
cmd->completed();
|
|
||||||
if(m_sampleSink != NULL)
|
if (m_sampleSink != NULL)
|
||||||
{
|
{
|
||||||
DSPSignalNotification* signal = DSPSignalNotification::create(m_currentOutputSampleRate, m_currentCenterFrequency);
|
DSPSignalNotification notif(m_currentOutputSampleRate, m_currentCenterFrequency);
|
||||||
if(!m_sampleSink->handleMessage(signal)) {
|
m_sampleSink->handleMessage(notif);
|
||||||
signal->completed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(m_sampleSink != NULL) {
|
if (m_sampleSink != NULL)
|
||||||
|
{
|
||||||
return m_sampleSink->handleMessage(cmd);
|
return m_sampleSink->handleMessage(cmd);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ void DSPEngine::run()
|
|||||||
qDebug() << "DSPEngine::run";
|
qDebug() << "DSPEngine::run";
|
||||||
|
|
||||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
|
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;
|
m_state = StIdle;
|
||||||
|
|
||||||
@ -70,34 +71,34 @@ void DSPEngine::start()
|
|||||||
qDebug() << "DSPEngine::start";
|
qDebug() << "DSPEngine::start";
|
||||||
DSPPing cmd;
|
DSPPing cmd;
|
||||||
QThread::start();
|
QThread::start();
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEngine::stop()
|
void DSPEngine::stop()
|
||||||
{
|
{
|
||||||
qDebug() << "DSPEngine::stop";
|
qDebug() << "DSPEngine::stop";
|
||||||
DSPExit cmd;
|
DSPExit cmd;
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSPEngine::initAcquisition()
|
bool DSPEngine::initAcquisition()
|
||||||
{
|
{
|
||||||
DSPAcquisitionInit cmd;
|
DSPAcquisitionInit cmd;
|
||||||
|
|
||||||
return cmd.execute(&m_inputMessageQueue) == StReady;
|
return m_syncMessenger.sendWait(&cmd) == StReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSPEngine::startAcquisition()
|
bool DSPEngine::startAcquisition()
|
||||||
{
|
{
|
||||||
DSPAcquisitionStart cmd;
|
DSPAcquisitionStart cmd;
|
||||||
|
|
||||||
return cmd.execute(&m_inputMessageQueue) == StRunning;
|
return m_syncMessenger.sendWait(&cmd) == StRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEngine::stopAcquistion()
|
void DSPEngine::stopAcquistion()
|
||||||
{
|
{
|
||||||
DSPAcquisitionStop cmd;
|
DSPAcquisitionStop cmd;
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
|
|
||||||
if(m_dcOffsetCorrection)
|
if(m_dcOffsetCorrection)
|
||||||
{
|
{
|
||||||
@ -108,51 +109,51 @@ void DSPEngine::stopAcquistion()
|
|||||||
void DSPEngine::setSource(SampleSource* source)
|
void DSPEngine::setSource(SampleSource* source)
|
||||||
{
|
{
|
||||||
DSPSetSource cmd(source);
|
DSPSetSource cmd(source);
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEngine::addSink(SampleSink* sink)
|
void DSPEngine::addSink(SampleSink* sink)
|
||||||
{
|
{
|
||||||
qDebug() << "DSPEngine::addSink: " << sink->objectName().toStdString().c_str();
|
qDebug() << "DSPEngine::addSink: " << sink->objectName().toStdString().c_str();
|
||||||
DSPAddSink cmd(sink);
|
DSPAddSink cmd(sink);
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEngine::removeSink(SampleSink* sink)
|
void DSPEngine::removeSink(SampleSink* sink)
|
||||||
{
|
{
|
||||||
DSPRemoveSink cmd(sink);
|
DSPRemoveSink cmd(sink);
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEngine::addAudioSink(AudioFifo* audioFifo)
|
void DSPEngine::addAudioSink(AudioFifo* audioFifo)
|
||||||
{
|
{
|
||||||
DSPAddAudioSink cmd(audioFifo);
|
DSPAddAudioSink cmd(audioFifo);
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEngine::removeAudioSink(AudioFifo* audioFifo)
|
void DSPEngine::removeAudioSink(AudioFifo* audioFifo)
|
||||||
{
|
{
|
||||||
DSPRemoveAudioSink cmd(audioFifo);
|
DSPRemoveAudioSink cmd(audioFifo);
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEngine::configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection)
|
void DSPEngine::configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection)
|
||||||
{
|
{
|
||||||
Message* cmd = DSPConfigureCorrection::create(dcOffsetCorrection, iqImbalanceCorrection);
|
DSPConfigureCorrection* cmd = new DSPConfigureCorrection(dcOffsetCorrection, iqImbalanceCorrection);
|
||||||
cmd->submit(&m_inputMessageQueue);
|
m_inputMessageQueue.push(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DSPEngine::errorMessage()
|
QString DSPEngine::errorMessage()
|
||||||
{
|
{
|
||||||
DSPGetErrorMessage cmd;
|
DSPGetErrorMessage cmd;
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
return cmd.getErrorMessage();
|
return cmd.getErrorMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DSPEngine::sourceDeviceDescription()
|
QString DSPEngine::sourceDeviceDescription()
|
||||||
{
|
{
|
||||||
DSPGetSourceDeviceDescription cmd;
|
DSPGetSourceDeviceDescription cmd;
|
||||||
cmd.execute(&m_inputMessageQueue);
|
m_syncMessenger.sendWait(&cmd);
|
||||||
return cmd.getDeviceDescription();
|
return cmd.getDeviceDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,17 +230,17 @@ void DSPEngine::imbalance(SampleVector::iterator begin, SampleVector::iterator e
|
|||||||
void DSPEngine::work()
|
void DSPEngine::work()
|
||||||
{
|
{
|
||||||
SampleFifo* sampleFifo = m_sampleSource->getSampleFifo();
|
SampleFifo* sampleFifo = m_sampleSource->getSampleFifo();
|
||||||
size_t samplesDone = 0;
|
std::size_t samplesDone = 0;
|
||||||
bool positiveOnly = false;
|
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 part1begin;
|
||||||
SampleVector::iterator part1end;
|
SampleVector::iterator part1end;
|
||||||
SampleVector::iterator part2begin;
|
SampleVector::iterator part2begin;
|
||||||
SampleVector::iterator part2end;
|
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
|
// first part of FIFO data
|
||||||
if (part1begin != part1end)
|
if (part1begin != part1end)
|
||||||
@ -278,7 +279,7 @@ void DSPEngine::work()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adjust FIFO pointers
|
// adjust FIFO pointers
|
||||||
sampleFifo->readCommit(count);
|
sampleFifo->readCommit((unsigned int) count);
|
||||||
samplesDone += count;
|
samplesDone += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,7 +315,7 @@ DSPEngine::State DSPEngine::gotoIdle()
|
|||||||
(*it)->stop();
|
(*it)->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sampleSource->stopInput();
|
m_sampleSource->stop();
|
||||||
m_deviceDescription.clear();
|
m_deviceDescription.clear();
|
||||||
m_audioSink.stop();
|
m_audioSink.stop();
|
||||||
m_sampleRate = 0;
|
m_sampleRate = 0;
|
||||||
@ -362,14 +363,14 @@ DSPEngine::State DSPEngine::gotoInit()
|
|||||||
for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
|
for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
|
||||||
{
|
{
|
||||||
qDebug() << " - initializing " << (*it)->objectName().toStdString().c_str();
|
qDebug() << " - initializing " << (*it)->objectName().toStdString().c_str();
|
||||||
DSPSignalNotification* notif = DSPSignalNotification::create(m_sampleRate, m_centerFrequency);
|
DSPSignalNotification notif(m_sampleRate, m_centerFrequency);
|
||||||
(*it)->init(notif);
|
(*it)->init(notif);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass sample rate to main window
|
// pass sample rate to main window
|
||||||
|
|
||||||
Message* rep = DSPEngineReport::create(m_sampleRate, m_centerFrequency);
|
DSPEngineReport* rep = new DSPEngineReport(m_sampleRate, m_centerFrequency);
|
||||||
rep->submit(&m_outputMessageQueue);
|
m_outputMessageQueue.push(rep);
|
||||||
|
|
||||||
return StReady;
|
return StReady;
|
||||||
}
|
}
|
||||||
@ -402,7 +403,7 @@ DSPEngine::State DSPEngine::gotoRunning()
|
|||||||
|
|
||||||
// Start everything
|
// Start everything
|
||||||
|
|
||||||
if(!m_sampleSource->startInput(0))
|
if(!m_sampleSource->start(0))
|
||||||
{
|
{
|
||||||
return gotoError("Could not start sample source");
|
return gotoError("Could not start sample source");
|
||||||
}
|
}
|
||||||
@ -415,7 +416,7 @@ DSPEngine::State DSPEngine::gotoRunning()
|
|||||||
(*it)->start();
|
(*it)->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << " - input message queue pending: " << m_inputMessageQueue.countPending();
|
qDebug() << " - input message queue pending: " << m_inputMessageQueue.size();
|
||||||
|
|
||||||
return StRunning;
|
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()
|
void DSPEngine::handleData()
|
||||||
{
|
{
|
||||||
if(m_state == StRunning)
|
if(m_state == StRunning)
|
||||||
@ -483,24 +457,14 @@ void DSPEngine::handleData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEngine::handleInputMessages()
|
void DSPEngine::handleSynchronousMessages(Message *message)
|
||||||
{
|
{
|
||||||
Message* message;
|
if (DSPExit::match(message))
|
||||||
|
|
||||||
while ((message = m_inputMessageQueue.accept()) != NULL)
|
|
||||||
{
|
|
||||||
qDebug("DSPEngine::handleInputMessages: Message: %s", message->getIdentifier());
|
|
||||||
|
|
||||||
if (DSPPing::match(message))
|
|
||||||
{
|
|
||||||
message->completed(m_state);
|
|
||||||
}
|
|
||||||
else if (DSPExit::match(message))
|
|
||||||
{
|
{
|
||||||
gotoIdle();
|
gotoIdle();
|
||||||
m_state = StNotStarted;
|
m_state = StNotStarted;
|
||||||
exit();
|
exit();
|
||||||
message->completed(m_state);
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPAcquisitionInit::match(message))
|
else if (DSPAcquisitionInit::match(message))
|
||||||
{
|
{
|
||||||
@ -510,7 +474,7 @@ void DSPEngine::handleInputMessages()
|
|||||||
m_state = gotoInit(); // State goes ready if init is performed
|
m_state = gotoInit(); // State goes ready if init is performed
|
||||||
}
|
}
|
||||||
|
|
||||||
message->completed(m_state);
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPAcquisitionStart::match(message))
|
else if (DSPAcquisitionStart::match(message))
|
||||||
{
|
{
|
||||||
@ -518,55 +482,67 @@ void DSPEngine::handleInputMessages()
|
|||||||
m_state = gotoRunning();
|
m_state = gotoRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
message->completed(m_state);
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPAcquisitionStop::match(message))
|
else if (DSPAcquisitionStop::match(message))
|
||||||
{
|
{
|
||||||
m_state = gotoIdle();
|
m_state = gotoIdle();
|
||||||
message->completed(m_state);
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPGetSourceDeviceDescription::match(message))
|
else if (DSPGetSourceDeviceDescription::match(message))
|
||||||
{
|
{
|
||||||
((DSPGetSourceDeviceDescription*)message)->setDeviceDescription(m_deviceDescription);
|
((DSPGetSourceDeviceDescription*)message)->setDeviceDescription(m_deviceDescription);
|
||||||
message->completed();
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPGetErrorMessage::match(message))
|
else if (DSPGetErrorMessage::match(message))
|
||||||
{
|
{
|
||||||
((DSPGetErrorMessage*)message)->setErrorMessage(m_errorMessage);
|
((DSPGetErrorMessage*)message)->setErrorMessage(m_errorMessage);
|
||||||
message->completed();
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPSetSource::match(message)) {
|
else if (DSPSetSource::match(message)) {
|
||||||
handleSetSource(((DSPSetSource*)message)->getSampleSource());
|
handleSetSource(((DSPSetSource*)message)->getSampleSource());
|
||||||
message->completed();
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPAddSink::match(message))
|
else if (DSPAddSink::match(message))
|
||||||
{
|
{
|
||||||
SampleSink* sink = ((DSPAddSink*)message)->getSampleSink();
|
SampleSink* sink = ((DSPAddSink*)message)->getSampleSink();
|
||||||
m_sampleSinks.push_back(sink);
|
m_sampleSinks.push_back(sink);
|
||||||
message->completed();
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPRemoveSink::match(message))
|
else if (DSPRemoveSink::match(message))
|
||||||
{
|
{
|
||||||
SampleSink* sink = ((DSPAddSink*)message)->getSampleSink();
|
SampleSink* sink = ((DSPRemoveSink*)message)->getSampleSink();
|
||||||
|
|
||||||
if(m_state == StRunning) {
|
if(m_state == StRunning) {
|
||||||
sink->stop();
|
sink->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sampleSinks.remove(sink);
|
m_sampleSinks.remove(sink);
|
||||||
message->completed();
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPAddAudioSink::match(message))
|
else if (DSPAddAudioSink::match(message))
|
||||||
{
|
{
|
||||||
m_audioSink.addFifo(((DSPAddAudioSink*)message)->getAudioFifo());
|
m_audioSink.addFifo(((DSPAddAudioSink*)message)->getAudioFifo());
|
||||||
message->completed();
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPRemoveAudioSink::match(message))
|
else if (DSPRemoveAudioSink::match(message))
|
||||||
{
|
{
|
||||||
m_audioSink.removeFifo(((DSPAddAudioSink*)message)->getAudioFifo());
|
m_audioSink.removeFifo(((DSPRemoveAudioSink*)message)->getAudioFifo());
|
||||||
message->completed();
|
m_syncMessenger.done(m_state);
|
||||||
}
|
}
|
||||||
else if (DSPConfigureCorrection::match(message))
|
|
||||||
|
m_syncMessenger.done(m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSPEngine::handleInputMessages()
|
||||||
|
{
|
||||||
|
Message* message;
|
||||||
|
|
||||||
|
while ((message = m_inputMessageQueue.pop()) != 0)
|
||||||
|
{
|
||||||
|
qDebug("DSPEngine::handleInputMessages: Message: %s", message->getIdentifier());
|
||||||
|
|
||||||
|
if (DSPConfigureCorrection::match(message))
|
||||||
{
|
{
|
||||||
DSPConfigureCorrection* conf = (DSPConfigureCorrection*)message;
|
DSPConfigureCorrection* conf = (DSPConfigureCorrection*)message;
|
||||||
m_iqImbalanceCorrection = conf->getIQImbalanceCorrection();
|
m_iqImbalanceCorrection = conf->getIQImbalanceCorrection();
|
||||||
@ -585,20 +561,8 @@ void DSPEngine::handleInputMessages()
|
|||||||
m_qRange = 1 << 16;
|
m_qRange = 1 << 16;
|
||||||
m_imbalance = 65536;
|
m_imbalance = 65536;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message->completed();
|
delete message;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (DSPSignalNotification::match(message))
|
|
||||||
{
|
|
||||||
DSPSignalNotification *conf = (DSPSignalNotification*)message;
|
|
||||||
qDebug() << " (" << conf->getSampleRate() << "," << conf->getFrequencyOffset() << ")";
|
|
||||||
}
|
|
||||||
if (!distributeMessage(message))
|
|
||||||
{
|
|
||||||
message->completed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "dsp/filesink.h"
|
#include "dsp/filesink.h"
|
||||||
|
#include "dsp/dspcommands.h"
|
||||||
#include "util/simpleserializer.h"
|
#include "util/simpleserializer.h"
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
|
|
||||||
@ -23,23 +24,26 @@ FileSink::~FileSink()
|
|||||||
stopRecording();
|
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);
|
Message* cmd = MsgConfigureFileSink::create(filename);
|
||||||
cmd->submit(msgQueue, this);
|
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_sampleRate = notif->getSampleRate();
|
||||||
m_centerFrequency = notif->getFrequencyOffset();
|
m_centerFrequency = notif->getFrequencyOffset();
|
||||||
qDebug() << "FileSink::init: DSPSignalNotification: m_inputSampleRate: " << m_sampleRate;
|
qDebug() << "FileSink::init: DSPSignalNotification: m_inputSampleRate: " << m_sampleRate;
|
||||||
cmd->completed();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
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;
|
MsgConfigureFileSink* conf = (MsgConfigureFileSink*) &message;
|
||||||
handleConfigure(conf->getFileName(), conf->getSampleRate(), conf->getCenterFrequency());
|
handleConfigure(conf->getFileName());
|
||||||
qDebug() << "FileSink::handleMessage:"
|
qDebug() << "FileSink::handleMessage:"
|
||||||
<< " fileName: " << m_fileName.c_str()
|
<< " fileName: " << m_fileName.c_str();
|
||||||
<< " sampleRate: " << m_sampleRate
|
|
||||||
<< " centerFrequency: " << m_centerFrequency;
|
|
||||||
message->completed();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
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();
|
stopRecording();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fileName = fileName;
|
m_fileName = fileName;
|
||||||
m_sampleRate = sampleRate;
|
|
||||||
m_centerFrequency = centerFrequency;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSink::writeHeader()
|
void FileSink::writeHeader()
|
||||||
|
@ -7,6 +7,15 @@ NullSink::NullSink()
|
|||||||
setObjectName("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)
|
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 false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
@ -7,65 +7,3 @@ SampleSink::SampleSink()
|
|||||||
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
|
|
||||||
|
@ -32,6 +32,10 @@ ScopeVis::ScopeVis(GLScope* glScope) :
|
|||||||
m_traceback.resize(20*m_traceChunkSize);
|
m_traceback.resize(20*m_traceChunkSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScopeVis::~ScopeVis()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ScopeVis::configure(MessageQueue* msgQueue,
|
void ScopeVis::configure(MessageQueue* msgQueue,
|
||||||
TriggerChannel triggerChannel,
|
TriggerChannel triggerChannel,
|
||||||
Real triggerLevel,
|
Real triggerLevel,
|
||||||
@ -48,7 +52,21 @@ void ScopeVis::configure(MessageQueue* msgQueue,
|
|||||||
triggerPre,
|
triggerPre,
|
||||||
triggerDelay,
|
triggerDelay,
|
||||||
traceSize);
|
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)
|
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)) {
|
if (MsgConfigureScopeVis::match(&message))
|
||||||
DSPSignalNotification* signal = (DSPSignalNotification*)message;
|
{
|
||||||
m_sampleRate = signal->getSampleRate();
|
MsgConfigureScopeVis* conf = (MsgConfigureScopeVis*) &message;
|
||||||
/*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;
|
|
||||||
m_tracebackCount = 0;
|
m_tracebackCount = 0;
|
||||||
m_triggerState = Config;
|
m_triggerState = Config;
|
||||||
m_triggerChannel = (TriggerChannel) conf->getTriggerChannel();
|
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
|
if (newSize > m_traceback.size()) { // fitting the exact required space is not a requirement for the back trace
|
||||||
m_traceback.resize(newSize);
|
m_traceback.resize(newSize);
|
||||||
}
|
}
|
||||||
qDebug() << "ScopeVis::handleMessageKeep:"
|
qDebug() << "ScopeVis::handleMessage:"
|
||||||
<< " m_triggerChannel: " << m_triggerChannel
|
<< " m_triggerChannel: " << m_triggerChannel
|
||||||
<< " m_triggerLevel: " << m_triggerLevel
|
<< " m_triggerLevel: " << m_triggerLevel
|
||||||
<< " m_triggerPositiveEdge: " << (m_triggerPositiveEdge ? "edge+" : "edge-")
|
<< " m_triggerPositiveEdge: " << (m_triggerPositiveEdge ? "edge+" : "edge-")
|
||||||
@ -239,31 +250,13 @@ bool ScopeVis::handleMessageKeep(Message* message)
|
|||||||
<< " m_triggerDelay: " << m_triggerDelay
|
<< " m_triggerDelay: " << m_triggerDelay
|
||||||
<< " m_traceSize: " << m_trace.size();
|
<< " m_traceSize: " << m_trace.size();
|
||||||
return true;
|
return true;
|
||||||
/*
|
}
|
||||||
} else if(DSPConfigureScopeVis::match(message)) {
|
else
|
||||||
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 {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScopeVis::handleMessage(Message* message)
|
|
||||||
{
|
|
||||||
bool done = handleMessageKeep(message);
|
|
||||||
|
|
||||||
if (done)
|
|
||||||
{
|
|
||||||
message->completed();
|
|
||||||
}
|
|
||||||
|
|
||||||
return done;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScopeVis::setSampleRate(int sampleRate)
|
void ScopeVis::setSampleRate(int sampleRate)
|
||||||
{
|
{
|
||||||
m_sampleRate = sampleRate;
|
m_sampleRate = sampleRate;
|
||||||
|
@ -9,6 +9,18 @@ SpectrumScopeComboVis::SpectrumScopeComboVis(SpectrumVis* spectrumVis, ScopeVis*
|
|||||||
setObjectName("SpectrumScopeComboVis");
|
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)
|
void SpectrumScopeComboVis::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||||
{
|
{
|
||||||
m_scopeVis->feed(begin, end, false);
|
m_scopeVis->feed(begin, end, false);
|
||||||
@ -28,15 +40,10 @@ void SpectrumScopeComboVis::stop()
|
|||||||
m_scopeVis->stop();
|
m_scopeVis->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpectrumScopeComboVis::handleMessage(Message* message)
|
bool SpectrumScopeComboVis::handleMessage(const Message& message)
|
||||||
{
|
{
|
||||||
bool spectDone = m_spectrumVis->handleMessageKeep(message);
|
bool spectDone = m_spectrumVis->handleMessage(message);
|
||||||
bool scopeDone = m_scopeVis->handleMessageKeep(message);
|
bool scopeDone = m_scopeVis->handleMessage(message);
|
||||||
|
|
||||||
if (spectDone || scopeDone)
|
|
||||||
{
|
|
||||||
message->completed();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (spectDone || scopeDone);
|
return (spectDone || scopeDone);
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,15 @@ SpectrumVis::~SpectrumVis()
|
|||||||
delete m_fft;
|
delete m_fft;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SpectrumVis::init(const Message& cmd)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void SpectrumVis::configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, FFTWindow::Function window)
|
void SpectrumVis::configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, FFTWindow::Function window)
|
||||||
{
|
{
|
||||||
Message* cmd = DSPConfigureSpectrumVis::create(fftSize, overlapPercent, window);
|
DSPConfigureSpectrumVis* cmd = new DSPConfigureSpectrumVis(fftSize, overlapPercent, window);
|
||||||
cmd->submit(msgQueue, this);
|
msgQueue->push(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpectrumVis::feedTriggered(SampleVector::const_iterator triggerPoint, SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
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)) {
|
if(DSPConfigureSpectrumVis::match(&message))
|
||||||
DSPConfigureSpectrumVis* conf = (DSPConfigureSpectrumVis*)message;
|
{
|
||||||
|
DSPConfigureSpectrumVis* conf = (DSPConfigureSpectrumVis*) &message;
|
||||||
handleConfigure(conf->getFFTSize(), conf->getOverlapPercent(), conf->getWindow());
|
handleConfigure(conf->getFFTSize(), conf->getOverlapPercent(), conf->getWindow());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return false;
|
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)
|
void SpectrumVis::handleConfigure(int fftSize, int overlapPercent, FFTWindow::Function window)
|
||||||
{
|
{
|
||||||
if(fftSize > MAX_FFT_SIZE)
|
if (fftSize > MAX_FFT_SIZE)
|
||||||
|
{
|
||||||
fftSize = MAX_FFT_SIZE;
|
fftSize = MAX_FFT_SIZE;
|
||||||
else if(fftSize < 64)
|
}
|
||||||
|
else if (fftSize < 64)
|
||||||
|
{
|
||||||
fftSize = 64;
|
fftSize = 64;
|
||||||
if(overlapPercent > 100)
|
}
|
||||||
|
|
||||||
|
if (overlapPercent > 100)
|
||||||
|
{
|
||||||
m_overlapPercent = 100;
|
m_overlapPercent = 100;
|
||||||
else if(overlapPercent < 0)
|
}
|
||||||
|
else if (overlapPercent < 0)
|
||||||
|
{
|
||||||
m_overlapPercent = 0;
|
m_overlapPercent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
m_fftSize = fftSize;
|
m_fftSize = fftSize;
|
||||||
m_overlapPercent = overlapPercent;
|
m_overlapPercent = overlapPercent;
|
||||||
|
@ -319,7 +319,7 @@ void MainWindow::handleDSPMessages()
|
|||||||
{
|
{
|
||||||
Message* message;
|
Message* message;
|
||||||
|
|
||||||
while ((message = m_dspEngine->getOutputMessageQueue()->accept()) != 0)
|
while ((message = m_dspEngine->getOutputMessageQueue()->pop()) != 0)
|
||||||
{
|
{
|
||||||
qDebug("Message: %s", message->getIdentifier());
|
qDebug("Message: %s", message->getIdentifier());
|
||||||
|
|
||||||
@ -333,10 +333,11 @@ void MainWindow::handleDSPMessages()
|
|||||||
qDebug("SampleRate:%d, CenterFrequency:%llu", rep->getSampleRate(), rep->getCenterFrequency());
|
qDebug("SampleRate:%d, CenterFrequency:%llu", rep->getSampleRate(), rep->getCenterFrequency());
|
||||||
updateCenterFreqDisplay();
|
updateCenterFreqDisplay();
|
||||||
updateSampleRate();
|
updateSampleRate();
|
||||||
message->completed();
|
|
||||||
qDebug() << "MainWindow::handleMessages: m_fileSink->configure";
|
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;
|
Message* message;
|
||||||
|
|
||||||
while ((message = m_messageQueue->accept()) != 0)
|
while ((message = m_messageQueue->pop()) != 0)
|
||||||
{
|
{
|
||||||
qDebug("Message: %s", message->getIdentifier());
|
qDebug("Message: %s", message->getIdentifier());
|
||||||
|
|
||||||
std::cerr << "MainWindow::handleMessages: " << message->getIdentifier() << std::endl;
|
std::cerr << "MainWindow::handleMessages: " << message->getIdentifier() << std::endl;
|
||||||
|
|
||||||
if (!m_pluginManager->handleMessage(message)) {
|
if (!m_pluginManager->handleMessage(message))
|
||||||
message->completed();
|
{
|
||||||
|
delete message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 <QWaitCondition>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
@ -6,20 +23,12 @@
|
|||||||
const char* Message::m_identifier = "Message";
|
const char* Message::m_identifier = "Message";
|
||||||
|
|
||||||
Message::Message() :
|
Message::Message() :
|
||||||
m_destination(NULL),
|
m_destination(0)
|
||||||
m_synchronous(false),
|
|
||||||
m_waitCondition(NULL),
|
|
||||||
m_mutex(NULL),
|
|
||||||
m_complete(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::~Message()
|
Message::~Message()
|
||||||
{
|
{
|
||||||
if(m_waitCondition != NULL)
|
|
||||||
delete m_waitCondition;
|
|
||||||
if(m_mutex != NULL)
|
|
||||||
delete m_mutex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Message::getIdentifier() const
|
const char* Message::getIdentifier() const
|
||||||
@ -32,48 +41,7 @@ bool Message::matchIdentifier(const char* identifier) const
|
|||||||
return m_identifier == identifier;
|
return m_identifier == identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Message::match(Message* message)
|
bool Message::match(const Message* message)
|
||||||
{
|
{
|
||||||
return message->matchIdentifier(m_identifier);
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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/messagequeue.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
|
|
||||||
@ -10,29 +27,44 @@ MessageQueue::MessageQueue(QObject* parent) :
|
|||||||
|
|
||||||
MessageQueue::~MessageQueue()
|
MessageQueue::~MessageQueue()
|
||||||
{
|
{
|
||||||
Message* cmd;
|
Message* message;
|
||||||
while((cmd = accept()) != NULL)
|
|
||||||
cmd->completed();
|
while ((message = pop()) != 0)
|
||||||
|
{
|
||||||
|
delete message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageQueue::submit(Message* message)
|
void MessageQueue::push(Message* message, bool emitSignal)
|
||||||
{
|
{
|
||||||
|
if (message)
|
||||||
|
{
|
||||||
m_lock.lock();
|
m_lock.lock();
|
||||||
m_queue.append(message);
|
m_queue.append(message);
|
||||||
m_lock.unlock();
|
m_lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emitSignal)
|
||||||
|
{
|
||||||
emit messageEnqueued();
|
emit messageEnqueued();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Message* MessageQueue::accept()
|
Message* MessageQueue::pop()
|
||||||
{
|
{
|
||||||
SpinlockHolder spinlockHolder(&m_lock);
|
SpinlockHolder spinlockHolder(&m_lock);
|
||||||
|
|
||||||
if(m_queue.isEmpty())
|
if (m_queue.isEmpty())
|
||||||
return NULL;
|
{
|
||||||
else return m_queue.takeFirst();
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_queue.takeFirst();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MessageQueue::countPending()
|
int MessageQueue::size()
|
||||||
{
|
{
|
||||||
SpinlockHolder spinlockHolder(&m_lock);
|
SpinlockHolder spinlockHolder(&m_lock);
|
||||||
|
|
||||||
|
56
sdrbase/util/syncmessenger.cpp
Normal file
56
sdrbase/util/syncmessenger.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user