diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index 1588003..d4c5a82 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -2,11 +2,14 @@ #include #include #include "CubicSDR.h" +#include +#include DemodulatorInstance::DemodulatorInstance() : t_Demod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(false), audioTerminated(false), demodTerminated( false) { + label = new std::string("Unnamed"); threadQueueDemod = new DemodulatorThreadInputQueue; threadQueueCommand = new DemodulatorThreadCommandQueue; threadQueueNotify = new DemodulatorThreadCommandQueue; @@ -23,10 +26,6 @@ DemodulatorInstance::~DemodulatorInstance() { delete audioInputQueue; delete threadQueueDemod; -#ifndef __APPLE__ -// delete t_Demod; -#endif -// delete t_Audio; } void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) { @@ -53,6 +52,13 @@ void DemodulatorInstance::run() { #endif } +void DemodulatorInstance::updateLabel(int freq) { + std::stringstream newLabel; + newLabel.precision(3); + newLabel << std::fixed << ((float) freq / 1000000.0); + setLabel(newLabel.str()); +} + DemodulatorThreadCommandQueue *DemodulatorInstance::getCommandQueue() { return threadQueueCommand; } @@ -73,11 +79,16 @@ void DemodulatorInstance::terminate() { } std::string DemodulatorInstance::getLabel() { - return label; + return *(label.load()); } void DemodulatorInstance::setLabel(std::string labelStr) { - label = labelStr; + std::string *newLabel = new std::string; + newLabel->append(labelStr); + std::string *oldLabel; + oldLabel = label; + label = newLabel; + delete oldLabel; } DemodulatorMgr::DemodulatorMgr() : diff --git a/src/demod/DemodulatorMgr.h b/src/demod/DemodulatorMgr.h index 388ef3b..a936ddd 100644 --- a/src/demod/DemodulatorMgr.h +++ b/src/demod/DemodulatorMgr.h @@ -37,9 +37,10 @@ public: void setLabel(std::string labelStr); bool isTerminated(); + void updateLabel(int freq); private: - std::string label; + std::atomic label; bool terminated; bool demodTerminated; bool audioTerminated; diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index 9a9e204..02e7bdf 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -81,6 +81,9 @@ void SDRPostThread::threadMain() { } if (demodulators.size()) { + DemodulatorThreadIQData dummyDataOut; + dummyDataOut.frequency = data_in.frequency; + dummyDataOut.bandwidth = data_in.bandwidth; DemodulatorThreadIQData demodDataOut; demodDataOut.frequency = data_in.frequency; demodDataOut.bandwidth = data_in.bandwidth; @@ -89,6 +92,14 @@ void SDRPostThread::threadMain() { for (int i = 0, iMax = demodulators.size(); i < iMax; i++) { DemodulatorInstance *demod = demodulators[i]; DemodulatorThreadInputQueue *demodQueue = demod->threadQueueDemod; + + if (demod->getParams().frequency != data_in.frequency) { + if (abs(data_in.frequency - demod->getParams().frequency) > (int) ((float) ((float) SRATE / 2.0) * 1.15)) { + demodQueue->push(dummyDataOut); + continue; + } + } + demodQueue->push(demodDataOut); } } diff --git a/src/visual/PrimaryGLContext.cpp b/src/visual/PrimaryGLContext.cpp index 91c4c4b..793132a 100644 --- a/src/visual/PrimaryGLContext.cpp +++ b/src/visual/PrimaryGLContext.cpp @@ -188,7 +188,7 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, float r, float g, f glEnable(GL_DEPTH_TEST); } -void PrimaryGLContext::DrawFreqSelector(float uxPos, float r, float g, float b) { +void PrimaryGLContext::DrawFreqSelector(float uxPos, float r, float g, float b, float w) { DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); int bw = 0; @@ -211,7 +211,13 @@ 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) bw) / (float) SRATE; + float ofs; + + if (w) { + ofs = w; + } else { + 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 2887971..d2495f5 100644 --- a/src/visual/PrimaryGLContext.h +++ b/src/visual/PrimaryGLContext.h @@ -21,7 +21,7 @@ public: void BeginDraw(); void EndDraw(); - void DrawFreqSelector(float uxPos, float r = 1, float g = 1, float b = 1); + void DrawFreqSelector(float uxPos, float r = 1, float g = 1, float b = 1, float w=0); void DrawDemod(DemodulatorInstance *demod, float r = 1, float g = 1, float b = 1); void DrawDemodInfo(DemodulatorInstance *demod, float r = 1, float g = 1, float b = 1); diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index 8550e1d..0974d3b 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -21,7 +21,6 @@ EVT_IDLE(SpectrumCanvas::OnIdle) EVT_MOTION(SpectrumCanvas::mouseMoved) EVT_LEFT_DOWN(SpectrumCanvas::mouseDown) EVT_LEFT_UP(SpectrumCanvas::mouseReleased) -//EVT_RIGHT_DOWN(SpectrumCanvas::rightClick) EVT_LEAVE_WINDOW(SpectrumCanvas::mouseLeftWindow) EVT_MOUSEWHEEL(SpectrumCanvas::mouseWheelMoved) wxEND_EVENT_TABLE() diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 1cc470c..a1e674b 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -31,7 +31,7 @@ wxEND_EVENT_TABLE() WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), shiftDown( - false), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0) { + false), altDown(false), ctrlDown(false), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0) { int in_block_size = BUF_SIZE / 2; int out_block_size = FFT_SIZE; @@ -78,24 +78,46 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator(); if (mTracker.mouseInView()) { + if (nextDragState == WF_DRAG_RANGE) { + if (mTracker.mouseDown()) { + float width = mTracker.getOriginDeltaMouseX(); + float centerPos = mTracker.getOriginMouseX()+width/2.0; - if (activeDemodulator == NULL) { - if (lastActiveDemodulator) { if (shiftDown) { glContext->DrawDemod(lastActiveDemodulator); - glContext->DrawFreqSelector(mTracker.getMouseX(), 0, 1, 0); + glContext->DrawFreqSelector(centerPos, 0, 1, 0, width?width:(1.0/(float)ClientSize.x)); } else { glContext->DrawDemod(lastActiveDemodulator, 1, 0, 0); + glContext->DrawFreqSelector(centerPos, 1, 1, 0, width?width:(1.0/(float)ClientSize.x)); + } + } else { + if (shiftDown) { + glContext->DrawDemod(lastActiveDemodulator); + glContext->DrawFreqSelector(mTracker.getMouseX(), 0, 1, 0, 1.0/(float)ClientSize.x); + } else { + glContext->DrawDemod(lastActiveDemodulator, 1, 0, 0); + glContext->DrawFreqSelector(mTracker.getMouseX(), 1, 1, 0, 1.0/(float)ClientSize.x); + } + } + } else { + if (activeDemodulator == NULL) { + if (lastActiveDemodulator) { + if (shiftDown) { + glContext->DrawDemod(lastActiveDemodulator); + glContext->DrawFreqSelector(mTracker.getMouseX(), 0, 1, 0); + } else { + glContext->DrawDemod(lastActiveDemodulator, 1, 0, 0); + glContext->DrawFreqSelector(mTracker.getMouseX(), 1, 1, 0); + } + } else { glContext->DrawFreqSelector(mTracker.getMouseX(), 1, 1, 0); } } else { - glContext->DrawFreqSelector(mTracker.getMouseX(), 1, 1, 0); + if (lastActiveDemodulator) { + glContext->DrawDemod(lastActiveDemodulator); + } + glContext->DrawDemod(activeDemodulator, 1, 1, 0); } - } else { - if (lastActiveDemodulator) { - glContext->DrawDemod(lastActiveDemodulator); - } - glContext->DrawDemod(activeDemodulator, 1, 1, 0); } } else { if (activeDemodulator) { @@ -120,7 +142,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) { shiftDown = event.ShiftDown(); - + altDown = event.AltDown(); + ctrlDown = event.ControlDown(); // switch (event.GetKeyCode()) { // } } @@ -129,6 +152,8 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { float angle = 5.0; shiftDown = event.ShiftDown(); + altDown = event.AltDown(); + ctrlDown = event.ControlDown(); DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); @@ -244,6 +269,8 @@ void WaterfallCanvas::mouseMoved(wxMouseEvent& event) { mTracker.OnMouseMoved(event); shiftDown = event.ShiftDown(); + altDown = event.AltDown(); + ctrlDown = event.ControlDown(); DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator(); @@ -290,6 +317,8 @@ void WaterfallCanvas::mouseMoved(wxMouseEvent& event) { command.int_value = activeDemodulatorFrequency; demod->getCommandQueue()->push(command); + + demod->updateLabel(activeDemodulatorFrequency); } } else { int freqPos = GetFrequencyAt(mTracker.getMouseX()); @@ -298,7 +327,11 @@ void WaterfallCanvas::mouseMoved(wxMouseEvent& event) { wxGetApp().getDemodMgr().setActiveDemodulator(NULL); - if (demodsHover->size()) { + if (altDown) { + nextDragState = WF_DRAG_RANGE; + mTracker.setVertDragLock(true); + mTracker.setHorizDragLock(false); + } else if (demodsHover->size()) { int hovered = -1; int near_dist = SRATE; @@ -365,8 +398,10 @@ void WaterfallCanvas::mouseDown(wxMouseEvent& event) { dragState = nextDragState; shiftDown = event.ShiftDown(); + altDown = event.AltDown(); + ctrlDown = event.ControlDown(); - if (dragState) { + if (dragState && dragState != WF_DRAG_RANGE) { wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getActiveDemodulator(), false); } @@ -382,9 +417,11 @@ void WaterfallCanvas::mouseReleased(wxMouseEvent& event) { mTracker.OnMouseReleased(event); shiftDown = event.ShiftDown(); + altDown = event.AltDown(); + ctrlDown = event.ControlDown(); - mTracker.setVertDragLock(true); - mTracker.setHorizDragLock(true); + mTracker.setVertDragLock(false); + mTracker.setHorizDragLock(false); if (mTracker.getOriginDeltaMouseX() == 0 && mTracker.getOriginDeltaMouseY() == 0) { DemodulatorInstance *demod; @@ -393,29 +430,30 @@ 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 && wxGetApp().getDemodMgr().getDemodulators().size()) { - demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); - } else { - demod = wxGetApp().getDemodMgr().newThread(); - demod->getParams().frequency = freq; - - if (DemodulatorInstance *last = wxGetApp().getDemodMgr().getLastActiveDemodulator()) { - demod->getParams().bandwidth = last->getParams().bandwidth; - } - - demod->run(); - - wxGetApp().bindDemodulator(demod); - - wxGetApp().getDemodMgr().setActiveDemodulator(demod); - } - if (dragState == WF_DRAG_NONE) { + if (!shiftDown && wxGetApp().getDemodMgr().getDemodulators().size()) { + demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + } else { + demod = wxGetApp().getDemodMgr().newThread(); + demod->getParams().frequency = freq; + + if (DemodulatorInstance *last = wxGetApp().getDemodMgr().getLastActiveDemodulator()) { + demod->getParams().bandwidth = last->getParams().bandwidth; + } + + demod->run(); + + wxGetApp().bindDemodulator(demod); + + wxGetApp().getDemodMgr().setActiveDemodulator(demod); + } if (demod == NULL) { return; } + demod->updateLabel(freq); + DemodulatorThreadCommand command; command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY; command.int_value = freq; diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index 0942372..589b1d7 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -14,7 +14,7 @@ class WaterfallCanvas: public wxGLCanvas { public: - enum DragState { WF_DRAG_NONE, WF_DRAG_BANDWIDTH_LEFT, WF_DRAG_BANDWIDTH_RIGHT, WF_DRAG_FREQUENCY }; + enum DragState { WF_DRAG_NONE, WF_DRAG_BANDWIDTH_LEFT, WF_DRAG_BANDWIDTH_RIGHT, WF_DRAG_FREQUENCY, WF_DRAG_RANGE }; WaterfallCanvas(wxWindow *parent, int *attribList = NULL); ~WaterfallCanvas(); @@ -61,8 +61,9 @@ private: DragState nextDragState; bool shiftDown; - -// event table + bool altDown; + bool ctrlDown; + // event table wxDECLARE_EVENT_TABLE(); };