mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-09-28 08:16:37 -04:00
Move code out of frame, proper thread termination
This commit is contained in:
parent
ac20bc1e84
commit
cae1855fc5
@ -26,7 +26,7 @@ EVT_IDLE(AppFrame::OnIdle)
|
|||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
AppFrame::AppFrame() :
|
AppFrame::AppFrame() :
|
||||||
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")), frequency(DEFAULT_FREQ) {
|
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")) {
|
||||||
|
|
||||||
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
@ -58,26 +58,6 @@ AppFrame::AppFrame() :
|
|||||||
Centre();
|
Centre();
|
||||||
Show();
|
Show();
|
||||||
|
|
||||||
audioInputQueue = new AudioThreadInputQueue;
|
|
||||||
audioThread = new AudioThread(audioInputQueue);
|
|
||||||
|
|
||||||
threadAudio = new std::thread(&AudioThread::threadMain, audioThread);
|
|
||||||
|
|
||||||
demodulatorTest = demodMgr.newThread();
|
|
||||||
demodulatorTest->params.audioInputQueue = audioInputQueue;
|
|
||||||
demodulatorTest->init();
|
|
||||||
|
|
||||||
audioVisualQueue = new DemodulatorThreadOutputQueue();
|
|
||||||
demodulatorTest->setVisualOutputQueue(audioVisualQueue);
|
|
||||||
|
|
||||||
threadCmdQueueSDR = new SDRThreadCommandQueue;
|
|
||||||
sdrThread = new SDRThread(threadCmdQueueSDR);
|
|
||||||
sdrThread->bindDemodulator(demodulatorTest);
|
|
||||||
|
|
||||||
iqVisualQueue = new SDRThreadIQDataQueue;
|
|
||||||
sdrThread->setIQVisualQueue(iqVisualQueue);
|
|
||||||
|
|
||||||
threadSDR = new std::thread(&SDRThread::threadMain, sdrThread);
|
|
||||||
|
|
||||||
// static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
|
// static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
|
||||||
// wxLogStatus("Double-buffered display %s supported", wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
|
// wxLogStatus("Double-buffered display %s supported", wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
|
||||||
@ -87,9 +67,7 @@ AppFrame::AppFrame() :
|
|||||||
AppFrame::~AppFrame() {
|
AppFrame::~AppFrame() {
|
||||||
|
|
||||||
// delete t_SDR;
|
// delete t_SDR;
|
||||||
delete audioInputQueue;
|
|
||||||
delete audioThread;
|
|
||||||
delete threadCmdQueueSDR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppFrame::OnClose(wxCommandEvent& WXUNUSED(event)) {
|
void AppFrame::OnClose(wxCommandEvent& WXUNUSED(event)) {
|
||||||
@ -109,9 +87,9 @@ void AppFrame::OnThread(wxCommandEvent& event) {
|
|||||||
void AppFrame::OnIdle(wxIdleEvent& event) {
|
void AppFrame::OnIdle(wxIdleEvent& event) {
|
||||||
bool work_done = false;
|
bool work_done = false;
|
||||||
|
|
||||||
if (!iqVisualQueue->empty()) {
|
if (!wxGetApp().getIQVisualQueue()->empty()) {
|
||||||
SDRThreadIQData iqData;
|
SDRThreadIQData iqData;
|
||||||
iqVisualQueue->pop(iqData);
|
wxGetApp().getIQVisualQueue()->pop(iqData);
|
||||||
|
|
||||||
if (iqData.data.size()) {
|
if (iqData.data.size()) {
|
||||||
spectrumCanvas->setData(&iqData.data);
|
spectrumCanvas->setData(&iqData.data);
|
||||||
@ -122,9 +100,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
work_done = true;
|
work_done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!audioVisualQueue->empty()) {
|
if (!wxGetApp().getAudioVisualQueue()->empty()) {
|
||||||
AudioThreadInput demodAudioData;
|
AudioThreadInput demodAudioData;
|
||||||
audioVisualQueue->pop(demodAudioData);
|
wxGetApp().getAudioVisualQueue()->pop(demodAudioData);
|
||||||
if (demodAudioData.data.size()) {
|
if (demodAudioData.data.size()) {
|
||||||
|
|
||||||
if (scopeCanvas->waveform_points.size() != demodAudioData.data.size() * 2) {
|
if (scopeCanvas->waveform_points.size() != demodAudioData.data.size() * 2) {
|
||||||
@ -146,14 +124,3 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
event.Skip();
|
event.Skip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppFrame::setFrequency(unsigned int freq) {
|
|
||||||
frequency = freq;
|
|
||||||
SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_TUNE);
|
|
||||||
command.int_value = freq;
|
|
||||||
threadCmdQueueSDR->push(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
int AppFrame::getFrequency() {
|
|
||||||
return frequency;
|
|
||||||
}
|
|
||||||
|
@ -2,14 +2,11 @@
|
|||||||
|
|
||||||
#include "wx/frame.h"
|
#include "wx/frame.h"
|
||||||
#include "PrimaryGLContext.h"
|
#include "PrimaryGLContext.h"
|
||||||
#include "SDRThread.h"
|
|
||||||
#include "AudioThread.h"
|
|
||||||
#include "DemodulatorMgr.h"
|
|
||||||
|
|
||||||
#include "ScopeCanvas.h"
|
#include "ScopeCanvas.h"
|
||||||
#include "SpectrumCanvas.h"
|
#include "SpectrumCanvas.h"
|
||||||
#include "WaterfallCanvas.h"
|
#include "WaterfallCanvas.h"
|
||||||
#include "ThreadQueue.h"
|
|
||||||
|
|
||||||
// Define a new frame type
|
// Define a new frame type
|
||||||
class AppFrame: public wxFrame {
|
class AppFrame: public wxFrame {
|
||||||
@ -19,8 +16,6 @@ public:
|
|||||||
void OnThread(wxCommandEvent& event);
|
void OnThread(wxCommandEvent& event);
|
||||||
void OnEventInput(wxThreadEvent& event);
|
void OnEventInput(wxThreadEvent& event);
|
||||||
|
|
||||||
void setFrequency(unsigned int freq);
|
|
||||||
int getFrequency();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnClose(wxCommandEvent& event);
|
void OnClose(wxCommandEvent& event);
|
||||||
@ -31,23 +26,6 @@ private:
|
|||||||
SpectrumCanvas *spectrumCanvas;
|
SpectrumCanvas *spectrumCanvas;
|
||||||
WaterfallCanvas *waterfallCanvas;
|
WaterfallCanvas *waterfallCanvas;
|
||||||
|
|
||||||
DemodulatorMgr demodMgr;
|
|
||||||
|
|
||||||
wxCriticalSection m_pThreadCS;
|
|
||||||
unsigned int frequency;
|
|
||||||
|
|
||||||
DemodulatorInstance *demodulatorTest;
|
|
||||||
|
|
||||||
AudioThreadInputQueue *audioInputQueue;
|
|
||||||
AudioThread *audioThread;
|
|
||||||
|
|
||||||
SDRThread *sdrThread;
|
|
||||||
SDRThreadCommandQueue* threadCmdQueueSDR;
|
|
||||||
SDRThreadIQDataQueue* iqVisualQueue;
|
|
||||||
DemodulatorThreadOutputQueue* audioVisualQueue;
|
|
||||||
|
|
||||||
std::thread *threadAudio;
|
|
||||||
std::thread *threadSDR;
|
|
||||||
|
|
||||||
// event table
|
// event table
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
|
@ -19,22 +19,56 @@ bool CubicSDR::OnInit() {
|
|||||||
if (!wxApp::OnInit())
|
if (!wxApp::OnInit())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
frequency = DEFAULT_FREQ;
|
||||||
|
|
||||||
|
audioInputQueue = new AudioThreadInputQueue;
|
||||||
|
audioThread = new AudioThread(audioInputQueue);
|
||||||
|
|
||||||
|
threadAudio = new std::thread(&AudioThread::threadMain, audioThread);
|
||||||
|
|
||||||
|
demodulatorTest = demodMgr.newThread();
|
||||||
|
demodulatorTest->params.audioInputQueue = audioInputQueue;
|
||||||
|
demodulatorTest->init();
|
||||||
|
|
||||||
|
audioVisualQueue = new DemodulatorThreadOutputQueue();
|
||||||
|
demodulatorTest->setVisualOutputQueue(audioVisualQueue);
|
||||||
|
|
||||||
|
threadCmdQueueSDR = new SDRThreadCommandQueue;
|
||||||
|
sdrThread = new SDRThread(threadCmdQueueSDR);
|
||||||
|
sdrThread->bindDemodulator(demodulatorTest);
|
||||||
|
|
||||||
|
iqVisualQueue = new SDRThreadIQDataQueue;
|
||||||
|
sdrThread->setIQVisualQueue(iqVisualQueue);
|
||||||
|
|
||||||
|
threadSDR = new std::thread(&SDRThread::threadMain, sdrThread);
|
||||||
|
|
||||||
AppFrame *appframe = new AppFrame();
|
AppFrame *appframe = new AppFrame();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CubicSDR::OnExit() {
|
int CubicSDR::OnExit() {
|
||||||
delete m_glContext;
|
std::cout << "Terminating SDR thread.." << std::endl;
|
||||||
|
sdrThread->terminate();
|
||||||
|
threadSDR->join();
|
||||||
|
|
||||||
// while (1) {
|
delete sdrThread;
|
||||||
// { wxCriticalSectionLocker enter(m_pThreadCS);
|
delete threadSDR;
|
||||||
// if (!m_pThread)
|
|
||||||
// break;
|
demodMgr.terminateAll();
|
||||||
// }
|
|
||||||
// // wait for thread completion
|
audioThread->terminate();
|
||||||
// wxThread::This()->Sleep(1);
|
threadAudio->join();
|
||||||
// }
|
|
||||||
|
delete audioThread;
|
||||||
|
delete threadAudio;
|
||||||
|
|
||||||
|
delete audioInputQueue;
|
||||||
|
delete threadCmdQueueSDR;
|
||||||
|
|
||||||
|
delete iqVisualQueue;
|
||||||
|
delete audioVisualQueue;
|
||||||
|
delete m_glContext;
|
||||||
|
|
||||||
return wxApp::OnExit();
|
return wxApp::OnExit();
|
||||||
}
|
}
|
||||||
@ -51,3 +85,13 @@ PrimaryGLContext& CubicSDR::GetContext(wxGLCanvas *canvas) {
|
|||||||
return *glContext;
|
return *glContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CubicSDR::setFrequency(unsigned int freq) {
|
||||||
|
frequency = freq;
|
||||||
|
SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_TUNE);
|
||||||
|
command.int_value = freq;
|
||||||
|
threadCmdQueueSDR->push(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CubicSDR::getFrequency() {
|
||||||
|
return frequency;
|
||||||
|
}
|
||||||
|
@ -4,9 +4,16 @@
|
|||||||
//WX_GL_MAJOR_VERSION 3
|
//WX_GL_MAJOR_VERSION 3
|
||||||
//WX_GL_MINOR_VERSION 2
|
//WX_GL_MINOR_VERSION 2
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "wx/glcanvas.h"
|
#include "wx/glcanvas.h"
|
||||||
#include "PrimaryGLContext.h"
|
#include "PrimaryGLContext.h"
|
||||||
|
|
||||||
|
#include "ThreadQueue.h"
|
||||||
|
#include "SDRThread.h"
|
||||||
|
#include "AudioThread.h"
|
||||||
|
#include "DemodulatorMgr.h"
|
||||||
|
|
||||||
class CubicSDR: public wxApp {
|
class CubicSDR: public wxApp {
|
||||||
public:
|
public:
|
||||||
CubicSDR() {
|
CubicSDR() {
|
||||||
@ -18,9 +25,36 @@ public:
|
|||||||
virtual bool OnInit();
|
virtual bool OnInit();
|
||||||
virtual int OnExit();
|
virtual int OnExit();
|
||||||
|
|
||||||
|
void setFrequency(unsigned int freq);
|
||||||
|
int getFrequency();
|
||||||
|
|
||||||
|
DemodulatorThreadOutputQueue* getAudioVisualQueue() {
|
||||||
|
return audioVisualQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDRThreadIQDataQueue* getIQVisualQueue() {
|
||||||
|
return iqVisualQueue;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PrimaryGLContext *m_glContext;
|
PrimaryGLContext *m_glContext;
|
||||||
|
|
||||||
|
DemodulatorMgr demodMgr;
|
||||||
|
|
||||||
|
unsigned int frequency;
|
||||||
|
|
||||||
|
DemodulatorInstance *demodulatorTest;
|
||||||
|
|
||||||
|
AudioThreadInputQueue *audioInputQueue;
|
||||||
|
AudioThread *audioThread;
|
||||||
|
|
||||||
|
SDRThread *sdrThread;
|
||||||
|
SDRThreadCommandQueue* threadCmdQueueSDR;
|
||||||
|
SDRThreadIQDataQueue* iqVisualQueue;
|
||||||
|
DemodulatorThreadOutputQueue* audioVisualQueue;
|
||||||
|
|
||||||
|
std::thread *threadAudio;
|
||||||
|
std::thread *threadSDR;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_APP(CubicSDR)
|
DECLARE_APP(CubicSDR)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue) :
|
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue) :
|
||||||
inputQueue(inputQueue), stream(NULL) {
|
inputQueue(inputQueue), stream(NULL), terminated(false) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,11 +41,6 @@ void AudioThread::threadMain() {
|
|||||||
|
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
|
|
||||||
// err = Pa_OpenStream(&stream, NULL, &outputParameters, AUDIO_FREQUENCY,
|
|
||||||
// paFramesPerBufferUnspecified,
|
|
||||||
// paPrimeOutputBuffersUsingStreamCallback | paClipOff, &audioCallback,
|
|
||||||
// this);
|
|
||||||
|
|
||||||
err = Pa_OpenStream(&stream, NULL, &outputParameters, AUDIO_FREQUENCY,
|
err = Pa_OpenStream(&stream, NULL, &outputParameters, AUDIO_FREQUENCY,
|
||||||
paFramesPerBufferUnspecified, paClipOff, NULL, NULL);
|
paFramesPerBufferUnspecified, paClipOff, NULL, NULL);
|
||||||
|
|
||||||
@ -56,101 +51,18 @@ void AudioThread::threadMain() {
|
|||||||
std::cout << "\tPortAudio error: " << Pa_GetErrorText(err) << std::endl;
|
std::cout << "\tPortAudio error: " << Pa_GetErrorText(err) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (!terminated) {
|
||||||
AudioThreadInput inp;
|
AudioThreadInput inp;
|
||||||
inputQueue->pop(inp);
|
inputQueue->pop(inp);
|
||||||
Pa_WriteStream(stream, &inp.data[0], inp.data.size()/2);
|
if (inp.data.size()) {
|
||||||
|
Pa_WriteStream(stream, &inp.data[0], inp.data.size()/2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void AudioThread::terminate() {
|
||||||
#ifdef WIN32
|
std::cout << "Terminating audio thread.." << std::endl;
|
||||||
#include <algorithm>
|
terminated = true;
|
||||||
#include <functional>
|
AudioThreadInput endCond; // push an empty input to bump the queue
|
||||||
#include <cctype>
|
inputQueue->push(endCond);
|
||||||
#include <locale>
|
}
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
// trim from start
|
|
||||||
static inline std::wstring &wltrim(std::wstring &s) {
|
|
||||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trim from end
|
|
||||||
static inline std::wstring &wrtrim(std::wstring &s) {
|
|
||||||
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trim from both ends
|
|
||||||
static inline std::wstring &wtrim(std::wstring &s) {
|
|
||||||
return wltrim(wrtrim(s));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//wxDEFINE_EVENT(wxEVT_COMMAND_AudioThread_INPUT, wxThreadEvent);
|
|
||||||
|
|
||||||
AudioThread::AudioThread(AudioThreadQueue* pQueue, int id) :
|
|
||||||
wxThread(wxTHREAD_DETACHED), m_pQueue(pQueue), m_ID(id), audio_queue_ptr(0), stream(NULL) {
|
|
||||||
|
|
||||||
}
|
|
||||||
AudioThread::~AudioThread() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
wxThread::ExitCode AudioThread::Entry() {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//#ifdef WIN32
|
|
||||||
// wchar_t dev_str[255];
|
|
||||||
// memset(dev_str, 0, sizeof(wchar_t) * 255);
|
|
||||||
// std::wstring env_name(L"PA_RECOMMENDED_OUTPUT_DEVICE");
|
|
||||||
// GetEnvironmentVariable(wtrim(env_name).c_str(), dev_str, 255);
|
|
||||||
// std::wistringstream env_result(dev_str);
|
|
||||||
//
|
|
||||||
// if (!env_result.eof()) {
|
|
||||||
// int env_dev = -1;
|
|
||||||
// env_result >> env_dev;
|
|
||||||
//
|
|
||||||
// if (env_result.eof()) { // read everything, was all a number
|
|
||||||
// if (env_dev >= 0) {
|
|
||||||
// std::cout << "Using preferred PortAudio device PA_RECOMMENDED_OUTPUT_DEVICE=" << env_dev << std::endl;
|
|
||||||
// preferred_device = env_dev;
|
|
||||||
// } else {
|
|
||||||
// std::cout << "Environment variable PA_RECOMMENDED_OUTPUT_DEVICE not set, using PortAudio defaults." << std::endl;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// std::cout << "Environment variable PA_RECOMMENDED_OUTPUT_DEVICE didn't evaluate to a number, using PortAudio defaults." << std::endl;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
while (!TestDestroy()) {
|
|
||||||
|
|
||||||
if (m_pQueue->stackSize()) {
|
|
||||||
|
|
||||||
while (m_pQueue->stackSize()) {
|
|
||||||
AudioThreadTask task = m_pQueue->pop(); // pop a task from the queue. this will block the worker thread if queue is empty
|
|
||||||
switch (task.m_cmd) {
|
|
||||||
case AudioThreadTask::AUDIO_THREAD_DATA:
|
|
||||||
if (!TestDestroy()) {
|
|
||||||
audio_queue.push(task.data->data);
|
|
||||||
}
|
|
||||||
delete task.data;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this->Yield();
|
|
||||||
this->Sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << std::endl << "Audio Thread Done." << std::endl << std::endl;
|
|
||||||
|
|
||||||
return (wxThread::ExitCode) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <atomic>
|
||||||
#include "wx/wxprec.h"
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
@ -28,14 +29,15 @@ typedef ThreadQueue<AudioThreadInput> AudioThreadInputQueue;
|
|||||||
class AudioThread {
|
class AudioThread {
|
||||||
public:
|
public:
|
||||||
AudioThread(AudioThreadInputQueue *inputQueue);
|
AudioThread(AudioThreadInputQueue *inputQueue);
|
||||||
|
|
||||||
~AudioThread();
|
~AudioThread();
|
||||||
|
|
||||||
void threadMain();
|
void threadMain();
|
||||||
|
void terminate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AudioThreadInputQueue *inputQueue;
|
AudioThreadInputQueue *inputQueue;
|
||||||
PaStreamParameters outputParameters;
|
PaStreamParameters outputParameters;
|
||||||
PaStream *stream;
|
PaStream *stream;
|
||||||
|
std::atomic<bool> terminated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,16 +3,23 @@
|
|||||||
DemodulatorInstance::DemodulatorInstance() :
|
DemodulatorInstance::DemodulatorInstance() :
|
||||||
t_Demod(NULL), threadQueueDemod(NULL), demodulatorThread(NULL) {
|
t_Demod(NULL), threadQueueDemod(NULL), demodulatorThread(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DemodulatorInstance::~DemodulatorInstance() {
|
||||||
|
delete threadQueueDemod;
|
||||||
|
delete demodulatorThread;
|
||||||
|
delete t_Demod;
|
||||||
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
|
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
|
||||||
demodulatorThread->setVisualOutputQueue(tQueue);
|
demodulatorThread->setVisualOutputQueue(tQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::init() {
|
void DemodulatorInstance::init() {
|
||||||
if (threadQueueDemod) {
|
|
||||||
delete threadQueueDemod;
|
|
||||||
}
|
|
||||||
if (demodulatorThread) {
|
if (demodulatorThread) {
|
||||||
|
terminate();
|
||||||
|
delete threadQueueDemod;
|
||||||
delete demodulatorThread;
|
delete demodulatorThread;
|
||||||
|
delete t_Demod;
|
||||||
}
|
}
|
||||||
|
|
||||||
threadQueueDemod = new DemodulatorThreadInputQueue;
|
threadQueueDemod = new DemodulatorThreadInputQueue;
|
||||||
@ -21,16 +28,17 @@ void DemodulatorInstance::init() {
|
|||||||
t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread);
|
t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DemodulatorInstance::terminate() {
|
||||||
|
demodulatorThread->terminate();
|
||||||
|
t_Demod->join();
|
||||||
|
}
|
||||||
|
|
||||||
DemodulatorMgr::DemodulatorMgr() {
|
DemodulatorMgr::DemodulatorMgr() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorMgr::~DemodulatorMgr() {
|
DemodulatorMgr::~DemodulatorMgr() {
|
||||||
while (demods.size()) {
|
terminateAll();
|
||||||
DemodulatorInstance *d = demods.back();
|
|
||||||
demods.pop_back();
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::newThread() {
|
DemodulatorInstance *DemodulatorMgr::newThread() {
|
||||||
@ -38,3 +46,12 @@ DemodulatorInstance *DemodulatorMgr::newThread() {
|
|||||||
demods.push_back(newDemod);
|
demods.push_back(newDemod);
|
||||||
return newDemod;
|
return newDemod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DemodulatorMgr::terminateAll() {
|
||||||
|
while (demods.size()) {
|
||||||
|
DemodulatorInstance *d = demods.back();
|
||||||
|
demods.pop_back();
|
||||||
|
d->terminate();
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,8 +14,10 @@ public:
|
|||||||
DemodulatorThreadParameters params;
|
DemodulatorThreadParameters params;
|
||||||
|
|
||||||
DemodulatorInstance();
|
DemodulatorInstance();
|
||||||
|
~DemodulatorInstance();
|
||||||
void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue);
|
void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue);
|
||||||
void init();
|
void init();
|
||||||
|
void terminate();
|
||||||
};
|
};
|
||||||
|
|
||||||
class DemodulatorMgr {
|
class DemodulatorMgr {
|
||||||
@ -25,6 +27,7 @@ public:
|
|||||||
|
|
||||||
DemodulatorInstance *newThread();
|
DemodulatorInstance *newThread();
|
||||||
|
|
||||||
|
void terminateAll();
|
||||||
private:
|
private:
|
||||||
std::vector<DemodulatorInstance *> demods;
|
std::vector<DemodulatorInstance *> demods;
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue, DemodulatorThreadParameters *params_in) :
|
DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue, DemodulatorThreadParameters *params_in) :
|
||||||
inputQueue(pQueue), visOutQueue(NULL) {
|
inputQueue(pQueue), visOutQueue(NULL), terminated(false) {
|
||||||
|
|
||||||
DemodulatorThreadParameters defaultParams;
|
DemodulatorThreadParameters defaultParams;
|
||||||
if (!params_in) {
|
if (!params_in) {
|
||||||
@ -55,7 +55,7 @@ DemodulatorThread::~DemodulatorThread() {
|
|||||||
|
|
||||||
void DemodulatorThread::threadMain() {
|
void DemodulatorThread::threadMain() {
|
||||||
|
|
||||||
while (1) {
|
while (!terminated) {
|
||||||
DemodulatorThreadIQData inp;
|
DemodulatorThreadIQData inp;
|
||||||
inputQueue->pop(inp);
|
inputQueue->pop(inp);
|
||||||
|
|
||||||
@ -143,3 +143,9 @@ void DemodulatorThread::threadMain() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DemodulatorThread::terminate() {
|
||||||
|
std::cout << "Terminating demodulator thread.." << std::endl;
|
||||||
|
terminated = true;
|
||||||
|
DemodulatorThreadIQData inp; // push dummy to nudge queue
|
||||||
|
inputQueue->push(inp);
|
||||||
|
}
|
||||||
|
@ -101,6 +101,8 @@ public:
|
|||||||
visOutQueue->set_max_num_items(1);
|
visOutQueue->set_max_num_items(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void terminate();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DemodulatorThreadInputQueue* inputQueue;
|
DemodulatorThreadInputQueue* inputQueue;
|
||||||
DemodulatorThreadOutputQueue* visOutQueue;
|
DemodulatorThreadOutputQueue* visOutQueue;
|
||||||
@ -119,4 +121,6 @@ protected:
|
|||||||
|
|
||||||
DemodulatorThreadParameters params;
|
DemodulatorThreadParameters params;
|
||||||
freqdem fdem;
|
freqdem fdem;
|
||||||
|
|
||||||
|
std::atomic<bool> terminated;
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "CubicSDR.h"
|
#include "CubicSDR.h"
|
||||||
|
|
||||||
SDRThread::SDRThread(SDRThreadCommandQueue* pQueue) :
|
SDRThread::SDRThread(SDRThreadCommandQueue* pQueue) :
|
||||||
m_pQueue(pQueue), iqDataOutQueue(NULL), iqVisualQueue(NULL) {
|
m_pQueue(pQueue), iqDataOutQueue(NULL), iqVisualQueue(NULL), terminated(false) {
|
||||||
dev = NULL;
|
dev = NULL;
|
||||||
sample_rate = SRATE;
|
sample_rate = SRATE;
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ void SDRThread::threadMain() {
|
|||||||
double seconds = 0.0;
|
double seconds = 0.0;
|
||||||
|
|
||||||
std::cout << "Sampling..";
|
std::cout << "Sampling..";
|
||||||
while (1) {
|
while (!terminated) {
|
||||||
if (!m_pQueue->empty()) {
|
if (!m_pQueue->empty()) {
|
||||||
bool freq_changed = false;
|
bool freq_changed = false;
|
||||||
float new_freq;
|
float new_freq;
|
||||||
@ -186,3 +186,6 @@ void SDRThread::threadMain() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDRThread::terminate() {
|
||||||
|
terminated = true;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include "wx/wxprec.h"
|
#include "wx/wxprec.h"
|
||||||
#include "rtl-sdr.h"
|
#include "rtl-sdr.h"
|
||||||
|
|
||||||
@ -19,7 +21,7 @@ public:
|
|||||||
SDR_THREAD_CMD_TUNE
|
SDR_THREAD_CMD_TUNE
|
||||||
};
|
};
|
||||||
|
|
||||||
SDRThreadCommand() : cmd(cmd), int_value(SDR_THREAD_CMD_NULL){
|
SDRThreadCommand() : cmd(cmd), int_value(SDR_THREAD_CMD_NULL) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +79,8 @@ public:
|
|||||||
iqVisualQueue = iqVisQueue;
|
iqVisualQueue = iqVisQueue;
|
||||||
iqVisualQueue->set_max_num_items(1);
|
iqVisualQueue->set_max_num_items(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void terminate();
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
uint32_t sample_rate;
|
uint32_t sample_rate;
|
||||||
@ -85,4 +89,5 @@ protected:
|
|||||||
SDRThreadIQDataQueue* iqVisualQueue;
|
SDRThreadIQDataQueue* iqVisualQueue;
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> demodulators;
|
std::vector<DemodulatorInstance *> demodulators;
|
||||||
|
std::atomic<bool> terminated;
|
||||||
};
|
};
|
||||||
|
@ -54,14 +54,14 @@ void ScopeCanvas::OnKeyDown(wxKeyEvent& event) {
|
|||||||
unsigned int freq;
|
unsigned int freq;
|
||||||
switch (event.GetKeyCode()) {
|
switch (event.GetKeyCode()) {
|
||||||
case WXK_RIGHT:
|
case WXK_RIGHT:
|
||||||
freq = ((AppFrame*) parent)->getFrequency();
|
freq = wxGetApp().getFrequency();
|
||||||
freq += 100000;
|
freq += 100000;
|
||||||
((AppFrame*) parent)->setFrequency(freq);
|
wxGetApp().setFrequency(freq);
|
||||||
break;
|
break;
|
||||||
case WXK_LEFT:
|
case WXK_LEFT:
|
||||||
freq = ((AppFrame*) parent)->getFrequency();
|
wxGetApp().getFrequency();
|
||||||
freq -= 100000;
|
freq -= 100000;
|
||||||
((AppFrame*) parent)->setFrequency(freq);
|
wxGetApp().setFrequency(freq);
|
||||||
break;
|
break;
|
||||||
case WXK_DOWN:
|
case WXK_DOWN:
|
||||||
break;
|
break;
|
||||||
|
@ -60,14 +60,14 @@ void SpectrumCanvas::OnKeyDown(wxKeyEvent& event) {
|
|||||||
unsigned int freq;
|
unsigned int freq;
|
||||||
switch (event.GetKeyCode()) {
|
switch (event.GetKeyCode()) {
|
||||||
case WXK_RIGHT:
|
case WXK_RIGHT:
|
||||||
freq = ((AppFrame*) parent)->getFrequency();
|
freq = wxGetApp().getFrequency();
|
||||||
freq += 100000;
|
freq += 100000;
|
||||||
((AppFrame*) parent)->setFrequency(freq);
|
wxGetApp().setFrequency(freq);
|
||||||
break;
|
break;
|
||||||
case WXK_LEFT:
|
case WXK_LEFT:
|
||||||
freq = ((AppFrame*) parent)->getFrequency();
|
freq = wxGetApp().getFrequency();
|
||||||
freq -= 100000;
|
freq -= 100000;
|
||||||
((AppFrame*) parent)->setFrequency(freq);
|
wxGetApp().setFrequency(freq);
|
||||||
break;
|
break;
|
||||||
case WXK_DOWN:
|
case WXK_DOWN:
|
||||||
break;
|
break;
|
||||||
|
@ -60,14 +60,14 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
|
|||||||
unsigned int freq;
|
unsigned int freq;
|
||||||
switch (event.GetKeyCode()) {
|
switch (event.GetKeyCode()) {
|
||||||
case WXK_RIGHT:
|
case WXK_RIGHT:
|
||||||
freq = ((AppFrame*) parent)->getFrequency();
|
freq = wxGetApp().getFrequency();
|
||||||
freq += 100000;
|
freq += 100000;
|
||||||
((AppFrame*) parent)->setFrequency(freq);
|
wxGetApp().setFrequency(freq);
|
||||||
break;
|
break;
|
||||||
case WXK_LEFT:
|
case WXK_LEFT:
|
||||||
freq = ((AppFrame*) parent)->getFrequency();
|
wxGetApp().getFrequency();
|
||||||
freq -= 100000;
|
freq -= 100000;
|
||||||
((AppFrame*) parent)->setFrequency(freq);
|
wxGetApp().setFrequency(freq);
|
||||||
break;
|
break;
|
||||||
case WXK_DOWN:
|
case WXK_DOWN:
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user