diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 9dd3fcb..bbc2654 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -41,6 +41,9 @@ AppFrame::AppFrame() : this->SetSizer(vbox); + waterfallCanvas->SetFocusFromKbd(); + waterfallCanvas->SetFocus(); + // SetIcon(wxICON(sample)); // Make a menubar diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index f7707c6..d9c417c 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -21,15 +21,11 @@ bool CubicSDR::OnInit() { frequency = DEFAULT_FREQ; - for (int i = 0; i < NUM_DEMODULATORS; i++) { - demodulatorTest[i] = demodMgr.newThread(); - demodulatorTest[i]->getParams().frequency = DEFAULT_FREQ; - demodulatorTest[i]->run(); - } - audioVisualQueue = new DemodulatorThreadOutputQueue(); - demodulatorTest[0]->setVisualOutputQueue(audioVisualQueue); - demodMgr.setActiveDemodulator(demodulatorTest[0]); + audioVisualQueue->set_max_num_items(1); + +// demodulatorTest[0]->setVisualOutputQueue(audioVisualQueue); +// demodMgr.setActiveDemodulator(demodulatorTest[0]); threadCmdQueueSDR = new SDRThreadCommandQueue; sdrThread = new SDRThread(threadCmdQueueSDR); @@ -38,15 +34,12 @@ bool CubicSDR::OnInit() { iqPostDataQueue = new SDRThreadIQDataQueue; iqVisualQueue = new SDRThreadIQDataQueue; + iqVisualQueue->set_max_num_items(1); sdrThread->setIQDataOutQueue(iqPostDataQueue); sdrPostThread->setIQDataInQueue(iqPostDataQueue); sdrPostThread->setIQVisualQueue(iqVisualQueue); - for (int i = 0; i < NUM_DEMODULATORS; i++) { - sdrPostThread->bindDemodulator(demodulatorTest[i]); - } - t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread); t_SDR = new std::thread(&SDRThread::threadMain, sdrThread); @@ -82,7 +75,6 @@ int CubicSDR::OnExit() { demodMgr.terminateAll(); - delete threadCmdQueueSDR; delete iqVisualQueue; @@ -117,3 +109,29 @@ void CubicSDR::setFrequency(unsigned int freq) { int CubicSDR::getFrequency() { return frequency; } + +DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() { + return audioVisualQueue; +} + +SDRThreadIQDataQueue* CubicSDR::getIQVisualQueue() { + return iqVisualQueue; +} + +DemodulatorMgr &CubicSDR::getDemodMgr() { + return demodMgr; +} + +void CubicSDR::bindDemodulator(DemodulatorInstance *demod) { + if (!demod) { + return; + } + sdrPostThread->bindDemodulator(demod); +} + +void CubicSDR::removeDemodulator(DemodulatorInstance *demod) { + if (!demod) { + return; + } + sdrPostThread->removeDemodulator(demod); +} diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 1b990e7..5128368 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -21,7 +21,7 @@ class CubicSDR: public wxApp { public: CubicSDR() : m_glContext(NULL), t_PostSDR(NULL), t_SDR(NULL), audioVisualQueue(NULL), threadCmdQueueSDR(NULL), iqVisualQueue(NULL), frequency( - DEFAULT_FREQ), sdrPostThread(NULL), iqPostDataQueue(NULL), sdrThread(NULL) { + DEFAULT_FREQ), sdrPostThread(NULL), iqPostDataQueue(NULL), sdrThread(NULL) { } @@ -33,25 +33,12 @@ public: void setFrequency(unsigned int freq); int getFrequency(); - DemodulatorThreadOutputQueue* getAudioVisualQueue() { - return audioVisualQueue; - } + DemodulatorThreadOutputQueue* getAudioVisualQueue(); + SDRThreadIQDataQueue* getIQVisualQueue(); + DemodulatorMgr &getDemodMgr(); - SDRThreadIQDataQueue* getIQVisualQueue() { - return iqVisualQueue; - } - - DemodulatorInstance *getDemodTest() { - return demodulatorTest[0]; - } - - DemodulatorMgr &getDemodMgr() { - return demodMgr; - } - - void bindDemodulator(DemodulatorInstance *newDemod) { - sdrPostThread->bindDemodulator(newDemod); - } + void bindDemodulator(DemodulatorInstance *demod); + void removeDemodulator(DemodulatorInstance *demod); private: PrimaryGLContext *m_glContext; @@ -60,8 +47,6 @@ private: unsigned int frequency; - DemodulatorInstance *demodulatorTest[NUM_DEMODULATORS]; - SDRThread *sdrThread; SDRPostThread *sdrPostThread; diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index 9302eb2..d5e8313 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -1,6 +1,7 @@ #include #include #include +#include "CubicSDR.h" DemodulatorInstance::DemodulatorInstance() : t_Demod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL) { @@ -83,14 +84,12 @@ DemodulatorThreadParameters &DemodulatorInstance::getParams() { void DemodulatorInstance::terminate() { std::cout << "Terminating demodulator thread.." << std::endl; demodulatorThread->terminate(); -#ifdef __APPLE__ - pthread_join(t_Demod,NULL); -#else - t_Demod->join(); -#endif +//#ifdef __APPLE__ +// pthread_join(t_Demod,NULL); +//#else +//#endif std::cout << "Terminating demodulator audio thread.." << std::endl; audioThread->terminate(); - t_Audio->join(); } std::string DemodulatorInstance::getLabel() { @@ -102,7 +101,7 @@ void DemodulatorInstance::setLabel(std::string labelStr) { } DemodulatorMgr::DemodulatorMgr() : - activeDemodulator(NULL), lastActiveDemodulator(NULL) { + activeDemodulator(NULL), lastActiveDemodulator(NULL), activeVisualDemodulator(NULL) { } @@ -127,7 +126,6 @@ void DemodulatorMgr::terminateAll() { DemodulatorInstance *d = demods.back(); demods.pop_back(); d->terminate(); - delete d; } } @@ -135,6 +133,27 @@ std::vector &DemodulatorMgr::getDemodulators() { return demods; } +void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) { + std::vector::iterator i; + + i = std::find(demods.begin(),demods.end(),demod); + + if (activeDemodulator == demod) { + activeDemodulator = NULL; + } + if (lastActiveDemodulator == demod) { + lastActiveDemodulator = NULL; + } + if (activeVisualDemodulator == demod) { + activeVisualDemodulator = NULL; + } + + if (i != demods.end()) { + demods.erase(i); + demod->terminate(); + } +} + std::vector *DemodulatorMgr::getDemodulatorsAt(int freq, int bandwidth) { std::vector *foundDemods = new std::vector(); @@ -163,6 +182,22 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo lastActiveDemodulator = demod; } } + + if (activeVisualDemodulator) { + activeVisualDemodulator->setVisualOutputQueue(NULL); + } + if (demod) { + demod->setVisualOutputQueue(wxGetApp().getAudioVisualQueue()); + activeVisualDemodulator = demod; + } else { + DemodulatorInstance *last = getLastActiveDemodulator(); + if (last) { + last->setVisualOutputQueue(wxGetApp().getAudioVisualQueue()); + } + activeVisualDemodulator = last; + } + + activeDemodulator = demod; } diff --git a/src/demod/DemodulatorMgr.h b/src/demod/DemodulatorMgr.h index 9b6ad28..2bed534 100644 --- a/src/demod/DemodulatorMgr.h +++ b/src/demod/DemodulatorMgr.h @@ -47,6 +47,7 @@ public: DemodulatorInstance *newThread(); std::vector &getDemodulators(); std::vector *getDemodulatorsAt(int freq, int bandwidth); + void deleteThread(DemodulatorInstance *); void terminateAll(); @@ -58,4 +59,5 @@ private: std::vector demods; DemodulatorInstance *activeDemodulator; DemodulatorInstance *lastActiveDemodulator; + DemodulatorInstance *activeVisualDemodulator; }; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index dda7d05..10048e0 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -255,7 +255,5 @@ void DemodulatorThread::terminate() { terminated = true; DemodulatorThreadIQData inp; // push dummy to nudge queue inputQueue->push(inp); - workerThread->terminate(); - t_Worker->join(); } diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 227182f..7c593e0 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -131,7 +131,6 @@ public: void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) { visOutQueue = tQueue; - visOutQueue->set_max_num_items(1); } void setCommandQueue(DemodulatorThreadCommandQueue *tQueue) { diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index cd48b1b..e052cff 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -50,7 +50,9 @@ void SDRPostThread::threadMain() { } if (iqVisualQueue != NULL) { - iqVisualQueue.load()->push(dataOut); + if (iqVisualQueue.load()->empty()) { + iqVisualQueue.load()->push(dataOut); + } } if (demodulators.size()) { diff --git a/src/sdr/SDRPostThread.h b/src/sdr/SDRPostThread.h index 4b3d737..5d79fa0 100644 --- a/src/sdr/SDRPostThread.h +++ b/src/sdr/SDRPostThread.h @@ -1,6 +1,7 @@ #pragma once #include "SDRThread.h" +#include class SDRPostThread { public: @@ -15,6 +16,20 @@ public: demodulators.push_back(demod); } + void removeDemodulator(DemodulatorInstance *demod) { + if (!demod) { + return; + } + + std::vector::iterator i; + + i = std::find(demodulators.begin(), demodulators.end(), demod); + + if (i != demodulators.end()) { + demodulators.erase(i); + } + } + void threadMain(); void setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue) { @@ -25,7 +40,6 @@ public: } void setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue) { iqVisualQueue = iqVisQueue; - iqVisualQueue.load()->set_max_num_items(1); } void terminate(); diff --git a/src/visual/PrimaryGLContext.cpp b/src/visual/PrimaryGLContext.cpp index f34d47f..91c4c4b 100644 --- a/src/visual/PrimaryGLContext.cpp +++ b/src/visual/PrimaryGLContext.cpp @@ -194,7 +194,7 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, float r, float g, float b) int bw = 0; if (!demod) { - bw = 200000; + bw = defaultDemodParams.bandwidth; } else { bw = demod->getParams().bandwidth; } @@ -211,7 +211,7 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, float r, float g, float b) glVertex3f((uxPos - 0.5) * 2.0, 1.0, 0.0); glVertex3f((uxPos - 0.5) * 2.0, -1.0, 0.0); - float ofs = ((float) demod->getParams().bandwidth) / (float) SRATE; + float ofs = ((float) bw) / (float) SRATE; glVertex3f((uxPos - 0.5) * 2.0 - ofs, 1.0, 0.0); glVertex3f((uxPos - 0.5) * 2.0 - ofs, -1.0, 0.0); diff --git a/src/visual/PrimaryGLContext.h b/src/visual/PrimaryGLContext.h index 7551c92..2887971 100644 --- a/src/visual/PrimaryGLContext.h +++ b/src/visual/PrimaryGLContext.h @@ -29,4 +29,5 @@ public: private: static GLFont fonts[GLFONT_MAX]; + DemodulatorThreadParameters defaultDemodParams; }; diff --git a/src/visual/ScopeCanvas.cpp b/src/visual/ScopeCanvas.cpp index 442f476..54db54d 100644 --- a/src/visual/ScopeCanvas.cpp +++ b/src/visual/ScopeCanvas.cpp @@ -16,7 +16,6 @@ #include wxBEGIN_EVENT_TABLE(ScopeCanvas, wxGLCanvas) EVT_PAINT(ScopeCanvas::OnPaint) -EVT_KEY_DOWN(ScopeCanvas::OnKeyDown) EVT_IDLE(ScopeCanvas::OnIdle) wxEND_EVENT_TABLE() @@ -48,35 +47,6 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { SwapBuffers(); } -void ScopeCanvas::OnKeyDown(wxKeyEvent& event) { - float angle = 5.0; - - unsigned int freq; - switch (event.GetKeyCode()) { - case WXK_RIGHT: - freq = wxGetApp().getFrequency(); - freq += SRATE/2; - wxGetApp().setFrequency(freq); - ((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), freq)); - break; - case WXK_LEFT: - freq = wxGetApp().getFrequency(); - freq -= SRATE/2; - wxGetApp().setFrequency(freq); - ((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), freq)); - break; - case WXK_DOWN: - break; - case WXK_UP: - break; - case WXK_SPACE: - break; - default: - event.Skip(); - return; - } -} - void ScopeCanvas::OnIdle(wxIdleEvent &event) { // timer.update(); // frameTimer += timer.lastUpdateSeconds(); diff --git a/src/visual/ScopeCanvas.h b/src/visual/ScopeCanvas.h index bc12903..9cd40f9 100644 --- a/src/visual/ScopeCanvas.h +++ b/src/visual/ScopeCanvas.h @@ -21,7 +21,6 @@ public: void setWaveformPoints(std::vector &waveform_points_in); private: void OnPaint(wxPaintEvent& event); - void OnKeyDown(wxKeyEvent& event); void OnIdle(wxIdleEvent &event); diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index b3edee5..8550e1d 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -17,7 +17,6 @@ #include wxBEGIN_EVENT_TABLE(SpectrumCanvas, wxGLCanvas) EVT_PAINT(SpectrumCanvas::OnPaint) -EVT_KEY_DOWN(SpectrumCanvas::OnKeyDown) EVT_IDLE(SpectrumCanvas::OnIdle) EVT_MOTION(SpectrumCanvas::mouseMoved) EVT_LEFT_DOWN(SpectrumCanvas::mouseDown) @@ -75,35 +74,6 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { SwapBuffers(); } -void SpectrumCanvas::OnKeyDown(wxKeyEvent& event) { - float angle = 5.0; - - unsigned int freq; - switch (event.GetKeyCode()) { - case WXK_RIGHT: - freq = wxGetApp().getFrequency(); - freq += SRATE / 2; - wxGetApp().setFrequency(freq); - ((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), freq)); - break; - case WXK_LEFT: - freq = wxGetApp().getFrequency(); - freq -= SRATE / 2; - wxGetApp().setFrequency(freq); - ((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), freq)); - break; - case WXK_DOWN: - break; - case WXK_UP: - break; - case WXK_SPACE: - break; - default: - event.Skip(); - return; - } -} - void SpectrumCanvas::setData(std::vector *data) { if (data && data->size()) { diff --git a/src/visual/SpectrumCanvas.h b/src/visual/SpectrumCanvas.h index 46d68ef..5f96fd5 100644 --- a/src/visual/SpectrumCanvas.h +++ b/src/visual/SpectrumCanvas.h @@ -20,7 +20,6 @@ public: void setData(std::vector *data); private: void OnPaint(wxPaintEvent& event); - void OnKeyDown(wxKeyEvent& event); void OnIdle(wxIdleEvent &event); diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index e1c844d..1cc470c 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -30,8 +30,8 @@ wxEND_EVENT_TABLE() WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, - wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), activeDemodulatorBandwidth(0), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), shiftDown( - false) { + wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), shiftDown( + false), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0) { int in_block_size = BUF_SIZE / 2; int out_block_size = FFT_SIZE; @@ -88,6 +88,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glContext->DrawDemod(lastActiveDemodulator, 1, 0, 0); glContext->DrawFreqSelector(mTracker.getMouseX(), 1, 1, 0); } + } else { + glContext->DrawFreqSelector(mTracker.getMouseX(), 1, 1, 0); } } else { if (lastActiveDemodulator) { @@ -117,6 +119,7 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { } void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) { + shiftDown = event.ShiftDown(); // switch (event.GetKeyCode()) { // } @@ -125,6 +128,10 @@ void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) { void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { float angle = 5.0; + shiftDown = event.ShiftDown(); + + DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); + unsigned int freq; switch (event.GetKeyCode()) { case WXK_RIGHT: @@ -139,12 +146,15 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { wxGetApp().setFrequency(freq); ((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), freq)); break; - case WXK_DOWN: - break; - case WXK_UP: - break; - case WXK_SPACE: + case 'D': + case WXK_DELETE: + if (!activeDemod) { + break; + } + wxGetApp().getDemodMgr().deleteThread(activeDemod); + wxGetApp().removeDemodulator(activeDemod); break; + default: event.Skip(); return; @@ -354,6 +364,8 @@ void WaterfallCanvas::mouseDown(wxMouseEvent& event) { mTracker.OnMouseDown(event); dragState = nextDragState; + shiftDown = event.ShiftDown(); + if (dragState) { wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getActiveDemodulator(), false); } @@ -363,13 +375,14 @@ void WaterfallCanvas::mouseDown(wxMouseEvent& event) { } void WaterfallCanvas::mouseWheelMoved(wxMouseEvent& event) { - DemodulatorInstance *demod = wxGetApp().getDemodTest(); mTracker.OnMouseWheelMoved(event); } void WaterfallCanvas::mouseReleased(wxMouseEvent& event) { mTracker.OnMouseReleased(event); + shiftDown = event.ShiftDown(); + mTracker.setVertDragLock(true); mTracker.setHorizDragLock(true); @@ -380,7 +393,7 @@ void WaterfallCanvas::mouseReleased(wxMouseEvent& event) { int center_freq = wxGetApp().getFrequency(); int freq = center_freq - (int) (0.5 * (float) SRATE) + (int) ((float) pos * (float) SRATE); - if (!shiftDown) { + if (!shiftDown && wxGetApp().getDemodMgr().getDemodulators().size()) { demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); } else { demod = wxGetApp().getDemodMgr().newThread(); @@ -393,6 +406,8 @@ void WaterfallCanvas::mouseReleased(wxMouseEvent& event) { demod->run(); wxGetApp().bindDemodulator(demod); + + wxGetApp().getDemodMgr().setActiveDemodulator(demod); } if (dragState == WF_DRAG_NONE) { @@ -401,12 +416,13 @@ void WaterfallCanvas::mouseReleased(wxMouseEvent& event) { return; } - DemodulatorThreadCommand command; command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY; command.int_value = freq; + demod->getCommandQueue()->push(command); // doesn't always work on first push? demod->getCommandQueue()->push(command); + ((wxFrame*) parent)->GetStatusBar()->SetStatusText( wxString::Format(wxT("Set demodulator frequency: %s"), wxNumberFormatter::ToString((long) freq, wxNumberFormatter::Style_WithThousandsSep)));