From 1a53e454ab6aed1b8fd04f958621c734f5a235d8 Mon Sep 17 00:00:00 2001 From: vsonnier Date: Sun, 8 Jan 2017 12:46:31 +0100 Subject: [PATCH] FIX: missing demod displays due to wrong input/queue setups order --- src/AppFrame.cpp | 24 ++++++++++++++++++------ src/CubicSDR.cpp | 24 +++++++++++++++++------- src/IOThread.cpp | 6 +++++- src/IOThread.h | 6 +++++- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 9563e33..4c47dce 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -281,7 +281,7 @@ AppFrame::AppFrame() : // vbox->Add(demodTray, 12, wxEXPAND | wxALL, 0); // vbox->AddSpacer(1); - bookmarkSplitter = new wxSplitterWindow( mainSplitter, wxID_BM_SPLITTER, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH | wxSP_LIVE_UPDATE ); + bookmarkSplitter = new wxSplitterWindow(mainSplitter, wxID_BM_SPLITTER, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH | wxSP_LIVE_UPDATE ); bookmarkSplitter->SetMinimumPaneSize(1); bookmarkSplitter->SetSashGravity(1.0f / 20.0f); @@ -1395,7 +1395,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demodGainMeter->setInputValue(demod->getGain()); wxGetApp().getDemodMgr().setLastGain(demod->getGain()); int outputDevice = demod->getOutputDevice(); - if (scopeCanvas) scopeCanvas->setDeviceName(outputDevices[outputDevice].name); + if (scopeCanvas) { + scopeCanvas->setDeviceName(outputDevices[outputDevice].name); + } // outputDeviceMenuItems[outputDevice]->Check(true); std::string dType = demod->getDemodulatorType(); demodModeSelector->setSelection(dType); @@ -1575,12 +1577,16 @@ void AppFrame::OnIdle(wxIdleEvent& event) { if (demodWaterfallCanvas && wxGetApp().getFrequency() != demodWaterfallCanvas->getCenterFrequency()) { demodWaterfallCanvas->setCenterFrequency(wxGetApp().getFrequency()); - if (demodSpectrumCanvas) demodSpectrumCanvas->setCenterFrequency(wxGetApp().getFrequency()); + if (demodSpectrumCanvas) { + demodSpectrumCanvas->setCenterFrequency(wxGetApp().getFrequency()); + } } + if (spectrumCanvas->getViewState() && abs(wxGetApp().getFrequency()-spectrumCanvas->getCenterFrequency()) > (wxGetApp().getSampleRate()/2)) { spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency()); waterfallCanvas->setCenterFrequency(wxGetApp().getFrequency()); } + if (demodMuteButton->modeChanged()) { int muteMode = demodMuteButton->getSelection(); if (muteMode == -1) { @@ -1685,7 +1691,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) { wxGetApp().getSpectrumProcessor()->setPeakHold(peakHoldMode == 1); //make the peak hold act on the current dmod also, like a zoomed-in version. - if (wxGetApp().getDemodSpectrumProcessor()) wxGetApp().getDemodSpectrumProcessor()->setPeakHold(peakHoldMode == 1); + if (wxGetApp().getDemodSpectrumProcessor()) { + wxGetApp().getDemodSpectrumProcessor()->setPeakHold(peakHoldMode == 1); + } peakHoldButton->clearModeChanged(); } @@ -1933,7 +1941,9 @@ void AppFrame::setMainWaterfallFFTSize(int fftSize) { } void AppFrame::setScopeDeviceName(std::string deviceName) { - if (scopeCanvas) scopeCanvas->setDeviceName(deviceName); + if (scopeCanvas) { + scopeCanvas->setDeviceName(deviceName); + } } @@ -2199,7 +2209,9 @@ int AppFrame::OnGlobalKeyUp(wxKeyEvent &event) { break; case 'P': wxGetApp().getSpectrumProcessor()->setPeakHold(!wxGetApp().getSpectrumProcessor()->getPeakHold()); - if (wxGetApp().getDemodSpectrumProcessor()) wxGetApp().getDemodSpectrumProcessor()->setPeakHold(wxGetApp().getSpectrumProcessor()->getPeakHold()); + if (wxGetApp().getDemodSpectrumProcessor()) { + wxGetApp().getDemodSpectrumProcessor()->setPeakHold(wxGetApp().getSpectrumProcessor()->getPeakHold()); + } peakHoldButton->setSelection(wxGetApp().getSpectrumProcessor()->getPeakHold()?1:0); peakHoldButton->clearModeChanged(); break; diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 8292292..23c8705 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -301,7 +301,6 @@ bool CubicSDR::OnInit() { getSpectrumProcessor()->setInput(pipeIQVisualData); getSpectrumProcessor()->setHideDC(true); - // I/Q Data pipeSDRIQData = new SDRThreadIQDataQueue(); pipeSDRIQData->set_max_num_items(100); @@ -314,10 +313,7 @@ bool CubicSDR::OnInit() { sdrPostThread->setOutputQueue("IQVisualDataOutput", pipeIQVisualData); sdrPostThread->setOutputQueue("IQDataOutput", pipeWaterfallIQVisualData); - - t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread); - t_SpectrumVisual = new std::thread(&SpectrumVisualDataThread::threadMain, spectrumVisualThread); - + #if CUBICSDR_ENABLE_VIEW_SCOPE pipeAudioVisualData = new DemodulatorThreadOutputQueue(); pipeAudioVisualData->set_max_num_items(1); @@ -331,15 +327,29 @@ bool CubicSDR::OnInit() { demodVisualThread = new SpectrumVisualDataThread(); pipeDemodIQVisualData = new DemodulatorThreadInputQueue(); pipeDemodIQVisualData->set_max_num_items(1); - if (getDemodSpectrumProcessor()) getDemodSpectrumProcessor()->setInput(pipeDemodIQVisualData); + + if (getDemodSpectrumProcessor()) { + getDemodSpectrumProcessor()->setInput(pipeDemodIQVisualData); + } sdrPostThread->setOutputQueue("IQActiveDemodVisualDataOutput", pipeDemodIQVisualData); - t_DemodVisual = new std::thread(&SpectrumVisualDataThread::threadMain, demodVisualThread); #else demodVisualThread = nullptr; pipeDemodIQVisualData = nullptr; t_DemodVisual = nullptr; #endif + + // Now that input/output queue plumbing is completely done, we can + //safely starts all the threads: + t_SpectrumVisual = new std::thread(&SpectrumVisualDataThread::threadMain, spectrumVisualThread); + + if (demodVisualThread != nullptr) { + t_DemodVisual = new std::thread(&SpectrumVisualDataThread::threadMain, demodVisualThread); + } + + //Start SDRPostThread last. + t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread); + sdrEnum = new SDREnumerator(); SDREnumerator::setManuals(config.getManualDevices()); diff --git a/src/IOThread.cpp b/src/IOThread.cpp index 4668630..029fe73 100644 --- a/src/IOThread.cpp +++ b/src/IOThread.cpp @@ -72,7 +72,7 @@ void IOThread::terminate() { }; void IOThread::onBindOutput(std::string /* name */, ThreadQueueBase* /* threadQueue */) { - + }; void IOThread::onBindInput(std::string /* name */, ThreadQueueBase* /* threadQueue */) { @@ -80,20 +80,24 @@ void IOThread::onBindInput(std::string /* name */, ThreadQueueBase* /* threadQue }; void IOThread::setInputQueue(std::string qname, ThreadQueueBase *threadQueue) { + std::lock_guard < std::mutex > lock(m_queue_bindings_mutex); input_queues[qname] = threadQueue; this->onBindInput(qname, threadQueue); }; ThreadQueueBase *IOThread::getInputQueue(std::string qname) { + std::lock_guard < std::mutex > lock(m_queue_bindings_mutex); return input_queues[qname]; }; void IOThread::setOutputQueue(std::string qname, ThreadQueueBase *threadQueue) { + std::lock_guard < std::mutex > lock(m_queue_bindings_mutex); output_queues[qname] = threadQueue; this->onBindOutput(qname, threadQueue); }; ThreadQueueBase *IOThread::getOutputQueue(std::string qname) { + std::lock_guard < std::mutex > lock(m_queue_bindings_mutex); return output_queues[qname]; }; diff --git a/src/IOThread.h b/src/IOThread.h index 84fae4e..9750366 100644 --- a/src/IOThread.h +++ b/src/IOThread.h @@ -221,7 +221,10 @@ public: protected: std::map input_queues; std::map output_queues; - + + //this protects against concurrent changes in input/output bindings: get/set/Input/OutPutQueue + mutable std::mutex m_queue_bindings_mutex; + //true when a termination is ordered std::atomic_bool stopping; Timer gTimer; @@ -230,4 +233,5 @@ private: //true when the thread has really ended, i.e run() from threadMain() has returned. std::atomic_bool terminated; + };