mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-26 05:38:39 -05:00
THREAD_CLEAN_PART2: Assure correct terminate()/isTerminated(delay)/delete sequence +
Removed the NotifyQueue between DemodulatorInstance participants, actually not needed since DemodulatorInstance::IsTerminated() is explicitly called on some events for cleanups DELETE_CLEANUP: properly nullify deleted pointers when needed
This commit is contained in:
parent
cf90a829b0
commit
567d84711f
110
src/CubicSDR.cpp
110
src/CubicSDR.cpp
@ -293,43 +293,63 @@ int CubicSDR::OnExit() {
|
|||||||
demodMgr.terminateAll();
|
demodMgr.terminateAll();
|
||||||
|
|
||||||
std::cout << "Terminating SDR thread.." << std::endl;
|
std::cout << "Terminating SDR thread.." << std::endl;
|
||||||
if (!sdrThread->isTerminated()) {
|
sdrThread->terminate();
|
||||||
sdrThread->terminate();
|
sdrThread->isTerminated(1000);
|
||||||
if (t_SDR) {
|
|
||||||
t_SDR->join();
|
if (t_SDR) {
|
||||||
}
|
t_SDR->join();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Terminating SDR post-processing thread.." << std::endl;
|
std::cout << "Terminating SDR post-processing thread.." << std::endl;
|
||||||
sdrPostThread->terminate();
|
sdrPostThread->terminate();
|
||||||
t_PostSDR->join();
|
|
||||||
|
|
||||||
std::cout << "Terminating Visual Processor threads.." << std::endl;
|
std::cout << "Terminating Visual Processor threads.." << std::endl;
|
||||||
spectrumVisualThread->terminate();
|
spectrumVisualThread->terminate();
|
||||||
t_SpectrumVisual->join();
|
|
||||||
|
|
||||||
demodVisualThread->terminate();
|
demodVisualThread->terminate();
|
||||||
t_DemodVisual->join();
|
|
||||||
|
|
||||||
//Poor man join
|
//Wait nicely
|
||||||
sdrPostThread->isTerminated(1000);
|
sdrPostThread->isTerminated(1000);
|
||||||
spectrumVisualThread->isTerminated(1000);
|
spectrumVisualThread->isTerminated(1000);
|
||||||
demodVisualThread->isTerminated(1000);
|
demodVisualThread->isTerminated(1000);
|
||||||
|
|
||||||
|
//Then join the thread themselves
|
||||||
|
t_PostSDR->join();
|
||||||
|
t_DemodVisual->join();
|
||||||
|
t_SpectrumVisual->join();
|
||||||
|
|
||||||
|
//Now only we can delete
|
||||||
delete sdrThread;
|
delete sdrThread;
|
||||||
|
sdrThread = nullptr;
|
||||||
|
|
||||||
delete sdrPostThread;
|
delete sdrPostThread;
|
||||||
|
sdrPostThread = nullptr;
|
||||||
|
|
||||||
delete t_PostSDR;
|
delete t_PostSDR;
|
||||||
|
t_PostSDR = nullptr;
|
||||||
|
|
||||||
delete t_SpectrumVisual;
|
delete t_SpectrumVisual;
|
||||||
|
t_SpectrumVisual = nullptr;
|
||||||
|
|
||||||
delete spectrumVisualThread;
|
delete spectrumVisualThread;
|
||||||
|
spectrumVisualThread = nullptr;
|
||||||
|
|
||||||
delete t_DemodVisual;
|
delete t_DemodVisual;
|
||||||
|
t_DemodVisual = nullptr;
|
||||||
|
|
||||||
delete demodVisualThread;
|
delete demodVisualThread;
|
||||||
|
demodVisualThread = nullptr;
|
||||||
|
|
||||||
delete pipeIQVisualData;
|
delete pipeIQVisualData;
|
||||||
|
pipeIQVisualData = nullptr;
|
||||||
|
|
||||||
delete pipeAudioVisualData;
|
delete pipeAudioVisualData;
|
||||||
|
pipeAudioVisualData = nullptr;
|
||||||
|
|
||||||
delete pipeSDRIQData;
|
delete pipeSDRIQData;
|
||||||
|
pipeSDRIQData = nullptr;
|
||||||
|
|
||||||
delete m_glContext;
|
delete m_glContext;
|
||||||
|
m_glContext = nullptr;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
AudioThread::deviceCleanup();
|
AudioThread::deviceCleanup();
|
||||||
@ -427,6 +447,7 @@ void CubicSDR::sdrThreadNotify(SDRThread::SDRThreadState state, std::string mess
|
|||||||
if (state == SDRThread::SDR_THREAD_TERMINATED) {
|
if (state == SDRThread::SDR_THREAD_TERMINATED) {
|
||||||
t_SDR->join();
|
t_SDR->join();
|
||||||
delete t_SDR;
|
delete t_SDR;
|
||||||
|
t_SDR = nullptr;
|
||||||
}
|
}
|
||||||
if (state == SDRThread::SDR_THREAD_FAILED) {
|
if (state == SDRThread::SDR_THREAD_FAILED) {
|
||||||
notifyMessage = message;
|
notifyMessage = message;
|
||||||
@ -532,14 +553,15 @@ void CubicSDR::stopDevice(bool store) {
|
|||||||
}
|
}
|
||||||
sdrThread->setDevice(nullptr);
|
sdrThread->setDevice(nullptr);
|
||||||
|
|
||||||
if (!sdrThread->isTerminated()) {
|
sdrThread->terminate();
|
||||||
sdrThread->terminate();
|
sdrThread->isTerminated(1000);
|
||||||
if (t_SDR) {
|
|
||||||
t_SDR->join();
|
if (t_SDR) {
|
||||||
delete t_SDR;
|
t_SDR->join();
|
||||||
t_SDR = nullptr;
|
delete t_SDR;
|
||||||
}
|
t_SDR = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CubicSDR::reEnumerateDevices() {
|
void CubicSDR::reEnumerateDevices() {
|
||||||
@ -550,12 +572,14 @@ void CubicSDR::reEnumerateDevices() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CubicSDR::setDevice(SDRDeviceInfo *dev) {
|
void CubicSDR::setDevice(SDRDeviceInfo *dev) {
|
||||||
if (!sdrThread->isTerminated()) {
|
|
||||||
sdrThread->terminate();
|
sdrThread->terminate();
|
||||||
if (t_SDR) {
|
sdrThread->isTerminated(1000);
|
||||||
t_SDR->join();
|
|
||||||
delete t_SDR;
|
if (t_SDR) {
|
||||||
}
|
t_SDR->join();
|
||||||
|
delete t_SDR;
|
||||||
|
t_SDR = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SoapySDR::Kwargs::const_iterator i = settingArgs.begin(); i != settingArgs.end(); i++) {
|
for (SoapySDR::Kwargs::const_iterator i = settingArgs.begin(); i != settingArgs.end(); i++) {
|
||||||
@ -872,17 +896,27 @@ RigThread *CubicSDR::getRigThread() {
|
|||||||
|
|
||||||
void CubicSDR::initRig(int rigModel, std::string rigPort, int rigSerialRate) {
|
void CubicSDR::initRig(int rigModel, std::string rigPort, int rigSerialRate) {
|
||||||
if (rigThread) {
|
if (rigThread) {
|
||||||
if (!rigThread->isTerminated()) {
|
|
||||||
rigThread->terminate();
|
rigThread->terminate();
|
||||||
}
|
rigThread->isTerminated(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t_Rig && t_Rig->joinable()) {
|
||||||
|
t_Rig->join();
|
||||||
|
}
|
||||||
|
|
||||||
|
//now we can delete
|
||||||
|
if (rigThread) {
|
||||||
|
|
||||||
delete rigThread;
|
delete rigThread;
|
||||||
rigThread = nullptr;
|
rigThread = nullptr;
|
||||||
}
|
}
|
||||||
if (t_Rig && t_Rig->joinable()) {
|
if (t_Rig) {
|
||||||
t_Rig->join();
|
|
||||||
delete t_Rig;
|
delete t_Rig;
|
||||||
t_Rig = nullptr;
|
t_Rig = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
rigThread = new RigThread();
|
rigThread = new RigThread();
|
||||||
rigThread->initRig(rigModel, rigPort, rigSerialRate);
|
rigThread->initRig(rigModel, rigPort, rigSerialRate);
|
||||||
rigThread->setControlMode(wxGetApp().getConfig()->getRigControlMode());
|
rigThread->setControlMode(wxGetApp().getConfig()->getRigControlMode());
|
||||||
@ -899,14 +933,24 @@ void CubicSDR::stopRig() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rigThread) {
|
if (rigThread) {
|
||||||
if (!rigThread->isTerminated()) {
|
|
||||||
rigThread->terminate();
|
rigThread->terminate();
|
||||||
}
|
rigThread->isTerminated(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t_Rig && t_Rig->joinable()) {
|
||||||
|
t_Rig->join();
|
||||||
|
}
|
||||||
|
|
||||||
|
//now we can delete
|
||||||
|
if (rigThread) {
|
||||||
|
|
||||||
delete rigThread;
|
delete rigThread;
|
||||||
rigThread = nullptr;
|
rigThread = nullptr;
|
||||||
}
|
}
|
||||||
if (t_Rig && t_Rig->joinable()) {
|
|
||||||
t_Rig->join();
|
if (t_Rig) {
|
||||||
|
|
||||||
delete t_Rig;
|
delete t_Rig;
|
||||||
t_Rig = nullptr;
|
t_Rig = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -180,10 +180,10 @@ private:
|
|||||||
|
|
||||||
DemodulatorMgr demodMgr;
|
DemodulatorMgr demodMgr;
|
||||||
|
|
||||||
long long frequency;
|
std::atomic_llong frequency;
|
||||||
long long offset;
|
std::atomic_llong offset;
|
||||||
int ppm, snap;
|
std::atomic_int ppm, snap;
|
||||||
long long sampleRate;
|
std::atomic_llong sampleRate;
|
||||||
std::atomic_bool agcMode;
|
std::atomic_bool agcMode;
|
||||||
|
|
||||||
SDRThread *sdrThread;
|
SDRThread *sdrThread;
|
||||||
@ -224,7 +224,7 @@ private:
|
|||||||
std::atomic_bool soloMode;
|
std::atomic_bool soloMode;
|
||||||
SDRDeviceInfo *stoppedDev;
|
SDRDeviceInfo *stoppedDev;
|
||||||
#ifdef USE_HAMLIB
|
#ifdef USE_HAMLIB
|
||||||
RigThread *rigThread;
|
RigThread* rigThread;
|
||||||
std::thread *t_Rig;
|
std::thread *t_Rig;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "IOThread.h"
|
#include "IOThread.h"
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
std::mutex ReBufferGC::g_mutex;
|
std::mutex ReBufferGC::g_mutex;
|
||||||
std::set<ReferenceCounter *> ReBufferGC::garbage;
|
std::set<ReferenceCounter *> ReBufferGC::garbage;
|
||||||
@ -122,5 +123,7 @@ bool IOThread::isTerminated(int waitMs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "ERROR: thread '" << typeid(*this).name() << "' has not terminated in time ! (> " << waitMs << " ms)" << std::endl;
|
||||||
|
|
||||||
return terminated.load();
|
return terminated.load();
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ std::map<int, int> AudioThread::deviceSampleRate;
|
|||||||
std::map<int, std::thread *> AudioThread::deviceThread;
|
std::map<int, std::thread *> AudioThread::deviceThread;
|
||||||
|
|
||||||
AudioThread::AudioThread() : IOThread(),
|
AudioThread::AudioThread() : IOThread(),
|
||||||
currentInput(NULL), inputQueue(NULL), nBufferFrames(1024), threadQueueNotify(NULL), sampleRate(0) {
|
currentInput(NULL), inputQueue(NULL), nBufferFrames(1024), sampleRate(0) {
|
||||||
|
|
||||||
audioQueuePtr.store(0);
|
audioQueuePtr.store(0);
|
||||||
underflowCount.store(0);
|
underflowCount.store(0);
|
||||||
@ -378,7 +378,6 @@ void AudioThread::run() {
|
|||||||
// std::cout << "Audio thread started." << std::endl;
|
// std::cout << "Audio thread started." << std::endl;
|
||||||
|
|
||||||
inputQueue = static_cast<AudioThreadInputQueue *>(getInputQueue("AudioDataInput"));
|
inputQueue = static_cast<AudioThreadInputQueue *>(getInputQueue("AudioDataInput"));
|
||||||
threadQueueNotify = static_cast<DemodulatorThreadCommandQueue*>(getOutputQueue("NotifyQueue"));
|
|
||||||
|
|
||||||
while (!stopping) {
|
while (!stopping) {
|
||||||
AudioThreadCommand command;
|
AudioThreadCommand command;
|
||||||
@ -420,12 +419,7 @@ void AudioThread::run() {
|
|||||||
e.printMessage();
|
e.printMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (threadQueueNotify != NULL) {
|
|
||||||
DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED);
|
|
||||||
tCmd.context = this;
|
|
||||||
threadQueueNotify->push(tCmd);
|
|
||||||
}
|
|
||||||
// std::cout << "Audio thread done." << std::endl;
|
// std::cout << "Audio thread done." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,6 @@ private:
|
|||||||
RtAudio::StreamOptions opts;
|
RtAudio::StreamOptions opts;
|
||||||
RtAudio::StreamParameters parameters;
|
RtAudio::StreamParameters parameters;
|
||||||
AudioThreadCommandQueue cmdQueue;
|
AudioThreadCommandQueue cmdQueue;
|
||||||
DemodulatorThreadCommandQueue* threadQueueNotify;
|
|
||||||
int sampleRate;
|
int sampleRate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -10,29 +10,7 @@
|
|||||||
#include "IOThread.h"
|
#include "IOThread.h"
|
||||||
|
|
||||||
class DemodulatorThread;
|
class DemodulatorThread;
|
||||||
class DemodulatorThreadCommand {
|
|
||||||
public:
|
|
||||||
enum DemodulatorThreadCommandEnum {
|
|
||||||
DEMOD_THREAD_CMD_NULL,
|
|
||||||
DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED,
|
|
||||||
DEMOD_THREAD_CMD_DEMOD_TERMINATED,
|
|
||||||
DEMOD_THREAD_CMD_AUDIO_TERMINATED
|
|
||||||
};
|
|
||||||
|
|
||||||
DemodulatorThreadCommand() :
|
|
||||||
cmd(DEMOD_THREAD_CMD_NULL), context(NULL), llong_value(0) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DemodulatorThreadCommand(DemodulatorThreadCommandEnum cmd) :
|
|
||||||
cmd(cmd), context(NULL), llong_value(0) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DemodulatorThreadCommandEnum cmd;
|
|
||||||
void *context;
|
|
||||||
long long llong_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DemodulatorThreadControlCommand {
|
class DemodulatorThreadControlCommand {
|
||||||
public:
|
public:
|
||||||
@ -120,5 +98,4 @@ public:
|
|||||||
|
|
||||||
typedef ThreadQueue<DemodulatorThreadIQData *> DemodulatorThreadInputQueue;
|
typedef ThreadQueue<DemodulatorThreadIQData *> DemodulatorThreadInputQueue;
|
||||||
typedef ThreadQueue<DemodulatorThreadPostIQData *> DemodulatorThreadPostInputQueue;
|
typedef ThreadQueue<DemodulatorThreadPostIQData *> DemodulatorThreadPostInputQueue;
|
||||||
typedef ThreadQueue<DemodulatorThreadCommand> DemodulatorThreadCommandQueue;
|
|
||||||
typedef ThreadQueue<DemodulatorThreadControlCommand> DemodulatorThreadControlCommandQueue;
|
typedef ThreadQueue<DemodulatorThreadControlCommand> DemodulatorThreadControlCommandQueue;
|
||||||
|
@ -51,14 +51,12 @@ DemodulatorInstance::DemodulatorInstance() {
|
|||||||
|
|
||||||
pipeIQInputData = new DemodulatorThreadInputQueue;
|
pipeIQInputData = new DemodulatorThreadInputQueue;
|
||||||
pipeIQDemodData = new DemodulatorThreadPostInputQueue;
|
pipeIQDemodData = new DemodulatorThreadPostInputQueue;
|
||||||
pipeDemodNotify = new DemodulatorThreadCommandQueue;
|
|
||||||
|
|
||||||
audioThread = new AudioThread();
|
audioThread = new AudioThread();
|
||||||
|
|
||||||
demodulatorPreThread = new DemodulatorPreThread(this);
|
demodulatorPreThread = new DemodulatorPreThread(this);
|
||||||
demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData);
|
demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData);
|
||||||
demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData);
|
demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData);
|
||||||
demodulatorPreThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
|
|
||||||
|
|
||||||
pipeAudioData = new AudioThreadInputQueue;
|
pipeAudioData = new AudioThreadInputQueue;
|
||||||
threadQueueControl = new DemodulatorThreadControlCommandQueue;
|
threadQueueControl = new DemodulatorThreadControlCommandQueue;
|
||||||
@ -66,11 +64,9 @@ DemodulatorInstance::DemodulatorInstance() {
|
|||||||
demodulatorThread = new DemodulatorThread(this);
|
demodulatorThread = new DemodulatorThread(this);
|
||||||
demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData);
|
demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData);
|
||||||
demodulatorThread->setInputQueue("ControlQueue",threadQueueControl);
|
demodulatorThread->setInputQueue("ControlQueue",threadQueueControl);
|
||||||
demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
|
|
||||||
demodulatorThread->setOutputQueue("AudioDataOutput", pipeAudioData);
|
demodulatorThread->setOutputQueue("AudioDataOutput", pipeAudioData);
|
||||||
|
|
||||||
audioThread->setInputQueue("AudioDataInput", pipeAudioData);
|
audioThread->setInputQueue("AudioDataInput", pipeAudioData);
|
||||||
audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance::~DemodulatorInstance() {
|
DemodulatorInstance::~DemodulatorInstance() {
|
||||||
@ -82,7 +78,6 @@ DemodulatorInstance::~DemodulatorInstance() {
|
|||||||
delete demodulatorPreThread;
|
delete demodulatorPreThread;
|
||||||
delete pipeIQInputData;
|
delete pipeIQInputData;
|
||||||
delete pipeIQDemodData;
|
delete pipeIQDemodData;
|
||||||
delete pipeDemodNotify;
|
|
||||||
delete threadQueueControl;
|
delete threadQueueControl;
|
||||||
delete pipeAudioData;
|
delete pipeAudioData;
|
||||||
}
|
}
|
||||||
@ -151,56 +146,59 @@ void DemodulatorInstance::setLabel(std::string labelStr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DemodulatorInstance::isTerminated() {
|
bool DemodulatorInstance::isTerminated() {
|
||||||
while (!pipeDemodNotify->empty()) {
|
|
||||||
DemodulatorThreadCommand cmd;
|
|
||||||
pipeDemodNotify->pop(cmd);
|
|
||||||
|
|
||||||
switch (cmd.cmd) {
|
|
||||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED:
|
|
||||||
if (t_Audio) {
|
|
||||||
t_Audio->join();
|
|
||||||
|
|
||||||
delete t_Audio;
|
|
||||||
t_Audio = nullptr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED:
|
|
||||||
if (t_Demod) {
|
|
||||||
#ifdef __APPLE__
|
|
||||||
pthread_join(t_Demod, nullptr);
|
|
||||||
#else
|
|
||||||
t_Demod->join();
|
|
||||||
delete t_Demod;
|
|
||||||
#endif
|
|
||||||
t_Demod = nullptr;
|
|
||||||
}
|
|
||||||
#if ENABLE_DIGITAL_LAB
|
|
||||||
if (activeOutput) {
|
|
||||||
closeOutput();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED:
|
|
||||||
if (t_PreDemod) {
|
|
||||||
#ifdef __APPLE__
|
|
||||||
pthread_join(t_PreDemod, NULL);
|
|
||||||
#else
|
|
||||||
t_PreDemod->join();
|
|
||||||
delete t_PreDemod;
|
|
||||||
#endif
|
|
||||||
t_PreDemod = nullptr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
bool audioTerminated = audioThread->isTerminated();
|
bool audioTerminated = audioThread->isTerminated();
|
||||||
bool demodTerminated = demodulatorThread->isTerminated();
|
bool demodTerminated = demodulatorThread->isTerminated();
|
||||||
bool preDemodTerminated = demodulatorPreThread->isTerminated();
|
bool preDemodTerminated = demodulatorPreThread->isTerminated();
|
||||||
|
|
||||||
|
|
||||||
|
//Cleanup the worker threads, if the threads are indeed terminated
|
||||||
|
if (audioTerminated) {
|
||||||
|
|
||||||
|
if (t_Audio) {
|
||||||
|
|
||||||
|
t_Audio->join();
|
||||||
|
|
||||||
|
delete t_Audio;
|
||||||
|
t_Audio = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (demodTerminated) {
|
||||||
|
|
||||||
|
if (t_Demod) {
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
pthread_join(t_Demod, nullptr);
|
||||||
|
#else
|
||||||
|
t_Demod->join();
|
||||||
|
delete t_Demod;
|
||||||
|
#endif
|
||||||
|
t_Demod = nullptr;
|
||||||
|
}
|
||||||
|
#if ENABLE_DIGITAL_LAB
|
||||||
|
if (activeOutput) {
|
||||||
|
closeOutput();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preDemodTerminated) {
|
||||||
|
|
||||||
|
if (t_PreDemod) {
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
pthread_join(t_PreDemod, NULL);
|
||||||
|
#else
|
||||||
|
t_PreDemod->join();
|
||||||
|
delete t_PreDemod;
|
||||||
|
#endif
|
||||||
|
t_PreDemod = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool terminated = audioTerminated && demodTerminated && preDemodTerminated;
|
bool terminated = audioTerminated && demodTerminated && preDemodTerminated;
|
||||||
|
|
||||||
return terminated;
|
return terminated;
|
||||||
|
@ -47,8 +47,6 @@ public:
|
|||||||
|
|
||||||
void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue);
|
void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue);
|
||||||
|
|
||||||
DemodulatorThreadCommandQueue *getCommandQueue();
|
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
void terminate();
|
void terminate();
|
||||||
std::string getLabel();
|
std::string getLabel();
|
||||||
@ -131,7 +129,6 @@ protected:
|
|||||||
DemodulatorThreadInputQueue* pipeIQInputData;
|
DemodulatorThreadInputQueue* pipeIQInputData;
|
||||||
DemodulatorThreadPostInputQueue* pipeIQDemodData;
|
DemodulatorThreadPostInputQueue* pipeIQDemodData;
|
||||||
AudioThreadInputQueue *pipeAudioData;
|
AudioThreadInputQueue *pipeAudioData;
|
||||||
DemodulatorThreadCommandQueue* pipeDemodNotify;
|
|
||||||
DemodulatorPreThread *demodulatorPreThread;
|
DemodulatorPreThread *demodulatorPreThread;
|
||||||
DemodulatorThread *demodulatorThread;
|
DemodulatorThread *demodulatorThread;
|
||||||
DemodulatorThreadControlCommandQueue *threadQueueControl;
|
DemodulatorThreadControlCommandQueue *threadQueueControl;
|
||||||
|
@ -148,14 +148,18 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
|
|||||||
if (i != demods.end()) {
|
if (i != demods.end()) {
|
||||||
demods.erase(i);
|
demods.erase(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Ask for termination
|
||||||
demod->terminate();
|
demod->terminate();
|
||||||
|
|
||||||
|
//Do not cleanup immediatly
|
||||||
demods_deleted.push_back(demod);
|
demods_deleted.push_back(demod);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> *DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) {
|
std::vector<DemodulatorInstance *> DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
std::vector<DemodulatorInstance *> *foundDemods = new std::vector<DemodulatorInstance *>();
|
|
||||||
|
std::vector<DemodulatorInstance *> foundDemods;
|
||||||
|
|
||||||
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
|
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
|
||||||
DemodulatorInstance *testDemod = demods[i];
|
DemodulatorInstance *testDemod = demods[i];
|
||||||
@ -167,7 +171,7 @@ std::vector<DemodulatorInstance *> *DemodulatorMgr::getDemodulatorsAt(long long
|
|||||||
long long halfBuffer = bandwidth / 2;
|
long long halfBuffer = bandwidth / 2;
|
||||||
|
|
||||||
if ((freq <= (freqTest + ((testDemod->getDemodulatorType() != "LSB")?halfBandwidthTest:0) + halfBuffer)) && (freq >= (freqTest - ((testDemod->getDemodulatorType() != "USB")?halfBandwidthTest:0) - halfBuffer))) {
|
if ((freq <= (freqTest + ((testDemod->getDemodulatorType() != "LSB")?halfBandwidthTest:0) + halfBuffer)) && (freq >= (freqTest - ((testDemod->getDemodulatorType() != "USB")?halfBandwidthTest:0) - halfBuffer))) {
|
||||||
foundDemods->push_back(testDemod);
|
foundDemods.push_back(testDemod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ public:
|
|||||||
DemodulatorInstance *newThread();
|
DemodulatorInstance *newThread();
|
||||||
std::vector<DemodulatorInstance *> &getDemodulators();
|
std::vector<DemodulatorInstance *> &getDemodulators();
|
||||||
std::vector<DemodulatorInstance *> getOrderedDemodulators(bool actives = true);
|
std::vector<DemodulatorInstance *> getOrderedDemodulators(bool actives = true);
|
||||||
std::vector<DemodulatorInstance *> *getDemodulatorsAt(long long freq, int bandwidth);
|
std::vector<DemodulatorInstance *> getDemodulatorsAt(long long freq, int bandwidth);
|
||||||
DemodulatorInstance *getPreviousDemodulator(DemodulatorInstance *demod, bool actives = true);
|
DemodulatorInstance *getPreviousDemodulator(DemodulatorInstance *demod, bool actives = true);
|
||||||
DemodulatorInstance *getNextDemodulator(DemodulatorInstance *demod, bool actives = true);
|
DemodulatorInstance *getNextDemodulator(DemodulatorInstance *demod, bool actives = true);
|
||||||
DemodulatorInstance *getLastDemodulator();
|
DemodulatorInstance *getLastDemodulator();
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "CubicSDR.h"
|
#include "CubicSDR.h"
|
||||||
#include "DemodulatorInstance.h"
|
#include "DemodulatorInstance.h"
|
||||||
|
|
||||||
DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL)
|
DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL)
|
||||||
{
|
{
|
||||||
initialized.store(false);
|
initialized.store(false);
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
@ -58,7 +58,6 @@ void DemodulatorPreThread::run() {
|
|||||||
|
|
||||||
iqInputQueue = static_cast<DemodulatorThreadInputQueue*>(getInputQueue("IQDataInput"));
|
iqInputQueue = static_cast<DemodulatorThreadInputQueue*>(getInputQueue("IQDataInput"));
|
||||||
iqOutputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getOutputQueue("IQDataOutput"));
|
iqOutputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getOutputQueue("IQDataOutput"));
|
||||||
threadQueueNotify = static_cast<DemodulatorThreadCommandQueue*>(getOutputQueue("NotifyQueue"));
|
|
||||||
|
|
||||||
std::vector<liquid_float_complex> in_buf_data;
|
std::vector<liquid_float_complex> in_buf_data;
|
||||||
std::vector<liquid_float_complex> out_buf_data;
|
std::vector<liquid_float_complex> out_buf_data;
|
||||||
@ -276,11 +275,6 @@ void DemodulatorPreThread::run() {
|
|||||||
tmp->decRefCount();
|
tmp->decRefCount();
|
||||||
}
|
}
|
||||||
buffers.purge();
|
buffers.purge();
|
||||||
|
|
||||||
DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED);
|
|
||||||
tCmd.context = this;
|
|
||||||
threadQueueNotify->push(tCmd);
|
|
||||||
// std::cout << "Demodulator preprocessor thread done." << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorPreThread::setDemodType(std::string demodType) {
|
void DemodulatorPreThread::setDemodType(std::string demodType) {
|
||||||
@ -346,12 +340,22 @@ void DemodulatorPreThread::terminate() {
|
|||||||
iqInputQueue->push(inp);
|
iqInputQueue->push(inp);
|
||||||
DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_NULL);
|
DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_NULL);
|
||||||
workerQueue->push(command);
|
workerQueue->push(command);
|
||||||
|
|
||||||
workerThread->terminate();
|
workerThread->terminate();
|
||||||
|
workerThread->isTerminated(1000);
|
||||||
|
|
||||||
t_Worker->join();
|
t_Worker->join();
|
||||||
delete t_Worker;
|
delete t_Worker;
|
||||||
|
t_Worker = nullptr;
|
||||||
|
|
||||||
delete workerThread;
|
delete workerThread;
|
||||||
|
workerThread = nullptr;
|
||||||
|
|
||||||
delete workerResults;
|
delete workerResults;
|
||||||
|
workerResults = nullptr;
|
||||||
|
|
||||||
delete workerQueue;
|
delete workerQueue;
|
||||||
|
workerQueue = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Modem *DemodulatorPreThread::getModem() {
|
Modem *DemodulatorPreThread::getModem() {
|
||||||
|
@ -79,5 +79,4 @@ protected:
|
|||||||
|
|
||||||
DemodulatorThreadInputQueue* iqInputQueue;
|
DemodulatorThreadInputQueue* iqInputQueue;
|
||||||
DemodulatorThreadPostInputQueue* iqOutputQueue;
|
DemodulatorThreadPostInputQueue* iqOutputQueue;
|
||||||
DemodulatorThreadCommandQueue* threadQueueNotify;
|
|
||||||
};
|
};
|
||||||
|
@ -69,8 +69,7 @@ void DemodulatorThread::run() {
|
|||||||
iqInputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getInputQueue("IQDataInput"));
|
iqInputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getInputQueue("IQDataInput"));
|
||||||
audioOutputQueue = static_cast<AudioThreadInputQueue*>(getOutputQueue("AudioDataOutput"));
|
audioOutputQueue = static_cast<AudioThreadInputQueue*>(getOutputQueue("AudioDataOutput"));
|
||||||
threadQueueControl = static_cast<DemodulatorThreadControlCommandQueue *>(getInputQueue("ControlQueue"));
|
threadQueueControl = static_cast<DemodulatorThreadControlCommandQueue *>(getInputQueue("ControlQueue"));
|
||||||
threadQueueNotify = static_cast<DemodulatorThreadCommandQueue*>(getOutputQueue("NotifyQueue"));
|
|
||||||
|
|
||||||
ModemIQData modemData;
|
ModemIQData modemData;
|
||||||
|
|
||||||
while (!stopping) {
|
while (!stopping) {
|
||||||
@ -290,13 +289,6 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
outputBuffers.purge();
|
outputBuffers.purge();
|
||||||
|
|
||||||
//Guard the cleanup of audioVisOutputQueue properly.
|
|
||||||
std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue);
|
|
||||||
|
|
||||||
DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED);
|
|
||||||
tCmd.context = this;
|
|
||||||
threadQueueNotify->push(tCmd);
|
|
||||||
|
|
||||||
// std::cout << "Demodulator thread done." << std::endl;
|
// std::cout << "Demodulator thread done." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@ protected:
|
|||||||
AudioThreadInputQueue *audioOutputQueue = nullptr;
|
AudioThreadInputQueue *audioOutputQueue = nullptr;
|
||||||
DemodulatorThreadOutputQueue* audioVisOutputQueue = nullptr;
|
DemodulatorThreadOutputQueue* audioVisOutputQueue = nullptr;
|
||||||
DemodulatorThreadControlCommandQueue *threadQueueControl = nullptr;
|
DemodulatorThreadControlCommandQueue *threadQueueControl = nullptr;
|
||||||
DemodulatorThreadCommandQueue* threadQueueNotify = nullptr;
|
|
||||||
|
|
||||||
//protects the audioVisOutputQueue dynamic binding change at runtime (in DemodulatorMgr)
|
//protects the audioVisOutputQueue dynamic binding change at runtime (in DemodulatorMgr)
|
||||||
mutable std::mutex m_mutexAudioVisOutputQueue;
|
mutable std::mutex m_mutexAudioVisOutputQueue;
|
||||||
|
@ -400,7 +400,6 @@ void GLFont::loadFontOnce() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//2) then load from memory
|
//2) then load from memory
|
||||||
lodepng::State state;
|
|
||||||
unsigned error = lodepng::decode(image, imgWidth, imgHeight, raw_image, png_size);
|
unsigned error = lodepng::decode(image, imgWidth, imgHeight, raw_image, png_size);
|
||||||
|
|
||||||
delete[] raw_image;
|
delete[] raw_image;
|
||||||
|
@ -492,7 +492,7 @@ void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
|
|||||||
void WaterfallCanvas::updateHoverState() {
|
void WaterfallCanvas::updateHoverState() {
|
||||||
long long freqPos = getFrequencyAt(mouseTracker.getMouseX());
|
long long freqPos = getFrequencyAt(mouseTracker.getMouseX());
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> *demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000);
|
std::vector<DemodulatorInstance *> demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000);
|
||||||
|
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(NULL);
|
wxGetApp().getDemodMgr().setActiveDemodulator(NULL);
|
||||||
|
|
||||||
@ -505,13 +505,13 @@ void WaterfallCanvas::updateHoverState() {
|
|||||||
} else {
|
} else {
|
||||||
setStatusText("Click and drag to set the current demodulator range.");
|
setStatusText("Click and drag to set the current demodulator range.");
|
||||||
}
|
}
|
||||||
} else if (demodsHover->size() && !shiftDown) {
|
} else if (demodsHover.size() && !shiftDown) {
|
||||||
long near_dist = getBandwidth();
|
long near_dist = getBandwidth();
|
||||||
|
|
||||||
DemodulatorInstance *activeDemodulator = NULL;
|
DemodulatorInstance *activeDemodulator = NULL;
|
||||||
|
|
||||||
for (int i = 0, iMax = demodsHover->size(); i < iMax; i++) {
|
for (int i = 0, iMax = demodsHover.size(); i < iMax; i++) {
|
||||||
DemodulatorInstance *demod = (*demodsHover)[i];
|
DemodulatorInstance *demod = demodsHover[i];
|
||||||
long long freqDiff = demod->getFrequency() - freqPos;
|
long long freqDiff = demod->getFrequency() - freqPos;
|
||||||
long halfBw = (demod->getBandwidth() / 2);
|
long halfBw = (demod->getBandwidth() / 2);
|
||||||
long long currentBw = getBandwidth();
|
long long currentBw = getBandwidth();
|
||||||
@ -574,18 +574,18 @@ void WaterfallCanvas::updateHoverState() {
|
|||||||
mouseTracker.setHorizDragLock(false);
|
mouseTracker.setHorizDragLock(false);
|
||||||
setStatusText("Click and drag to change demodulator frequency; SPACE or numeric key for direct input. [, ] to nudge, M for mute, D to delete, C to center, E to edit label.");
|
setStatusText("Click and drag to change demodulator frequency; SPACE or numeric key for direct input. [, ] to nudge, M for mute, D to delete, C to center, E to edit label.");
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
SetCursor(wxCURSOR_CROSS);
|
SetCursor(wxCURSOR_CROSS);
|
||||||
nextDragState = WF_DRAG_NONE;
|
nextDragState = WF_DRAG_NONE;
|
||||||
if (shiftDown) {
|
if (shiftDown) {
|
||||||
setStatusText("Click to create a new demodulator or hold ALT to drag range, SPACE or numeric key for direct center frequency input.");
|
setStatusText("Click to create a new demodulator or hold ALT to drag range, SPACE or numeric key for direct center frequency input.");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
setStatusText(
|
setStatusText(
|
||||||
"Click to set active demodulator frequency or hold ALT to drag range; hold SHIFT to create new. Right drag or wheel to Zoom. Arrow keys to navigate/zoom, C to center.");
|
"Click to set active demodulator frequency or hold ALT to drag range; hold SHIFT to create new. Right drag or wheel to Zoom. Arrow keys to navigate/zoom, C to center.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete demodsHover;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
||||||
|
Loading…
Reference in New Issue
Block a user