From 4ee791ac0c605c3b591409c8fdffbb02661185ac Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 20 Jun 2015 20:19:52 -0400 Subject: [PATCH 01/53] Initial GLPanel prototype, testing nested layouts --- CMakeLists.txt | 7 +++ src/AppFrame.cpp | 5 ++ src/AppFrame.h | 2 + src/ui/GLPanel.cpp | 121 +++++++++++++++++++++++++++++++++++++++ src/ui/GLPanel.h | 109 +++++++++++++++++++++++++++++++++++ src/ui/UITestCanvas.cpp | 85 +++++++++++++++++++++++++++ src/ui/UITestCanvas.h | 36 ++++++++++++ src/ui/UITestContext.cpp | 42 ++++++++++++++ src/ui/UITestContext.h | 20 +++++++ 9 files changed, 427 insertions(+) create mode 100644 src/ui/GLPanel.cpp create mode 100644 src/ui/GLPanel.h create mode 100644 src/ui/UITestCanvas.cpp create mode 100644 src/ui/UITestCanvas.h create mode 100644 src/ui/UITestContext.cpp create mode 100644 src/ui/UITestContext.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d80c3f..c6518a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,6 +257,7 @@ SET (cubicsdr_sources src/visual/SpectrumContext.cpp src/visual/WaterfallCanvas.cpp src/visual/WaterfallContext.cpp + src/ui/GLPanel.cpp external/rtaudio/RtAudio.cpp external/lodepng/lodepng.cpp external/tinyxml/tinyxml.cpp @@ -302,6 +303,11 @@ SET (cubicsdr_headers src/visual/SpectrumContext.h src/visual/WaterfallCanvas.h src/visual/WaterfallContext.h + src/ui/GLPanel.h + src/ui/UITestCanvas.cpp + src/ui/UITestCanvas.h + src/ui/UITestContext.cpp + src/ui/UITestContext.h external/rtaudio/RtAudio.h external/lodepng/lodepng.h external/tinyxml/tinyxml.h @@ -314,6 +320,7 @@ include_directories ( ${PROJECT_SOURCE_DIR}/src/audio ${PROJECT_SOURCE_DIR}/src/util ${PROJECT_SOURCE_DIR}/src/visual + ${PROJECT_SOURCE_DIR}/src/ui ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/external/rtaudio ${PROJECT_SOURCE_DIR}/external/lodepng diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index b659b0f..e94783f 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -119,6 +119,11 @@ AppFrame::AppFrame() : spectrumCanvas->attachWaterfallCanvas(waterfallCanvas); vbox->Add(waterfallCanvas, 20, wxEXPAND | wxALL, 0); + + vbox->AddSpacer(1); + testCanvas = new UITestCanvas(this, attribList); + vbox->Add(testCanvas, 20, wxEXPAND | wxALL, 0); + this->SetSizer(vbox); // waterfallCanvas->SetFocusFromKbd(); diff --git a/src/AppFrame.h b/src/AppFrame.h index 5788bb7..e3fcc5b 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -9,6 +9,7 @@ #include "MeterCanvas.h" #include "TuningCanvas.h" #include "ModeSelectorCanvas.h" +#include "UITestCanvas.h" #include @@ -77,6 +78,7 @@ private: MeterCanvas *demodSignalMeter; MeterCanvas *demodGainMeter; TuningCanvas *demodTuner; + UITestCanvas *testCanvas; DemodulatorInstance *activeDemodulator; diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp new file mode 100644 index 0000000..79f9ac8 --- /dev/null +++ b/src/ui/GLPanel.cpp @@ -0,0 +1,121 @@ + +#include "GLPanel.h" + + + +GLPanel::GLPanel() : fill(GLPANEL_FILL_SOLID), coord(GLPANEL_Y_DOWN_ZERO_ONE), contentsVisible(true) { + pos[0] = 0.0f; + pos[1] = 0.0f; + size[0] = 1.0f; + size[1] = 1.0f; + + genArrays(); +} + +void GLPanel::setViewport() { + GLint vp[4]; + glGetIntegerv(GL_VIEWPORT, vp); + + view[0] = vp[2]; + view[1] = vp[3]; +} + +void GLPanel::setPosition(float x, float y) { + pos[0] = x; + pos[1] = y; +} + +void GLPanel::setSize(float w, float h) { + size[0] = w; + size[1] = h; +} + +float GLPanel::getWidthPx() { + return size[0]*view[0]; +} + +float GLPanel::getHeightPx() { + return size[1]*view[0]; +} + +void GLPanel::setFill(GLPanelFillType fill_mode) { + fill = fill_mode; +} + +void GLPanel::setMargin(float marg) { + margin.left = margin.right = margin.top = margin.bottom = marg; +} + +void GLPanel::setMargin(float margl, float margr, float margt, float margb) { + margin.left = margl; + margin.right = margr; + margin.top = margt; + margin.bottom = margb; +} + + +void GLPanel::addChild(GLPanel *childPanel) { + children.push_back(childPanel); +} + +void GLPanel::drawChildren() { + if (children.size()) { + std::vector::iterator panel_i; + + for (panel_i = children.begin(); panel_i != children.end(); panel_i++) { + (*panel_i)->draw(this); + } + } +} + +void GLPanel::drawPanelContents() { + drawChildren(); +} + +void GLPanel::draw(GLPanel *parent) { + if (!parent) { + if (coord == GLPANEL_Y_DOWN_ZERO_ONE) { + glPushMatrix(); + glTranslatef(-1.0f, 1.0f, 0.0f); + glScalef(2.0f, -2.0f, 2.0f); + } + if (coord == GLPANEL_Y_UP_ZERO_ONE) { + glPushMatrix(); + glTranslatef(-1.0f, -1.0f, 0.0f); + glScalef(2.0f, 2.0f, 2.0f); + } + if (coord == GLPANEL_Y_DOWN) { + glPushMatrix(); + glScalef(1.0f, -1.0f, 1.0f); + } + if (coord == GLPANEL_Y_UP) { + glPushMatrix(); + } + } + glPushMatrix(); + glTranslatef(pos[0]+margin.left, pos[1]+margin.top, 0); + glScalef(size[0]-(margin.left+margin.right), size[1]-(margin.top+margin.bottom), 0); + + if (fill != GLPANEL_FILL_NONE) { + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, &glPoints[0]); + glColorPointer(3, GL_FLOAT, 0, &glColors[0]); + + glDrawArrays(GL_QUADS, 0, glPoints.size() / 2); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } + + if (contentsVisible) { + glPushMatrix(); + drawPanelContents(); + glPopMatrix(); + } + + glPopMatrix(); + if (!parent) { + glPopMatrix(); + } +} diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h new file mode 100644 index 0000000..1d31bb7 --- /dev/null +++ b/src/ui/GLPanel.h @@ -0,0 +1,109 @@ +#pragma once + +#include +#include "GLExt.h" + +class GLPanelEdges { +public: + float left; + float right; + float top; + float bottom; + + GLPanelEdges(): left(0), right(0), top(0), bottom(0) { + } + + GLPanelEdges(float l, float r, float t, float b) { + left = l; + right = r; + top = t; + bottom = b; + } +}; + +class GLPanel { +private: + std::vector glPoints; + std::vector glColors; + + void genArrays() { + if (!glPoints.size()) { + glPoints.resize(2 * 4); + glColors.resize(3 * 4); + } + + float pts[2 * 4] = { + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f + }; + + float clr[3 * 4] = { + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0, + 1.0, 1.0, 1.0 + }; + + glPoints.reserve(2 * 4); + glColors.reserve(3 * 4); + glPoints.assign(pts, pts + (2 * 4)); + glColors.assign(clr, clr + (3 * 4)); + } + +public: + typedef enum GLPanelFillType { GLPANEL_FILL_NONE, GLPANEL_FILL_SOLID } GLPanelFillType; + typedef enum GLPanelCoordinateSystem { GLPANEL_Y_DOWN_ZERO_ONE, GLPANEL_Y_UP_ZERO_ONE, GLPANEL_Y_UP, GLPANEL_Y_DOWN } GLPanelCoordinateSystem; + float pos[2]; + float size[2]; + float view[2]; + GLPanelFillType fill; + GLPanelCoordinateSystem coord; + GLPanelEdges margin; + GLPanelEdges border; + bool contentsVisible; + + std::vector children; + + GLPanel(); + + void setViewport(); + void setPosition(float x, float y); + void setSize(float w, float h); + float getWidthPx(); + float getHeightPx(); + + void setFill(GLPanelFillType fill_mode); + void setMargin(float marg); + void setMargin(float margl, float margr, float margt, float margb); + + void addChild(GLPanel *childPanel); + + void drawChildren(); + virtual void drawPanelContents(); + void draw(GLPanel *parent=NULL); +}; + + +class GLTestPanel : public GLPanel { +public: + GLTestPanel() : GLPanel() { + + } + + void drawPanelContents() { + glColor3f(1.0,1.0,1.0); + glBegin(GL_LINES); + glVertex2f(0, 0.5); + glVertex2f(1, 0.5); + glVertex2f(0.5, 0); + glVertex2f(0.5, 1); + + glVertex2f(0.5, 1); + glVertex2f(0.48, 0.80); + glVertex2f(0.5, 1); + glVertex2f(0.52, 0.80); + glEnd(); + } +}; diff --git a/src/ui/UITestCanvas.cpp b/src/ui/UITestCanvas.cpp new file mode 100644 index 0000000..e94a993 --- /dev/null +++ b/src/ui/UITestCanvas.cpp @@ -0,0 +1,85 @@ +#include "UITestCanvas.h" + +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +#if !wxUSE_GLCANVAS +#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library" +#endif + +#include "CubicSDR.h" +#include "CubicSDRDefs.h" +#include "AppFrame.h" +#include + +wxBEGIN_EVENT_TABLE(UITestCanvas, wxGLCanvas) EVT_PAINT(UITestCanvas::OnPaint) +EVT_IDLE(UITestCanvas::OnIdle) +EVT_MOTION(UITestCanvas::OnMouseMoved) +EVT_LEFT_DOWN(UITestCanvas::OnMouseDown) +EVT_LEFT_UP(UITestCanvas::OnMouseReleased) +EVT_LEAVE_WINDOW(UITestCanvas::OnMouseLeftWindow) +EVT_ENTER_WINDOW(UITestCanvas::OnMouseEnterWindow) +wxEND_EVENT_TABLE() + +UITestCanvas::UITestCanvas(wxWindow *parent, int *attribList) : +InteractiveCanvas(parent, attribList) { + + glContext = new UITestContext(this, &wxGetApp().GetContext(this)); +} + +UITestCanvas::~UITestCanvas() { + +} + +void UITestCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { + wxPaintDC dc(this); +#ifdef __APPLE__ // force half-rate? + glFinish(); +#endif + const wxSize ClientSize = GetClientSize(); + + glContext->SetCurrent(*this); + initGLExtensions(); + + glViewport(0, 0, ClientSize.x, ClientSize.y); + + glContext->DrawBegin(); + + glContext->Draw(); + + glContext->DrawEnd(); + + SwapBuffers(); +} + +void UITestCanvas::OnIdle(wxIdleEvent &event) { + Refresh(false); +} + +void UITestCanvas::OnMouseMoved(wxMouseEvent& event) { + InteractiveCanvas::OnMouseMoved(event); + +} + +void UITestCanvas::OnMouseDown(wxMouseEvent& event) { + InteractiveCanvas::OnMouseDown(event); +} + +void UITestCanvas::OnMouseWheelMoved(wxMouseEvent& event) { + InteractiveCanvas::OnMouseWheelMoved(event); +} + +void UITestCanvas::OnMouseReleased(wxMouseEvent& event) { + InteractiveCanvas::OnMouseReleased(event); +} + +void UITestCanvas::OnMouseLeftWindow(wxMouseEvent& event) { + InteractiveCanvas::OnMouseLeftWindow(event); +} + +void UITestCanvas::OnMouseEnterWindow(wxMouseEvent& event) { + InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event); +} diff --git a/src/ui/UITestCanvas.h b/src/ui/UITestCanvas.h new file mode 100644 index 0000000..29e042c --- /dev/null +++ b/src/ui/UITestCanvas.h @@ -0,0 +1,36 @@ +#pragma once + +#include "wx/glcanvas.h" +#include "wx/timer.h" + +#include +#include + +#include "InteractiveCanvas.h" +#include "UITestContext.h" +#include "MouseTracker.h" + +#include "fftw3.h" +#include "Timer.h" + +class UITestCanvas: public InteractiveCanvas { +public: + UITestCanvas(wxWindow *parent, int *attribList = NULL); + ~UITestCanvas(); + +private: + void OnPaint(wxPaintEvent& event); + void OnIdle(wxIdleEvent &event); + + void OnMouseMoved(wxMouseEvent& event); + void OnMouseDown(wxMouseEvent& event); + void OnMouseWheelMoved(wxMouseEvent& event); + void OnMouseReleased(wxMouseEvent& event); + void OnMouseEnterWindow(wxMouseEvent& event); + void OnMouseLeftWindow(wxMouseEvent& event); + + UITestContext *glContext; + + wxDECLARE_EVENT_TABLE(); +}; + diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp new file mode 100644 index 0000000..f7c5e2a --- /dev/null +++ b/src/ui/UITestContext.cpp @@ -0,0 +1,42 @@ +#include "UITestContext.h" +#include "UITestCanvas.h" +#include "ColorTheme.h" + +UITestContext::UITestContext(UITestCanvas *canvas, wxGLContext *sharedContext) : +PrimaryGLContext(canvas, sharedContext) { + testPanel.setPosition(0.0, 0.0); + testPanel.setSize(1.0, 1.0); + testPanel.setMargin(0.02, 0.02, 0.1, 0.1); + testChildPanel.setPosition(0.0, 0.0); + testChildPanel.setMargin(0.05); + testChildPanel.setSize(1.0, 0.3); + testChildPanel2.setPosition(0.0, 0.3); + testChildPanel2.setSize(1.0, 0.3); + testChildPanel2.setMargin(0.05); + testPanel.addChild(&testChildPanel); + testPanel.addChild(&testChildPanel2); +} + +void UITestContext::DrawBegin() { + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + glClearColor(ThemeMgr::mgr.currentTheme->generalBackground.r, ThemeMgr::mgr.currentTheme->generalBackground.g, ThemeMgr::mgr.currentTheme->generalBackground.b, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_TEXTURE_2D); +} + +void UITestContext::Draw() { + testPanel.draw(); +} + +void UITestContext::DrawEnd() { + glFlush(); + + CheckGLError(); +} + diff --git a/src/ui/UITestContext.h b/src/ui/UITestContext.h new file mode 100644 index 0000000..9ac27bb --- /dev/null +++ b/src/ui/UITestContext.h @@ -0,0 +1,20 @@ +#pragma once + +#include "PrimaryGLContext.h" +#include "GLPanel.h" + +class UITestCanvas; + +class UITestContext: public PrimaryGLContext { +public: + UITestContext(UITestCanvas *canvas, wxGLContext *sharedContext); + + void DrawBegin(); + void Draw(); + void DrawEnd(); + +private: + GLPanel testPanel; + GLTestPanel testChildPanel; + GLPanel testChildPanel2; +}; From ab438738aa6f2479a0fcea76bd7e71bb7c4a64ff Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 21 Jun 2015 10:51:13 -0400 Subject: [PATCH 02/53] Fix conflict with wx RGBColor struct --- src/ui/GLPanel.h | 2 +- src/visual/ColorTheme.cpp | 280 ++++++++++++++++---------------- src/visual/ColorTheme.h | 54 +++--- src/visual/PrimaryGLContext.cpp | 8 +- src/visual/PrimaryGLContext.h | 8 +- src/visual/TuningCanvas.cpp | 8 +- src/visual/TuningContext.cpp | 4 +- src/visual/TuningContext.h | 4 +- 8 files changed, 184 insertions(+), 184 deletions(-) diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index 1d31bb7..9532cbd 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -53,7 +53,7 @@ private: } public: - typedef enum GLPanelFillType { GLPANEL_FILL_NONE, GLPANEL_FILL_SOLID } GLPanelFillType; + typedef enum GLPanelFillType { GLPANEL_FILL_NONE, GLPANEL_FILL_SOLID, GLPANEL_FILL_GRAD_X, GLPANEL_FILL_GRAD_Y, GLPANEL_FILL_GRAD_BAR_X, GLPANEL_FILL_GRAD_BAR_Y } GLPanelFillType; typedef enum GLPanelCoordinateSystem { GLPANEL_Y_DOWN_ZERO_ONE, GLPANEL_Y_UP_ZERO_ONE, GLPANEL_Y_UP, GLPANEL_Y_DOWN } GLPanelCoordinateSystem; float pos[2]; float size[2]; diff --git a/src/visual/ColorTheme.cpp b/src/visual/ColorTheme.cpp index 65b05b5..4038a1e 100644 --- a/src/visual/ColorTheme.cpp +++ b/src/visual/ColorTheme.cpp @@ -41,27 +41,27 @@ DefaultColorTheme::DefaultColorTheme() { waterfallGradient.addColor(GradientColor(1.0, 1.0, 0)); waterfallGradient.addColor(GradientColor(1.0, 0.2, 0.0)); waterfallGradient.generate(256); - waterfallHighlight = RGBColor(1, 1, 1); - waterfallNew = RGBColor(0, 1, 0); - waterfallHover = RGBColor(1, 1, 0); - waterfallDestroy = RGBColor(1, 0, 0); - fftLine = RGBColor(0.9, 0.9, 0.9); - fftHighlight = RGBColor(1, 1, 1); - scopeLine = RGBColor(0.9, 0.9, 0.9); - tuningBarLight = RGBColor(0.2, 0.2, 0.9); - tuningBarDark = RGBColor(0.0, 0.0, 0.35); - tuningBarUp = RGBColor(1.0, 139.0/255.0, 96.0/255.0); - tuningBarDown = RGBColor(148.0/255.0, 148.0/255.0, 1.0); - meterLevel = RGBColor(0.1, 0.75, 0.1); - meterValue = RGBColor(0.75, 0.1, 0.1); - text = RGBColor(1, 1, 1); - freqLine = RGBColor(1, 1, 1); - button = RGBColor(0.65, 0.65, 0.65); - buttonHighlight = RGBColor(1, 1, 0); + waterfallHighlight = RGB(1, 1, 1); + waterfallNew = RGB(0, 1, 0); + waterfallHover = RGB(1, 1, 0); + waterfallDestroy = RGB(1, 0, 0); + fftLine = RGB(0.9, 0.9, 0.9); + fftHighlight = RGB(1, 1, 1); + scopeLine = RGB(0.9, 0.9, 0.9); + tuningBarLight = RGB(0.2, 0.2, 0.9); + tuningBarDark = RGB(0.0, 0.0, 0.35); + tuningBarUp = RGB(1.0, 139.0/255.0, 96.0/255.0); + tuningBarDown = RGB(148.0/255.0, 148.0/255.0, 1.0); + meterLevel = RGB(0.1, 0.75, 0.1); + meterValue = RGB(0.75, 0.1, 0.1); + text = RGB(1, 1, 1); + freqLine = RGB(1, 1, 1); + button = RGB(0.65, 0.65, 0.65); + buttonHighlight = RGB(1, 1, 0); - scopeBackground = RGBColor(0.1, 0.1, 0.1); - fftBackground = RGBColor(0.1, 0.1, 0.1); - generalBackground = RGBColor(0.1, 0.1, 0.1); + scopeBackground = RGB(0.1, 0.1, 0.1); + fftBackground = RGB(0.1, 0.1, 0.1); + generalBackground = RGB(0.1, 0.1, 0.1); } @@ -72,27 +72,27 @@ RadarColorTheme::RadarColorTheme() { waterfallGradient.addColor(GradientColor(40.0 / 255.0, 240.0 / 255.0, 60.0 / 255.0)); waterfallGradient.addColor(GradientColor(250.0 / 255.0, 250.0 / 255.0, 250.0 / 255.0)); waterfallGradient.generate(256); - waterfallHighlight = RGBColor(1, 1, 1); - waterfallNew = RGBColor(0, 1, 0); - waterfallHover = RGBColor(1, 1, 0); - waterfallDestroy = RGBColor(1, 0, 0); - fftLine = RGBColor(0.8, 1.0, 0.8); - fftHighlight = RGBColor(1, 1, 1); - scopeLine = RGBColor(0.8, 1.0, 0.8); - tuningBarLight = RGBColor(0.0, 0.45, 0.0); - tuningBarDark = RGBColor(0.0, 0.1, 0.0); - tuningBarUp = RGBColor(1.0, 139.0/255.0, 96.0/255.0); - tuningBarDown = RGBColor(148.0/255.0, 0.0, 0.0); - meterLevel = RGBColor(0, 0.5, 0); - meterValue = RGBColor(0, 0.5, 0); - text = RGBColor(0.8, 1.0, 0.8); - freqLine = RGBColor(1, 1, 1); - button = RGBColor(0.65, 0.75, 0.65); - buttonHighlight = RGBColor(0.65, 1.0, 0.65); + waterfallHighlight = RGB(1, 1, 1); + waterfallNew = RGB(0, 1, 0); + waterfallHover = RGB(1, 1, 0); + waterfallDestroy = RGB(1, 0, 0); + fftLine = RGB(0.8, 1.0, 0.8); + fftHighlight = RGB(1, 1, 1); + scopeLine = RGB(0.8, 1.0, 0.8); + tuningBarLight = RGB(0.0, 0.45, 0.0); + tuningBarDark = RGB(0.0, 0.1, 0.0); + tuningBarUp = RGB(1.0, 139.0/255.0, 96.0/255.0); + tuningBarDown = RGB(148.0/255.0, 0.0, 0.0); + meterLevel = RGB(0, 0.5, 0); + meterValue = RGB(0, 0.5, 0); + text = RGB(0.8, 1.0, 0.8); + freqLine = RGB(1, 1, 1); + button = RGB(0.65, 0.75, 0.65); + buttonHighlight = RGB(0.65, 1.0, 0.65); - scopeBackground = RGBColor(0.05, 0.1, 0.05); - fftBackground = RGBColor(0.05, 0.1, 0.05); - generalBackground = RGBColor(0.05, 0.1, 0.05); + scopeBackground = RGB(0.05, 0.1, 0.05); + fftBackground = RGB(0.05, 0.1, 0.05); + generalBackground = RGB(0.05, 0.1, 0.05); } BlackAndWhiteColorTheme::BlackAndWhiteColorTheme() { @@ -101,27 +101,27 @@ BlackAndWhiteColorTheme::BlackAndWhiteColorTheme() { waterfallGradient.addColor(GradientColor(0.75, 0.75, 0.75)); waterfallGradient.addColor(GradientColor(1.0, 1.0, 1.0)); waterfallGradient.generate(256); - waterfallHighlight = RGBColor(1, 1, 0.9); - waterfallNew = RGBColor(0, 1, 0); - waterfallHover = RGBColor(1, 1, 0); - waterfallDestroy = RGBColor(1, 0, 0); - fftLine = RGBColor(0.9, 0.9, 0.9); - fftHighlight = RGBColor(1, 1, 0.9); - scopeLine = RGBColor(0.9, 0.9, 0.9); - tuningBarLight = RGBColor(0.4, 0.4, 0.4); - tuningBarDark = RGBColor(0.1, 0.1, 0.1); - tuningBarUp = RGBColor(0.8, 0.8, 0.8); - tuningBarDown = RGBColor(0.4, 0.4, 0.4); - meterLevel = RGBColor(0.5, 0.5, 0.5); - meterValue = RGBColor(0.5, 0.5, 0.5); - text = RGBColor(1, 1, 1); - freqLine = RGBColor(1, 1, 1); - button = RGBColor(0.65, 0.65, 0.65); - buttonHighlight = RGBColor(1, 1, 1); + waterfallHighlight = RGB(1, 1, 0.9); + waterfallNew = RGB(0, 1, 0); + waterfallHover = RGB(1, 1, 0); + waterfallDestroy = RGB(1, 0, 0); + fftLine = RGB(0.9, 0.9, 0.9); + fftHighlight = RGB(1, 1, 0.9); + scopeLine = RGB(0.9, 0.9, 0.9); + tuningBarLight = RGB(0.4, 0.4, 0.4); + tuningBarDark = RGB(0.1, 0.1, 0.1); + tuningBarUp = RGB(0.8, 0.8, 0.8); + tuningBarDown = RGB(0.4, 0.4, 0.4); + meterLevel = RGB(0.5, 0.5, 0.5); + meterValue = RGB(0.5, 0.5, 0.5); + text = RGB(1, 1, 1); + freqLine = RGB(1, 1, 1); + button = RGB(0.65, 0.65, 0.65); + buttonHighlight = RGB(1, 1, 1); - scopeBackground = RGBColor(0.1, 0.1, 0.1); - fftBackground = RGBColor(0.1, 0.1, 0.1); - generalBackground = RGBColor(0.1, 0.1, 0.1); + scopeBackground = RGB(0.1, 0.1, 0.1); + fftBackground = RGB(0.1, 0.1, 0.1); + generalBackground = RGB(0.1, 0.1, 0.1); } @@ -139,27 +139,27 @@ SharpColorTheme::SharpColorTheme() { waterfallGradient.addColor(GradientColor(1.0, 0.25, 0.0)); waterfallGradient.addColor(GradientColor(0.5, 0.1, 0.0)); waterfallGradient.generate(256); - waterfallHighlight = RGBColor(0.9, 0.9, 1.0); - waterfallNew = RGBColor(0, 1, 0); - waterfallHover = RGBColor(1, 1, 0); - waterfallDestroy = RGBColor(1, 0, 0); - fftLine = RGBColor(0.9, 0.9, 1.0); - fftHighlight = RGBColor(0.9, 0.9, 1.0); - scopeLine = RGBColor(0.85, 0.85, 1.0); - tuningBarLight = RGBColor(28.0 / 255.0, 106.0 / 255.0, 179.0 / 255.0); - tuningBarDark = RGBColor(14.0 / 255.0, 53.0 / 255.0, 89.5 / 255.0); - tuningBarUp = RGBColor(0.7, 0.7, 0.7); - tuningBarDown = RGBColor(1.0, 0.0, 0.0); - meterLevel = RGBColor(28.0 / 255.0, 106.0 / 255.0, 179.0 / 255.0); - meterValue = RGBColor(190.0 / 255.0, 190.0 / 255.0, 60.0 / 255.0); - text = RGBColor(0.9, 0.9, 1); - freqLine = RGBColor(0.85, 0.85, 1.0); - button = RGBColor(217.0 / 255.0, 218.0 / 255.0, 228.0 / 255.0); - buttonHighlight = RGBColor(208.0 / 255.0, 249.0 / 255.0, 255.0 / 255.0); + waterfallHighlight = RGB(0.9, 0.9, 1.0); + waterfallNew = RGB(0, 1, 0); + waterfallHover = RGB(1, 1, 0); + waterfallDestroy = RGB(1, 0, 0); + fftLine = RGB(0.9, 0.9, 1.0); + fftHighlight = RGB(0.9, 0.9, 1.0); + scopeLine = RGB(0.85, 0.85, 1.0); + tuningBarLight = RGB(28.0 / 255.0, 106.0 / 255.0, 179.0 / 255.0); + tuningBarDark = RGB(14.0 / 255.0, 53.0 / 255.0, 89.5 / 255.0); + tuningBarUp = RGB(0.7, 0.7, 0.7); + tuningBarDown = RGB(1.0, 0.0, 0.0); + meterLevel = RGB(28.0 / 255.0, 106.0 / 255.0, 179.0 / 255.0); + meterValue = RGB(190.0 / 255.0, 190.0 / 255.0, 60.0 / 255.0); + text = RGB(0.9, 0.9, 1); + freqLine = RGB(0.85, 0.85, 1.0); + button = RGB(217.0 / 255.0, 218.0 / 255.0, 228.0 / 255.0); + buttonHighlight = RGB(208.0 / 255.0, 249.0 / 255.0, 255.0 / 255.0); - scopeBackground = RGBColor(0.05, 0.05, 0.15); - fftBackground = RGBColor(0.05, 0.05, 0.15); - generalBackground = RGBColor(0.05, 0.05, 0.15); + scopeBackground = RGB(0.05, 0.05, 0.15); + fftBackground = RGB(0.05, 0.05, 0.15); + generalBackground = RGB(0.05, 0.05, 0.15); } RadColorTheme::RadColorTheme() { @@ -170,27 +170,27 @@ RadColorTheme::RadColorTheme() { waterfallGradient.addColor(GradientColor(1.0, 40.0 / 255.0, 40.0 / 255.0)); waterfallGradient.addColor(GradientColor(1.0, 1.0, 1.0)); waterfallGradient.generate(256); - waterfallHighlight = RGBColor(1, 1, 1); - waterfallNew = RGBColor(0, 1, 0); - waterfallHover = RGBColor(1, 1, 0); - waterfallDestroy = RGBColor(1, 0, 0); - fftLine = RGBColor(1.0, 0.9, 0.9); - fftHighlight = RGBColor(1, 1, 1); - scopeLine = RGBColor(1.0, 0.9, 0.9); - tuningBarLight = RGBColor(0.0, 0.45, 0.0); - tuningBarDark = RGBColor(0.0, 0.1, 0.0); - tuningBarUp = RGBColor(1.0, 0.0, 0.0); - tuningBarDown = RGBColor(0.0, 0.5, 1.0); - meterLevel = RGBColor(0, 0.5, 0); - meterValue = RGBColor(0.5, 0, 0); - text = RGBColor(1, 1, 1); - freqLine = RGBColor(1, 1, 1); - button = RGBColor(0.65, 0.65, 0.65); - buttonHighlight = RGBColor(0.76, 0.65, 0); + waterfallHighlight = RGB(1, 1, 1); + waterfallNew = RGB(0, 1, 0); + waterfallHover = RGB(1, 1, 0); + waterfallDestroy = RGB(1, 0, 0); + fftLine = RGB(1.0, 0.9, 0.9); + fftHighlight = RGB(1, 1, 1); + scopeLine = RGB(1.0, 0.9, 0.9); + tuningBarLight = RGB(0.0, 0.45, 0.0); + tuningBarDark = RGB(0.0, 0.1, 0.0); + tuningBarUp = RGB(1.0, 0.0, 0.0); + tuningBarDown = RGB(0.0, 0.5, 1.0); + meterLevel = RGB(0, 0.5, 0); + meterValue = RGB(0.5, 0, 0); + text = RGB(1, 1, 1); + freqLine = RGB(1, 1, 1); + button = RGB(0.65, 0.65, 0.65); + buttonHighlight = RGB(0.76, 0.65, 0); - scopeBackground = RGBColor(13.0 / 255.0, 47.0 / 255.0, 9.0 / 255.0); - fftBackground = RGBColor(0, 0, 50.0 / 255.0); - generalBackground = RGBColor(13.0 / 255.0, 47.0 / 255.0, 9.0 / 255.0); + scopeBackground = RGB(13.0 / 255.0, 47.0 / 255.0, 9.0 / 255.0); + fftBackground = RGB(0, 0, 50.0 / 255.0); + generalBackground = RGB(13.0 / 255.0, 47.0 / 255.0, 9.0 / 255.0); } TouchColorTheme::TouchColorTheme() { @@ -204,27 +204,27 @@ TouchColorTheme::TouchColorTheme() { waterfallGradient.addColor(GradientColor(255.0 / 255.0, 0.0 / 255.0, 0.0 / 255.0)); waterfallGradient.addColor(GradientColor(255.0 / 255.0, 255.0 / 255.0, 255.0 / 255.0)); waterfallGradient.generate(256); - waterfallHighlight = RGBColor(1, 1, 1); - waterfallNew = RGBColor(0, 1, 0); - waterfallHover = RGBColor(1, 1, 0); - waterfallDestroy = RGBColor(1, 0, 0); - fftLine = RGBColor(234.0 / 255.0, 232.0 / 255.0, 247.0 / 255.0); - fftHighlight = RGBColor(1.0, 1.0, 1.0); - scopeLine = RGBColor(234.0 / 255.0, 232.0 / 255.0, 247.0 / 255.0); - tuningBarLight = RGBColor(0.2, 0.2, 0.7); - tuningBarDark = RGBColor(0.1, 0.1, 0.45); - tuningBarUp = RGBColor(0.5, 139.0/255.0, 96.0/255.0); - tuningBarDown = RGBColor(0.6, 108.0/255.0, 1.0); - meterLevel = RGBColor(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); - meterValue = RGBColor(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); - text = RGBColor(1, 1, 1); - freqLine = RGBColor(1, 1, 1); - button = RGBColor(1.0, 1.0, 1.0); - buttonHighlight = RGBColor(208.0 / 255.0, 202.0 / 255.0, 247.0 / 255.0); + waterfallHighlight = RGB(1, 1, 1); + waterfallNew = RGB(0, 1, 0); + waterfallHover = RGB(1, 1, 0); + waterfallDestroy = RGB(1, 0, 0); + fftLine = RGB(234.0 / 255.0, 232.0 / 255.0, 247.0 / 255.0); + fftHighlight = RGB(1.0, 1.0, 1.0); + scopeLine = RGB(234.0 / 255.0, 232.0 / 255.0, 247.0 / 255.0); + tuningBarLight = RGB(0.2, 0.2, 0.7); + tuningBarDark = RGB(0.1, 0.1, 0.45); + tuningBarUp = RGB(0.5, 139.0/255.0, 96.0/255.0); + tuningBarDown = RGB(0.6, 108.0/255.0, 1.0); + meterLevel = RGB(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); + meterValue = RGB(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); + text = RGB(1, 1, 1); + freqLine = RGB(1, 1, 1); + button = RGB(1.0, 1.0, 1.0); + buttonHighlight = RGB(208.0 / 255.0, 202.0 / 255.0, 247.0 / 255.0); - scopeBackground = RGBColor(39.0 / 255.0, 36.0 / 255.0, 56.0 / 255.0); - fftBackground = RGBColor(39.0 / 255.0, 36.0 / 255.0, 56.0 / 255.0); - generalBackground = RGBColor(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); + scopeBackground = RGB(39.0 / 255.0, 36.0 / 255.0, 56.0 / 255.0); + fftBackground = RGB(39.0 / 255.0, 36.0 / 255.0, 56.0 / 255.0); + generalBackground = RGB(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); } @@ -239,27 +239,27 @@ HDColorTheme::HDColorTheme() { waterfallGradient.addColor(GradientColor(255.0 / 255.0, 235.0 / 255.0, 100.0 / 255.0)); waterfallGradient.addColor(GradientColor(250.0 / 255.0, 250.0 / 255.0, 250.0 / 255.0)); waterfallGradient.generate(256); - waterfallHighlight = RGBColor(1, 1, 1); - waterfallNew = RGBColor(0, 1, 0); - waterfallHover = RGBColor(1, 1, 0); - waterfallDestroy = RGBColor(1, 0, 0); - fftLine = RGBColor(0.9, 0.9, 0.9); - fftHighlight = RGBColor(1, 1, 1); - scopeLine = RGBColor(0.9, 0.9, 0.9); - tuningBarLight = RGBColor(0.4, 0.4, 1.0); - tuningBarDark = RGBColor(0.1, 0.1, 0.45); - tuningBarUp = RGBColor(1.0, 139.0/255.0, 96.0/255.0); - tuningBarDown = RGBColor(148.0/255.0, 148.0/255.0, 1.0); - meterLevel = RGBColor(0, 0.5, 0); - meterValue = RGBColor(0.0, 0.0, 1.0); - text = RGBColor(1, 1, 1); - freqLine = RGBColor(1, 1, 1); - button = RGBColor(0, 0.7, 0.7); - buttonHighlight = RGBColor(1, 1, 1); + waterfallHighlight = RGB(1, 1, 1); + waterfallNew = RGB(0, 1, 0); + waterfallHover = RGB(1, 1, 0); + waterfallDestroy = RGB(1, 0, 0); + fftLine = RGB(0.9, 0.9, 0.9); + fftHighlight = RGB(1, 1, 1); + scopeLine = RGB(0.9, 0.9, 0.9); + tuningBarLight = RGB(0.4, 0.4, 1.0); + tuningBarDark = RGB(0.1, 0.1, 0.45); + tuningBarUp = RGB(1.0, 139.0/255.0, 96.0/255.0); + tuningBarDown = RGB(148.0/255.0, 148.0/255.0, 1.0); + meterLevel = RGB(0, 0.5, 0); + meterValue = RGB(0.0, 0.0, 1.0); + text = RGB(1, 1, 1); + freqLine = RGB(1, 1, 1); + button = RGB(0, 0.7, 0.7); + buttonHighlight = RGB(1, 1, 1); - scopeBackground = RGBColor(0.0, 0.0, 48.0 / 255.0); - fftBackground = RGBColor(0.0, 0.0, 48.0 / 255.0); - generalBackground = RGBColor(0.0, 0.0, 0.0); + scopeBackground = RGB(0.0, 0.0, 48.0 / 255.0); + fftBackground = RGB(0.0, 0.0, 48.0 / 255.0); + generalBackground = RGB(0.0, 0.0, 0.0); } diff --git a/src/visual/ColorTheme.h b/src/visual/ColorTheme.h index f7d44e0..971863d 100644 --- a/src/visual/ColorTheme.h +++ b/src/visual/ColorTheme.h @@ -15,21 +15,21 @@ #define COLOR_THEME_RADAR 6 #define COLOR_THEME_MAX 7 -class RGBColor { +class RGB { public: float r, g, b; - RGBColor(float r, float g, float b) : + RGB(float r, float g, float b) : r(r), g(g), b(b) { } - RGBColor() : - RGBColor(0, 0, 0) { + RGB() : + RGB(0, 0, 0) { } - ~RGBColor() { + ~RGB() { } - RGBColor & operator=(const RGBColor &other) { + RGB & operator=(const RGB &other) { r = other.r; g = other.g; b = other.b; @@ -39,28 +39,28 @@ public: class ColorTheme { public: - RGBColor waterfallHighlight; - RGBColor waterfallNew; - RGBColor wfHighlight; - RGBColor waterfallHover; - RGBColor waterfallDestroy; - RGBColor fftLine; - RGBColor fftHighlight; - RGBColor scopeLine; - RGBColor tuningBarLight; - RGBColor tuningBarDark; - RGBColor tuningBarUp; - RGBColor tuningBarDown; - RGBColor meterLevel; - RGBColor meterValue; - RGBColor text; - RGBColor freqLine; - RGBColor button; - RGBColor buttonHighlight; + RGB waterfallHighlight; + RGB waterfallNew; + RGB wfHighlight; + RGB waterfallHover; + RGB waterfallDestroy; + RGB fftLine; + RGB fftHighlight; + RGB scopeLine; + RGB tuningBarLight; + RGB tuningBarDark; + RGB tuningBarUp; + RGB tuningBarDown; + RGB meterLevel; + RGB meterValue; + RGB text; + RGB freqLine; + RGB button; + RGB buttonHighlight; - RGBColor scopeBackground; - RGBColor fftBackground; - RGBColor generalBackground; + RGB scopeBackground; + RGB fftBackground; + RGB generalBackground; Gradient waterfallGradient; diff --git a/src/visual/PrimaryGLContext.cpp b/src/visual/PrimaryGLContext.cpp index 427f436..66655b6 100644 --- a/src/visual/PrimaryGLContext.cpp +++ b/src/visual/PrimaryGLContext.cpp @@ -95,7 +95,7 @@ GLFont &PrimaryGLContext::getFont(GLFontSize esize) { return fonts[esize]; } -void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBColor color, long long center_freq, long long srate) { +void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGB color, long long center_freq, long long srate) { if (!demod) { return; } @@ -176,7 +176,7 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBColor color, } -void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBColor color, long long center_freq, long long srate) { +void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGB color, long long center_freq, long long srate) { if (!demod) { return; } @@ -273,7 +273,7 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBColor color, lon } -void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBColor color, float w, long long center_freq, long long srate) { +void PrimaryGLContext::DrawFreqSelector(float uxPos, RGB color, float w, long long center_freq, long long srate) { DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); long long bw = 0; @@ -324,7 +324,7 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBColor color, float w, lo } -void PrimaryGLContext::DrawRangeSelector(float uxPos1, float uxPos2, RGBColor color) { +void PrimaryGLContext::DrawRangeSelector(float uxPos1, float uxPos2, RGB color) { if (uxPos2 < uxPos1) { float temp = uxPos2; uxPos2=uxPos1; diff --git a/src/visual/PrimaryGLContext.h b/src/visual/PrimaryGLContext.h index 1a4371b..1f276f8 100644 --- a/src/visual/PrimaryGLContext.h +++ b/src/visual/PrimaryGLContext.h @@ -24,10 +24,10 @@ public: void BeginDraw(float r, float g, float b); void EndDraw(); - void DrawFreqSelector(float uxPos, RGBColor color, float w = 0, long long center_freq = -1, long long srate = 0); - void DrawRangeSelector(float uxPos1, float uxPos2, RGBColor color); - void DrawDemod(DemodulatorInstance *demod, RGBColor color, long long center_freq = -1, long long srate = 0); - void DrawDemodInfo(DemodulatorInstance *demod, RGBColor color, long long center_freq = -1, long long srate = 0); + void DrawFreqSelector(float uxPos, RGB color, float w = 0, long long center_freq = -1, long long srate = 0); + void DrawRangeSelector(float uxPos1, float uxPos2, RGB color); + void DrawDemod(DemodulatorInstance *demod, RGB color, long long center_freq = -1, long long srate = 0); + void DrawDemodInfo(DemodulatorInstance *demod, RGB color, long long center_freq = -1, long long srate = 0); static GLFont &getFont(GLFontSize esize); diff --git a/src/visual/TuningCanvas.cpp b/src/visual/TuningCanvas.cpp index 273fbf0..d64edbd 100644 --- a/src/visual/TuningCanvas.cpp +++ b/src/visual/TuningCanvas.cpp @@ -84,10 +84,10 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { 0.75, mouseTracker.getOriginMouseX(), mouseTracker.getMouseX()); } - RGBColor clr = top ? ThemeMgr::mgr.currentTheme->tuningBarUp : ThemeMgr::mgr.currentTheme->tuningBarDown; + RGB clr = top ? ThemeMgr::mgr.currentTheme->tuningBarUp : ThemeMgr::mgr.currentTheme->tuningBarDown; - RGBColor clrDark = ThemeMgr::mgr.currentTheme->tuningBarDark; - RGBColor clrMid = ThemeMgr::mgr.currentTheme->tuningBarLight; + RGB clrDark = ThemeMgr::mgr.currentTheme->tuningBarDark; + RGB clrMid = ThemeMgr::mgr.currentTheme->tuningBarLight; glContext->DrawTunerBarIndexed(1, 3, 11, freqDP, freqW, clrMid, 0.25, true, true); // freq glContext->DrawTunerBarIndexed(4, 6, 11, freqDP, freqW, clrDark, 0.25, true, true); @@ -129,7 +129,7 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glContext->DrawTuner(freq, 11, freqDP, freqW); int snap = wxGetApp().getFrequencySnap(); if (snap != 1) { - glContext->DrawTunerDigitBox((int)log10(snap), 11, freqDP, freqW, RGBColor(1.0,0.0,0.0)); + glContext->DrawTunerDigitBox((int)log10(snap), 11, freqDP, freqW, RGB(1.0,0.0,0.0)); } } glContext->DrawTuner(bw, 7, bwDP, bwW); diff --git a/src/visual/TuningContext.cpp b/src/visual/TuningContext.cpp index 8d1bdba..338a6b1 100644 --- a/src/visual/TuningContext.cpp +++ b/src/visual/TuningContext.cpp @@ -112,7 +112,7 @@ void TuningContext::DrawTuner(long long freq, int count, float displayPos, float } -void TuningContext::DrawTunerDigitBox(int index, int count, float displayPos, float displayWidth, RGBColor c) { +void TuningContext::DrawTunerDigitBox(int index, int count, float displayPos, float displayWidth, RGB c) { GLint vp[4]; glGetIntegerv( GL_VIEWPORT, vp); @@ -152,7 +152,7 @@ int TuningContext::GetTunerDigitIndex(float mPos, int count, float displayPos, f return count - index; } -void TuningContext::DrawTunerBarIndexed(int start, int end, int count, float displayPos, float displayWidth, RGBColor color, float alpha, bool top, +void TuningContext::DrawTunerBarIndexed(int start, int end, int count, float displayPos, float displayWidth, RGB color, float alpha, bool top, bool bottom) { float ofs = (displayWidth / (float) count); float p2 = displayPos + ofs * (float) (count - start + 1); diff --git a/src/visual/TuningContext.h b/src/visual/TuningContext.h index 436a1f1..ee88a37 100644 --- a/src/visual/TuningContext.h +++ b/src/visual/TuningContext.h @@ -14,9 +14,9 @@ public: void DrawBegin(); void Draw(float r, float g, float b, float a, float p1, float p2); void DrawTuner(long long freq, int count, float displayPos, float displayWidth); - void DrawTunerDigitBox(int index, int count, float displayPos, float displayWidth, RGBColor c); + void DrawTunerDigitBox(int index, int count, float displayPos, float displayWidth, RGB c); int GetTunerDigitIndex(float mPos, int count, float displayPos, float displayWidth); - void DrawTunerBarIndexed(int start, int end, int count, float displayPos, float displayWidth, RGBColor color, float alpha, bool top, bool bottom); + void DrawTunerBarIndexed(int start, int end, int count, float displayPos, float displayWidth, RGB color, float alpha, bool top, bool bottom); void DrawDemodFreqBw(long long freq, unsigned int bw, long long center); void DrawEnd(); From adbb853c6df605ebe5ac98dc130e492d6ce4f9d4 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 21 Jun 2015 11:58:14 -0400 Subject: [PATCH 03/53] GLPanel gradient background fills --- src/ui/GLPanel.cpp | 148 +++++++++++++++++++++++++++++++++++++-- src/ui/GLPanel.h | 47 ++----------- src/ui/UITestContext.cpp | 10 +++ 3 files changed, 160 insertions(+), 45 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index 79f9ac8..5342e0e 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -2,16 +2,115 @@ #include "GLPanel.h" - -GLPanel::GLPanel() : fill(GLPANEL_FILL_SOLID), coord(GLPANEL_Y_DOWN_ZERO_ONE), contentsVisible(true) { +GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), coord(GLPANEL_Y_DOWN_ZERO_ONE), contentsVisible(true) { pos[0] = 0.0f; pos[1] = 0.0f; size[0] = 1.0f; size[1] = 1.0f; - + fill[0] = RGB(0.5,0.5,0.5); + fill[1] = RGB(0.1,0.1,0.1); genArrays(); } +void GLPanel::genArrays() { + if (fillType == GLPANEL_FILL_SOLID || fillType == GLPANEL_FILL_GRAD_X || fillType == GLPANEL_FILL_GRAD_Y) { + glPoints.reserve(2 * 4); + glPoints.resize(2 * 4); + glColors.reserve(3 * 4); + glColors.resize(3 * 4); + + float pts[2 * 4] = { + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f + }; + + RGB c[4]; + + if (fillType == GLPANEL_FILL_SOLID) { + c[0] = c[1] = c[2] = c[3] = fill[0]; + } else if (fillType == GLPANEL_FILL_GRAD_X) { + c[0] = c[1] = fill[0]; + c[2] = c[3] = fill[1]; + } else if (fillType == GLPANEL_FILL_GRAD_Y) { + c[0] = c[3] = fill[0]; + c[1] = c[2] = fill[1]; + } + + float clr[3 * 4] = { + c[0].r, c[0].g, c[0].b, + c[1].r, c[1].g, c[1].b, + c[2].r, c[2].g, c[2].b, + c[3].r, c[3].g, c[3].b + }; + + glPoints.assign(pts, pts + (2 * 4)); + glColors.assign(clr, clr + (3 * 4)); + } else { + glPoints.reserve(2 * 8); + glPoints.resize(2 * 8); + glColors.reserve(3 * 8); + glColors.resize(3 * 8); + + RGB c[8]; + + if (fillType == GLPANEL_FILL_GRAD_BAR_X) { + float pts[2 * 8] = { + 0.0f, 0.0f, + 0.0f, 1.0f, + 0.5f, 1.0f, + 0.5f, 0.0f, + + 0.5f, 0.0f, + 0.5f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f + }; + glPoints.assign(pts, pts + (2 * 8)); + + c[0] = c[1] = fill[0]; + c[2] = c[3] = fill[1]; + + c[4] = c[5] = fill[1]; + c[6] = c[7] = fill[0]; + + } else if (fillType == GLPANEL_FILL_GRAD_BAR_Y) { + float pts[2 * 8] = { + 0.0f, 0.0f, + 0.0f, 0.5f, + 1.0f, 0.5f, + 1.0f, 0.0f, + + 0.0f, 0.5f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.5f + }; + glPoints.assign(pts, pts + (2 * 8)); + + c[0] = c[3] = fill[0]; + c[1] = c[2] = fill[1]; + + c[4] = c[7] = fill[1]; + c[5] = c[6] = fill[0]; + } + + float clr[3 * 8] = { + c[0].r, c[0].g, c[0].b, + c[1].r, c[1].g, c[1].b, + c[2].r, c[2].g, c[2].b, + c[3].r, c[3].g, c[3].b, + c[4].r, c[4].g, c[4].b, + c[5].r, c[5].g, c[5].b, + c[6].r, c[6].g, c[6].b, + c[7].r, c[7].g, c[7].b + }; + + glColors.assign(clr, clr + (3 * 8)); + } +} + void GLPanel::setViewport() { GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp); @@ -39,9 +138,22 @@ float GLPanel::getHeightPx() { } void GLPanel::setFill(GLPanelFillType fill_mode) { - fill = fill_mode; + fillType = fill_mode; + genArrays(); } +void GLPanel::setFillColor(RGB color1) { + fill[0] = color1; + genArrays(); +} + +void GLPanel::setFillColor(RGB color1, RGB color2) { + fill[0] = color1; + fill[1] = color2; + genArrays(); +} + + void GLPanel::setMargin(float marg) { margin.left = margin.right = margin.top = margin.bottom = marg; } @@ -96,7 +208,7 @@ void GLPanel::draw(GLPanel *parent) { glTranslatef(pos[0]+margin.left, pos[1]+margin.top, 0); glScalef(size[0]-(margin.left+margin.right), size[1]-(margin.top+margin.bottom), 0); - if (fill != GLPANEL_FILL_NONE) { + if (fillType != GLPANEL_FILL_NONE) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_FLOAT, 0, &glPoints[0]); @@ -119,3 +231,29 @@ void GLPanel::draw(GLPanel *parent) { glPopMatrix(); } } + + + + + + +void GLTestPanel::drawPanelContents() { + glColor3f(1.0,1.0,1.0); + glBegin(GL_LINES); + glVertex2f(0, 0.5); + glVertex2f(1, 0.5); + glVertex2f(0.5, 0); + glVertex2f(0.5, 1); + + glVertex2f(0.5, 1); + glVertex2f(0.48, 0.80); + glVertex2f(0.5, 1); + glVertex2f(0.52, 0.80); + + glVertex2f(1, 0.5); + glVertex2f(0.90, 0.25); + glVertex2f(1, 0.5); + glVertex2f(0.90, 0.75); + + glEnd(); +} diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index 9532cbd..7654c04 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -2,6 +2,7 @@ #include #include "GLExt.h" +#include "ColorTheme.h" class GLPanelEdges { public: @@ -26,31 +27,7 @@ private: std::vector glPoints; std::vector glColors; - void genArrays() { - if (!glPoints.size()) { - glPoints.resize(2 * 4); - glColors.resize(3 * 4); - } - - float pts[2 * 4] = { - 0.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, - 1.0f, 0.0f - }; - - float clr[3 * 4] = { - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0, - 1.0, 1.0, 1.0 - }; - - glPoints.reserve(2 * 4); - glColors.reserve(3 * 4); - glPoints.assign(pts, pts + (2 * 4)); - glColors.assign(clr, clr + (3 * 4)); - } + void genArrays(); public: typedef enum GLPanelFillType { GLPANEL_FILL_NONE, GLPANEL_FILL_SOLID, GLPANEL_FILL_GRAD_X, GLPANEL_FILL_GRAD_Y, GLPANEL_FILL_GRAD_BAR_X, GLPANEL_FILL_GRAD_BAR_Y } GLPanelFillType; @@ -58,10 +35,11 @@ public: float pos[2]; float size[2]; float view[2]; - GLPanelFillType fill; + GLPanelFillType fillType; GLPanelCoordinateSystem coord; GLPanelEdges margin; GLPanelEdges border; + RGB fill[2]; bool contentsVisible; std::vector children; @@ -75,6 +53,8 @@ public: float getHeightPx(); void setFill(GLPanelFillType fill_mode); + void setFillColor(RGB color1); + void setFillColor(RGB color1, RGB color2); void setMargin(float marg); void setMargin(float margl, float margr, float margt, float margb); @@ -92,18 +72,5 @@ public: } - void drawPanelContents() { - glColor3f(1.0,1.0,1.0); - glBegin(GL_LINES); - glVertex2f(0, 0.5); - glVertex2f(1, 0.5); - glVertex2f(0.5, 0); - glVertex2f(0.5, 1); - - glVertex2f(0.5, 1); - glVertex2f(0.48, 0.80); - glVertex2f(0.5, 1); - glVertex2f(0.52, 0.80); - glEnd(); - } + void drawPanelContents(); }; diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index f7c5e2a..aecd307 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -4,15 +4,25 @@ UITestContext::UITestContext(UITestCanvas *canvas, wxGLContext *sharedContext) : PrimaryGLContext(canvas, sharedContext) { + testPanel.setPosition(0.0, 0.0); testPanel.setSize(1.0, 1.0); testPanel.setMargin(0.02, 0.02, 0.1, 0.1); + testPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_Y); + testPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); + testChildPanel.setPosition(0.0, 0.0); testChildPanel.setMargin(0.05); testChildPanel.setSize(1.0, 0.3); + testChildPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X); + testChildPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); + testChildPanel2.setPosition(0.0, 0.3); testChildPanel2.setSize(1.0, 0.3); testChildPanel2.setMargin(0.05); + testChildPanel2.setFill(GLPanel::GLPANEL_FILL_GRAD_X); + testChildPanel2.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); + testPanel.addChild(&testChildPanel); testPanel.addChild(&testChildPanel2); } From f2601edaa1a327fbfce04cb6b5869712d3958736 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 22 Jun 2015 22:07:46 -0400 Subject: [PATCH 04/53] Borders, mixed coordinate preparations --- src/ui/GLPanel.cpp | 122 +++++++++++++++++++++++++++++++-------- src/ui/GLPanel.h | 7 ++- src/ui/UITestContext.cpp | 3 + 3 files changed, 108 insertions(+), 24 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index 5342e0e..e09217a 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -9,10 +9,24 @@ GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), coord(GLPANEL_Y_DOWN_ZERO_ONE size[1] = 1.0f; fill[0] = RGB(0.5,0.5,0.5); fill[1] = RGB(0.1,0.1,0.1); + borderColor = RGB(0.8, 0.8, 0.8); genArrays(); } void GLPanel::genArrays() { + + float min, mid, max; + + if (coord == GLPANEL_Y_DOWN || coord == GLPANEL_Y_UP) { + min = -1; + mid = 0; + max = 1; + } else { + min = 0; + mid = 0.5; + max = 1; + } + if (fillType == GLPANEL_FILL_SOLID || fillType == GLPANEL_FILL_GRAD_X || fillType == GLPANEL_FILL_GRAD_Y) { glPoints.reserve(2 * 4); glPoints.resize(2 * 4); @@ -20,10 +34,10 @@ void GLPanel::genArrays() { glColors.resize(3 * 4); float pts[2 * 4] = { - 0.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, - 1.0f, 0.0f + min, min, + min, max, + max, max, + max, min }; RGB c[4]; @@ -57,15 +71,15 @@ void GLPanel::genArrays() { if (fillType == GLPANEL_FILL_GRAD_BAR_X) { float pts[2 * 8] = { - 0.0f, 0.0f, - 0.0f, 1.0f, - 0.5f, 1.0f, - 0.5f, 0.0f, + min, min, + min, max, + mid, max, + mid, min, - 0.5f, 0.0f, - 0.5f, 1.0f, - 1.0f, 1.0f, - 1.0f, 0.0f + mid, min, + mid, max, + max, max, + max, min }; glPoints.assign(pts, pts + (2 * 8)); @@ -77,15 +91,15 @@ void GLPanel::genArrays() { } else if (fillType == GLPANEL_FILL_GRAD_BAR_Y) { float pts[2 * 8] = { - 0.0f, 0.0f, - 0.0f, 0.5f, - 1.0f, 0.5f, - 1.0f, 0.0f, + min, min, + min, mid, + max, mid, + max, min, - 0.0f, 0.5f, - 0.0f, 1.0f, - 1.0f, 1.0f, - 1.0f, 0.5f + min, mid, + min, max, + max, max, + max, mid }; glPoints.assign(pts, pts + (2 * 8)); @@ -153,7 +167,6 @@ void GLPanel::setFillColor(RGB color1, RGB color2) { genArrays(); } - void GLPanel::setMargin(float marg) { margin.left = margin.right = margin.top = margin.bottom = marg; } @@ -165,6 +178,20 @@ void GLPanel::setMargin(float margl, float margr, float margt, float margb) { margin.bottom = margb; } +void GLPanel::setBorderColor(RGB clr) { + borderColor = clr; +} + +void GLPanel::setBorder(float bord) { + border.left = border.right = border.top = border.bottom = bord; +} + +void GLPanel::setBorder(float bordl, float bordr, float bordt, float bordb) { + border.left = bordl; + border.right = bordr; + border.top = bordt; + border.bottom = bordb; +} void GLPanel::addChild(GLPanel *childPanel) { children.push_back(childPanel); @@ -185,6 +212,18 @@ void GLPanel::drawPanelContents() { } void GLPanel::draw(GLPanel *parent) { + float min, mid, max; + + if (coord == GLPANEL_Y_DOWN || coord == GLPANEL_Y_UP) { + min = -1; + mid = 0; + max = 1; + } else { + min = 0; + mid = 0.5; + max = 1; + } + if (!parent) { if (coord == GLPANEL_Y_DOWN_ZERO_ONE) { glPushMatrix(); @@ -218,6 +257,45 @@ void GLPanel::draw(GLPanel *parent) { glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); + + if (border.left || border.right || border.top || border.bottom) { + glEnable(GL_LINE_SMOOTH); + glColor3f(borderColor.r, borderColor.g, borderColor.b); + + if (border.left) { + glLineWidth(border.left); + glBegin(GL_LINES); + glVertex2f(min, min); + glVertex2f(min, max); + glEnd(); + } + + if (border.right) { + glLineWidth(border.right); + glBegin(GL_LINES); + glVertex2f(max, min); + glVertex2f(max, max); + glEnd(); + } + + if (border.top) { + glLineWidth(border.top); + glBegin(GL_LINES); + glVertex2f(min, min); + glVertex2f(max, min); + glEnd(); + } + + if (border.bottom) { + glLineWidth(border.bottom); + glBegin(GL_LINES); + glVertex2f(min, max); + glVertex2f(max, max); + glEnd(); + } + + glDisable(GL_LINE_SMOOTH); + } } if (contentsVisible) { @@ -235,8 +313,6 @@ void GLPanel::draw(GLPanel *parent) { - - void GLTestPanel::drawPanelContents() { glColor3f(1.0,1.0,1.0); glBegin(GL_LINES); diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index 7654c04..4ec248d 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -40,6 +40,7 @@ public: GLPanelEdges margin; GLPanelEdges border; RGB fill[2]; + RGB borderColor; bool contentsVisible; std::vector children; @@ -57,7 +58,11 @@ public: void setFillColor(RGB color1, RGB color2); void setMargin(float marg); void setMargin(float margl, float margr, float margt, float margb); - + + void setBorderColor(RGB clr); + void setBorder(float bord); + void setBorder(float bordl, float bordr, float bordt, float bordb); + void addChild(GLPanel *childPanel); void drawChildren(); diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index aecd307..b1b48fb 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -16,12 +16,15 @@ PrimaryGLContext(canvas, sharedContext) { testChildPanel.setSize(1.0, 0.3); testChildPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X); testChildPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); + testChildPanel.setBorder(1); testChildPanel2.setPosition(0.0, 0.3); testChildPanel2.setSize(1.0, 0.3); testChildPanel2.setMargin(0.05); testChildPanel2.setFill(GLPanel::GLPANEL_FILL_GRAD_X); testChildPanel2.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); + testChildPanel2.setBorderColor(RGB(1.0,0.0,0.0)); + testChildPanel2.setBorder(2,4,6,8); testPanel.addChild(&testChildPanel); testPanel.addChild(&testChildPanel2); From 8753be05e74862fd19d78c12dd08eb50edd9a8b9 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 26 Jun 2015 22:04:16 -0400 Subject: [PATCH 05/53] Import cubicvr2 math; implement for GLPanel --- CMakeLists.txt | 16 ++ external/cubicvr2/math/aabb.h | 110 ++++++++++ external/cubicvr2/math/cubic_math.cpp | 27 +++ external/cubicvr2/math/cubic_math.h | 35 +++ external/cubicvr2/math/cubic_types.h | 41 ++++ external/cubicvr2/math/frustum.h | 166 ++++++++++++++ external/cubicvr2/math/mat3.h | 83 +++++++ external/cubicvr2/math/mat4.h | 304 ++++++++++++++++++++++++++ external/cubicvr2/math/plane.h | 32 +++ external/cubicvr2/math/quaternion.h | 100 +++++++++ external/cubicvr2/math/sphere.h | 34 +++ external/cubicvr2/math/transform.h | 175 +++++++++++++++ external/cubicvr2/math/triangle.h | 40 ++++ external/cubicvr2/math/vec2.h | 92 ++++++++ external/cubicvr2/math/vec3.h | 170 ++++++++++++++ external/cubicvr2/math/vec4.h | 71 ++++++ src/ui/GLPanel.cpp | 93 +++++--- src/ui/GLPanel.h | 13 +- src/ui/UITestContext.cpp | 2 +- 19 files changed, 1565 insertions(+), 39 deletions(-) create mode 100644 external/cubicvr2/math/aabb.h create mode 100644 external/cubicvr2/math/cubic_math.cpp create mode 100644 external/cubicvr2/math/cubic_math.h create mode 100644 external/cubicvr2/math/cubic_types.h create mode 100644 external/cubicvr2/math/frustum.h create mode 100644 external/cubicvr2/math/mat3.h create mode 100644 external/cubicvr2/math/mat4.h create mode 100644 external/cubicvr2/math/plane.h create mode 100644 external/cubicvr2/math/quaternion.h create mode 100644 external/cubicvr2/math/sphere.h create mode 100644 external/cubicvr2/math/transform.h create mode 100644 external/cubicvr2/math/triangle.h create mode 100644 external/cubicvr2/math/vec2.h create mode 100644 external/cubicvr2/math/vec3.h create mode 100644 external/cubicvr2/math/vec4.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c6518a7..9a66d2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -264,6 +264,7 @@ SET (cubicsdr_sources external/tinyxml/tinystr.cpp external/tinyxml/tinyxmlparser.cpp external/tinyxml/tinyxmlerror.cpp + external/cubicvr2/math/cubic_math.cpp ) SET (cubicsdr_headers @@ -312,6 +313,20 @@ SET (cubicsdr_headers external/lodepng/lodepng.h external/tinyxml/tinyxml.h external/tinyxml/tinystr.h + external/cubicvr2/math/aabb.h + external/cubicvr2/math/cubic_math.h + external/cubicvr2/math/cubic_types.h + external/cubicvr2/math/frustum.h + external/cubicvr2/math/mat3.h + external/cubicvr2/math/mat4.h + external/cubicvr2/math/plane.h + external/cubicvr2/math/quaternion.h + external/cubicvr2/math/sphere.h + external/cubicvr2/math/transform.h + external/cubicvr2/math/triangle.h + external/cubicvr2/math/vec2.h + external/cubicvr2/math/vec3.h + external/cubicvr2/math/vec4.h ) include_directories ( @@ -325,6 +340,7 @@ include_directories ( ${PROJECT_SOURCE_DIR}/external/rtaudio ${PROJECT_SOURCE_DIR}/external/lodepng ${PROJECT_SOURCE_DIR}/external/tinyxml + ${PROJECT_SOURCE_DIR}/external/cubicvr2/math ) IF (MSVC) diff --git a/external/cubicvr2/math/aabb.h b/external/cubicvr2/math/aabb.h new file mode 100644 index 0000000..bcf34ba --- /dev/null +++ b/external/cubicvr2/math/aabb.h @@ -0,0 +1,110 @@ +// +// aabb.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__aabb__ +#define __CubicVR2__aabb__ + +#include +#include "vec3.h" + +namespace CubicVR { + + enum aabb_enum { AABB_DISJOINT, AABB_A_INSIDE_B, AABB_B_INSIDE_A, AABB_INTERSECT }; + + struct aabb { + vec3 min, max; + + aabb(vec3 min_in, vec3 max_in) { + min=min_in; + max=max_in; + } + + aabb() { + min=max=vec3(0,0,0); + } + + aabb engulf(aabb aabb, vec3 point) { + if (aabb.min[0] > point[0]) { + aabb.min[0] = point[0]; + } + if (aabb.min[1] > point[1]) { + aabb.min[1] = point[1]; + } + if (aabb.min[2] > point[2]) { + aabb.min[2] = point[2]; + } + if (aabb.max[0] < point[0]) { + aabb.max[0] = point[0]; + } + if (aabb.max[1] < point[1]) { + aabb.max[1] = point[1]; + } + if (aabb.max[2] < point[2]) { + aabb.max[2] = point[2]; + } + return aabb; + }; + + static aabb reset(aabb aabb, vec3 point=vec3(0.0f,0.0f,0.0f)) { + + aabb.min[0] = point[0]; + aabb.min[1] = point[1]; + aabb.min[2] = point[2]; + aabb.max[0] = point[0]; + aabb.max[1] = point[1]; + aabb.max[2] = point[2]; + + return aabb; + }; + + static vec3 size(aabb aabb) { + __float x = aabb.min[0] < aabb.max[0] ? aabb.max[0] - aabb.min[0] : aabb.min[0] - aabb.max[0]; + __float y = aabb.min[1] < aabb.max[1] ? aabb.max[1] - aabb.min[1] : aabb.min[1] - aabb.max[1]; + __float z = aabb.min[2] < aabb.max[2] ? aabb.max[2] - aabb.min[2] : aabb.min[2] - aabb.max[2]; + return vec3(x,y,z); + }; + /** + Returns positive integer if intersect between A and B, 0 otherwise. + For more detailed intersect result check value: + CubicVR.enums.aabb.INTERSECT if AABBs intersect + CubicVR.enums.aabb.A_INSIDE_B if boxA is inside boxB + CubicVR.enums.aabb.B_INSIDE_A if boxB is inside boxA + CubicVR.enums.aabb.DISJOINT if AABBs are disjoint (do not intersect) + */ + aabb_enum intersects(aabb boxA, aabb boxB) { + // Disjoint + if( boxA.min[0] > boxB.max[0] || boxA.max[0] < boxB.min[0] ){ + return AABB_DISJOINT; + } + if( boxA.min[1] > boxB.max[1] || boxA.max[1] < boxB.min[1] ){ + return AABB_DISJOINT; + } + if( boxA.min[2] > boxB.max[2] || boxA.max[2] < boxB.min[2] ){ + return AABB_DISJOINT; + } + + // boxA is inside boxB. + if( boxA.min[0] >= boxB.min[0] && boxA.max[0] <= boxB.max[0] && + boxA.min[1] >= boxB.min[1] && boxA.max[1] <= boxB.max[1] && + boxA.min[2] >= boxB.min[2] && boxA.max[2] <= boxB.max[2]) { + return AABB_A_INSIDE_B; + } + // boxB is inside boxA. + if( boxB.min[0] >= boxA.min[0] && boxB.max[0] <= boxA.max[0] && + boxB.min[1] >= boxA.min[1] && boxB.max[1] <= boxA.max[1] && + boxB.min[2] >= boxA.min[2] && boxB.max[2] <= boxA.max[2]) { + return AABB_B_INSIDE_A; + } + + // Otherwise AABB's intersect. + return AABB_INTERSECT; + } + }; +}; + +#endif /* defined(__CubicVR2__aabb__) */ diff --git a/external/cubicvr2/math/cubic_math.cpp b/external/cubicvr2/math/cubic_math.cpp new file mode 100644 index 0000000..45470ff --- /dev/null +++ b/external/cubicvr2/math/cubic_math.cpp @@ -0,0 +1,27 @@ +// +// math.cpp +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#include "cubic_math.h" + +namespace CubicVR { + std::ostream& operator<<(std::ostream &strm, const vec4 &v) { + return strm << "{" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << "}"; + } + std::ostream& operator<<(std::ostream &strm, const vec3 &v) { + return strm << "{" << v.x << ", " << v.y << ", " << v.z << "}"; + } + std::ostream& operator<<(std::ostream &strm, const vec2 &v) { + return strm << "{" << v.x << ", " << v.y << "}"; + } + std::ostream& operator<<(std::ostream &strm, const mat4 &m) { + return strm << "{ " << m[0] << ", " << m[1] << ", " << m[2] << ", " << m[3] << endl + << " " << m[4] << ", " << m[5] << ", " << m[6] << ", " << m[7] << endl + << " " << m[8] << ", " << m[9] << ", " << m[10] << ", " << m[11] << endl + << " " << m[12] << ", " << m[13] << ", " << m[14] << ", " << m[15] << " }" << endl; + } +} diff --git a/external/cubicvr2/math/cubic_math.h b/external/cubicvr2/math/cubic_math.h new file mode 100644 index 0000000..7f74264 --- /dev/null +++ b/external/cubicvr2/math/cubic_math.h @@ -0,0 +1,35 @@ +// +// math.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__math__ +#define __CubicVR2__math__ + +#include + +#include "aabb.h" +#include "mat3.h" +#include "mat4.h" +#include "quaternion.h" +#include "transform.h" +#include "triangle.h" +#include "vec2.h" +#include "vec3.h" +#include "vec4.h" +#include "plane.h" +#include "sphere.h" +#include "frustum.h" + +namespace CubicVR { + std::ostream& operator<<(std::ostream &strm, const vec4 &v); + std::ostream& operator<<(std::ostream &strm, const vec3 &v); + std::ostream& operator<<(std::ostream &strm, const vec2 &v); + std::ostream& operator<<(std::ostream &strm, const mat4 &m); +} + + +#endif /* defined(__CubicVR2__math__) */ diff --git a/external/cubicvr2/math/cubic_types.h b/external/cubicvr2/math/cubic_types.h new file mode 100644 index 0000000..bc4ddc7 --- /dev/null +++ b/external/cubicvr2/math/cubic_types.h @@ -0,0 +1,41 @@ +// +// types.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-21. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef CubicVR2_types_h +#define CubicVR2_types_h + +namespace CubicVR { + + typedef double __float64; + typedef float __float32; + + typedef __float32 __float; + + #define COMBINE(x,y) x ## y + #define floatSG(c, x,y) \ + __float COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(__float value) { y = value; return *this; } + #define intSG(c, x,y) \ + int COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(int value) { y = value; return *this; } + #define uintSG(c, x,y) \ + unsigned int COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(unsigned int value) { y = value; return *this; } + #define boolSG(c,x,y) \ + bool COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(bool value) { y = value; return *this; } + #define stringSG(c,x,y) \ + string COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(string value) { y = value; return *this; } + #define isBoolSG(c,x,y) \ + bool COMBINE(is,x)() { return y; } \ + c & COMBINE(set,x)(bool value) { y = value; return *this; } + +} + +#endif diff --git a/external/cubicvr2/math/frustum.h b/external/cubicvr2/math/frustum.h new file mode 100644 index 0000000..5da030f --- /dev/null +++ b/external/cubicvr2/math/frustum.h @@ -0,0 +1,166 @@ +// +// frustum.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef CubicVR2_frustum_h +#define CubicVR2_frustum_h + +#include +#include "mat4.h" +#include "vec3.h" +#include "vec4.h" +#include "plane.h" + +namespace CubicVR { + + enum frustum_plane { PLANE_LEFT, PLANE_RIGHT, PLANE_TOP, PLANE_BOTTOM, PLANE_NEAR, PLANE_FAR }; + + struct frustum { + std::vector planes; + vec4 sphere; + + frustum() { + planes.resize(6); + for (int i = 0; i < 6; ++i) { + planes[i] = vec4(0, 0, 0, 0); + } //for + } //Frustum::Constructor + + void extract(vec3 position, mat4 mvMatrix, mat4 pMatrix) { + mat4 comboMatrix = mat4::multiply(pMatrix, mvMatrix, true); + + // Left clipping plane + planes[PLANE_LEFT][0] = comboMatrix[3] + comboMatrix[0]; + planes[PLANE_LEFT][1] = comboMatrix[7] + comboMatrix[4]; + planes[PLANE_LEFT][2] = comboMatrix[11] + comboMatrix[8]; + planes[PLANE_LEFT][3] = comboMatrix[15] + comboMatrix[12]; + + // Right clipping plane + planes[PLANE_RIGHT][0] = comboMatrix[3] - comboMatrix[0]; + planes[PLANE_RIGHT][1] = comboMatrix[7] - comboMatrix[4]; + planes[PLANE_RIGHT][2] = comboMatrix[11] - comboMatrix[8]; + planes[PLANE_RIGHT][3] = comboMatrix[15] - comboMatrix[12]; + + // Top clipping plane + planes[PLANE_TOP][0] = comboMatrix[3] - comboMatrix[1]; + planes[PLANE_TOP][1] = comboMatrix[7] - comboMatrix[5]; + planes[PLANE_TOP][2] = comboMatrix[11] - comboMatrix[9]; + planes[PLANE_TOP][3] = comboMatrix[15] - comboMatrix[13]; + + // Bottom clipping plane + planes[PLANE_BOTTOM][0] = comboMatrix[3] + comboMatrix[1]; + planes[PLANE_BOTTOM][1] = comboMatrix[7] + comboMatrix[5]; + planes[PLANE_BOTTOM][2] = comboMatrix[11] + comboMatrix[9]; + planes[PLANE_BOTTOM][3] = comboMatrix[15] + comboMatrix[13]; + + // Near clipping plane + planes[PLANE_NEAR][0] = comboMatrix[3] + comboMatrix[2]; + planes[PLANE_NEAR][1] = comboMatrix[7] + comboMatrix[6]; + planes[PLANE_NEAR][2] = comboMatrix[11] + comboMatrix[10]; + planes[PLANE_NEAR][3] = comboMatrix[15] + comboMatrix[14]; + + // Far clipping plane + planes[PLANE_FAR][0] = comboMatrix[3] - comboMatrix[2]; + planes[PLANE_FAR][1] = comboMatrix[7] - comboMatrix[6]; + planes[PLANE_FAR][2] = comboMatrix[11] - comboMatrix[10]; + planes[PLANE_FAR][3] = comboMatrix[15] - comboMatrix[14]; + + for (unsigned int i = 0; i < 6; ++i) { + planes[i] = vec4::normalize(planes[i]); + } + + //Sphere + __float fov = 1 / pMatrix[5]; + __float near = -planes[PLANE_NEAR][3]; + __float far = planes[PLANE_FAR][3]; + __float view_length = far - near; + __float height = view_length * fov; + __float width = height; + + vec3 P(0, 0, near + view_length * 0.5f); + vec3 Q(width, height, near + view_length); + vec3 diff = vec3::subtract(P, Q); + __float diff_mag = vec3::length(diff); + + vec3 look_v = vec3(comboMatrix[3], comboMatrix[9], comboMatrix[10]); + __float look_mag = vec3::length(look_v); + look_v = vec3::multiply(look_v, 1 / look_mag); + + vec3 pos = vec3(position[0], position[1], position[2]); + pos = vec3::add(pos, vec3::multiply(look_v, view_length * 0.5f)); + pos = vec3::add(pos, vec3::multiply(look_v, 1)); + + sphere = vec4(pos[0], pos[1], pos[2], diff_mag); + + }; //Frustum::extract + + int contains_sphere(vec4 sphere) { + + for (unsigned int i = 0; i < 6; ++i) { + vec4 &p = planes[i]; + vec3 normal = vec3(p[0], p[1], p[2]); + __float distance = vec3::dot(normal, vec3(sphere[0],sphere[1],sphere[2])) + p[3]; + + //OUT + if (distance < -sphere[3]) { + return -1; + } + + //INTERSECT + if (fabs(distance) < sphere[3]) { + return 0; + } + + } //for + //IN + return 1; + }; //Frustum::contains_sphere + + int contains_box(aabb bbox) { + int total_in = 0; + + vec3 points[8]; + + points[0] = bbox.min; + points[1] = vec3(bbox.min[0], bbox.min[1], bbox.max[2]); + points[2] = vec3(bbox.min[0], bbox.max[1], bbox.min[2]); + points[3] = vec3(bbox.min[0], bbox.max[1], bbox.max[2]); + points[4] = vec3(bbox.max[0], bbox.min[1], bbox.min[2]); + points[5] = vec3(bbox.max[0], bbox.min[1], bbox.max[2]); + points[6] = vec3(bbox.max[0], bbox.max[1], bbox.min[2]); + points[7] = bbox.max; + + for (unsigned int i = 0; i < 6; ++i) { + unsigned int in_count = 8; + unsigned int point_in = 1; + + for (unsigned int j = 0; j < 8; ++j) { + if (plane::classifyPoint(planes[i], points[j]) == -1) { + point_in = 0; + --in_count; + } //if + } //for j + + //OUT + if (in_count == 0) { + return -1; + } + + total_in += point_in; + } //for i + //IN + if (total_in == 6) { + return 1; + } + + return 0; + }; //Frustum::contains_box + + }; +} + +#endif diff --git a/external/cubicvr2/math/mat3.h b/external/cubicvr2/math/mat3.h new file mode 100644 index 0000000..90553c4 --- /dev/null +++ b/external/cubicvr2/math/mat3.h @@ -0,0 +1,83 @@ +// +// mat3.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__mat3__ +#define __CubicVR2__mat3__ + +#include +#include "vec3.h" + +namespace CubicVR { + + #define mat3SG(c,x,y) \ + mat3 COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(mat3 value) { y = value; return *this; } + + struct mat3 { + __float a,b,c,d,e,f,g,h,i; + + // __float operator [] (unsigned i) const { return ((__float *)this)[i]; } + __float& operator [] (unsigned i) { return ((__float *)this)[i]; } + operator __float*() const { return (__float *)this; } + + mat3(__float ai,__float bi,__float ci,__float di,__float ei,__float fi,__float gi,__float hi,__float ii) { + a = ai; b = bi; c = ci; d = di; e = ei; f = fi; g = gi; h = hi; i = ii; + }; + + mat3() { memset((__float *)this, 0, sizeof(mat3)); } + // mat3 operator* (mat4 m) { return mat3::multiply(*this,m); }; + // void operator*= (mat4 m) { *this = mat3::multiply(*this,m); }; + + + static mat3 identity() { + return mat3(1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f); + } + + static void transpose_inline(mat3 &mat) { + __float a01 = mat[1], a02 = mat[2], a12 = mat[5]; + + mat[1] = mat[3]; + mat[2] = mat[6]; + mat[3] = a01; + mat[5] = mat[7]; + mat[6] = a02; + mat[7] = a12; + }; + + static mat3 transpose(mat3 mat_in) { + __float a01 = mat_in[1], a02 = mat_in[2], a12 = mat_in[5]; + + mat3 mat; + + mat[1] = mat_in[3]; + mat[2] = mat_in[6]; + mat[3] = a01; + mat[5] = mat_in[7]; + mat[6] = a02; + mat[7] = a12; + + return mat; + }; + + static vec3 multiply(mat3 m1, vec3 m2) { + vec3 mOut; + + mOut[0] = m2[0] * m1[0] + m2[3] * m1[1] + m2[6] * m1[2] ; + mOut[1] = m2[1] * m1[0] + m2[4] * m1[1] + m2[7] * m1[2] ; + mOut[2] = m2[2] * m1[0] + m2[5] * m1[1] + m2[8] * m1[2]; + + return mOut; + }; + }; + + +} + +#endif /* defined(__CubicVR2__mat3__) */ diff --git a/external/cubicvr2/math/mat4.h b/external/cubicvr2/math/mat4.h new file mode 100644 index 0000000..b54029b --- /dev/null +++ b/external/cubicvr2/math/mat4.h @@ -0,0 +1,304 @@ +// +// mat4.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-21. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__mat4__ +#define __CubicVR2__mat4__ + +#include +#include "cubic_types.h" +#include "vec3.h" +#include "vec4.h" +#include "mat3.h" +#include + +namespace CubicVR { + using namespace std; + #define mat4SG(c,x,y) \ + mat4 COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(mat4 value) { y = value; return *this; } + struct mat4 { + __float a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p; + + // __float operator [] (unsigned i) const { return ((__float *)this)[i]; } + __float& operator [] (unsigned i) { return ((__float *)this)[i]; } + operator __float*() const { return (__float *)this; } + mat4(__float ai,__float bi,__float ci,__float di,__float ei,__float fi,__float gi,__float hi,__float ii,__float ji,__float ki,__float li,__float mi,__float ni,__float oi,__float pi) { + a = ai; b = bi; c = ci; d = di; e = ei; f = fi; g = gi; h = hi; i = ii; j = ji; k = ki; l = li; m = mi; n = ni; o = oi; p = pi; + } + mat4() { memset(this,0,sizeof(mat4)); } + mat4 operator* (mat4 m) { return mat4::multiply(*this, m, true); }; + void operator*= (mat4 m) { *this = mat4::multiply(*this, m, true); }; +// mat4 &operator= (const mat4 &m) { memcpy(this,(__float *)m,sizeof(__float)*16); return *this; }; + + static mat4 identity() { + return mat4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); + } + + static mat4 multiply(mat4 mLeft, mat4 mRight, bool updated) { + mat4 mOut; + + mOut[0] = mLeft[0] * mRight[0] + mLeft[4] * mRight[1] + mLeft[8] * mRight[2] + mLeft[12] * mRight[3]; + mOut[1] = mLeft[1] * mRight[0] + mLeft[5] * mRight[1] + mLeft[9] * mRight[2] + mLeft[13] * mRight[3]; + mOut[2] = mLeft[2] * mRight[0] + mLeft[6] * mRight[1] + mLeft[10] * mRight[2] + mLeft[14] * mRight[3]; + mOut[3] = mLeft[3] * mRight[0] + mLeft[7] * mRight[1] + mLeft[11] * mRight[2] + mLeft[15] * mRight[3]; + mOut[4] = mLeft[0] * mRight[4] + mLeft[4] * mRight[5] + mLeft[8] * mRight[6] + mLeft[12] * mRight[7]; + mOut[5] = mLeft[1] * mRight[4] + mLeft[5] * mRight[5] + mLeft[9] * mRight[6] + mLeft[13] * mRight[7]; + mOut[6] = mLeft[2] * mRight[4] + mLeft[6] * mRight[5] + mLeft[10] * mRight[6] + mLeft[14] * mRight[7]; + mOut[7] = mLeft[3] * mRight[4] + mLeft[7] * mRight[5] + mLeft[11] * mRight[6] + mLeft[15] * mRight[7]; + mOut[8] = mLeft[0] * mRight[8] + mLeft[4] * mRight[9] + mLeft[8] * mRight[10] + mLeft[12] * mRight[11]; + mOut[9] = mLeft[1] * mRight[8] + mLeft[5] * mRight[9] + mLeft[9] * mRight[10] + mLeft[13] * mRight[11]; + mOut[10] = mLeft[2] * mRight[8] + mLeft[6] * mRight[9] + mLeft[10] * mRight[10] + mLeft[14] * mRight[11]; + mOut[11] = mLeft[3] * mRight[8] + mLeft[7] * mRight[9] + mLeft[11] * mRight[10] + mLeft[15] * mRight[11]; + mOut[12] = mLeft[0] * mRight[12] + mLeft[4] * mRight[13] + mLeft[8] * mRight[14] + mLeft[12] * mRight[15]; + mOut[13] = mLeft[1] * mRight[12] + mLeft[5] * mRight[13] + mLeft[9] * mRight[14] + mLeft[13] * mRight[15]; + mOut[14] = mLeft[2] * mRight[12] + mLeft[6] * mRight[13] + mLeft[10] * mRight[14] + mLeft[14] * mRight[15]; + mOut[15] = mLeft[3] * mRight[12] + mLeft[7] * mRight[13] + mLeft[11] * mRight[14] + mLeft[15] * mRight[15]; + + return mOut; + }; + + static vec3 multiply(mat4 m1, vec3 m2, bool updated) { + vec3 mOut; + + mOut[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12]; + mOut[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13]; + mOut[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14]; + + return mOut; + } + + static mat4 perspective(__float fovy, __float aspect, __float near, __float far) { + __float yFac = tan(fovy * (float)M_PI / 360.0f); + __float xFac = yFac * aspect; + + return mat4( + 1.0f / xFac, 0, 0, 0, 0, 1.0f / yFac, 0, 0, 0, 0, -(far + near) / (far - near), -1, 0, 0, -(2.0f * far * near) / (far - near), 0); + }; + static mat4 ortho(__float left,__float right,__float bottom,__float top,__float near,__float far) { + return mat4(2.0f / (right - left), 0, 0, 0, 0, 2.0f / (top - bottom), 0, 0, 0, 0, -2.0f / (far - near), 0, -(left + right) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1); + }; + static __float determinant(mat4 m) { + + __float a0 = m[0] * m[5] - m[1] * m[4]; + __float a1 = m[0] * m[6] - m[2] * m[4]; + __float a2 = m[0] * m[7] - m[3] * m[4]; + __float a3 = m[1] * m[6] - m[2] * m[5]; + __float a4 = m[1] * m[7] - m[3] * m[5]; + __float a5 = m[2] * m[7] - m[3] * m[6]; + __float b0 = m[8] * m[13] - m[9] * m[12]; + __float b1 = m[8] * m[14] - m[10] * m[12]; + __float b2 = m[8] * m[15] - m[11] * m[12]; + __float b3 = m[9] * m[14] - m[10] * m[13]; + __float b4 = m[9] * m[15] - m[11] * m[13]; + __float b5 = m[10] * m[15] - m[11] * m[14]; + + __float det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0; + + return det; + }; + // coFactor: function (m, n, out) { + // // .. todo.. + // }, + + static mat4 transpose(mat4 m) { + return mat4(m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]); + }; + + static mat3 inverse_mat3(mat4 mat) { + mat3 dest; + + __float a00 = mat[0], a01 = mat[1], a02 = mat[2], + a10 = mat[4], a11 = mat[5], a12 = mat[6], + a20 = mat[8], a21 = mat[9], a22 = mat[10]; + + __float b01 = a22*a11-a12*a21, + b11 = -a22*a10+a12*a20, + b21 = a21*a10-a11*a20; + + __float d = a00*b01 + a01*b11 + a02*b21; + if (!d) { return dest; } + __float id = 1/d; + + dest[0] = b01*id; + dest[1] = (-a22*a01 + a02*a21)*id; + dest[2] = (a12*a01 - a02*a11)*id; + dest[3] = b11*id; + dest[4] = (a22*a00 - a02*a20)*id; + dest[5] = (-a12*a00 + a02*a10)*id; + dest[6] = b21*id; + dest[7] = (-a21*a00 + a01*a20)*id; + dest[8] = (a11*a00 - a01*a10)*id; + + return dest; + }; + + static mat4 inverse(mat4 m) { + mat4 m_inv; + + __float a0 = m[0] * m[5] - m[1] * m[4]; + __float a1 = m[0] * m[6] - m[2] * m[4]; + __float a2 = m[0] * m[7] - m[3] * m[4]; + __float a3 = m[1] * m[6] - m[2] * m[5]; + __float a4 = m[1] * m[7] - m[3] * m[5]; + __float a5 = m[2] * m[7] - m[3] * m[6]; + __float b0 = m[8] * m[13] - m[9] * m[12]; + __float b1 = m[8] * m[14] - m[10] * m[12]; + __float b2 = m[8] * m[15] - m[11] * m[12]; + __float b3 = m[9] * m[14] - m[10] * m[13]; + __float b4 = m[9] * m[15] - m[11] * m[13]; + __float b5 = m[10] * m[15] - m[11] * m[14]; + + __float determinant = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0; + + if (determinant != 0) { + m_inv[0] = 0 + m[5] * b5 - m[6] * b4 + m[7] * b3; + m_inv[4] = 0 - m[4] * b5 + m[6] * b2 - m[7] * b1; + m_inv[8] = 0 + m[4] * b4 - m[5] * b2 + m[7] * b0; + m_inv[12] = 0 - m[4] * b3 + m[5] * b1 - m[6] * b0; + m_inv[1] = 0 - m[1] * b5 + m[2] * b4 - m[3] * b3; + m_inv[5] = 0 + m[0] * b5 - m[2] * b2 + m[3] * b1; + m_inv[9] = 0 - m[0] * b4 + m[1] * b2 - m[3] * b0; + m_inv[13] = 0 + m[0] * b3 - m[1] * b1 + m[2] * b0; + m_inv[2] = 0 + m[13] * a5 - m[14] * a4 + m[15] * a3; + m_inv[6] = 0 - m[12] * a5 + m[14] * a2 - m[15] * a1; + m_inv[10] = 0 + m[12] * a4 - m[13] * a2 + m[15] * a0; + m_inv[14] = 0 - m[12] * a3 + m[13] * a1 - m[14] * a0; + m_inv[3] = 0 - m[9] * a5 + m[10] * a4 - m[11] * a3; + m_inv[7] = 0 + m[8] * a5 - m[10] * a2 + m[11] * a1; + m_inv[11] = 0 - m[8] * a4 + m[9] * a2 - m[11] * a0; + m_inv[15] = 0 + m[8] * a3 - m[9] * a1 + m[10] * a0; + + __float inverse_det = 1.0f / determinant; + + m_inv[0] *= inverse_det; + m_inv[1] *= inverse_det; + m_inv[2] *= inverse_det; + m_inv[3] *= inverse_det; + m_inv[4] *= inverse_det; + m_inv[5] *= inverse_det; + m_inv[6] *= inverse_det; + m_inv[7] *= inverse_det; + m_inv[8] *= inverse_det; + m_inv[9] *= inverse_det; + m_inv[10] *= inverse_det; + m_inv[11] *= inverse_det; + m_inv[12] *= inverse_det; + m_inv[13] *= inverse_det; + m_inv[14] *= inverse_det; + m_inv[15] *= inverse_det; + + return m_inv; + } + + return mat4::identity(); + }; + + static mat4 translate(__float x, __float y, __float z) { + mat4 m = mat4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, x, y, z, 1.0f); + + return m; + }; + + static mat4 rotateAxis(__float r, __float x, __float y, __float z) { // rotate r about axis x,y,z + __float sAng = sinf(r*((float)M_PI/180.0f)); + __float cAng = cosf(r*((float)M_PI/180.0f)); + + return mat4( cAng+(x*x)*(1.0f-cAng), x*y*(1.0f-cAng) - z*sAng, x*z*(1.0f-cAng) + y*sAng, 0, + y*x*(1.0f-cAng)+z*sAng, cAng + y*y*(1.0f-cAng), y*z*(1.0f-cAng)-x*sAng, 0, + z*x*(1.0f-cAng)-y*sAng, z*y*(1.0f-cAng)+x*sAng, cAng+(z*z)*(1.0f-cAng), 0, + 0, 0, 0, 1 ); + }; + + static mat4 rotate(__float x, __float y, __float z) { // rotate each axis, angles x, y, z in turn + __float sAng,cAng; + mat4 mOut = mat4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); + + if (z!=0) { + sAng = sinf(z*((float)M_PI/180.0f)); + cAng = cosf(z*((float)M_PI/180.0f)); + + mOut *= mat4(cAng, sAng, 0.0f, 0.0f, -sAng, cAng, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); + } + + if (y!=0) { + sAng = sinf(y*((float)M_PI/180.0f)); + cAng = cosf(y*((float)M_PI/180.0f)); + + mOut *= mat4(cAng, 0.0f, -sAng, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, sAng, 0.0f, cAng, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); + } + + if (x!=0) { + sAng = sinf(x*((float)M_PI/180.0f)); + cAng = cosf(x*((float)M_PI/180.0f)); + + mOut *= mat4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, cAng, sAng, 0.0f, 0.0f, -sAng, cAng, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); + } + + return mOut; + }; + + static mat4 scale(__float x, __float y, __float z) { + return mat4(x, 0.0f, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 0.0f, z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); + }; + + static mat4 transform(vec3 position, vec3 rotation, vec3 scale) { + mat4 m = mat4::identity(); + + if (position!=NULL) { + m *= mat4::translate(position[0],position[1],position[2]); + } + if (rotation!=NULL) { + if (!(rotation[0] == 0 && rotation[1] == 0 && rotation[2] == 0)) { + m *= mat4::rotate(rotation[0],rotation[1],rotation[2]); + } + } + if (scale!=NULL) { + if (!(scale[0] == 1 && scale[1] == 1 && scale[2] == 1)) { + m *= mat4::scale(scale[0],scale[1],scale[2]); + } + } + + return m; + }; + static vec4 vec4_multiply(vec4 m1, mat4 m2) { + vec4 mOut; + + mOut[0] = m2[0] * m1[0] + m2[4] * m1[1] + m2[8] * m1[2] + m2[12] * m1[3]; + mOut[1] = m2[1] * m1[0] + m2[5] * m1[1] + m2[9] * m1[2] + m2[13] * m1[3]; + mOut[2] = m2[2] * m1[0] + m2[6] * m1[1] + m2[10] * m1[2] + m2[14] * m1[3]; + mOut[3] = m2[3] * m1[0] + m2[7] * m1[1] + m2[11] * m1[2] + m2[15] * m1[3]; + + return mOut; + }; + static mat4 lookat(__float eyex, __float eyey, __float eyez, __float centerx, __float centery, __float centerz, __float upx, __float upy, __float upz) { + vec3 forward, side, up; + + forward[0] = centerx - eyex; + forward[1] = centery - eyey; + forward[2] = centerz - eyez; + + up[0] = upx; + up[1] = upy; + up[2] = upz; + + forward = vec3::normalize(forward); + + /* Side = forward x up */ + side = vec3::cross(forward, up); + side = vec3::normalize(side); + + /* Recompute up as: up = side x forward */ + up = vec3::cross(side, forward); + + return mat4::translate(-eyex,-eyey,-eyez) * mat4( side[0], up[0], -forward[0], 0, side[1], up[1], -forward[1], 0, side[2], up[2], -forward[2], 0, 0, 0, 0, 1); + }; + }; + +} + +#endif /* defined(__CubicVR2__mat4__) */ diff --git a/external/cubicvr2/math/plane.h b/external/cubicvr2/math/plane.h new file mode 100644 index 0000000..4db2c2c --- /dev/null +++ b/external/cubicvr2/math/plane.h @@ -0,0 +1,32 @@ +// +// plane.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef CubicVR2_plane_h +#define CubicVR2_plane_h + +#include "vec4.h" +#include "vec3.h" + +namespace CubicVR { + + struct plane : vec4 { + static int classifyPoint(vec4 plane, vec3 pt) { + __float dist = (plane[0] * pt[0]) + (plane[1] * pt[1]) + (plane[2] * pt[2]) + (plane[3]); + if (dist < 0) { + return -1; + } + else if (dist > 0) { + return 1; + } + return 0; + }; + }; + +} + +#endif diff --git a/external/cubicvr2/math/quaternion.h b/external/cubicvr2/math/quaternion.h new file mode 100644 index 0000000..41d33db --- /dev/null +++ b/external/cubicvr2/math/quaternion.h @@ -0,0 +1,100 @@ +// +// quaternion.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__quaternion__ +#define __CubicVR2__quaternion__ + +#include +#include "vec4.h" +#include "mat4.h" + +namespace CubicVR { + + struct quaternion : vec4 { + + static vec4 fromMatrix(mat4 mat) { + __float t = 1 + mat[0] + mat[5] + mat[10]; + __float S,X,Y,Z,W; + + if ( t > 0.00000001 ) { + S = sqrtf(t) * 2; + X = ( mat[9] - mat[6] ) / S; + Y = ( mat[2] - mat[8] ) / S; + Z = ( mat[4] - mat[1] ) / S; + W = 0.25f * S; + } else { + if ( mat[0] > mat[5] && mat[0] > mat[10] ) { // Column 0: + S = sqrtf( 1.0f + mat[0] - mat[5] - mat[10] ) * 2.0f; + X = 0.25f * S; + Y = (mat[4] + mat[1] ) / S; + Z = (mat[2] + mat[8] ) / S; + W = (mat[9] - mat[6] ) / S; + } else if ( mat[5] > mat[10] ) { // Column 1: + S = sqrtf( 1.0f + mat[5] - mat[0] - mat[10] ) * 2.0f; + X = (mat[4] + mat[1] ) / S; + Y = 0.25f * S; + Z = (mat[9] + mat[6] ) / S; + W = (mat[2] - mat[8] ) / S; + } else { // Column 2: + S = sqrtf( 1.0f + mat[10] - mat[0] - mat[5] ) * 2.0f; + X = (mat[2] + mat[8] ) / S; + Y = (mat[9] + mat[6] ) / S; + Z = 0.25f * S; + W = (mat[4] - mat[1] ) / S; + } + } + + return vec4(X,Y,Z,W); + }; + + static vec4 fromEuler(__float bank, __float heading, __float pitch) { // x,y,z + __float c1 = cosf(((float)M_PI / 180.0f) * heading / 2.0f); + __float s1 = sinf(((float)M_PI / 180.0f) * heading / 2.0f); + __float c2 = cosf(((float)M_PI / 180.0f) * pitch / 2.0f); + __float s2 = sinf(((float)M_PI / 180.0f) * pitch / 2.0f); + __float c3 = cosf(((float)M_PI / 180.0f) * bank / 2.0f); + __float s3 = sinf(((float)M_PI / 180.0f) * bank / 2.0f); + __float c1c2 = c1 * c2; + __float s1s2 = s1 * s2; + + vec4 mOut; + + mOut[0] = c1c2 * c3 - s1s2 * s3; + mOut[1] = c1c2 * s3 + s1s2 * c3; + mOut[2] = s1 * c2 * c3 + c1 * s2 * s3; + mOut[3] = c1 * s2 * c3 - s1 * c2 * s3; + + return mOut; + }; + + static vec3 toEuler(vec4 q) { + __float sqx = q[0] * q[0]; + __float sqy = q[1] * q[1]; + __float sqz = q[2] * q[2]; + __float sqw = q[3] * q[3]; + + __float x = (180.0f / (float)M_PI) * ((atan2f(2.0f * (q[1] * q[2] + q[0] * q[3]), (-sqx - sqy + sqz + sqw)))); + __float y = (180.0f / (float)M_PI) * ((asinf(-2.0f * (q[0] * q[2] - q[1] * q[3])))); + __float z = (180.0f / (float)M_PI) * ((atan2f(2.0f * (q[0] * q[1] + q[2] * q[3]), (sqx - sqy - sqz + sqw)))); + + return vec3(x, y, z); + }; + + static vec4 multiply(vec4 q1, vec4 q2) { + __float x = q1[0] * q2[3] + q1[3] * q2[0] + q1[1] * q2[2] - q1[2] * q2[1]; + __float y = q1[1] * q2[3] + q1[3] * q2[1] + q1[2] * q2[0] - q1[0] * q2[2]; + __float z = q1[2] * q2[3] + q1[3] * q2[2] + q1[0] * q2[1] - q1[1] * q2[0]; + __float w = q1[3] * q2[3] - q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2]; + + return vec4(x,y,z,w); + }; + + }; +} + +#endif /* defined(__CubicVR2__quaternion__) */ diff --git a/external/cubicvr2/math/sphere.h b/external/cubicvr2/math/sphere.h new file mode 100644 index 0000000..8e33530 --- /dev/null +++ b/external/cubicvr2/math/sphere.h @@ -0,0 +1,34 @@ +// +// sphere.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef CubicVR2_sphere_h +#define CubicVR2_sphere_h + +#include "vec3.h" +#include "vec4.h" + +namespace CubicVR { + + struct sphere { + bool intersects(vec4 sphere, vec4 other) { + vec3 spherePos(sphere[0], sphere[1], sphere[2]); + vec3 otherPos(other[0], other[1], other[2]); + vec3 diff = vec3::subtract(spherePos, otherPos); + + __float mag = sqrtf(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2]); + __float sum_radii = sphere[3] + other[3]; + + if (mag * mag < sum_radii * sum_radii) { + return true; + } + return false; + } + }; +} + +#endif diff --git a/external/cubicvr2/math/transform.h b/external/cubicvr2/math/transform.h new file mode 100644 index 0000000..bd6ddde --- /dev/null +++ b/external/cubicvr2/math/transform.h @@ -0,0 +1,175 @@ +// +// Transform.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__Transform__ +#define __CubicVR2__Transform__ + +#include +#include "cubic_types.h" +#include "mat4.h" +#include "vec3.h" +#include + +namespace CubicVR { + + class transform { + std::vector m_stack; + std::vector m_cache; + int c_stack; + int valid; + mat4 result; + + transform() { + c_stack = 0; + valid = false; + result = mat4::identity(); + }; + + transform(mat4 init_mat) { + clearStack(init_mat); + }; + + void setIdentity() { + m_stack[c_stack] = mat4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); + if (valid == c_stack && c_stack) { + valid--; + } + } + + mat4 getIdentity() { + return mat4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); + } + + void invalidate() { + valid = 0; + result = mat4::identity(); + } + + mat4 getResult() { + if (!c_stack) { + return m_stack[0]; + } + + mat4 m = getIdentity(); + + if (valid > c_stack-1) valid = c_stack-1; + + for (int i = valid; i < c_stack+1; i++) { + m = mat4::multiply(m, m_stack[i], true); + m_cache[i] = m; + } + + valid = c_stack-1; + + result = m_cache[c_stack]; + + return result; + } + + void pushMatrix(mat4 m) { + c_stack++; + m_stack[c_stack] = (m ? m : getIdentity()); + } + + void popMatrix() { + if (c_stack == 0) { + return; + } + c_stack--; + } + + void clearStack(mat4 init_mat) { + m_stack.clear(); + m_cache.clear(); + c_stack = 0; + valid = 0; + delete result; + result = mat4::identity(); + + if (init_mat != NULL) { + m_stack[0] = init_mat; + } else { + setIdentity(); + } + } + + void translate(__float x, __float y, __float z) { + mat4 m = getIdentity(); + + m[12] = x; + m[13] = y; + m[14] = z; + + m_stack[c_stack] = mat4::multiply(m, m_stack[c_stack], true); + if (valid == c_stack && c_stack) { + valid--; + } + } + + void scale(__float x, __float y, __float z) { + mat4 m = getIdentity(); + + m[0] = x; + m[5] = y; + m[10] = z; + + m_stack[c_stack] = mat4::multiply(m, m_stack[c_stack], true); + if (valid == c_stack && c_stack) { + valid--; + } + } + + void rotate(__float ang, __float x, __float y, __float z) { + __float sAng, cAng; + + if (x || y || z) { + sAng = sin(-ang * ((float)M_PI / 180.0f)); + cAng = cos(-ang * ((float)M_PI / 180.0f)); + } + + if (x) { + mat4 X_ROT = getIdentity(); + + X_ROT[5] = cAng * x; + X_ROT[9] = sAng * x; + X_ROT[6] = -sAng * x; + X_ROT[10] = cAng * x; + + m_stack[c_stack] = mat4::multiply(m_stack[c_stack], X_ROT, true); + } + + if (y) { + mat4 Y_ROT = getIdentity(); + + Y_ROT[0] = cAng * y; + Y_ROT[8] = -sAng * y; + Y_ROT[2] = sAng * y; + Y_ROT[10] = cAng * y; + + m_stack[c_stack] = mat4::multiply(m_stack[c_stack], Y_ROT, true); + } + + if (z) { + mat4 Z_ROT = getIdentity(); + + Z_ROT[0] = cAng * z; + Z_ROT[4] = sAng * z; + Z_ROT[1] = -sAng * z; + Z_ROT[5] = cAng * z; + + m_stack[c_stack] = mat4::multiply(m_stack[c_stack], Z_ROT, true); + } + + if (valid == c_stack && c_stack) { + valid--; + } + }; + }; +} + +#endif /* defined(__CubicVR2__Transform__) */ diff --git a/external/cubicvr2/math/triangle.h b/external/cubicvr2/math/triangle.h new file mode 100644 index 0000000..147380d --- /dev/null +++ b/external/cubicvr2/math/triangle.h @@ -0,0 +1,40 @@ +// +// triangle.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__triangle__ +#define __CubicVR2__triangle__ + +#include +#include "vec3.h" + +namespace CubicVR { + + struct triangle { + static vec3 normal(vec3 pt1, vec3 pt2, vec3 pt3) { + + __float v10 = pt1[0] - pt2[0]; + __float v11 = pt1[1] - pt2[1]; + __float v12 = pt1[2] - pt2[2]; + __float v20 = pt2[0] - pt3[0]; + __float v21 = pt2[1] - pt3[1]; + __float v22 = pt2[2] - pt3[2]; + + vec3 mOut; + + mOut[0] = v11 * v22 - v12 * v21; + mOut[1] = v12 * v20 - v10 * v22; + mOut[2] = v10 * v21 - v11 * v20; + + return mOut; + }; + }; + +} + + +#endif /* defined(__CubicVR2__triangle__) */ diff --git a/external/cubicvr2/math/vec2.h b/external/cubicvr2/math/vec2.h new file mode 100644 index 0000000..d7a7aad --- /dev/null +++ b/external/cubicvr2/math/vec2.h @@ -0,0 +1,92 @@ +// +// vec2.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__vec2__ +#define __CubicVR2__vec2__ + +#include +#include +#include "cubic_types.h" + +namespace CubicVR { + #define vec2SG(c,x,y) \ + vec2 COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(vec2 value) { y = value; return *this; } + + struct vec2 { + __float x, y; + public: + __float& u() { return x; } + __float& v() { return y; } + +// __float operator [] (unsigned i) const { return ((__float *)this)[i]; } + __float& operator [] (unsigned i) { return ((__float *)this)[i]; } + + vec2 (__float xi,__float yi) { x = xi; y = yi; } + vec2 () { x = y = 0.0f; } + + operator __float*() const { return (__float *)this; } + + vec2 operator*(__float v) { return vec2( x*v, y*v ); } + // vec2 operator*(vec2 v) { return vec2::cross(*this,v); } + vec2 operator+(vec2 v) { return vec2::add(*this,v); } + vec2 operator-(vec2 v) { return vec2::subtract(*this,v); } + + + static bool equal(vec2 a, vec2 b, __float epsilon = 0.00000001) { + return (fabs(a[0] - b[0]) < epsilon && fabs(a[1] - b[1]) < epsilon); + }; + + static bool onLine(vec2 a, vec2 b,vec2 c) { + __float minx = (a[0]b[0])?a[0]:b[0]; + __float maxy = (a[1]>b[1])?a[1]:b[1]; + + if ((minx <= c[0] && c[0] <= maxx) && (miny <= c[1] && c[1] <= maxy)) { + return true; + } else { + return false; + } + }; + + static vec2 lineIntersect(vec2 a1, vec2 a2, vec2 b1, vec2 b2) { + __float x1 = a1[0], y1 = a1[1], x2 = a2[0], y2 = a2[1]; + __float x3 = b1[0], y3 = b1[1], x4 = b2[0], y4 = b2[1]; + + __float d = ((x1-x2) * (y3-y4)) - ((y1-y2) * (x3-x4)); + if (d == 0) return vec2(INFINITY,INFINITY); + + __float xi = (((x3-x4) * ((x1*y2)-(y1*x2))) - ((x1-x2) *((x3*y4)-(y3*x4))))/d; + __float yi = (((y3-y4) * ((x1*y2)-(y1*x2))) - ((y1-y2) *((x3*y4)-(y3*x4))))/d; + + return vec2( xi,yi ); + }; + + static vec2 add(vec2 a,vec2 b) { + return vec2(a[0]+b[0],a[1]+b[1]); + }; + + static vec2 subtract(vec2 a, vec2 b) { + return vec2(a[0]-b[0],a[1]-b[1]); + }; + + static __float length(vec2 a,vec2 b) { + vec2 s(a[0]-b[0],a[1]-b[1]); + + return sqrtf(s[0]*s[0]+s[1]*s[1]); + }; + + static __float length(vec2 a) { + return sqrtf(a[0]*a[0]+a[1]*a[1]); + }; + + }; + +} +#endif /* defined(__CubicVR2__vec2__) */ diff --git a/external/cubicvr2/math/vec3.h b/external/cubicvr2/math/vec3.h new file mode 100644 index 0000000..9dcdca6 --- /dev/null +++ b/external/cubicvr2/math/vec3.h @@ -0,0 +1,170 @@ +// +// vec3.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-21. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__vec3__ +#define __CubicVR2__vec3__ + +#include +#include "cubic_types.h" +#include + +namespace CubicVR { + +#define vec3SG(c,x,y) \ + vec3 COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(vec3 value) { y = value; return *this; } + + + struct vec3 { + __float x,y,z; + + operator __float*() const { return (__float *)this; } + + __float& r() { return x; } + __float& g() { return y; } + __float& b() { return z; } + + __float& operator [] (unsigned i) { return ((__float *)this)[i]; } + vec3 (__float xi,__float yi,__float zi) { x = xi; y = yi; z = zi; } + vec3 () { x = y = z = 0.0f; } + + + vec3 operator*(__float v) { return vec3(x*v, y*v, z*v); } + vec3 operator*(vec3 v) { return vec3::cross(*this,v); } + vec3 operator+(vec3 v) { return vec3::add(*this,v); } + vec3 operator-(vec3 v) { return vec3::subtract(*this,v); } + + + static __float length(vec3 pta, vec3 ptb) { + __float a,b,c; + a = ptb[0]-pta[0]; + b = ptb[1]-pta[1]; + c = ptb[2]-pta[2]; + return sqrtf((a*a) + (b*b) + (c*c)); + }; + static __float length(vec3 pta) { + __float a,b,c; + a = pta[0]; + b = pta[1]; + c = pta[2]; + return sqrtf((a*a) + (b*b) + (c*c)); + }; + static vec3 normalize(vec3 pt) { + __float a = pt[0], b = pt[1], c = pt[2], + d = sqrtf((a*a) + (b*b) + (c*c)); + if (d) { + pt[0] = pt[0]/d; + pt[1] = pt[1]/d; + pt[2] = pt[2]/d; + + return pt; + } + + pt = vec3(0.0f,0.0f,0.0f); + + return pt; + }; + static __float dot(vec3 v1, vec3 v2) { + return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; + }; + static __float angle(vec3 v1, vec3 v2) { + __float a = acosf((v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]) / (sqrtf(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]) * sqrtf(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]))); + + return a; + }; + static vec3 cross(vec3 vectA, vec3 vectB) { + return vec3( + vectA[1] * vectB[2] - vectB[1] * vectA[2], vectA[2] * vectB[0] - vectB[2] * vectA[0], vectA[0] * vectB[1] - vectB[0] * vectA[1] + ); + }; + static vec3 multiply(vec3 vectA, __float constB) { + return vec3(vectA[0] * constB, vectA[1] * constB, vectA[2] * constB); + }; + static vec3 add(vec3 vectA, vec3 vectB) { + return vec3(vectA[0] + vectB[0], vectA[1] + vectB[1], vectA[2] + vectB[2]); + }; + + static vec3 subtract(vec3 vectA, vec3 vectB) { + return vec3(vectA[0] - vectB[0], vectA[1] - vectB[1], vectA[2] - vectB[2]); + }; + + static bool equal(vec3 a, vec3 b, __float epsilon = 0.0000001f) { + return ((fabs(a[0] - b[0]) < epsilon) && (fabs(a[1] - b[1]) < epsilon) && (fabs(a[2] - b[2]) < epsilon)); + }; + + static vec3 moveViewRelative(vec3 position, vec3 target, __float xdelta, __float zdelta) { + __float ang = atan2f(zdelta, xdelta); + __float cam_ang = atan2f(target[2] - position[2], target[0] - position[0]); + __float mag = sqrtf(xdelta * xdelta + zdelta * zdelta); + + __float move_ang = cam_ang + ang + (float)M_PI/2.0f; + + // if (typeof(alt_source) === 'object') { + // return [alt_source[0] + mag * Math.cos(move_ang), alt_source[1], alt_source[2] + mag * Math.sin(move_ang)]; + // } + + return vec3(position[0] + mag * cosf(move_ang), position[1], position[2] + mag * sinf(move_ang)); + }; + + static vec3 trackTarget(vec3 position, vec3 target, __float trackingSpeed, __float safeDistance) { + vec3 camv = vec3::subtract(target, position); + vec3 dist = camv; + __float fdist = vec3::length(dist); + vec3 motionv = camv; + + motionv = vec3::normalize(motionv); + motionv = vec3::multiply(motionv, trackingSpeed * (1.0f / (1.0f / (fdist - safeDistance)))); + + vec3 ret_pos; + + if (fdist > safeDistance) { + ret_pos = vec3::add(position, motionv); + } else if (fdist < safeDistance) { + motionv = camv; + motionv = vec3::normalize(motionv); + motionv = vec3::multiply(motionv, trackingSpeed * (1.0f / (1.0f / (fabsf(fdist - safeDistance))))); + ret_pos = vec3::subtract(position, motionv); + } else { + ret_pos = vec3(position[0], position[1] + motionv[2], position[2]); + } + + return ret_pos; + }; + + static vec3 getClosestTo(vec3 ptA, vec3 ptB, vec3 ptTest) { + vec3 S, T, U; + + S = vec3::subtract(ptB, ptA); + T = vec3::subtract(ptTest, ptA); + U = vec3::add(vec3::multiply(S, vec3::dot(S, T) / vec3::dot(S, S)), ptA); + + return U; + }; + + // linePlaneIntersect: function(normal, point_on_plane, segment_start, segment_end) + // { + // // form a plane from normal and point_on_plane and test segment start->end to find intersect point + // var denom,mu; + // + // var d = - normal[0] * point_on_plane[0] - normal[1] * point_on_plane[1] - normal[2] * point_on_plane[2]; + // + // // calculate position where the plane intersects the segment + // denom = normal[0] * (segment_end[0] - segment_start[0]) + normal[1] * (segment_end[1] - segment_start[1]) + normal[2] * (segment_end[2] - segment_start[2]); + // if (Math.fabs(denom) < 0.001) return false; + // + // mu = - (d + normal[0] * segment_start[0] + normal[1] * segment_start[1] + normal[2] * segment_start[2]) / denom; + // return [ + // (segment_start[0] + mu * (segment_end[0] - segment_start[0])), + // (segment_start[1] + mu * (segment_end[1] - segment_start[1])), + // (segment_start[2] + mu * (segment_end[2] - segment_start[2])) + // ]; + // } + }; + +} +#endif /* defined(__CubicVR2__vec3__) */ diff --git a/external/cubicvr2/math/vec4.h b/external/cubicvr2/math/vec4.h new file mode 100644 index 0000000..5975079 --- /dev/null +++ b/external/cubicvr2/math/vec4.h @@ -0,0 +1,71 @@ +// +// vec4.h +// CubicVR2 +// +// Created by Charles J. Cliffe on 2013-02-22. +// Copyright (c) 2013 Charles J. Cliffe. All rights reserved. +// + +#ifndef __CubicVR2__vec4__ +#define __CubicVR2__vec4__ + +#include +#include "cubic_types.h" +#include + +namespace CubicVR { + +#define vec4SG(c,x,y) \ + vec3 COMBINE(get,x)() { return y; } \ + c & COMBINE(set,x)(vec3 value) { y = value; return *this; } + + struct vec4 { + __float x,y,z,w; + public: + __float& r() { return x; } + __float& g() { return y; } + __float& b() { return z; } + __float& a() { return w; } + +// __float operator [] (unsigned i) const { return ((__float *)this)[i]; } + __float& operator [] (unsigned i) { return ((__float *)this)[i]; } + + vec4 (__float xi,__float yi,__float zi,__float wi) { x = xi; y = yi; z = zi; w = wi; } + vec4 () { x = y = z = w = 0.0f; } + + operator __float*() const { return (__float *)this; } + + vec4 operator*(__float v) { return vec4(x*v, y*v, z*v, w*v); } +// vec4 operator*(vec4 v) { return vec4::cross(*this,v); } +// vec4 operator+(vec4 v) { return vec4::add(*this,v); } +// vec4 operator-(vec4 v) { return vec4::subtract(*this,v); } + + static __float length(vec4 a, vec4 b) { + __float v[4] = {a[0]-b[0],a[1]-b[1],a[2]-b[2],a[3]-b[3]}; + return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]); + }; + + static __float length(vec4 v) { + return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]); + }; + + static vec4 normalize(vec4 v) { + __float n = sqrtf(vec4::length(v)); + + v[0] /= n; + v[1] /= n; + v[2] /= n; + v[3] /= n; + + return v; + }; + + static __float dot(vec4 v1, vec4 v2) { + return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2] + v1[3] * v2[3]; + }; + + }; + +} + +#endif /* defined(__CubicVR2__vec4__) */ diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index e09217a..5b0c6aa 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -1,8 +1,8 @@ #include "GLPanel.h" +#include "cubic_math.h" - -GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), coord(GLPANEL_Y_DOWN_ZERO_ONE), contentsVisible(true) { +GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transform(CubicVR::mat4::identity()) { pos[0] = 0.0f; pos[1] = 0.0f; size[0] = 1.0f; @@ -10,7 +10,7 @@ GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), coord(GLPANEL_Y_DOWN_ZERO_ONE fill[0] = RGB(0.5,0.5,0.5); fill[1] = RGB(0.1,0.1,0.1); borderColor = RGB(0.8, 0.8, 0.8); - genArrays(); + setCoordinateSystem(GLPANEL_Y_DOWN_ZERO_ONE); } void GLPanel::genArrays() { @@ -125,6 +125,7 @@ void GLPanel::genArrays() { } } + void GLPanel::setViewport() { GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp); @@ -151,6 +152,23 @@ float GLPanel::getHeightPx() { return size[1]*view[0]; } + +void GLPanel::setCoordinateSystem(GLPanelCoordinateSystem coord_in) { + coord = coord_in; + + if (coord == GLPANEL_Y_DOWN || coord == GLPANEL_Y_UP) { + min = -1; + mid = 0; + max = 1; + } else { + min = 0; + mid = 0.5; + max = 1; + } + + genArrays(); +} + void GLPanel::setFill(GLPanelFillType fill_mode) { fillType = fill_mode; genArrays(); @@ -202,7 +220,7 @@ void GLPanel::drawChildren() { std::vector::iterator panel_i; for (panel_i = children.begin(); panel_i != children.end(); panel_i++) { - (*panel_i)->draw(this); + (*panel_i)->draw(transform, this); } } } @@ -211,41 +229,53 @@ void GLPanel::drawPanelContents() { drawChildren(); } -void GLPanel::draw(GLPanel *parent) { - float min, mid, max; +void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { + using namespace CubicVR; - if (coord == GLPANEL_Y_DOWN || coord == GLPANEL_Y_UP) { - min = -1; - mid = 0; - max = 1; - } else { - min = 0; - mid = 0.5; - max = 1; - } + mat4 mCoord = mat4::identity(); if (!parent) { if (coord == GLPANEL_Y_DOWN_ZERO_ONE) { - glPushMatrix(); - glTranslatef(-1.0f, 1.0f, 0.0f); - glScalef(2.0f, -2.0f, 2.0f); + mCoord *= mat4::translate(-1.0f, 1.0f, 0.0f) * mat4::scale(2.0f, -2.0f, 2.0f); } if (coord == GLPANEL_Y_UP_ZERO_ONE) { - glPushMatrix(); - glTranslatef(-1.0f, -1.0f, 0.0f); - glScalef(2.0f, 2.0f, 2.0f); + mCoord = mat4::translate(-1.0f, -1.0f, 0.0f) * mat4::scale(2.0f, 2.0f, 2.0f); } if (coord == GLPANEL_Y_DOWN) { - glPushMatrix(); - glScalef(1.0f, -1.0f, 1.0f); - } - if (coord == GLPANEL_Y_UP) { - glPushMatrix(); + mCoord = mat4::scale(2.0f, 2.0f, 2.0f); } +// if (coord == GLPANEL_Y_UP) { +// } } - glPushMatrix(); - glTranslatef(pos[0]+margin.left, pos[1]+margin.top, 0); - glScalef(size[0]-(margin.left+margin.right), size[1]-(margin.top+margin.bottom), 0); + + // compute local transform + localTransform = mCoord * mat4::translate(pos[0]+margin.left, pos[1]+margin.top, 0) * + mat4::scale(size[0]-(margin.left+margin.right), size[1]-(margin.top+margin.bottom), 0); + + // compute global transform + transform = transform_in * localTransform; + + glLoadMatrixf(transform); + + // init view[] + setViewport(); + + // get min/max transform + vec4 vmin_t = mat4::vec4_multiply(vec4(min, min, 0, 1), transform); + vec4 vmax_t = mat4::vec4_multiply(vec4(max, max, 0, 1), transform); + + // screen dimensions + vec2 vmin((vmin_t.x>vmax_t.x)?vmax_t.x:vmin_t.x, vmin.y = (vmin_t.y>vmax_t.y)?vmax_t.y:vmin_t.y); + vec2 vmax((vmin_t.y>vmax_t.y)?vmin_t.y:vmax_t.y, vmax.y = (vmin_t.y>vmax_t.y)?vmin_t.y:vmax_t.y); + + // unit dimensions + vec2 umin = (vmin * 0.5) + vec2(1,1); + vec2 umax = (vmax * 0.5) + vec2(1,1); + + // pixel dimensions + vec2 pdim((umax.x - umin.x) * view[0], (umax.y - umin.y) * view[1]); + + std::cout << umin << " :: " << umax << " :: " << pdim << std::endl; if (fillType != GLPANEL_FILL_NONE) { glEnableClientState(GL_VERTEX_ARRAY); @@ -303,11 +333,6 @@ void GLPanel::draw(GLPanel *parent) { drawPanelContents(); glPopMatrix(); } - - glPopMatrix(); - if (!parent) { - glPopMatrix(); - } } diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index 4ec248d..5de11d1 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -3,6 +3,7 @@ #include #include "GLExt.h" #include "ColorTheme.h" +#include "cubic_math.h" class GLPanelEdges { public: @@ -26,8 +27,9 @@ class GLPanel { private: std::vector glPoints; std::vector glColors; - + void genArrays(); + void setViewport(); public: typedef enum GLPanelFillType { GLPANEL_FILL_NONE, GLPANEL_FILL_SOLID, GLPANEL_FILL_GRAD_X, GLPANEL_FILL_GRAD_Y, GLPANEL_FILL_GRAD_BAR_X, GLPANEL_FILL_GRAD_BAR_Y } GLPanelFillType; @@ -42,16 +44,19 @@ public: RGB fill[2]; RGB borderColor; bool contentsVisible; - + CubicVR::mat4 transform; + CubicVR::mat4 localTransform; + float min, mid, max; + std::vector children; GLPanel(); - void setViewport(); void setPosition(float x, float y); void setSize(float w, float h); float getWidthPx(); float getHeightPx(); + void setCoordinateSystem(GLPanelCoordinateSystem coord); void setFill(GLPanelFillType fill_mode); void setFillColor(RGB color1); @@ -67,7 +72,7 @@ public: void drawChildren(); virtual void drawPanelContents(); - void draw(GLPanel *parent=NULL); + void draw(CubicVR::mat4 transform, GLPanel *parent=NULL); }; diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index b1b48fb..3169469 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -44,7 +44,7 @@ void UITestContext::DrawBegin() { } void UITestContext::Draw() { - testPanel.draw(); + testPanel.draw(CubicVR::mat4::identity()); } void UITestContext::DrawEnd() { From df978cef8964ce86154e30798f97f7607ac84413 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 26 Jun 2015 22:18:49 -0400 Subject: [PATCH 06/53] unify min/max/mid, use vmin/vmax for border --- src/ui/GLPanel.cpp | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index 5b0c6aa..0095e2b 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -14,19 +14,6 @@ GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transf } void GLPanel::genArrays() { - - float min, mid, max; - - if (coord == GLPANEL_Y_DOWN || coord == GLPANEL_Y_UP) { - min = -1; - mid = 0; - max = 1; - } else { - min = 0; - mid = 0.5; - max = 1; - } - if (fillType == GLPANEL_FILL_SOLID || fillType == GLPANEL_FILL_GRAD_X || fillType == GLPANEL_FILL_GRAD_Y) { glPoints.reserve(2 * 4); glPoints.resize(2 * 4); @@ -265,8 +252,8 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { vec4 vmax_t = mat4::vec4_multiply(vec4(max, max, 0, 1), transform); // screen dimensions - vec2 vmin((vmin_t.x>vmax_t.x)?vmax_t.x:vmin_t.x, vmin.y = (vmin_t.y>vmax_t.y)?vmax_t.y:vmin_t.y); - vec2 vmax((vmin_t.y>vmax_t.y)?vmin_t.y:vmax_t.y, vmax.y = (vmin_t.y>vmax_t.y)?vmin_t.y:vmax_t.y); + vec2 vmin((vmin_t.x>vmax_t.x)?vmax_t.x:vmin_t.x, (vmin_t.y>vmax_t.y)?vmax_t.y:vmin_t.y); + vec2 vmax((vmin_t.x>vmax_t.x)?vmin_t.x:vmax_t.x, (vmin_t.y>vmax_t.y)?vmin_t.y:vmax_t.y); // unit dimensions vec2 umin = (vmin * 0.5) + vec2(1,1); @@ -276,7 +263,7 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { vec2 pdim((umax.x - umin.x) * view[0], (umax.y - umin.y) * view[1]); std::cout << umin << " :: " << umax << " :: " << pdim << std::endl; - + if (fillType != GLPANEL_FILL_NONE) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); @@ -289,42 +276,45 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { glDisableClientState(GL_COLOR_ARRAY); if (border.left || border.right || border.top || border.bottom) { + glLoadMatrixf(mat4::identity()); + glEnable(GL_LINE_SMOOTH); glColor3f(borderColor.r, borderColor.g, borderColor.b); if (border.left) { glLineWidth(border.left); glBegin(GL_LINES); - glVertex2f(min, min); - glVertex2f(min, max); + glVertex2f(vmin.x, vmin.y); + glVertex2f(vmin.x, vmax.y); glEnd(); } if (border.right) { glLineWidth(border.right); glBegin(GL_LINES); - glVertex2f(max, min); - glVertex2f(max, max); + glVertex2f(vmax.x, vmin.y); + glVertex2f(vmax.x, vmax.y); glEnd(); } if (border.top) { glLineWidth(border.top); glBegin(GL_LINES); - glVertex2f(min, min); - glVertex2f(max, min); + glVertex2f(vmin.x, vmin.y); + glVertex2f(vmax.x, vmin.y); glEnd(); } if (border.bottom) { glLineWidth(border.bottom); glBegin(GL_LINES); - glVertex2f(min, max); - glVertex2f(max, max); + glVertex2f(vmin.x, vmax.y); + glVertex2f(vmax.x, vmax.y); glEnd(); } glDisable(GL_LINE_SMOOTH); + glLoadMatrixf(transform); } } From c770a0e20e6f8a107b9379660c37dd4615241478 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 27 Jun 2015 01:26:07 -0400 Subject: [PATCH 07/53] Margin now specified in pixels --- src/ui/GLPanel.cpp | 88 +++++++++++++++++++++------------------- src/ui/GLPanel.h | 12 +++--- src/ui/UITestContext.cpp | 10 ++--- 3 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index 0095e2b..b3839b6 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -172,30 +172,30 @@ void GLPanel::setFillColor(RGB color1, RGB color2) { genArrays(); } -void GLPanel::setMargin(float marg) { - margin.left = margin.right = margin.top = margin.bottom = marg; +void GLPanel::setMarginPx(float marg) { + marginPx.left = marginPx.right = marginPx.top = marginPx.bottom = marg; } -void GLPanel::setMargin(float margl, float margr, float margt, float margb) { - margin.left = margl; - margin.right = margr; - margin.top = margt; - margin.bottom = margb; +void GLPanel::setMarginPx(float margl, float margr, float margt, float margb) { + marginPx.left = margl; + marginPx.right = margr; + marginPx.top = margt; + marginPx.bottom = margb; } void GLPanel::setBorderColor(RGB clr) { borderColor = clr; } -void GLPanel::setBorder(float bord) { - border.left = border.right = border.top = border.bottom = bord; +void GLPanel::setBorderPx(float bord) { + borderPx.left = borderPx.right = borderPx.top = borderPx.bottom = bord; } -void GLPanel::setBorder(float bordl, float bordr, float bordt, float bordb) { - border.left = bordl; - border.right = bordr; - border.top = bordt; - border.bottom = bordb; +void GLPanel::setBorderPx(float bordl, float bordr, float bordt, float bordb) { + borderPx.left = bordl; + borderPx.right = bordr; + borderPx.top = bordt; + borderPx.bottom = bordb; } void GLPanel::addChild(GLPanel *childPanel) { @@ -236,14 +236,10 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { } // compute local transform - localTransform = mCoord * mat4::translate(pos[0]+margin.left, pos[1]+margin.top, 0) * - mat4::scale(size[0]-(margin.left+margin.right), size[1]-(margin.top+margin.bottom), 0); - + localTransform = mCoord * (mat4::translate(pos[0], pos[1], 0) * mat4::scale(size[0], size[1], 0)); // compute global transform transform = transform_in * localTransform; - glLoadMatrixf(transform); - // init view[] setViewport(); @@ -254,16 +250,27 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { // screen dimensions vec2 vmin((vmin_t.x>vmax_t.x)?vmax_t.x:vmin_t.x, (vmin_t.y>vmax_t.y)?vmax_t.y:vmin_t.y); vec2 vmax((vmin_t.x>vmax_t.x)?vmin_t.x:vmax_t.x, (vmin_t.y>vmax_t.y)?vmin_t.y:vmax_t.y); - + // unit dimensions vec2 umin = (vmin * 0.5) + vec2(1,1); vec2 umax = (vmax * 0.5) + vec2(1,1); + vec2 ucenter = (umin + umax) * 0.5; + // pixel dimensions vec2 pdim((umax.x - umin.x) * view[0], (umax.y - umin.y) * view[1]); + vec2 pvec((vmax.x-vmin.x) / pdim.x, (vmax.y-vmin.y) / pdim.y); + + std::cout << umin << " :: " << ucenter << " :: " << pdim << " :: " << pvec << std::endl; + + if (marginPx.left || marginPx.right || marginPx.top || marginPx.bottom) { + localTransform *= mat4::translate(marginPx.left*pvec.x, marginPx.top*pvec.y, 0) * + mat4::scale(1.0-(marginPx.left+marginPx.right)*pvec.x, 1.0-(marginPx.top+marginPx.bottom)*pvec.y, 0); + transform = transform_in * localTransform; + } + + glLoadMatrixf(transform); - std::cout << umin << " :: " << umax << " :: " << pdim << std::endl; - if (fillType != GLPANEL_FILL_NONE) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); @@ -275,46 +282,43 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - if (border.left || border.right || border.top || border.bottom) { - glLoadMatrixf(mat4::identity()); - + if (borderPx.left || borderPx.right || borderPx.top || borderPx.bottom) { glEnable(GL_LINE_SMOOTH); glColor3f(borderColor.r, borderColor.g, borderColor.b); - if (border.left) { - glLineWidth(border.left); + if (borderPx.left) { + glLineWidth(borderPx.left); glBegin(GL_LINES); - glVertex2f(vmin.x, vmin.y); - glVertex2f(vmin.x, vmax.y); + glVertex2f(min, min); + glVertex2f(min, max); glEnd(); } - if (border.right) { - glLineWidth(border.right); + if (borderPx.right) { + glLineWidth(borderPx.right); glBegin(GL_LINES); - glVertex2f(vmax.x, vmin.y); - glVertex2f(vmax.x, vmax.y); + glVertex2f(max, min); + glVertex2f(max, max); glEnd(); } - if (border.top) { - glLineWidth(border.top); + if (borderPx.top) { + glLineWidth(borderPx.top); glBegin(GL_LINES); - glVertex2f(vmin.x, vmin.y); - glVertex2f(vmax.x, vmin.y); + glVertex2f(min, min); + glVertex2f(max, min); glEnd(); } - if (border.bottom) { - glLineWidth(border.bottom); + if (borderPx.bottom) { + glLineWidth(borderPx.bottom); glBegin(GL_LINES); - glVertex2f(vmin.x, vmax.y); - glVertex2f(vmax.x, vmax.y); + glVertex2f(min, max); + glVertex2f(max, max); glEnd(); } glDisable(GL_LINE_SMOOTH); - glLoadMatrixf(transform); } } diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index 5de11d1..86b8aa7 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -39,8 +39,8 @@ public: float view[2]; GLPanelFillType fillType; GLPanelCoordinateSystem coord; - GLPanelEdges margin; - GLPanelEdges border; + GLPanelEdges marginPx; + GLPanelEdges borderPx; RGB fill[2]; RGB borderColor; bool contentsVisible; @@ -61,12 +61,12 @@ public: void setFill(GLPanelFillType fill_mode); void setFillColor(RGB color1); void setFillColor(RGB color1, RGB color2); - void setMargin(float marg); - void setMargin(float margl, float margr, float margt, float margb); + void setMarginPx(float marg); + void setMarginPx(float margl, float margr, float margt, float margb); void setBorderColor(RGB clr); - void setBorder(float bord); - void setBorder(float bordl, float bordr, float bordt, float bordb); + void setBorderPx(float bord); + void setBorderPx(float bordl, float bordr, float bordt, float bordb); void addChild(GLPanel *childPanel); diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index 3169469..8c43e10 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -7,24 +7,24 @@ PrimaryGLContext(canvas, sharedContext) { testPanel.setPosition(0.0, 0.0); testPanel.setSize(1.0, 1.0); - testPanel.setMargin(0.02, 0.02, 0.1, 0.1); + testPanel.setMarginPx(10); testPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_Y); testPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel.setPosition(0.0, 0.0); - testChildPanel.setMargin(0.05); + testChildPanel.setMarginPx(10); testChildPanel.setSize(1.0, 0.3); testChildPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X); testChildPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); - testChildPanel.setBorder(1); + testChildPanel.setBorderPx(1); testChildPanel2.setPosition(0.0, 0.3); testChildPanel2.setSize(1.0, 0.3); - testChildPanel2.setMargin(0.05); + testChildPanel2.setMarginPx(10); testChildPanel2.setFill(GLPanel::GLPANEL_FILL_GRAD_X); testChildPanel2.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel2.setBorderColor(RGB(1.0,0.0,0.0)); - testChildPanel2.setBorder(2,4,6,8); + testChildPanel2.setBorderPx(2,4,6,8); testPanel.addChild(&testChildPanel); testPanel.addChild(&testChildPanel2); From 8ccb060237148f0c2341a6d8d063902adf4c15ed Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 27 Jun 2015 01:55:39 -0400 Subject: [PATCH 08/53] margin tweaks --- src/ui/GLPanel.cpp | 4 ++-- src/ui/UITestContext.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index b3839b6..3f0f094 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -264,8 +264,8 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { std::cout << umin << " :: " << ucenter << " :: " << pdim << " :: " << pvec << std::endl; if (marginPx.left || marginPx.right || marginPx.top || marginPx.bottom) { - localTransform *= mat4::translate(marginPx.left*pvec.x, marginPx.top*pvec.y, 0) * - mat4::scale(1.0-(marginPx.left+marginPx.right)*pvec.x, 1.0-(marginPx.top+marginPx.bottom)*pvec.y, 0); + localTransform *= mat4::translate(marginPx.left*pvec.x/size[0], marginPx.top*pvec.y/size[1], 0) * + mat4::scale(1.0-(marginPx.left+marginPx.right)*pvec.x/size[0], 1.0-(marginPx.top+marginPx.bottom)*pvec.y/size[1], 0); transform = transform_in * localTransform; } diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index 8c43e10..b06cdb0 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -12,19 +12,19 @@ PrimaryGLContext(canvas, sharedContext) { testPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel.setPosition(0.0, 0.0); - testChildPanel.setMarginPx(10); - testChildPanel.setSize(1.0, 0.3); + testChildPanel.setMarginPx(10,10,10,5); + testChildPanel.setSize(1.0, 0.5); testChildPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X); testChildPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel.setBorderPx(1); - testChildPanel2.setPosition(0.0, 0.3); - testChildPanel2.setSize(1.0, 0.3); - testChildPanel2.setMarginPx(10); + testChildPanel2.setPosition(0.0, 0.5); + testChildPanel2.setSize(1.0, 0.5); + testChildPanel2.setMarginPx(10,10,5,10); testChildPanel2.setFill(GLPanel::GLPANEL_FILL_GRAD_X); testChildPanel2.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel2.setBorderColor(RGB(1.0,0.0,0.0)); - testChildPanel2.setBorderPx(2,4,6,8); + testChildPanel2.setBorderPx(1); testPanel.addChild(&testChildPanel); testPanel.addChild(&testChildPanel2); From b28c8dbc3efce2231b5e658f2dba1296d0e188b0 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 30 Jun 2015 23:07:39 -0400 Subject: [PATCH 09/53] Move static fonts to GLFont --- src/util/GLFont.cpp | 38 ++++++++++++++++++++++++ src/util/GLFont.h | 6 ++++ src/visual/ModeSelectorContext.cpp | 6 ++-- src/visual/PrimaryGLContext.cpp | 46 ++++-------------------------- src/visual/PrimaryGLContext.h | 6 ---- src/visual/ScopeContext.cpp | 8 +++--- src/visual/SpectrumContext.cpp | 2 +- src/visual/TuningContext.cpp | 10 +++---- 8 files changed, 62 insertions(+), 60 deletions(-) diff --git a/src/util/GLFont.cpp b/src/util/GLFont.cpp index c8c4b96..2edfda2 100644 --- a/src/util/GLFont.cpp +++ b/src/util/GLFont.cpp @@ -8,6 +8,9 @@ #define RES_FOLDER "" #endif + +GLFont GLFont::fonts[GLFONT_MAX]; + GLFontChar::GLFontChar() : id(0), x(0), y(0), width(0), height(0), xoffset(0), yoffset(0), xadvance(0), aspect(1), index(0) { @@ -475,3 +478,38 @@ void GLFont::drawString(std::string str, float xpos, float ypos, int pxHeight, A glDisable(GL_TEXTURE_2D); } + + +GLFont &GLFont::getFont(GLFontSize esize) { + if (!fonts[esize].isLoaded()) { + + std::string fontName; + switch (esize) { + case GLFONT_SIZE12: + fontName = "vera_sans_mono12.fnt"; + break; + case GLFONT_SIZE16: + fontName = "vera_sans_mono16.fnt"; + break; + case GLFONT_SIZE18: + fontName = "vera_sans_mono18.fnt"; + break; + case GLFONT_SIZE24: + fontName = "vera_sans_mono24.fnt"; + break; + case GLFONT_SIZE32: + fontName = "vera_sans_mono32.fnt"; + break; + case GLFONT_SIZE48: + fontName = "vera_sans_mono48.fnt"; + break; + default: + fontName = "vera_sans_mono12.fnt"; + break; + } + + fonts[esize].loadFont(fontName); + } + + return fonts[esize]; +} diff --git a/src/util/GLFont.h b/src/util/GLFont.h index 503dec1..f369ef0 100644 --- a/src/util/GLFont.h +++ b/src/util/GLFont.h @@ -56,6 +56,9 @@ public: enum Align { GLFONT_ALIGN_LEFT, GLFONT_ALIGN_RIGHT, GLFONT_ALIGN_CENTER, GLFONT_ALIGN_TOP, GLFONT_ALIGN_BOTTOM }; + enum GLFontSize { + GLFONT_SIZE12, GLFONT_SIZE16, GLFONT_SIZE18, GLFONT_SIZE24, GLFONT_SIZE32, GLFONT_SIZE48, GLFONT_MAX + }; GLFont(); ~GLFont(); @@ -65,6 +68,9 @@ public: float getStringWidth(std::string str, float size, float viewAspect); void drawString(std::string str, float xpos, float ypos, int pxHeight, Align hAlign = GLFONT_ALIGN_LEFT, Align vAlign = GLFONT_ALIGN_TOP); + static GLFont fonts[GLFONT_MAX]; + static GLFont &getFont(GLFontSize esize); + private: std::string nextParam(std::istringstream &str); std::string getParamKey(std::string param_str); diff --git a/src/visual/ModeSelectorContext.cpp b/src/visual/ModeSelectorContext.cpp index 3bb5adb..2e0f2eb 100644 --- a/src/visual/ModeSelectorContext.cpp +++ b/src/visual/ModeSelectorContext.cpp @@ -29,12 +29,12 @@ void ModeSelectorContext::DrawSelector(std::string label, int c, int cMax, bool float viewHeight = (float) vp[3]; float viewWidth = (float) vp[2]; - PrimaryGLContext::GLFontSize fontSize = GLFONT_SIZE16; + GLFont::GLFontSize fontSize = GLFont::GLFONT_SIZE16; int fontHeight = 16; if (viewWidth < 30) { - fontSize = GLFONT_SIZE12; + fontSize = GLFont::GLFONT_SIZE12; fontHeight = 12; } @@ -56,7 +56,7 @@ void ModeSelectorContext::DrawSelector(std::string label, int c, int cMax, bool glColor4f(0, 0, 0, a); } - getFont(fontSize).drawString(label, 0.0, y + height / 2.0, fontHeight, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(fontSize).drawString(label, 0.0, y + height / 2.0, fontHeight, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); } void ModeSelectorContext::DrawEnd() { diff --git a/src/visual/PrimaryGLContext.cpp b/src/visual/PrimaryGLContext.cpp index 66655b6..8bd1bf7 100644 --- a/src/visual/PrimaryGLContext.cpp +++ b/src/visual/PrimaryGLContext.cpp @@ -15,8 +15,6 @@ #include "AppFrame.h" #include -GLFont PrimaryGLContext::fonts[GLFONT_MAX]; - wxString PrimaryGLContext::glGetwxString(GLenum name) { const GLubyte *v = glGetString(name); if (v == 0) { @@ -61,40 +59,6 @@ PrimaryGLContext::PrimaryGLContext(wxGLCanvas *canvas, wxGLContext *sharedContex //#endif } -GLFont &PrimaryGLContext::getFont(GLFontSize esize) { - if (!fonts[esize].isLoaded()) { - - std::string fontName; - switch (esize) { - case GLFONT_SIZE12: - fontName = "vera_sans_mono12.fnt"; - break; - case GLFONT_SIZE16: - fontName = "vera_sans_mono16.fnt"; - break; - case GLFONT_SIZE18: - fontName = "vera_sans_mono18.fnt"; - break; - case GLFONT_SIZE24: - fontName = "vera_sans_mono24.fnt"; - break; - case GLFONT_SIZE32: - fontName = "vera_sans_mono32.fnt"; - break; - case GLFONT_SIZE48: - fontName = "vera_sans_mono48.fnt"; - break; - default: - fontName = "vera_sans_mono12.fnt"; - break; - } - - fonts[esize].loadFont(fontName); - } - - return fonts[esize]; -} - void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGB color, long long center_freq, long long srate) { if (!demod) { return; @@ -165,11 +129,11 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGB color, long glColor4f(1.0, 1.0, 1.0, 0.8); if (demod->getDemodulatorType() == DEMOD_TYPE_USB) { - getFont(PrimaryGLContext::GLFONT_SIZE16).drawString(demod->getLabel(), uxPos, hPos, 16, GLFont::GLFONT_ALIGN_LEFT, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demod->getLabel(), uxPos, hPos, 16, GLFont::GLFONT_ALIGN_LEFT, GLFont::GLFONT_ALIGN_CENTER); } else if (demod->getDemodulatorType() == DEMOD_TYPE_LSB) { - getFont(PrimaryGLContext::GLFONT_SIZE16).drawString(demod->getLabel(), uxPos, hPos, 16, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demod->getLabel(), uxPos, hPos, 16, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER); } else { - getFont(PrimaryGLContext::GLFONT_SIZE16).drawString(demod->getLabel(), uxPos, hPos, 16, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demod->getLabel(), uxPos, hPos, 16, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); } glDisable(GL_BLEND); @@ -264,10 +228,10 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGB color, long lon } glColor3f(0, 0, 0); - getFont(PrimaryGLContext::GLFONT_SIZE16).drawString(demodStr, 2.0 * (uxPos - 0.5) + xOfs, -1.0 + hPos - yOfs, 16, demodAlign, + GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodStr, 2.0 * (uxPos - 0.5) + xOfs, -1.0 + hPos - yOfs, 16, demodAlign, GLFont::GLFONT_ALIGN_CENTER); glColor3f(0.8, 0.8, 0.8); - getFont(PrimaryGLContext::GLFONT_SIZE16).drawString(demodStr, 2.0 * (uxPos - 0.5), -1.0 + hPos, 16, demodAlign, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodStr, 2.0 * (uxPos - 0.5), -1.0 + hPos, 16, demodAlign, GLFont::GLFONT_ALIGN_CENTER); glDisable(GL_BLEND); diff --git a/src/visual/PrimaryGLContext.h b/src/visual/PrimaryGLContext.h index 1f276f8..353f563 100644 --- a/src/visual/PrimaryGLContext.h +++ b/src/visual/PrimaryGLContext.h @@ -13,9 +13,6 @@ class PrimaryGLContext: public wxGLContext { public: - enum GLFontSize { - GLFONT_SIZE12, GLFONT_SIZE16, GLFONT_SIZE18, GLFONT_SIZE24, GLFONT_SIZE32, GLFONT_SIZE48, GLFONT_MAX - }; PrimaryGLContext(wxGLCanvas *canvas, wxGLContext *sharedContext); static wxString glGetwxString(GLenum name); @@ -29,12 +26,9 @@ public: void DrawDemod(DemodulatorInstance *demod, RGB color, long long center_freq = -1, long long srate = 0); void DrawDemodInfo(DemodulatorInstance *demod, RGB color, long long center_freq = -1, long long srate = 0); - static GLFont &getFont(GLFontSize esize); - void setHoverAlpha(float hoverAlpha); private: - static GLFont fonts[GLFONT_MAX]; DemodulatorThreadParameters defaultDemodParams; float hoverAlpha; }; diff --git a/src/visual/ScopeContext.cpp b/src/visual/ScopeContext.cpp index b90f19e..267b038 100644 --- a/src/visual/ScopeContext.cpp +++ b/src/visual/ScopeContext.cpp @@ -81,9 +81,9 @@ void ScopeContext::Plot(std::vector &points, bool stereo, bool ppmMode) { glColor3f(0.65, 0.65, 0.65); - getFont(PrimaryGLContext::GLFONT_SIZE12).drawString(ppmMode?"Device PPM":"Frequency", -0.66, -1.0+hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); - getFont(PrimaryGLContext::GLFONT_SIZE12).drawString("Bandwidth", 0.0, -1.0+hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); - getFont(PrimaryGLContext::GLFONT_SIZE12).drawString("Center Frequency", 0.66, -1.0+hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(GLFont::GLFONT_SIZE12).drawString(ppmMode?"Device PPM":"Frequency", -0.66, -1.0+hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(GLFont::GLFONT_SIZE12).drawString("Bandwidth", 0.0, -1.0+hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(GLFont::GLFONT_SIZE12).drawString("Center Frequency", 0.66, -1.0+hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); if (stereo) { @@ -151,7 +151,7 @@ void ScopeContext::DrawDeviceName(std::string deviceName) { float hPos = (float) (viewHeight - 20) / viewHeight; glColor3f(0.65, 0.65, 0.65); - getFont(PrimaryGLContext::GLFONT_SIZE12).drawString(deviceName.c_str(), 1.0, hPos, 12, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(GLFont::GLFONT_SIZE12).drawString(deviceName.c_str(), 1.0, hPos, 12, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER); } void ScopeContext::DrawEnd() { diff --git a/src/visual/SpectrumContext.cpp b/src/visual/SpectrumContext.cpp index c148179..8ee8cd7 100644 --- a/src/visual/SpectrumContext.cpp +++ b/src/visual/SpectrumContext.cpp @@ -147,7 +147,7 @@ void SpectrumContext::Draw(std::vector &points, long long freq, int bandw glEnd(); glColor4f(ThemeMgr::mgr.currentTheme->text.r, ThemeMgr::mgr.currentTheme->text.g, ThemeMgr::mgr.currentTheme->text.b,1.0); - getFont(PrimaryGLContext::GLFONT_SIZE12).drawString(label.str(), m, hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(GLFont::GLFONT_SIZE12).drawString(label.str(), m, hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); label.str(std::string()); diff --git a/src/visual/TuningContext.cpp b/src/visual/TuningContext.cpp index 338a6b1..e055cb4 100644 --- a/src/visual/TuningContext.cpp +++ b/src/visual/TuningContext.cpp @@ -74,19 +74,19 @@ void TuningContext::DrawTuner(long long freq, int count, float displayPos, float freqStr << freq; std::string freqChars = freqStr.str(); - PrimaryGLContext::GLFontSize fontSize = GLFONT_SIZE24; + GLFont::GLFontSize fontSize = GLFont::GLFONT_SIZE24; int fontHeight = 24; if (viewHeight < 28) { - fontSize = GLFONT_SIZE18; + fontSize = GLFont::GLFONT_SIZE18; fontHeight = 18; } if (viewHeight < 24) { - fontSize = GLFONT_SIZE16; + fontSize = GLFont::GLFONT_SIZE16; fontHeight = 16; } if (viewHeight < 18) { - fontSize = GLFONT_SIZE12; + fontSize = GLFont::GLFONT_SIZE12; fontHeight = 12; } @@ -95,7 +95,7 @@ void TuningContext::DrawTuner(long long freq, int count, float displayPos, float int ofs = count - numChars; for (int i = ofs; i < count; i++) { float xpos = displayPos + (displayWidth / (float) count) * (float) i + ((displayWidth / 2.0) / (float) count); - getFont(fontSize).drawString(freqStr.str().substr(i - ofs, 1), xpos, 0, fontHeight, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); + GLFont::getFont(fontSize).drawString(freqStr.str().substr(i - ofs, 1), xpos, 0, fontHeight, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); } glColor4f(0.65, 0.65, 0.65, 0.25); From 48308145b7917f61b2e69fa2d365a90dee4ad0eb Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 1 Jul 2015 00:34:32 -0400 Subject: [PATCH 10/53] add GLTextPanel, initial work on nested coordinate systems --- src/ui/GLPanel.cpp | 50 ++++++++++++++++++++++++++++++++-------- src/ui/GLPanel.h | 18 +++++++++++++++ src/ui/UITestContext.cpp | 4 ++++ src/ui/UITestContext.h | 1 + src/util/GLFont.cpp | 16 ++++++++----- src/util/GLFont.h | 2 +- 6 files changed, 75 insertions(+), 16 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index 3f0f094..df0bdc8 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -233,6 +233,21 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { } // if (coord == GLPANEL_Y_UP) { // } + } else if (parent->coord != coord) { + if (parent->coord == GLPANEL_Y_DOWN_ZERO_ONE && coord == GLPANEL_Y_UP_ZERO_ONE) { + mCoord *= mat4::translate(0.0f, 1.0f, 0.0f) * mat4::scale(1.0f, -1.0f, 1.0f); + } + if (parent->coord == GLPANEL_Y_UP_ZERO_ONE && coord == GLPANEL_Y_DOWN_ZERO_ONE) { + mCoord *= mat4::translate(0.0f, -1.0f, 0.0f) * mat4::scale(1.0f, -1.0f, 1.0f); + } +// if (coord == GLPANEL_Y_UP_ZERO_ONE) { +// mCoord = mat4::translate(-1.0f, -1.0f, 0.0f) * mat4::scale(2.0f, 2.0f, 2.0f); +// } +// if (coord == GLPANEL_Y_DOWN) { +// mCoord = mat4::scale(2.0f, 2.0f, 2.0f); +// } + // if (coord == GLPANEL_Y_UP) { + // } } // compute local transform @@ -248,24 +263,24 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { vec4 vmax_t = mat4::vec4_multiply(vec4(max, max, 0, 1), transform); // screen dimensions - vec2 vmin((vmin_t.x>vmax_t.x)?vmax_t.x:vmin_t.x, (vmin_t.y>vmax_t.y)?vmax_t.y:vmin_t.y); - vec2 vmax((vmin_t.x>vmax_t.x)?vmin_t.x:vmax_t.x, (vmin_t.y>vmax_t.y)?vmin_t.y:vmax_t.y); + vmin = vec2((vmin_t.x > vmax_t.x)?vmax_t.x:vmin_t.x, (vmin_t.y > vmax_t.y)?vmax_t.y:vmin_t.y); + vmax = vec2((vmin_t.x > vmax_t.x)?vmin_t.x:vmax_t.x, (vmin_t.y > vmax_t.y)?vmin_t.y:vmax_t.y); // unit dimensions - vec2 umin = (vmin * 0.5) + vec2(1,1); - vec2 umax = (vmax * 0.5) + vec2(1,1); + umin = (vmin * 0.5) + vec2(1,1); + umax = (vmax * 0.5) + vec2(1,1); - vec2 ucenter = (umin + umax) * 0.5; + ucenter = vec2((umin + umax) * 0.5); // pixel dimensions - vec2 pdim((umax.x - umin.x) * view[0], (umax.y - umin.y) * view[1]); - vec2 pvec((vmax.x-vmin.x) / pdim.x, (vmax.y-vmin.y) / pdim.y); + pdim = vec2((umax.x - umin.x) * view[0], (umax.y - umin.y) * view[1]); + pvec = vec2((vmax.x - vmin.x) / pdim.x, (vmax.y - vmin.y) / pdim.y); std::cout << umin << " :: " << ucenter << " :: " << pdim << " :: " << pvec << std::endl; if (marginPx.left || marginPx.right || marginPx.top || marginPx.bottom) { - localTransform *= mat4::translate(marginPx.left*pvec.x/size[0], marginPx.top*pvec.y/size[1], 0) * - mat4::scale(1.0-(marginPx.left+marginPx.right)*pvec.x/size[0], 1.0-(marginPx.top+marginPx.bottom)*pvec.y/size[1], 0); + localTransform *= mat4::translate(marginPx.left * pvec.x / size[0], marginPx.top * pvec.y / size[1], 0) * + mat4::scale(1.0 - (marginPx.left + marginPx.right) * pvec.x / size[0], 1.0 - (marginPx.top + marginPx.bottom) * pvec.y / size[1], 0); transform = transform_in * localTransform; } @@ -330,6 +345,23 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { } +GLTextPanel::GLTextPanel() : GLPanel() { + coord = GLPANEL_Y_UP_ZERO_ONE; +} + +void GLTextPanel::drawPanelContents() { + glColor4f(1, 1, 1, 1.0); + GLFont::getFont(GLFont::GLFONT_SIZE48).drawString(textVal, mid, mid, 48, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER, (int)pdim.x*2, (int)pdim.y*2); +} + +void GLTextPanel::setText(std::string text) { + textVal = text; +} + +std::string GLTextPanel::getText() { + return textVal; +} + void GLTestPanel::drawPanelContents() { diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index 86b8aa7..0d6175f 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -2,6 +2,7 @@ #include #include "GLExt.h" +#include "GLFont.h" #include "ColorTheme.h" #include "cubic_math.h" @@ -47,6 +48,12 @@ public: CubicVR::mat4 transform; CubicVR::mat4 localTransform; float min, mid, max; + // screen dimensions + CubicVR::vec2 vmin, vmax; + // unit dimensions + CubicVR::vec2 umin, umax, ucenter; + // pixel dimensions + CubicVR::vec2 pdim, pvec; std::vector children; @@ -76,6 +83,17 @@ public: }; +class GLTextPanel : public GLPanel { +private: + std::string textVal; +public: + GLTextPanel(); + + void drawPanelContents(); + void setText(std::string text); + std::string getText(); +}; + class GLTestPanel : public GLPanel { public: GLTestPanel() : GLPanel() { diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index b06cdb0..53a5e79 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -26,6 +26,10 @@ PrimaryGLContext(canvas, sharedContext) { testChildPanel2.setBorderColor(RGB(1.0,0.0,0.0)); testChildPanel2.setBorderPx(1); + testText1.setText("Testing 123.."); + testText1.setFill(GLPanel::GLPANEL_FILL_NONE); + testChildPanel2.addChild(&testText1); + testPanel.addChild(&testChildPanel); testPanel.addChild(&testChildPanel2); } diff --git a/src/ui/UITestContext.h b/src/ui/UITestContext.h index 9ac27bb..e84755a 100644 --- a/src/ui/UITestContext.h +++ b/src/ui/UITestContext.h @@ -17,4 +17,5 @@ private: GLPanel testPanel; GLTestPanel testChildPanel; GLPanel testChildPanel2; + GLTextPanel testText1; }; diff --git a/src/util/GLFont.cpp b/src/util/GLFont.cpp index 2edfda2..d922e33 100644 --- a/src/util/GLFont.cpp +++ b/src/util/GLFont.cpp @@ -397,16 +397,20 @@ float GLFont::getStringWidth(std::string str, float size, float viewAspect) { return width; } -void GLFont::drawString(std::string str, float xpos, float ypos, int pxHeight, Align hAlign, Align vAlign) { +void GLFont::drawString(std::string str, float xpos, float ypos, int pxHeight, Align hAlign, Align vAlign, int vpx, int vpy) { - GLint vp[4]; pxHeight *= 2; - glGetIntegerv( GL_VIEWPORT, vp); - - float size = (float) pxHeight / (float) vp[3]; - float viewAspect = (float) vp[2] / (float) vp[3]; + if (!vpx || !vpy) { + GLint vp[4]; + glGetIntegerv( GL_VIEWPORT, vp); + vpx = vp[2]; + vpy = vp[3]; + } + + float size = (float) pxHeight / (float) vpy; + float viewAspect = (float) vpx / (float) vpy; float msgWidth = getStringWidth(str, size, viewAspect); glPushMatrix(); diff --git a/src/util/GLFont.h b/src/util/GLFont.h index f369ef0..825459b 100644 --- a/src/util/GLFont.h +++ b/src/util/GLFont.h @@ -66,7 +66,7 @@ public: bool isLoaded(); float getStringWidth(std::string str, float size, float viewAspect); - void drawString(std::string str, float xpos, float ypos, int pxHeight, Align hAlign = GLFONT_ALIGN_LEFT, Align vAlign = GLFONT_ALIGN_TOP); + void drawString(std::string str, float xpos, float ypos, int pxHeight, Align hAlign = GLFONT_ALIGN_LEFT, Align vAlign = GLFONT_ALIGN_TOP, int vpx=0, int vpy=0); static GLFont fonts[GLFONT_MAX]; static GLFont &getFont(GLFontSize esize); From 5ac0dc8c41968991214344acb99927872348bf4f Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 5 Jul 2015 18:54:46 -0400 Subject: [PATCH 11/53] simplify alt. coordinate sys on panel contents only, y-up otherwise --- src/ui/GLPanel.cpp | 98 +++++++++++++++------------------------- src/ui/GLPanel.h | 3 +- src/ui/UITestContext.cpp | 21 ++++++--- src/ui/UITestContext.h | 1 + 4 files changed, 54 insertions(+), 69 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index df0bdc8..aed5d6b 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -10,10 +10,12 @@ GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transf fill[0] = RGB(0.5,0.5,0.5); fill[1] = RGB(0.1,0.1,0.1); borderColor = RGB(0.8, 0.8, 0.8); - setCoordinateSystem(GLPANEL_Y_DOWN_ZERO_ONE); + setCoordinateSystem(GLPANEL_Y_UP); } void GLPanel::genArrays() { + float min = -1.0, mid = 0, max = 1.0; + if (fillType == GLPANEL_FILL_SOLID || fillType == GLPANEL_FILL_GRAD_X || fillType == GLPANEL_FILL_GRAD_Y) { glPoints.reserve(2 * 4); glPoints.resize(2 * 4); @@ -173,15 +175,9 @@ void GLPanel::setFillColor(RGB color1, RGB color2) { } void GLPanel::setMarginPx(float marg) { - marginPx.left = marginPx.right = marginPx.top = marginPx.bottom = marg; + marginPx = marg; } -void GLPanel::setMarginPx(float margl, float margr, float margt, float margb) { - marginPx.left = margl; - marginPx.right = margr; - marginPx.top = margt; - marginPx.bottom = margb; -} void GLPanel::setBorderColor(RGB clr) { borderColor = clr; @@ -219,39 +215,9 @@ void GLPanel::drawPanelContents() { void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { using namespace CubicVR; - mat4 mCoord = mat4::identity(); - - if (!parent) { - if (coord == GLPANEL_Y_DOWN_ZERO_ONE) { - mCoord *= mat4::translate(-1.0f, 1.0f, 0.0f) * mat4::scale(2.0f, -2.0f, 2.0f); - } - if (coord == GLPANEL_Y_UP_ZERO_ONE) { - mCoord = mat4::translate(-1.0f, -1.0f, 0.0f) * mat4::scale(2.0f, 2.0f, 2.0f); - } - if (coord == GLPANEL_Y_DOWN) { - mCoord = mat4::scale(2.0f, 2.0f, 2.0f); - } -// if (coord == GLPANEL_Y_UP) { -// } - } else if (parent->coord != coord) { - if (parent->coord == GLPANEL_Y_DOWN_ZERO_ONE && coord == GLPANEL_Y_UP_ZERO_ONE) { - mCoord *= mat4::translate(0.0f, 1.0f, 0.0f) * mat4::scale(1.0f, -1.0f, 1.0f); - } - if (parent->coord == GLPANEL_Y_UP_ZERO_ONE && coord == GLPANEL_Y_DOWN_ZERO_ONE) { - mCoord *= mat4::translate(0.0f, -1.0f, 0.0f) * mat4::scale(1.0f, -1.0f, 1.0f); - } -// if (coord == GLPANEL_Y_UP_ZERO_ONE) { -// mCoord = mat4::translate(-1.0f, -1.0f, 0.0f) * mat4::scale(2.0f, 2.0f, 2.0f); -// } -// if (coord == GLPANEL_Y_DOWN) { -// mCoord = mat4::scale(2.0f, 2.0f, 2.0f); -// } - // if (coord == GLPANEL_Y_UP) { - // } - } // compute local transform - localTransform = mCoord * (mat4::translate(pos[0], pos[1], 0) * mat4::scale(size[0], size[1], 0)); + localTransform = mat4::translate(pos[0], pos[1], 0) * mat4::scale(size[0], size[1], 0); // compute global transform transform = transform_in * localTransform; @@ -273,15 +239,13 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { ucenter = vec2((umin + umax) * 0.5); // pixel dimensions - pdim = vec2((umax.x - umin.x) * view[0], (umax.y - umin.y) * view[1]); - pvec = vec2((vmax.x - vmin.x) / pdim.x, (vmax.y - vmin.y) / pdim.y); + pdim = vec2((vmax.x - vmin.x) / 2.0 * view[0], (vmax.y - vmin.y) / 2.0 * view[1]); + pvec = vec2(((vmax.x - vmin.x) / 2.0) / pdim.x, ((vmax.y - vmin.y) / 2.0) / pdim.y); std::cout << umin << " :: " << ucenter << " :: " << pdim << " :: " << pvec << std::endl; - if (marginPx.left || marginPx.right || marginPx.top || marginPx.bottom) { - localTransform *= mat4::translate(marginPx.left * pvec.x / size[0], marginPx.top * pvec.y / size[1], 0) * - mat4::scale(1.0 - (marginPx.left + marginPx.right) * pvec.x / size[0], 1.0 - (marginPx.top + marginPx.bottom) * pvec.y / size[1], 0); - transform = transform_in * localTransform; + if (marginPx) { + transform *= mat4::scale(1.0 - marginPx * 2.0 * pvec.x / size[0], 1.0 - marginPx * 2.0 * pvec.y / size[1], 0); } glLoadMatrixf(transform); @@ -338,20 +302,32 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { } if (contentsVisible) { - glPushMatrix(); + mat4 mCoord = mat4::identity(); + + if (coord == GLPANEL_Y_DOWN_ZERO_ONE) { + mCoord *= mat4::translate(-1.0f, 1.0f, 0.0f) * mat4::scale(2.0f, -2.0f, 2.0f); + } + if (coord == GLPANEL_Y_UP_ZERO_ONE) { + mCoord = mat4::translate(-1.0f, -1.0f, 0.0f) * mat4::scale(2.0f, 2.0f, 2.0f); + } + if (coord == GLPANEL_Y_DOWN) { + mCoord = mat4::scale(1.0f, -1.0f, 1.0f); + } + // if (coord == GLPANEL_Y_UP) { + // } + glLoadMatrixf(transform * mCoord); drawPanelContents(); - glPopMatrix(); } } GLTextPanel::GLTextPanel() : GLPanel() { - coord = GLPANEL_Y_UP_ZERO_ONE; + coord = GLPANEL_Y_UP; } void GLTextPanel::drawPanelContents() { glColor4f(1, 1, 1, 1.0); - GLFont::getFont(GLFont::GLFONT_SIZE48).drawString(textVal, mid, mid, 48, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER, (int)pdim.x*2, (int)pdim.y*2); + GLFont::getFont(GLFont::GLFONT_SIZE48).drawString(textVal, mid, mid, 48, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER, (int)pdim.x, (int)pdim.y); } void GLTextPanel::setText(std::string text) { @@ -367,20 +343,20 @@ std::string GLTextPanel::getText() { void GLTestPanel::drawPanelContents() { glColor3f(1.0,1.0,1.0); glBegin(GL_LINES); - glVertex2f(0, 0.5); - glVertex2f(1, 0.5); - glVertex2f(0.5, 0); - glVertex2f(0.5, 1); + glVertex2f(min, mid); + glVertex2f(max, mid); + glVertex2f(mid, min); + glVertex2f(mid, max); - glVertex2f(0.5, 1); - glVertex2f(0.48, 0.80); - glVertex2f(0.5, 1); - glVertex2f(0.52, 0.80); + glVertex2f(mid, max); + glVertex2f(mid - 0.02, max - 0.2); + glVertex2f(mid, 1); + glVertex2f(mid + 0.02, max - 0.2); - glVertex2f(1, 0.5); - glVertex2f(0.90, 0.25); - glVertex2f(1, 0.5); - glVertex2f(0.90, 0.75); + glVertex2f(max, mid); + glVertex2f(max - 0.1, mid + max * 0.25); + glVertex2f(max, mid); + glVertex2f(max - 0.1, mid - max * 0.25); glEnd(); } diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index 0d6175f..22d7600 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -40,7 +40,7 @@ public: float view[2]; GLPanelFillType fillType; GLPanelCoordinateSystem coord; - GLPanelEdges marginPx; + float marginPx; GLPanelEdges borderPx; RGB fill[2]; RGB borderColor; @@ -69,7 +69,6 @@ public: void setFillColor(RGB color1); void setFillColor(RGB color1, RGB color2); void setMarginPx(float marg); - void setMarginPx(float margl, float margr, float margt, float margb); void setBorderColor(RGB clr); void setBorderPx(float bord); diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index 53a5e79..f5c597b 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -12,26 +12,35 @@ PrimaryGLContext(canvas, sharedContext) { testPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel.setPosition(0.0, 0.0); - testChildPanel.setMarginPx(10,10,10,5); - testChildPanel.setSize(1.0, 0.5); + testChildPanel.setMarginPx(10); + testChildPanel.setSize(1.0, 0.33); testChildPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X); testChildPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel.setBorderPx(1); - testChildPanel2.setPosition(0.0, 0.5); - testChildPanel2.setSize(1.0, 0.5); - testChildPanel2.setMarginPx(10,10,5,10); + testChildPanel2.setPosition(0.0, -0.66); + testChildPanel2.setSize(1.0, 0.33); + testChildPanel2.setMarginPx(10); testChildPanel2.setFill(GLPanel::GLPANEL_FILL_GRAD_X); testChildPanel2.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel2.setBorderColor(RGB(1.0,0.0,0.0)); testChildPanel2.setBorderPx(1); - + + testChildPanel3.setPosition(0.0, 0.66); + testChildPanel3.setSize(1.0, 0.33); + testChildPanel3.setMarginPx(10); + testChildPanel3.setFill(GLPanel::GLPANEL_FILL_GRAD_X); + testChildPanel3.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); + testChildPanel3.setBorderColor(RGB(1.0,0.0,0.0)); + testChildPanel3.setBorderPx(1); + testText1.setText("Testing 123.."); testText1.setFill(GLPanel::GLPANEL_FILL_NONE); testChildPanel2.addChild(&testText1); testPanel.addChild(&testChildPanel); testPanel.addChild(&testChildPanel2); + testPanel.addChild(&testChildPanel3); } void UITestContext::DrawBegin() { diff --git a/src/ui/UITestContext.h b/src/ui/UITestContext.h index e84755a..f392336 100644 --- a/src/ui/UITestContext.h +++ b/src/ui/UITestContext.h @@ -17,5 +17,6 @@ private: GLPanel testPanel; GLTestPanel testChildPanel; GLPanel testChildPanel2; + GLPanel testChildPanel3; GLTextPanel testText1; }; From 237a7ad06f7e6901f561f7c12503ea4d37790ae9 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 5 Jul 2015 19:10:48 -0400 Subject: [PATCH 12/53] Separate transform calc and render --- src/ui/GLPanel.cpp | 16 +++++++++------- src/ui/GLPanel.h | 3 ++- src/ui/UITestContext.cpp | 3 ++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index aed5d6b..4643966 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -2,7 +2,9 @@ #include "GLPanel.h" #include "cubic_math.h" -GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transform(CubicVR::mat4::identity()) { +using namespace CubicVR; + +GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transform(mat4::identity()) { pos[0] = 0.0f; pos[1] = 0.0f; size[0] = 1.0f; @@ -203,7 +205,8 @@ void GLPanel::drawChildren() { std::vector::iterator panel_i; for (panel_i = children.begin(); panel_i != children.end(); panel_i++) { - (*panel_i)->draw(transform, this); + (*panel_i)->calcTransform(transform); + (*panel_i)->draw(); } } } @@ -212,10 +215,7 @@ void GLPanel::drawPanelContents() { drawChildren(); } -void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { - using namespace CubicVR; - - +void GLPanel::calcTransform(mat4 transform_in) { // compute local transform localTransform = mat4::translate(pos[0], pos[1], 0) * mat4::scale(size[0], size[1], 0); // compute global transform @@ -247,7 +247,9 @@ void GLPanel::draw(CubicVR::mat4 transform_in, GLPanel *parent) { if (marginPx) { transform *= mat4::scale(1.0 - marginPx * 2.0 * pvec.x / size[0], 1.0 - marginPx * 2.0 * pvec.y / size[1], 0); } - +} + +void GLPanel::draw() { glLoadMatrixf(transform); if (fillType != GLPANEL_FILL_NONE) { diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index 22d7600..c4c1ed2 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -78,7 +78,8 @@ public: void drawChildren(); virtual void drawPanelContents(); - void draw(CubicVR::mat4 transform, GLPanel *parent=NULL); + void calcTransform(CubicVR::mat4 transform); + void draw(); }; diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index f5c597b..5279d1f 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -57,7 +57,8 @@ void UITestContext::DrawBegin() { } void UITestContext::Draw() { - testPanel.draw(CubicVR::mat4::identity()); + testPanel.calcTransform(CubicVR::mat4::identity()); + testPanel.draw(); } void UITestContext::DrawEnd() { From 27aacb001e1bcb3b69d2c904b85c295d944cbdaa Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 5 Jul 2015 21:09:00 -0400 Subject: [PATCH 13/53] basic automatic font size --- src/ui/GLPanel.cpp | 40 +++++++++++++++++++++++++++++++++++++--- src/ui/GLPanel.h | 2 ++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index 4643966..4d3d943 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -135,12 +135,20 @@ void GLPanel::setSize(float w, float h) { size[1] = h; } +float GLPanel::getWidth() { + return size[0]; +} + +float GLPanel::getHeight() { + return size[1]; +} + float GLPanel::getWidthPx() { - return size[0]*view[0]; + return pdim.x; } float GLPanel::getHeightPx() { - return size[1]*view[0]; + return pdim.y; } @@ -329,7 +337,33 @@ GLTextPanel::GLTextPanel() : GLPanel() { void GLTextPanel::drawPanelContents() { glColor4f(1, 1, 1, 1.0); - GLFont::getFont(GLFont::GLFONT_SIZE48).drawString(textVal, mid, mid, 48, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER, (int)pdim.x, (int)pdim.y); + + GLFont::GLFontSize sz; + float size; + + + if (pdim.y < 16) { + sz = GLFont::GLFONT_SIZE12; + size = 12; + } else if (pdim.y < 18) { + sz = GLFont::GLFONT_SIZE16; + size = 16; + } else if(pdim.y < 24) { + sz = GLFont::GLFONT_SIZE18; + size = 18; + } else if(pdim.y < 32) { + sz = GLFont::GLFONT_SIZE24; + size = 24; + } else if(pdim.y < 48) { + sz = GLFont::GLFONT_SIZE32; + size = 32; + } else { + sz = GLFont::GLFONT_SIZE48; + size = 48; + } + + + GLFont::getFont(sz).drawString(textVal, mid, mid, size, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER, (int)pdim.x, (int)pdim.y); } void GLTextPanel::setText(std::string text) { diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index c4c1ed2..d03a60d 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -61,6 +61,8 @@ public: void setPosition(float x, float y); void setSize(float w, float h); + float getWidth(); + float getHeight(); float getWidthPx(); float getHeightPx(); void setCoordinateSystem(GLPanelCoordinateSystem coord); From 59b8c419067ae2c81eda9f0710510529aa111025 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 6 Jul 2015 23:05:49 -0400 Subject: [PATCH 14/53] border fix --- src/ui/GLPanel.cpp | 2 ++ src/ui/UITestContext.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index 4d3d943..e0d24ed 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -258,6 +258,8 @@ void GLPanel::calcTransform(mat4 transform_in) { } void GLPanel::draw() { + float min = -1.0, max = 1.0; + glLoadMatrixf(transform); if (fillType != GLPANEL_FILL_NONE) { diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index 5279d1f..8042981 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -12,15 +12,16 @@ PrimaryGLContext(canvas, sharedContext) { testPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel.setPosition(0.0, 0.0); - testChildPanel.setMarginPx(10); + testChildPanel.setMarginPx(5); testChildPanel.setSize(1.0, 0.33); + testChildPanel.setCoordinateSystem(GLPanel::GLPANEL_Y_DOWN_ZERO_ONE); testChildPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X); testChildPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel.setBorderPx(1); testChildPanel2.setPosition(0.0, -0.66); testChildPanel2.setSize(1.0, 0.33); - testChildPanel2.setMarginPx(10); + testChildPanel2.setMarginPx(5); testChildPanel2.setFill(GLPanel::GLPANEL_FILL_GRAD_X); testChildPanel2.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel2.setBorderColor(RGB(1.0,0.0,0.0)); @@ -28,7 +29,7 @@ PrimaryGLContext(canvas, sharedContext) { testChildPanel3.setPosition(0.0, 0.66); testChildPanel3.setSize(1.0, 0.33); - testChildPanel3.setMarginPx(10); + testChildPanel3.setMarginPx(5); testChildPanel3.setFill(GLPanel::GLPANEL_FILL_GRAD_X); testChildPanel3.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); testChildPanel3.setBorderColor(RGB(1.0,0.0,0.0)); From a8e24d5537b23c2093ff1546fe3bf20f45f91ada Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 27 Jul 2015 21:20:44 -0400 Subject: [PATCH 15/53] Visual Processor prototype link data -> visuals with common processing pipeline, chainable --- CMakeLists.txt | 2 ++ src/process/VisualProcessor.cpp | 1 + src/process/VisualProcessor.h | 41 +++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 src/process/VisualProcessor.cpp create mode 100644 src/process/VisualProcessor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a66d2f..a39272d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,6 +257,7 @@ SET (cubicsdr_sources src/visual/SpectrumContext.cpp src/visual/WaterfallCanvas.cpp src/visual/WaterfallContext.cpp + src/process/VisualProcessor.cpp src/ui/GLPanel.cpp external/rtaudio/RtAudio.cpp external/lodepng/lodepng.cpp @@ -304,6 +305,7 @@ SET (cubicsdr_headers src/visual/SpectrumContext.h src/visual/WaterfallCanvas.h src/visual/WaterfallContext.h + src/process/VisualProcessor.h src/ui/GLPanel.h src/ui/UITestCanvas.cpp src/ui/UITestCanvas.h diff --git a/src/process/VisualProcessor.cpp b/src/process/VisualProcessor.cpp new file mode 100644 index 0000000..c19fe88 --- /dev/null +++ b/src/process/VisualProcessor.cpp @@ -0,0 +1 @@ +#include "VisualProcessor.h" diff --git a/src/process/VisualProcessor.h b/src/process/VisualProcessor.h new file mode 100644 index 0000000..1cc23bd --- /dev/null +++ b/src/process/VisualProcessor.h @@ -0,0 +1,41 @@ +#pragma once + +#include "CubicSDRDefs.h" +#include "ThreadQueue.h" + +typedef ThreadQueue VisualDataQueue; + +class VisualProcessor { +public: + void setInput(VisualDataQueue *vis_in) { + // set input queue + } + + void attachOutput(VisualDataQueue *vis_out) { + // attach an output queue + } + + void removeOutput(VisualDataQueue *vis_out) { + // remove an output queue + } + + void pushInput(ReferenceCounter *input) { + // push input data + } + + virtual void process() { + // process input to output + // distribute(output); + } + +protected: + void distribute(ReferenceCounter *output) { + // distribute outputs + } + + VisualDataQueue * input; + std::vector outputs; + + std::mutex busy_update; +}; + From 090062191cfb10cd61d56647e4918c51bea0907a Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 27 Jul 2015 21:45:24 -0400 Subject: [PATCH 16/53] Visual processor basic framework --- src/CubicSDR.cpp | 6 ++++++ src/CubicSDR.h | 5 +---- src/process/VisualProcessor.h | 27 ++++++++++++++++++++++----- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 2c8c2cb..e6742e5 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -21,6 +21,12 @@ IMPLEMENT_APP(CubicSDR) +CubicSDR::CubicSDR() : appframe(NULL), m_glContext(NULL), frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), directSamplingMode(0), + sdrThread(NULL), sdrPostThread(NULL), threadCmdQueueSDR(NULL), iqPostDataQueue(NULL), iqVisualQueue(NULL), audioVisualQueue(NULL), t_SDR(NULL), t_PostSDR(NULL) { + +} + + bool CubicSDR::OnInit() { #ifdef _OSX_APP_ CFBundleRef mainBundle = CFBundleGetMainBundle(); diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 174318d..685f6d8 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -23,10 +23,7 @@ class CubicSDR: public wxApp { public: - CubicSDR() : - appframe(NULL), m_glContext(NULL), frequency(0), sdrThread(NULL), sdrPostThread(NULL), threadCmdQueueSDR(NULL), iqVisualQueue(NULL), iqPostDataQueue(NULL), audioVisualQueue(NULL), t_SDR(NULL), t_PostSDR(NULL), sampleRate(DEFAULT_SAMPLE_RATE), offset(0), snap(1), directSamplingMode(0), ppm(0) { - - } + CubicSDR(); PrimaryGLContext &GetContext(wxGLCanvas *canvas); diff --git a/src/process/VisualProcessor.h b/src/process/VisualProcessor.h index 1cc23bd..620cdfa 100644 --- a/src/process/VisualProcessor.h +++ b/src/process/VisualProcessor.h @@ -8,34 +8,51 @@ typedef ThreadQueue VisualDataQueue; class VisualProcessor { public: void setInput(VisualDataQueue *vis_in) { - // set input queue + busy_update.lock(); + input = vis_in; + busy_update.unlock(); } void attachOutput(VisualDataQueue *vis_out) { // attach an output queue + busy_update.lock(); + outputs.push_back(vis_out); + busy_update.unlock(); } void removeOutput(VisualDataQueue *vis_out) { // remove an output queue + busy_update.lock(); + std::vector::iterator i = std::find(outputs.begin(), outputs.end(), vis_out); + if (i != outputs.end()) { + outputs.erase(i); + } + busy_update.unlock(); } - void pushInput(ReferenceCounter *input) { - // push input data + void run() { + busy_update.lock(); + process(); + busy_update.unlock(); } virtual void process() { - // process input to output + // process inputs to output // distribute(output); } protected: void distribute(ReferenceCounter *output) { // distribute outputs + output->setRefCount(outputs.size()); + std::vector::iterator outputs_i; + for (outputs_i = outputs.begin(); outputs_i != outputs.begin(); outputs_i++) { + (*outputs_i)->push(output); + } } VisualDataQueue * input; std::vector outputs; - std::mutex busy_update; }; From 0198f2410ff630e75171866ec8b3fe58b5527aa4 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 27 Jul 2015 22:05:35 -0400 Subject: [PATCH 17/53] basic visual data pass-thru distributor --- src/process/VisualProcessor.h | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/process/VisualProcessor.h b/src/process/VisualProcessor.h index 620cdfa..f7ec6f5 100644 --- a/src/process/VisualProcessor.h +++ b/src/process/VisualProcessor.h @@ -32,16 +32,18 @@ public: void run() { busy_update.lock(); - process(); + if (input && !input->empty()) { + process(); + } busy_update.unlock(); } +protected: virtual void process() { // process inputs to output // distribute(output); } - -protected: + void distribute(ReferenceCounter *output) { // distribute outputs output->setRefCount(outputs.size()); @@ -56,3 +58,17 @@ protected: std::mutex busy_update; }; + +class VisualDataDistributor : public VisualProcessor { +protected: + virtual void process() { + while (!input->empty()) { + ReferenceCounter *inp; + input->pop(inp); + if (inp) { + distribute(inp); + } + } + } +}; + From 10bc0c8ec5aece4ef1325b1b09b0c4191ce7a908 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 27 Jul 2015 22:30:25 -0400 Subject: [PATCH 18/53] spectrum + waterfall processor init --- CMakeLists.txt | 73 +++++++++++++----------- src/process/SpectrumVisualProcessor.cpp | 1 + src/process/SpectrumVisualProcessor.h | 10 ++++ src/process/WaterfallVisualProcessor.cpp | 1 + src/process/WaterfallVisualProcessor.h | 11 ++++ 5 files changed, 62 insertions(+), 34 deletions(-) create mode 100644 src/process/SpectrumVisualProcessor.cpp create mode 100644 src/process/SpectrumVisualProcessor.h create mode 100644 src/process/WaterfallVisualProcessor.cpp create mode 100644 src/process/WaterfallVisualProcessor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a39272d..92cfe0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,7 @@ ENDIF (APPLE) SET (cubicsdr_sources - src/CubicSDR.cpp + src/CubicSDR.cpp src/AppFrame.cpp src/AppConfig.cpp src/FrequencyDialog.cpp @@ -241,7 +241,7 @@ SET (cubicsdr_sources src/util/MouseTracker.cpp src/util/GLExt.cpp src/util/GLFont.cpp - src/util/DataTree.cpp + src/util/DataTree.cpp src/visual/ColorTheme.cpp src/visual/PrimaryGLContext.cpp src/visual/InteractiveCanvas.cpp @@ -257,20 +257,22 @@ SET (cubicsdr_sources src/visual/SpectrumContext.cpp src/visual/WaterfallCanvas.cpp src/visual/WaterfallContext.cpp - src/process/VisualProcessor.cpp - src/ui/GLPanel.cpp + src/process/VisualProcessor.cpp + src/process/SpectrumVisualProcessor.cpp + src/process/WaterfallVisualProcessor.cpp + src/ui/GLPanel.cpp external/rtaudio/RtAudio.cpp external/lodepng/lodepng.cpp - external/tinyxml/tinyxml.cpp - external/tinyxml/tinystr.cpp - external/tinyxml/tinyxmlparser.cpp - external/tinyxml/tinyxmlerror.cpp - external/cubicvr2/math/cubic_math.cpp + external/tinyxml/tinyxml.cpp + external/tinyxml/tinystr.cpp + external/tinyxml/tinyxmlparser.cpp + external/tinyxml/tinyxmlerror.cpp + external/cubicvr2/math/cubic_math.cpp ) SET (cubicsdr_headers src/CubicSDRDefs.h - src/CubicSDR.h + src/CubicSDR.h src/AppFrame.h src/AppConfig.h src/FrequencyDialog.h @@ -289,7 +291,7 @@ SET (cubicsdr_headers src/util/MouseTracker.h src/util/GLExt.h src/util/GLFont.h - src/util/DataTree.h + src/util/DataTree.h src/visual/ColorTheme.h src/visual/PrimaryGLContext.h src/visual/InteractiveCanvas.h @@ -305,30 +307,32 @@ SET (cubicsdr_headers src/visual/SpectrumContext.h src/visual/WaterfallCanvas.h src/visual/WaterfallContext.h - src/process/VisualProcessor.h - src/ui/GLPanel.h - src/ui/UITestCanvas.cpp - src/ui/UITestCanvas.h - src/ui/UITestContext.cpp - src/ui/UITestContext.h + src/process/VisualProcessor.h + src/process/SpectrumVisualProcessor.h + src/process/WaterfallVisualProcessor.h + src/ui/GLPanel.h + src/ui/UITestCanvas.cpp + src/ui/UITestCanvas.h + src/ui/UITestContext.cpp + src/ui/UITestContext.h external/rtaudio/RtAudio.h external/lodepng/lodepng.h - external/tinyxml/tinyxml.h - external/tinyxml/tinystr.h - external/cubicvr2/math/aabb.h - external/cubicvr2/math/cubic_math.h - external/cubicvr2/math/cubic_types.h - external/cubicvr2/math/frustum.h - external/cubicvr2/math/mat3.h - external/cubicvr2/math/mat4.h - external/cubicvr2/math/plane.h - external/cubicvr2/math/quaternion.h - external/cubicvr2/math/sphere.h - external/cubicvr2/math/transform.h - external/cubicvr2/math/triangle.h - external/cubicvr2/math/vec2.h - external/cubicvr2/math/vec3.h - external/cubicvr2/math/vec4.h + external/tinyxml/tinyxml.h + external/tinyxml/tinystr.h + external/cubicvr2/math/aabb.h + external/cubicvr2/math/cubic_math.h + external/cubicvr2/math/cubic_types.h + external/cubicvr2/math/frustum.h + external/cubicvr2/math/mat3.h + external/cubicvr2/math/mat4.h + external/cubicvr2/math/plane.h + external/cubicvr2/math/quaternion.h + external/cubicvr2/math/sphere.h + external/cubicvr2/math/transform.h + external/cubicvr2/math/triangle.h + external/cubicvr2/math/vec2.h + external/cubicvr2/math/vec3.h + external/cubicvr2/math/vec4.h ) include_directories ( @@ -336,7 +340,8 @@ include_directories ( ${PROJECT_SOURCE_DIR}/src/demod ${PROJECT_SOURCE_DIR}/src/audio ${PROJECT_SOURCE_DIR}/src/util - ${PROJECT_SOURCE_DIR}/src/visual + ${PROJECT_SOURCE_DIR}/src/visual + ${PROJECT_SOURCE_DIR}/src/process ${PROJECT_SOURCE_DIR}/src/ui ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/external/rtaudio diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp new file mode 100644 index 0000000..dd69858 --- /dev/null +++ b/src/process/SpectrumVisualProcessor.cpp @@ -0,0 +1 @@ +#include "SpectrumVisualProcessor.h" \ No newline at end of file diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h new file mode 100644 index 0000000..2f9f9e8 --- /dev/null +++ b/src/process/SpectrumVisualProcessor.h @@ -0,0 +1,10 @@ +#pragma once + +#include "VisualProcessor.h" + +class SpectrumVisualProcessor : public VisualProcessor { +protected: + virtual void process() { + + } +}; \ No newline at end of file diff --git a/src/process/WaterfallVisualProcessor.cpp b/src/process/WaterfallVisualProcessor.cpp new file mode 100644 index 0000000..2b8a46e --- /dev/null +++ b/src/process/WaterfallVisualProcessor.cpp @@ -0,0 +1 @@ +#include "WaterfallVisualProcessor.h" \ No newline at end of file diff --git a/src/process/WaterfallVisualProcessor.h b/src/process/WaterfallVisualProcessor.h new file mode 100644 index 0000000..e1ee88f --- /dev/null +++ b/src/process/WaterfallVisualProcessor.h @@ -0,0 +1,11 @@ +#pragma once + +#include "VisualProcessor.h" + + +class WaterfallVisualProcessor : public VisualProcessor { +protected: + virtual void process() { + + } +}; \ No newline at end of file From 52e6de5f9de1868387c71b4fd4411885e1052dca Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 28 Jul 2015 18:19:39 -0400 Subject: [PATCH 19/53] prep code from waterfall/spectrum setData --- external/rtaudio/RtAudio.cpp | 4 +- src/process/SpectrumVisualProcessor.h | 77 ++++++- src/process/WaterfallVisualProcessor.h | 270 +++++++++++++++++++++++++ 3 files changed, 348 insertions(+), 3 deletions(-) diff --git a/external/rtaudio/RtAudio.cpp b/external/rtaudio/RtAudio.cpp index ddd8ff3..2167e84 100644 --- a/external/rtaudio/RtAudio.cpp +++ b/external/rtaudio/RtAudio.cpp @@ -10051,8 +10051,8 @@ void RtApi :: convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info void RtApi :: byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ) { - register char val; - register char *ptr; + char val; + char *ptr; ptr = buffer; if ( format == RTAUDIO_SINT16 ) { diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h index 2f9f9e8..20fa627 100644 --- a/src/process/SpectrumVisualProcessor.h +++ b/src/process/SpectrumVisualProcessor.h @@ -5,6 +5,81 @@ class SpectrumVisualProcessor : public VisualProcessor { protected: virtual void process() { - + /* + std::vector *data = &input->data; + if (data && data->size()) { + if (fft_size != data->size()) { + setup(data->size()); + } + if (spectrum_points.size() < fft_size * 2) { + if (spectrum_points.capacity() < fft_size * 2) { + spectrum_points.reserve(fft_size * 2); + } + spectrum_points.resize(fft_size * 2); + } + + for (int i = 0; i < fft_size; i++) { + in[i][0] = (*data)[i].real; + in[i][1] = (*data)[i].imag; + } + + fftwf_execute(plan); + + float fft_ceil = 0, fft_floor = 1; + + if (fft_result.size() != fft_size) { + if (fft_result.capacity() < fft_size) { + fft_result.reserve(fft_size); + fft_result_ma.reserve(fft_size); + fft_result_maa.reserve(fft_size); + } + fft_result.resize(fft_size); + fft_result_ma.resize(fft_size); + fft_result_maa.resize(fft_size); + } + + int n; + for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { + float a = out[i][0]; + float b = out[i][1]; + float c = sqrt(a * a + b * b); + + float x = out[fft_size / 2 + i][0]; + float y = out[fft_size / 2 + i][1]; + float z = sqrt(x * x + y * y); + + fft_result[i] = (z); + fft_result[fft_size / 2 + i] = (c); + } + + for (int i = 0, iMax = fft_size; i < iMax; i++) { + fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; + fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; + + if (fft_result_maa[i] > fft_ceil) { + fft_ceil = fft_result_maa[i]; + } + if (fft_result_maa[i] < fft_floor) { + fft_floor = fft_result_maa[i]; + } + } + + fft_ceil += 1; + fft_floor -= 1; + + fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.01; + fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.01; + + fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.01; + fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.01; + + for (int i = 0, iMax = fft_size; i < iMax; i++) { + float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); + spectrum_points[i * 2] = ((float) i / (float) iMax); + spectrum_points[i * 2 + 1] = v; + } + + } +*/ } }; \ No newline at end of file diff --git a/src/process/WaterfallVisualProcessor.h b/src/process/WaterfallVisualProcessor.h index e1ee88f..b33c37e 100644 --- a/src/process/WaterfallVisualProcessor.h +++ b/src/process/WaterfallVisualProcessor.h @@ -6,6 +6,276 @@ class WaterfallVisualProcessor : public VisualProcessor { protected: virtual void process() { +/* + long double currentZoom = zoom; + if (mouseZoom != 1) { + currentZoom = mouseZoom; + mouseZoom = mouseZoom + (1.0 - mouseZoom) * 0.2; + if (fabs(mouseZoom-1.0)<0.01) { + mouseZoom = 1; + } + } + + long long bw; + if (currentZoom != 1) { + long long freq = wxGetApp().getFrequency(); + + if (currentZoom < 1) { + centerFreq = getCenterFrequency(); + bw = getBandwidth(); + bw = (long long) ceil((long double) bw * currentZoom); + if (bw < 100000) { + bw = 100000; + } + if (mouseTracker.mouseInView()) { + long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); + setBandwidth(bw); + long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); + centerFreq += mfreqA - mfreqB; + } + + setView(centerFreq, bw); + if (spectrumCanvas) { + spectrumCanvas->setView(centerFreq, bw); + } + } else { + if (isView) { + bw = getBandwidth(); + bw = (long long) ceil((long double) bw * currentZoom); + if (bw >= wxGetApp().getSampleRate()) { + disableView(); + if (spectrumCanvas) { + spectrumCanvas->disableView(); + } + } else { + if (mouseTracker.mouseInView()) { + long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); + setBandwidth(bw); + long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); + centerFreq += mfreqA - mfreqB; + } + + setView(getCenterFrequency(), bw); + if (spectrumCanvas) { + spectrumCanvas->setView(centerFreq, bw); + } + } + } + } + if (centerFreq < freq && (centerFreq - bandwidth / 2) < (freq - wxGetApp().getSampleRate() / 2)) { + centerFreq = (freq - wxGetApp().getSampleRate() / 2) + bandwidth / 2; + } + if (centerFreq > freq && (centerFreq + bandwidth / 2) > (freq + wxGetApp().getSampleRate() / 2)) { + centerFreq = (freq + wxGetApp().getSampleRate() / 2) - bandwidth / 2; + } + } + + std::vector *data = &input->data; + + if (data && data->size()) { + // if (fft_size != data->size() && !isView) { + // Setup(data->size(), waterfall_lines); + // } + + // if (last_bandwidth != bandwidth && !isView) { + // Setup(bandwidth, waterfall_lines); + // } + + if (spectrum_points.size() < fft_size * 2) { + spectrum_points.resize(fft_size * 2); + } + + unsigned int num_written; + + if (isView) { + if (!input->frequency || !input->sampleRate) { + return; + } + + resamplerRatio = (double) (bandwidth) / (double) input->sampleRate; + + int desired_input_size = fft_size / resamplerRatio; + + if (input->data.size() < desired_input_size) { + // std::cout << "fft underflow, desired: " << desired_input_size << " actual:" << input->data.size() << std::endl; + desired_input_size = input->data.size(); + } + + if (centerFreq != input->frequency) { + if ((centerFreq - input->frequency) != shiftFrequency || lastInputBandwidth != input->sampleRate) { + if (abs(input->frequency - centerFreq) < (wxGetApp().getSampleRate() / 2)) { + shiftFrequency = centerFreq - input->frequency; + nco_crcf_reset(freqShifter); + nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) input->sampleRate))); + } + } + + if (shiftBuffer.size() != desired_input_size) { + if (shiftBuffer.capacity() < desired_input_size) { + shiftBuffer.reserve(desired_input_size); + } + shiftBuffer.resize(desired_input_size); + } + + if (shiftFrequency < 0) { + nco_crcf_mix_block_up(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); + } else { + nco_crcf_mix_block_down(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); + } + } else { + shiftBuffer.assign(input->data.begin(), input->data.end()); + } + + if (!resampler || bandwidth != lastBandwidth || lastInputBandwidth != input->sampleRate) { + float As = 60.0f; + + if (resampler) { + msresamp_crcf_destroy(resampler); + } + resampler = msresamp_crcf_create(resamplerRatio, As); + + lastBandwidth = bandwidth; + lastInputBandwidth = input->sampleRate; + } + + + int out_size = ceil((double) (desired_input_size) * resamplerRatio) + 512; + + if (resampleBuffer.size() != out_size) { + if (resampleBuffer.capacity() < out_size) { + resampleBuffer.reserve(out_size); + } + resampleBuffer.resize(out_size); + } + + + msresamp_crcf_execute(resampler, &shiftBuffer[0], desired_input_size, &resampleBuffer[0], &num_written); + + resampleBuffer.resize(fft_size); + + if (num_written < fft_size) { + for (int i = 0; i < num_written; i++) { + fft_in_data[i][0] = resampleBuffer[i].real; + fft_in_data[i][1] = resampleBuffer[i].imag; + } + for (int i = num_written; i < fft_size; i++) { + fft_in_data[i][0] = 0; + fft_in_data[i][1] = 0; + } + } else { + for (int i = 0; i < fft_size; i++) { + fft_in_data[i][0] = resampleBuffer[i].real; + fft_in_data[i][1] = resampleBuffer[i].imag; + } + } + } else { + num_written = data->size(); + if (data->size() < fft_size) { + for (int i = 0, iMax = data->size(); i < iMax; i++) { + fft_in_data[i][0] = (*data)[i].real; + fft_in_data[i][1] = (*data)[i].imag; + } + for (int i = data->size(); i < fft_size; i++) { + fft_in_data[i][0] = 0; + fft_in_data[i][1] = 0; + } + } else { + for (int i = 0; i < fft_size; i++) { + fft_in_data[i][0] = (*data)[i].real; + fft_in_data[i][1] = (*data)[i].imag; + } + } + } + + bool execute = false; + + if (num_written >= fft_size) { + execute = true; + memcpy(in, fft_in_data, fft_size * sizeof(fftwf_complex)); + memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); + + } else { + if (last_data_size + num_written < fft_size) { // priming + unsigned int num_copy = fft_size - last_data_size; + if (num_written > num_copy) { + num_copy = num_written; + } + memcpy(fft_last_data, fft_in_data, num_copy * sizeof(fftwf_complex)); + last_data_size += num_copy; + } else { + unsigned int num_last = (fft_size - num_written); + memcpy(in, fft_last_data + (last_data_size - num_last), num_last * sizeof(fftwf_complex)); + memcpy(in + num_last, fft_in_data, num_written * sizeof(fftwf_complex)); + memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); + execute = true; + } + } + + if (execute) { + fftwf_execute(plan); + + float fft_ceil = 0, fft_floor = 1; + + if (fft_result.size() < fft_size) { + fft_result.resize(fft_size); + fft_result_ma.resize(fft_size); + fft_result_maa.resize(fft_size); + } + + int n; + for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { + float a = out[i][0]; + float b = out[i][1]; + float c = sqrt(a * a + b * b); + + float x = out[fft_size / 2 + i][0]; + float y = out[fft_size / 2 + i][1]; + float z = sqrt(x * x + y * y); + + fft_result[i] = (z); + fft_result[fft_size / 2 + i] = (c); + } + + for (int i = 0, iMax = fft_size; i < iMax; i++) { + if (isView) { + fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; + fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; + } else { + fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; + fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; + } + + if (fft_result_maa[i] > fft_ceil) { + fft_ceil = fft_result_maa[i]; + } + if (fft_result_maa[i] < fft_floor) { + fft_floor = fft_result_maa[i]; + } + } + + fft_ceil += 0.25; + fft_floor -= 1; + + fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05; + fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.05; + + fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.05; + fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05; + + for (int i = 0, iMax = fft_size; i < iMax; i++) { + float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); + spectrum_points[i * 2] = ((float) i / (float) iMax); + spectrum_points[i * 2 + 1] = v; + } + + if (spectrumCanvas) { + spectrumCanvas->spectrum_points.assign(spectrum_points.begin(), spectrum_points.end()); + spectrumCanvas->getSpectrumContext()->setCeilValue(fft_ceil_maa); + spectrumCanvas->getSpectrumContext()->setFloorValue(fft_floor_maa); + } + } + } +*/ } }; \ No newline at end of file From f731602017286ea2ef8c70d195c1f9e6444fe7f6 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 28 Jul 2015 21:56:39 -0400 Subject: [PATCH 20/53] initial ScopeVisualProcessor, ReBuffer template --- CMakeLists.txt | 2 + src/CubicSDRDefs.h | 31 ++++++++++++++ src/demod/DemodulatorThread.cpp | 18 +------- src/demod/DemodulatorThread.h | 3 +- src/process/ScopeVisualProcessor.cpp | 1 + src/process/ScopeVisualProcessor.h | 63 ++++++++++++++++++++++++++++ src/sdr/SDRPostThread.cpp | 25 ++--------- src/sdr/SDRThread.cpp | 26 ++---------- 8 files changed, 108 insertions(+), 61 deletions(-) create mode 100644 src/process/ScopeVisualProcessor.cpp create mode 100644 src/process/ScopeVisualProcessor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 92cfe0a..5c164f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,6 +258,7 @@ SET (cubicsdr_sources src/visual/WaterfallCanvas.cpp src/visual/WaterfallContext.cpp src/process/VisualProcessor.cpp + src/process/ScopeVisualProcessor.cpp src/process/SpectrumVisualProcessor.cpp src/process/WaterfallVisualProcessor.cpp src/ui/GLPanel.cpp @@ -308,6 +309,7 @@ SET (cubicsdr_headers src/visual/WaterfallCanvas.h src/visual/WaterfallContext.h src/process/VisualProcessor.h + src/process/ScopeVisualProcessor.h src/process/SpectrumVisualProcessor.h src/process/WaterfallVisualProcessor.h src/ui/GLPanel.h diff --git a/src/CubicSDRDefs.h b/src/CubicSDRDefs.h index 2b6de43..ae8ca66 100644 --- a/src/CubicSDRDefs.h +++ b/src/CubicSDRDefs.h @@ -35,6 +35,7 @@ const char filePathSeparator = #include #include +#include class ReferenceCounter { public: @@ -54,3 +55,33 @@ public: protected: std::atomic_int refCount; }; + +template +class ReBuffer { + +public: + BufferType *getBuffer() { + BufferType* buf = NULL; + for (outputBuffersI = outputBuffers.begin(); outputBuffersI != outputBuffers.end(); outputBuffersI++) { + if ((*outputBuffersI)->getRefCount() <= 0) { + return (*outputBuffersI); + } + } + + buf = new BufferType(); + outputBuffers.push_back(buf); + + return buf; + } + + void purge() { + while (!outputBuffers.empty()) { + BufferType *ref = outputBuffers.front(); + outputBuffers.pop_front(); + delete ref; + } + } +private: + std::deque outputBuffers; + typename std::deque::iterator outputBuffersI; +}; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 86ce709..0194adb 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -307,17 +307,7 @@ void DemodulatorThread::threadMain() { if (audioOutputQueue != NULL) { if (!squelchEnabled || (signalLevel >= squelchLevel)) { - for (outputBuffersI = outputBuffers.begin(); outputBuffersI != outputBuffers.end(); outputBuffersI++) { - if ((*outputBuffersI)->getRefCount() <= 0) { - ati = (*outputBuffersI); - break; - } - } - - if (ati == NULL) { - ati = new AudioThreadInput; - outputBuffers.push_back(ati); - } + ati = outputBuffers.getBuffer(); ati->sampleRate = audioSampleRate; ati->setRefCount(1); @@ -491,11 +481,7 @@ void DemodulatorThread::threadMain() { nco_crcf_destroy(stereoPilot); resamp2_cccf_destroy(ssbFilt); - while (!outputBuffers.empty()) { - AudioThreadInput *audioDataDel = outputBuffers.front(); - outputBuffers.pop_front(); - delete audioDataDel; - } + outputBuffers.purge(); if (audioVisOutputQueue && !audioVisOutputQueue->empty()) { AudioThreadInput *dummy_vis; diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index be6cf69..bad7050 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -48,8 +48,7 @@ public: #endif protected: - std::deque outputBuffers; - std::deque::iterator outputBuffersI; + ReBuffer outputBuffers; std::vector agcData; std::vector agcAMData; diff --git a/src/process/ScopeVisualProcessor.cpp b/src/process/ScopeVisualProcessor.cpp new file mode 100644 index 0000000..89af21c --- /dev/null +++ b/src/process/ScopeVisualProcessor.cpp @@ -0,0 +1 @@ +#include "ScopeVisualProcessor.h" \ No newline at end of file diff --git a/src/process/ScopeVisualProcessor.h b/src/process/ScopeVisualProcessor.h new file mode 100644 index 0000000..e5dd56c --- /dev/null +++ b/src/process/ScopeVisualProcessor.h @@ -0,0 +1,63 @@ +#pragma once + +#include "VisualProcessor.h" +#include "AudioThread.h" + +class ScopeVisualProcessor : public VisualProcessor { +protected: + std::vector waveform_points; + + virtual void process() { + if (!input->empty()) { + ReferenceCounter *ati_ref; + input->pop(ati_ref); + + AudioThreadInput *ati = (AudioThreadInput *)ati_ref; + if (!ati) { + return; + } + int iMax = ati->data.size(); + if (!iMax) { + ati->decRefCount(); + return; + } + if (waveform_points.size() != iMax * 2) { + waveform_points.resize(iMax * 2); + } + + for (int i = 0; i < iMax; i++) { + waveform_points[i * 2 + 1] = ati->data[i] * 0.5f; + waveform_points[i * 2] = ((double) i / (double) iMax); + } + + // ati->channels + } +/* + if (!wxGetApp().getAudioVisualQueue()->empty()) { + AudioThreadInput *demodAudioData; + wxGetApp().getAudioVisualQueue()->pop(demodAudioData); + + int iMax = demodAudioData?demodAudioData->data.size():0; + + if (demodAudioData && iMax) { + if (waveform_points.size() != iMax * 2) { + waveform_points.resize(iMax * 2); + } + + demodAudioData->busy_update.lock(); + + for (int i = 0; i < iMax; i++) { + waveform_points[i * 2 + 1] = demodAudioData->data[i] * 0.5f; + waveform_points[i * 2] = ((double) i / (double) iMax); + } + + demodAudioData->busy_update.unlock(); + + setStereo(demodAudioData->channels == 2); + } else { + std::cout << "Incoming Demodulator data empty?" << std::endl; + } + } +*/ + } +}; \ No newline at end of file diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index 5a22aab..66d9c1a 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -94,8 +94,7 @@ void SDRPostThread::threadMain() { std::cout << "SDR post-processing thread started.." << std::endl; - std::deque buffers; - std::deque::iterator buffers_i; + ReBuffer buffers; std::vector fpData; std::vector dataOut; @@ -176,19 +175,7 @@ void SDRPostThread::threadMain() { if (demodulators.size()) { - DemodulatorThreadIQData *demodDataOut = NULL; - - for (buffers_i = buffers.begin(); buffers_i != buffers.end(); buffers_i++) { - if ((*buffers_i)->getRefCount() <= 0) { - demodDataOut = (*buffers_i); - break; - } - } - - if (demodDataOut == NULL) { - demodDataOut = new DemodulatorThreadIQData; - buffers.push_back(demodDataOut); - } + DemodulatorThreadIQData *demodDataOut = buffers.getBuffer(); // std::lock_guard < std::mutex > lock(demodDataOut->m_mutex); demodDataOut->frequency = data_in->frequency; @@ -242,12 +229,8 @@ void SDRPostThread::threadMain() { data_in->decRefCount(); } - while (!buffers.empty()) { - DemodulatorThreadIQData *demodDataDel = buffers.front(); - buffers.pop_front(); -// std::lock_guard < std::mutex > lock(demodDataDel->m_mutex); -// delete demodDataDel; - } +// buffers.purge(); + if (iqVisualQueue.load() && !iqVisualQueue.load()->empty()) { DemodulatorThreadIQData *visualDataDummy; iqVisualQueue.load()->pop(visualDataDummy); diff --git a/src/sdr/SDRThread.cpp b/src/sdr/SDRThread.cpp index 6f1a66e..88635f1 100644 --- a/src/sdr/SDRThread.cpp +++ b/src/sdr/SDRThread.cpp @@ -168,8 +168,7 @@ void SDRThread::threadMain() { std::cout << "SDR thread started.." << std::endl; - std::deque buffers; - std::deque::iterator buffers_i; + ReBuffer buffers; while (!terminated) { SDRThreadCommandQueue *cmdQueue = commandQueue.load(); @@ -274,19 +273,7 @@ void SDRThread::threadMain() { rtlsdr_read_sync(dev, buf, buf_size, &n_read); - SDRThreadIQData *dataOut = NULL; - - for (buffers_i = buffers.begin(); buffers_i != buffers.end(); buffers_i++) { - if ((*buffers_i)->getRefCount() <= 0) { - dataOut = (*buffers_i); - break; - } - } - - if (dataOut == NULL) { - dataOut = new SDRThreadIQData; - buffers.push_back(dataOut); - } + SDRThreadIQData *dataOut = buffers.getBuffer(); // std::lock_guard < std::mutex > lock(dataOut->m_mutex); dataOut->setRefCount(1); @@ -311,13 +298,8 @@ void SDRThread::threadMain() { } } - while (!buffers.empty()) { - SDRThreadIQData *iqDataDel = buffers.front(); - buffers.pop_front(); -// std::lock_guard < std::mutex > lock(iqDataDel->m_mutex); -// delete iqDataDel; - } - + // buffers.purge(); + std::cout << "SDR thread done." << std::endl; } From 2d8c2800cb549cb990c764099e7ca25a321ad699 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 28 Jul 2015 22:14:48 -0400 Subject: [PATCH 21/53] more ReBuffer<> updates --- src/demod/DemodulatorPreThread.cpp | 25 ++++--------------------- src/sdr/SDRPostThread.cpp | 2 +- src/sdr/SDRThread.cpp | 2 +- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 03ea87d..a449699 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -98,8 +98,7 @@ void DemodulatorPreThread::threadMain() { std::cout << "Demodulator preprocessor thread started.." << std::endl; - std::deque buffers; - std::deque::iterator buffers_i; + ReBuffer buffers; std::vector in_buf_data; std::vector out_buf_data; @@ -207,19 +206,7 @@ void DemodulatorPreThread::threadMain() { out_buf = temp_buf; } - DemodulatorThreadPostIQData *resamp = NULL; - - for (buffers_i = buffers.begin(); buffers_i != buffers.end(); buffers_i++) { - if ((*buffers_i)->getRefCount() <= 0) { - resamp = (*buffers_i); - break; - } - } - - if (resamp == NULL) { - resamp = new DemodulatorThreadPostIQData; - buffers.push_back(resamp); - } + DemodulatorThreadPostIQData *resamp = buffers.getBuffer(); int out_size = ceil((double) (bufSize) * iqResampleRatio) + 512; @@ -326,12 +313,8 @@ void DemodulatorPreThread::threadMain() { } } - while (!buffers.empty()) { - DemodulatorThreadPostIQData *iqDataDel = buffers.front(); - buffers.pop_front(); - delete iqDataDel; - } - + buffers.purge(); + DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index 66d9c1a..de155d5 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -229,7 +229,7 @@ void SDRPostThread::threadMain() { data_in->decRefCount(); } -// buffers.purge(); + buffers.purge(); if (iqVisualQueue.load() && !iqVisualQueue.load()->empty()) { DemodulatorThreadIQData *visualDataDummy; diff --git a/src/sdr/SDRThread.cpp b/src/sdr/SDRThread.cpp index 88635f1..b5eb73c 100644 --- a/src/sdr/SDRThread.cpp +++ b/src/sdr/SDRThread.cpp @@ -298,7 +298,7 @@ void SDRThread::threadMain() { } } - // buffers.purge(); + buffers.purge(); std::cout << "SDR thread done." << std::endl; } From 3ab8669d062298eaef631c410ba0cd4575ae2721 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 29 Jul 2015 18:34:58 -0400 Subject: [PATCH 22/53] Initial IOThread prototype --- CMakeLists.txt | 2 + src/AppFrame.cpp | 3 +- src/CubicSDRDefs.h | 52 -------------- src/IOThread.cpp | 1 + src/IOThread.h | 129 ++++++++++++++++++++++++++++++++++ src/demod/DemodDefs.h | 1 + src/process/VisualProcessor.h | 1 + 7 files changed, 136 insertions(+), 53 deletions(-) create mode 100644 src/IOThread.cpp create mode 100644 src/IOThread.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c164f7..39df351 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,6 +228,7 @@ SET (cubicsdr_sources src/AppFrame.cpp src/AppConfig.cpp src/FrequencyDialog.cpp + src/IOThread.cpp src/sdr/SDRThread.cpp src/sdr/SDRPostThread.cpp src/demod/DemodulatorPreThread.cpp @@ -277,6 +278,7 @@ SET (cubicsdr_headers src/AppFrame.h src/AppConfig.h src/FrequencyDialog.h + src/IOThread.h src/sdr/SDRThread.h src/sdr/SDRPostThread.h src/demod/DemodulatorPreThread.h diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 4aefbda..e345bba 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -120,10 +120,11 @@ AppFrame::AppFrame() : spectrumCanvas->attachWaterfallCanvas(waterfallCanvas); vbox->Add(waterfallCanvas, 20, wxEXPAND | wxALL, 0); - +/* vbox->AddSpacer(1); testCanvas = new UITestCanvas(this, attribList); vbox->Add(testCanvas, 20, wxEXPAND | wxALL, 0); +// */ this->SetSizer(vbox); diff --git a/src/CubicSDRDefs.h b/src/CubicSDRDefs.h index ae8ca66..b9191d2 100644 --- a/src/CubicSDRDefs.h +++ b/src/CubicSDRDefs.h @@ -33,55 +33,3 @@ const char filePathSeparator = #define DEFAULT_DEMOD_TYPE 1 #define DEFAULT_DEMOD_BW 200000 -#include -#include -#include - -class ReferenceCounter { -public: - mutable std::mutex m_mutex; - - void setRefCount(int rc) { - refCount.store(rc); - } - - void decRefCount() { - refCount.store(refCount.load()-1); - } - - int getRefCount() { - return refCount.load(); - } -protected: - std::atomic_int refCount; -}; - -template -class ReBuffer { - -public: - BufferType *getBuffer() { - BufferType* buf = NULL; - for (outputBuffersI = outputBuffers.begin(); outputBuffersI != outputBuffers.end(); outputBuffersI++) { - if ((*outputBuffersI)->getRefCount() <= 0) { - return (*outputBuffersI); - } - } - - buf = new BufferType(); - outputBuffers.push_back(buf); - - return buf; - } - - void purge() { - while (!outputBuffers.empty()) { - BufferType *ref = outputBuffers.front(); - outputBuffers.pop_front(); - delete ref; - } - } -private: - std::deque outputBuffers; - typename std::deque::iterator outputBuffersI; -}; diff --git a/src/IOThread.cpp b/src/IOThread.cpp new file mode 100644 index 0000000..5bde1fe --- /dev/null +++ b/src/IOThread.cpp @@ -0,0 +1 @@ +#include "IOThread.h" \ No newline at end of file diff --git a/src/IOThread.h b/src/IOThread.h new file mode 100644 index 0000000..8adb726 --- /dev/null +++ b/src/IOThread.h @@ -0,0 +1,129 @@ +#pragma once + +#include +#include +#include +#include +#include + + +struct map_string_less : public std::binary_function +{ + bool operator()(const std::string& a,const std::string& b) const + { + return a.compare(b) < 0; + } +}; + + +class ReferenceCounter { +public: + mutable std::mutex m_mutex; + + void setRefCount(int rc) { + refCount.store(rc); + } + + void decRefCount() { + refCount.store(refCount.load()-1); + } + + int getRefCount() { + return refCount.load(); + } +protected: + std::atomic_int refCount; +}; + + +template +class ReBuffer { + +public: + BufferType *getBuffer() { + BufferType* buf = NULL; + for (outputBuffersI = outputBuffers.begin(); outputBuffersI != outputBuffers.end(); outputBuffersI++) { + if ((*outputBuffersI)->getRefCount() <= 0) { + return (*outputBuffersI); + } + } + + buf = new BufferType(); + outputBuffers.push_back(buf); + + return buf; + } + + void purge() { + while (!outputBuffers.empty()) { + BufferType *ref = outputBuffers.front(); + outputBuffers.pop_front(); + delete ref; + } + } +private: + std::deque outputBuffers; + typename std::deque::iterator outputBuffersI; +}; + + +class IOThread { +public: + virtual void setup() { + + }; + + virtual void init() { + + }; + + virtual void onBindOutput(std::string name, void* threadQueue) { + + }; + + virtual void onBindInput(std::string name, void* threadQueue) { + + }; + +#ifdef __APPLE__ + virtual void *threadMain() { + return 0; + }; + + static void *pthread_helper(void *context) { + return ((IOThread *) context)->threadMain(); + }; + +#else + virtual void threadMain() { + + }; +#endif + + virtual void terminate() { + + }; + + void setInputQueue(std::string qname, void *threadQueue) { + input_queues[qname] = threadQueue; + this->onBindInput(qname, threadQueue); + }; + + void *getInputQueue(std::string qname) { + return input_queues[qname]; + }; + + void setOutputQueue(std::string qname, void *threadQueue) { + output_queues[qname] = threadQueue; + this->onBindOutput(qname, threadQueue); + }; + + void *getOutputQueue(std::string qname) { + return output_queues[qname]; + }; + + +protected: + std::map input_queues; + std::map output_queues; +}; diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index c5381d0..12a8dd4 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -15,6 +15,7 @@ #define DEMOD_TYPE_DSB 5 #define DEMOD_TYPE_RAW 6 +#include "IOThread.h" class DemodulatorThread; class DemodulatorThreadCommand { diff --git a/src/process/VisualProcessor.h b/src/process/VisualProcessor.h index f7ec6f5..c27dbb1 100644 --- a/src/process/VisualProcessor.h +++ b/src/process/VisualProcessor.h @@ -2,6 +2,7 @@ #include "CubicSDRDefs.h" #include "ThreadQueue.h" +#include "IOThread.h" typedef ThreadQueue VisualDataQueue; From 05cd99bbf10ef5f4e97a4f62fcadc81b332aaaf6 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 29 Jul 2015 20:57:02 -0400 Subject: [PATCH 23/53] IOThread all the things! --- src/IOThread.cpp | 67 +++++++++++++++++++++++- src/IOThread.h | 74 +++++++++------------------ src/audio/AudioThread.cpp | 27 +++++----- src/audio/AudioThread.h | 5 +- src/demod/DemodulatorPreThread.cpp | 15 +----- src/demod/DemodulatorPreThread.h | 9 +--- src/demod/DemodulatorThread.cpp | 11 +--- src/demod/DemodulatorThread.h | 9 +--- src/demod/DemodulatorWorkerThread.cpp | 5 +- src/demod/DemodulatorWorkerThread.h | 6 +-- src/sdr/SDRPostThread.cpp | 8 +-- src/sdr/SDRPostThread.h | 5 +- src/sdr/SDRThread.cpp | 10 +--- src/sdr/SDRThread.h | 7 +-- src/util/ThreadQueue.h | 6 ++- 15 files changed, 128 insertions(+), 136 deletions(-) diff --git a/src/IOThread.cpp b/src/IOThread.cpp index 5bde1fe..3a93e95 100644 --- a/src/IOThread.cpp +++ b/src/IOThread.cpp @@ -1 +1,66 @@ -#include "IOThread.h" \ No newline at end of file +#include "IOThread.h" + +IOThread::IOThread() { + terminated.store(false); +} + +IOThread::~IOThread() { + +} + +#ifdef __APPLE__ +void *IOThread::threadMain() { + run(); + return this; +}; + +void *IOThread::pthread_helper(void *context) { + return ((IOThread *) context)->threadMain(); +}; +#else +void IOThread::threadMain() { + run(); +}; +#endif + +void IOThread::setup() { + +}; + +void IOThread::run() { + +}; + +void IOThread::terminate() { + terminated.store(true); +}; + +void IOThread::onBindOutput(std::string name, ThreadQueueBase* threadQueue) { + +}; + +void IOThread::onBindInput(std::string name, ThreadQueueBase* threadQueue) { + +}; + +void IOThread::setInputQueue(std::string qname, ThreadQueueBase *threadQueue) { + input_queues[qname] = threadQueue; + this->onBindInput(qname, threadQueue); +}; + +void *IOThread::getInputQueue(std::string qname) { + return input_queues[qname]; +}; + +void IOThread::setOutputQueue(std::string qname, ThreadQueueBase *threadQueue) { + output_queues[qname] = threadQueue; + this->onBindOutput(qname, threadQueue); +}; + +void *IOThread::getOutputQueue(std::string qname) { + return output_queues[qname]; +}; + +bool IOThread::isTerminated() { + return terminated.load(); +} \ No newline at end of file diff --git a/src/IOThread.h b/src/IOThread.h index 8adb726..dc76267 100644 --- a/src/IOThread.h +++ b/src/IOThread.h @@ -6,6 +6,7 @@ #include #include +#include "ThreadQueue.h" struct map_string_less : public std::binary_function { @@ -69,61 +70,32 @@ private: class IOThread { public: - virtual void setup() { - - }; - - virtual void init() { - - }; - - virtual void onBindOutput(std::string name, void* threadQueue) { - - }; - - virtual void onBindInput(std::string name, void* threadQueue) { - - }; - + IOThread(); + ~IOThread(); + + static void *pthread_helper(void *context); + #ifdef __APPLE__ - virtual void *threadMain() { - return 0; - }; - - static void *pthread_helper(void *context) { - return ((IOThread *) context)->threadMain(); - }; - + virtual void *threadMain(); #else - virtual void threadMain() { - - }; + virtual void threadMain(); #endif - - virtual void terminate() { - - }; - - void setInputQueue(std::string qname, void *threadQueue) { - input_queues[qname] = threadQueue; - this->onBindInput(qname, threadQueue); - }; - - void *getInputQueue(std::string qname) { - return input_queues[qname]; - }; - - void setOutputQueue(std::string qname, void *threadQueue) { - output_queues[qname] = threadQueue; - this->onBindOutput(qname, threadQueue); - }; - - void *getOutputQueue(std::string qname) { - return output_queues[qname]; - }; + + virtual void setup(); + virtual void run(); + virtual void terminate(); + bool isTerminated(); + virtual void onBindOutput(std::string name, ThreadQueueBase* threadQueue); + virtual void onBindInput(std::string name, ThreadQueueBase* threadQueue); + + void setInputQueue(std::string qname, ThreadQueueBase *threadQueue); + void *getInputQueue(std::string qname); + void setOutputQueue(std::string qname, ThreadQueueBase *threadQueue); + void *getOutputQueue(std::string qname); protected: - std::map input_queues; - std::map output_queues; + std::map input_queues; + std::map output_queues; + std::atomic_bool terminated; }; diff --git a/src/audio/AudioThread.cpp b/src/audio/AudioThread.cpp index 384b28d..458d70c 100644 --- a/src/audio/AudioThread.cpp +++ b/src/audio/AudioThread.cpp @@ -11,13 +11,12 @@ std::map AudioThread::deviceController; std::map AudioThread::deviceSampleRate; std::map AudioThread::deviceThread; -AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) : +AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) : IOThread(), currentInput(NULL), inputQueue(inputQueue), gain( 1.0), threadQueueNotify(threadQueueNotify), sampleRate(0), nBufferFrames(1024) { audioQueuePtr.store(0); underflowCount.store(0); - terminated.store(false); active.store(false); outputDevice.store(-1); @@ -56,7 +55,7 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu float *out = (float*) outputBuffer; memset(out, 0, nBufferFrames * 2 * sizeof(float)); - if (src->terminated) { + if (src->isTerminated()) { return 1; } @@ -72,17 +71,17 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu for (int j = 0; j < src->boundThreads.load()->size(); j++) { AudioThread *srcmix = (*(src->boundThreads.load()))[j]; - if (srcmix->terminated || !srcmix->inputQueue || srcmix->inputQueue->empty() || !srcmix->isActive()) { + if (srcmix->isTerminated() || !srcmix->inputQueue || srcmix->inputQueue->empty() || !srcmix->isActive()) { continue; } if (!srcmix->currentInput) { srcmix->audioQueuePtr = 0; - if (srcmix->terminated || srcmix->inputQueue->empty()) { + if (srcmix->isTerminated() || srcmix->inputQueue->empty()) { continue; } srcmix->inputQueue->pop(srcmix->currentInput); - if (srcmix->terminated) { + if (srcmix->isTerminated()) { continue; } continue; @@ -117,11 +116,11 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu srcmix->currentInput->decRefCount(); srcmix->currentInput = NULL; } - if (srcmix->terminated || srcmix->inputQueue->empty()) { + if (srcmix->isTerminated() || srcmix->inputQueue->empty()) { continue; } srcmix->inputQueue->pop(srcmix->currentInput); - if (srcmix->terminated) { + if (srcmix->isTerminated()) { continue; } } @@ -138,11 +137,11 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu srcmix->currentInput->decRefCount(); srcmix->currentInput = NULL; } - if (srcmix->terminated || srcmix->inputQueue->empty()) { + if (srcmix->isTerminated() || srcmix->inputQueue->empty()) { break; } srcmix->inputQueue->pop(srcmix->currentInput); - if (srcmix->terminated) { + if (srcmix->isTerminated()) { break; } float srcPeak = srcmix->currentInput->peak * srcmix->gain; @@ -165,11 +164,11 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu srcmix->currentInput->decRefCount(); srcmix->currentInput = NULL; } - if (srcmix->terminated || srcmix->inputQueue->empty()) { + if (srcmix->isTerminated() || srcmix->inputQueue->empty()) { break; } srcmix->inputQueue->pop(srcmix->currentInput); - if (srcmix->terminated) { + if (srcmix->isTerminated()) { break; } float srcPeak = srcmix->currentInput->peak * srcmix->gain; @@ -359,7 +358,7 @@ void AudioThread::setInitOutputDevice(int deviceId, int sampleRate) { this->sampleRate = sampleRate; } -void AudioThread::threadMain() { +void AudioThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_RR) - 1; @@ -378,8 +377,6 @@ void AudioThread::threadMain() { std::cout << "Audio thread started." << std::endl; - terminated = false; - while (!terminated) { AudioThreadCommand command; cmdQueue.pop(command); diff --git a/src/audio/AudioThread.h b/src/audio/AudioThread.h index 2e2adbf..1409c49 100644 --- a/src/audio/AudioThread.h +++ b/src/audio/AudioThread.h @@ -47,14 +47,13 @@ public: typedef ThreadQueue AudioThreadInputQueue; typedef ThreadQueue AudioThreadCommandQueue; -class AudioThread { +class AudioThread : public IOThread { public: AudioThreadInput *currentInput; AudioThreadInputQueue *inputQueue; std::atomic_uint audioQueuePtr; std::atomic_uint underflowCount; - std::atomic_bool terminated; std::atomic_bool initialized; std::atomic_bool active; std::atomic_int outputDevice; @@ -70,7 +69,7 @@ public: int getOutputDevice(); void setSampleRate(int sampleRate); int getSampleRate(); - void threadMain(); + void run(); void terminate(); bool isActive(); diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index a449699..eb9958c 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -9,11 +9,10 @@ #include "CubicSDR.h" DemodulatorPreThread::DemodulatorPreThread(DemodulatorThreadInputQueue* iqInputQueue, DemodulatorThreadPostInputQueue* iqOutputQueue, - DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify) : + DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify) : IOThread(), iqInputQueue(iqInputQueue), iqOutputQueue(iqOutputQueue), audioResampler(NULL), stereoResampler(NULL), iqResampleRatio( 1), audioResampleRatio(1), firStereoRight(NULL), firStereoLeft(NULL), iirStereoPilot(NULL), iqResampler(NULL), commandQueue(NULL), threadQueueNotify(threadQueueNotify), threadQueueControl( threadQueueControl) { - terminated.store(false); initialized.store(false); freqShifter = nco_crcf_create(LIQUID_VCO); @@ -80,11 +79,7 @@ DemodulatorPreThread::~DemodulatorPreThread() { delete workerResults; } -#ifdef __APPLE__ -void *DemodulatorPreThread::threadMain() { -#else -void DemodulatorPreThread::threadMain() { -#endif +void DemodulatorPreThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO) - 1; @@ -105,8 +100,6 @@ void DemodulatorPreThread::threadMain() { // liquid_float_complex carrySample; // Keep the stream count even to simplify some demod operations // bool carrySampleFlag = false; - terminated = false; - while (!terminated) { DemodulatorThreadIQData *inp; iqInputQueue->pop(inp); @@ -319,10 +312,6 @@ void DemodulatorPreThread::threadMain() { tCmd.context = this; threadQueueNotify->push(tCmd); std::cout << "Demodulator preprocessor thread done." << std::endl; - -#ifdef __APPLE__ - return this; -#endif } void DemodulatorPreThread::terminate() { diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index b5e5ec2..6e3585a 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -7,18 +7,14 @@ #include "DemodDefs.h" #include "DemodulatorWorkerThread.h" -class DemodulatorPreThread { +class DemodulatorPreThread : public IOThread { public: DemodulatorPreThread(DemodulatorThreadInputQueue* iqInputQueue, DemodulatorThreadPostInputQueue* iqOutputQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify); ~DemodulatorPreThread(); -#ifdef __APPLE__ - void *threadMain(); -#else - void threadMain(); -#endif + void run(); void setCommandQueue(DemodulatorThreadCommandQueue *tQueue) { commandQueue = tQueue; @@ -68,7 +64,6 @@ protected: nco_crcf freqShifter; int shiftFrequency; - std::atomic_bool terminated; std::atomic_bool initialized; DemodulatorWorkerThread *workerThread; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 0194adb..a52d64e 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -12,14 +12,13 @@ #endif DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, - DemodulatorThreadCommandQueue* threadQueueNotify) : + DemodulatorThreadCommandQueue* threadQueueNotify) : IOThread(), iqInputQueue(iqInputQueue), audioVisOutputQueue(NULL), audioOutputQueue(NULL), iqAutoGain(NULL), amOutputCeil(1), amOutputCeilMA(1), amOutputCeilMAA( 1), threadQueueNotify(threadQueueNotify), threadQueueControl(threadQueueControl), squelchLevel(0), signalLevel( 0), squelchEnabled(false), audioSampleRate(0) { stereo.store(false); agcEnabled.store(false); - terminated.store(false); demodulatorType.store(DEMOD_TYPE_FM); demodFM = freqdem_create(0.5); @@ -33,11 +32,7 @@ DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQue DemodulatorThread::~DemodulatorThread() { } -#ifdef __APPLE__ -void *DemodulatorThread::threadMain() { -#else -void DemodulatorThread::threadMain() { -#endif +void DemodulatorThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO )-1; @@ -89,8 +84,6 @@ void DemodulatorThread::threadMain() { break; } - terminated = false; - while (!terminated) { DemodulatorThreadPostIQData *inp; iqInputQueue->pop(inp); diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index bad7050..55335b0 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -10,18 +10,14 @@ typedef ThreadQueue DemodulatorThreadOutputQueue; #define DEMOD_VIS_SIZE 1024 -class DemodulatorThread { +class DemodulatorThread : public IOThread { public: DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify); ~DemodulatorThread(); -#ifdef __APPLE__ - void *threadMain(); -#else - void threadMain(); -#endif + void run(); void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue); void setAudioOutputQueue(AudioThreadInputQueue *tQueue); @@ -76,7 +72,6 @@ protected: std::atomic_bool stereo; std::atomic_bool agcEnabled; - std::atomic_bool terminated; std::atomic_int demodulatorType; int audioSampleRate; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index a3d13cf..d7df90b 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -2,15 +2,14 @@ #include "CubicSDRDefs.h" #include -DemodulatorWorkerThread::DemodulatorWorkerThread(DemodulatorThreadWorkerCommandQueue* in, DemodulatorThreadWorkerResultQueue* out) : +DemodulatorWorkerThread::DemodulatorWorkerThread(DemodulatorThreadWorkerCommandQueue* in, DemodulatorThreadWorkerResultQueue* out) : IOThread(), commandQueue(in), resultQueue(out) { - terminated.store(false); } DemodulatorWorkerThread::~DemodulatorWorkerThread() { } -void DemodulatorWorkerThread::threadMain() { +void DemodulatorWorkerThread::run() { std::cout << "Demodulator worker thread started.." << std::endl; diff --git a/src/demod/DemodulatorWorkerThread.h b/src/demod/DemodulatorWorkerThread.h index 86c5baf..00afbcc 100644 --- a/src/demod/DemodulatorWorkerThread.h +++ b/src/demod/DemodulatorWorkerThread.h @@ -70,13 +70,13 @@ public: typedef ThreadQueue DemodulatorThreadWorkerCommandQueue; typedef ThreadQueue DemodulatorThreadWorkerResultQueue; -class DemodulatorWorkerThread { +class DemodulatorWorkerThread : public IOThread { public: DemodulatorWorkerThread(DemodulatorThreadWorkerCommandQueue* in, DemodulatorThreadWorkerResultQueue* out); ~DemodulatorWorkerThread(); - void threadMain(); + void run(); void setCommandQueue(DemodulatorThreadWorkerCommandQueue *tQueue) { commandQueue = tQueue; @@ -92,6 +92,4 @@ protected: DemodulatorThreadWorkerCommandQueue *commandQueue; DemodulatorThreadWorkerResultQueue *resultQueue; - - std::atomic_bool terminated; }; diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index de155d5..6a52046 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -5,10 +5,9 @@ #include #include -SDRPostThread::SDRPostThread() : +SDRPostThread::SDRPostThread() : IOThread(), iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), dcFilter(NULL), num_vis_samples(16384*2) { - terminated.store(false); swapIQ.store(false); // create a lookup table @@ -77,10 +76,7 @@ bool SDRPostThread::getSwapIQ() { return this->swapIQ.load(); } -void SDRPostThread::threadMain() { - int n_read; - double seconds = 0.0; - +void SDRPostThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO) - 1; diff --git a/src/sdr/SDRPostThread.h b/src/sdr/SDRPostThread.h index a1aed7d..d95e2a6 100644 --- a/src/sdr/SDRPostThread.h +++ b/src/sdr/SDRPostThread.h @@ -3,7 +3,7 @@ #include "SDRThread.h" #include -class SDRPostThread { +class SDRPostThread : public IOThread { public: SDRPostThread(); ~SDRPostThread(); @@ -21,7 +21,7 @@ public: void setSwapIQ(bool swapIQ); bool getSwapIQ(); - void threadMain(); + void run(); void terminate(); protected: @@ -31,7 +31,6 @@ protected: std::mutex busy_demod; std::vector demodulators; - std::atomic_bool terminated; iirfilt_crcf dcFilter; int num_vis_samples; std::atomic_bool swapIQ; diff --git a/src/sdr/SDRThread.cpp b/src/sdr/SDRThread.cpp index b5eb73c..99202bb 100644 --- a/src/sdr/SDRThread.cpp +++ b/src/sdr/SDRThread.cpp @@ -3,9 +3,8 @@ #include #include "CubicSDR.h" -SDRThread::SDRThread(SDRThreadCommandQueue* pQueue) : +SDRThread::SDRThread(SDRThreadCommandQueue* pQueue) : IOThread(), commandQueue(pQueue), iqDataOutQueue(NULL) { - terminated.store(false); offset.store(0); deviceId.store(-1); dev = NULL; @@ -114,7 +113,7 @@ int SDRThread::enumerate_rtl(std::vector *devs) { } -void SDRThread::threadMain() { +void SDRThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO) - 1; @@ -124,8 +123,6 @@ void SDRThread::threadMain() { std::cout << "SDR thread initializing.." << std::endl; - int devCount = rtlsdr_get_device_count(); - std::vector devs; if (deviceId == -1) { deviceId = enumerate_rtl(&devs); @@ -303,6 +300,3 @@ void SDRThread::threadMain() { std::cout << "SDR thread done." << std::endl; } -void SDRThread::terminate() { - terminated = true; -} diff --git a/src/sdr/SDRThread.h b/src/sdr/SDRThread.h index 67318a9..1ddaec0 100644 --- a/src/sdr/SDRThread.h +++ b/src/sdr/SDRThread.h @@ -122,7 +122,7 @@ public: typedef ThreadQueue SDRThreadCommandQueue; typedef ThreadQueue SDRThreadIQDataQueue; -class SDRThread { +class SDRThread : public IOThread { public: rtlsdr_dev_t *dev; @@ -131,14 +131,12 @@ public: static int enumerate_rtl(std::vector *devs); - void threadMain(); + void run(); void setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue) { iqDataOutQueue = iqDataQueue; } - void terminate(); - int getDeviceId() const { return deviceId.load(); } @@ -153,6 +151,5 @@ protected: std::atomic commandQueue; std::atomic iqDataOutQueue; - std::atomic_bool terminated; std::atomic_int deviceId; }; diff --git a/src/util/ThreadQueue.h b/src/util/ThreadQueue.h index 66dff2a..6ef108a 100644 --- a/src/util/ThreadQueue.h +++ b/src/util/ThreadQueue.h @@ -15,9 +15,13 @@ #include #include +class ThreadQueueBase { + +}; + /** A thread-safe asynchronous queue */ template> -class ThreadQueue { +class ThreadQueue : public ThreadQueueBase { typedef typename Container::value_type value_type; typedef typename Container::size_type size_type; From 1f6276d0903b41faa553fa125ff331b3cbef9fa3 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 29 Jul 2015 22:01:13 -0400 Subject: [PATCH 24/53] SDRThread convert to IOThread named queue handler --- src/CubicSDR.cpp | 7 ++++--- src/sdr/SDRThread.cpp | 12 ++++++------ src/sdr/SDRThread.h | 11 ++--------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index e6742e5..e11b766 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -54,8 +54,8 @@ bool CubicSDR::OnInit() { audioVisualQueue = new DemodulatorThreadOutputQueue(); audioVisualQueue->set_max_num_items(1); - threadCmdQueueSDR = new SDRThreadCommandQueue; - sdrThread = new SDRThread(threadCmdQueueSDR); + threadCmdQueueSDR = new SDRThreadCommandQueue(); + sdrThread = new SDRThread(); sdrPostThread = new SDRPostThread(); sdrPostThread->setNumVisSamples(16384 * 2); @@ -64,7 +64,8 @@ bool CubicSDR::OnInit() { iqVisualQueue = new DemodulatorThreadInputQueue; iqVisualQueue->set_max_num_items(1); - sdrThread->setIQDataOutQueue(iqPostDataQueue); + sdrThread->setInputQueue("SDRCommandQueue",threadCmdQueueSDR); + sdrThread->setOutputQueue("IQDataOutput",iqPostDataQueue); sdrPostThread->setIQDataInQueue(iqPostDataQueue); sdrPostThread->setIQVisualQueue(iqVisualQueue); diff --git a/src/sdr/SDRThread.cpp b/src/sdr/SDRThread.cpp index 99202bb..e31473c 100644 --- a/src/sdr/SDRThread.cpp +++ b/src/sdr/SDRThread.cpp @@ -3,8 +3,7 @@ #include #include "CubicSDR.h" -SDRThread::SDRThread(SDRThreadCommandQueue* pQueue) : IOThread(), - commandQueue(pQueue), iqDataOutQueue(NULL) { +SDRThread::SDRThread() : IOThread() { offset.store(0); deviceId.store(-1); dev = NULL; @@ -167,9 +166,10 @@ void SDRThread::run() { ReBuffer buffers; - while (!terminated) { - SDRThreadCommandQueue *cmdQueue = commandQueue.load(); + SDRThreadIQDataQueue* iqDataOutQueue = (SDRThreadIQDataQueue*) getOutputQueue("IQDataOutput"); + SDRThreadCommandQueue* cmdQueue = (SDRThreadCommandQueue*) getInputQueue("SDRCommandQueue"); + while (!terminated) { if (!cmdQueue->empty()) { bool freq_changed = false; bool offset_changed = false; @@ -290,8 +290,8 @@ void SDRThread::run() { double time_slice = (double) n_read / (double) sampleRate.load(); seconds += time_slice; - if (iqDataOutQueue.load() != NULL) { - iqDataOutQueue.load()->push(dataOut); + if (iqDataOutQueue != NULL) { + iqDataOutQueue->push(dataOut); } } diff --git a/src/sdr/SDRThread.h b/src/sdr/SDRThread.h index 1ddaec0..4b59d81 100644 --- a/src/sdr/SDRThread.h +++ b/src/sdr/SDRThread.h @@ -126,17 +126,13 @@ class SDRThread : public IOThread { public: rtlsdr_dev_t *dev; - SDRThread(SDRThreadCommandQueue* pQueue); + SDRThread(); ~SDRThread(); static int enumerate_rtl(std::vector *devs); void run(); - - void setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue) { - iqDataOutQueue = iqDataQueue; - } - + int getDeviceId() const { return deviceId.load(); } @@ -148,8 +144,5 @@ public: protected: std::atomic sampleRate; std::atomic_llong offset; - std::atomic commandQueue; - std::atomic iqDataOutQueue; - std::atomic_int deviceId; }; From 0d66c92f30e8382705750c3d114605db2c32c7a2 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 29 Jul 2015 22:19:00 -0400 Subject: [PATCH 25/53] SDRDeviceInfo cleanup --- CMakeLists.txt | 2 + src/sdr/SDRDeviceInfo.cpp | 65 +++++++++++++++++++++++++++++++ src/sdr/SDRDeviceInfo.h | 36 +++++++++++++++++ src/sdr/SDRThread.cpp | 8 ++++ src/sdr/SDRThread.h | 81 ++------------------------------------- 5 files changed, 114 insertions(+), 78 deletions(-) create mode 100644 src/sdr/SDRDeviceInfo.cpp create mode 100644 src/sdr/SDRDeviceInfo.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 39df351..f2f72e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -229,6 +229,7 @@ SET (cubicsdr_sources src/AppConfig.cpp src/FrequencyDialog.cpp src/IOThread.cpp + src/sdr/SDRDeviceInfo.cpp src/sdr/SDRThread.cpp src/sdr/SDRPostThread.cpp src/demod/DemodulatorPreThread.cpp @@ -279,6 +280,7 @@ SET (cubicsdr_headers src/AppConfig.h src/FrequencyDialog.h src/IOThread.h + src/sdr/SDRDeviceInfo.h src/sdr/SDRThread.h src/sdr/SDRPostThread.h src/demod/DemodulatorPreThread.h diff --git a/src/sdr/SDRDeviceInfo.cpp b/src/sdr/SDRDeviceInfo.cpp new file mode 100644 index 0000000..992f331 --- /dev/null +++ b/src/sdr/SDRDeviceInfo.cpp @@ -0,0 +1,65 @@ +#include "SDRDeviceInfo.h" + + +SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false) { + +} + +std::string SDRDeviceInfo::getDeviceId() { + std::string deviceId; + + deviceId.append(getName()); + deviceId.append(" :: "); + deviceId.append(getSerial()); + + return deviceId; +} + +bool SDRDeviceInfo::isAvailable() const { + return available; +} + +void SDRDeviceInfo::setAvailable(bool available) { + this->available = available; +} + +const std::string& SDRDeviceInfo::getName() const { + return name; +} + +void SDRDeviceInfo::setName(const std::string& name) { + this->name = name; +} + +const std::string& SDRDeviceInfo::getSerial() const { + return serial; +} + +void SDRDeviceInfo::setSerial(const std::string& serial) { + this->serial = serial; +} + +const std::string& SDRDeviceInfo::getTuner() const { + return tuner; +} + +void SDRDeviceInfo::setTuner(const std::string& tuner) { + this->tuner = tuner; +} + +const std::string& SDRDeviceInfo::getManufacturer() const { + return manufacturer; +} + +void SDRDeviceInfo::setManufacturer(const std::string& manufacturer) { + this->manufacturer = manufacturer; +} + +const std::string& SDRDeviceInfo::getProduct() const { + return product; +} + +void SDRDeviceInfo::setProduct(const std::string& product) { + this->product = product; +} + diff --git a/src/sdr/SDRDeviceInfo.h b/src/sdr/SDRDeviceInfo.h new file mode 100644 index 0000000..36086ad --- /dev/null +++ b/src/sdr/SDRDeviceInfo.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +class SDRDeviceInfo { +public: + SDRDeviceInfo(); + + std::string getDeviceId(); + + bool isAvailable() const; + void setAvailable(bool available); + + const std::string& getName() const; + void setName(const std::string& name); + + const std::string& getSerial() const; + void setSerial(const std::string& serial); + + const std::string& getTuner() const; + void setTuner(const std::string& tuner); + + const std::string& getManufacturer() const; + void setManufacturer(const std::string& manufacturer); + + const std::string& getProduct() const; + void setProduct(const std::string& product); + +private: + std::string name; + std::string serial; + std::string product; + std::string manufacturer; + std::string tuner; + bool available; +}; diff --git a/src/sdr/SDRThread.cpp b/src/sdr/SDRThread.cpp index e31473c..a9a0d43 100644 --- a/src/sdr/SDRThread.cpp +++ b/src/sdr/SDRThread.cpp @@ -300,3 +300,11 @@ void SDRThread::run() { std::cout << "SDR thread done." << std::endl; } + +int SDRThread::getDeviceId() const { + return deviceId.load(); +} + +void SDRThread::setDeviceId(int deviceId) { + this->deviceId.store(deviceId); +} diff --git a/src/sdr/SDRThread.h b/src/sdr/SDRThread.h index 4b59d81..4b3a8ac 100644 --- a/src/sdr/SDRThread.h +++ b/src/sdr/SDRThread.h @@ -6,77 +6,7 @@ #include "ThreadQueue.h" #include "DemodulatorMgr.h" - -class SDRDeviceInfo { -public: - SDRDeviceInfo() : name(""), serial(""), available(false) { } - - std::string getDeviceId() { - std::string deviceId; - - deviceId.append(getName()); - deviceId.append(" :: "); - deviceId.append(getSerial()); - - return deviceId; - } - - bool isAvailable() const { - return available; - } - - void setAvailable(bool available) { - this->available = available; - } - - const std::string& getName() const { - return name; - } - - void setName(const std::string& name) { - this->name = name; - } - - const std::string& getSerial() const { - return serial; - } - - void setSerial(const std::string& serial) { - this->serial = serial; - } - - const std::string& getTuner() const { - return tuner; - } - - void setTuner(const std::string& tuner) { - this->tuner = tuner; - } - - const std::string& getManufacturer() const { - return manufacturer; - } - - void setManufacturer(const std::string& manufacturer) { - this->manufacturer = manufacturer; - } - - const std::string& getProduct() const { - return product; - } - - void setProduct(const std::string& product) { - this->product = product; - } - -private: - std::string name; - std::string serial; - std::string product; - std::string manufacturer; - std::string tuner; - bool available; -}; +#include "SDRDeviceInfo.h" class SDRThreadCommand { public: @@ -133,13 +63,8 @@ public: void run(); - int getDeviceId() const { - return deviceId.load(); - } - - void setDeviceId(int deviceId) { - this->deviceId.store(deviceId); - } + int getDeviceId() const; + void setDeviceId(int deviceId); protected: std::atomic sampleRate; From d53aabf73a4cf977852003d6c0fd3d26a01a98fe Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 29 Jul 2015 22:52:54 -0400 Subject: [PATCH 26/53] DemodulatorPreThread convert to IOThread named queues --- src/IOThread.cpp | 2 ++ src/IOThread.h | 2 +- src/demod/DemodulatorInstance.cpp | 9 +++++++-- src/demod/DemodulatorPreThread.cpp | 29 ++++++++++++++++------------- src/demod/DemodulatorPreThread.h | 17 +---------------- 5 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/IOThread.cpp b/src/IOThread.cpp index 3a93e95..c9178c0 100644 --- a/src/IOThread.cpp +++ b/src/IOThread.cpp @@ -10,6 +10,7 @@ IOThread::~IOThread() { #ifdef __APPLE__ void *IOThread::threadMain() { + terminated.store(false); run(); return this; }; @@ -19,6 +20,7 @@ void *IOThread::pthread_helper(void *context) { }; #else void IOThread::threadMain() { + terminated.store(false); run(); }; #endif diff --git a/src/IOThread.h b/src/IOThread.h index dc76267..0b06f0a 100644 --- a/src/IOThread.h +++ b/src/IOThread.h @@ -71,7 +71,7 @@ private: class IOThread { public: IOThread(); - ~IOThread(); + virtual ~IOThread(); static void *pthread_helper(void *context); diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 38f1bb4..75b6441 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -25,8 +25,13 @@ DemodulatorInstance::DemodulatorInstance() : threadQueueNotify = new DemodulatorThreadCommandQueue; threadQueueControl = new DemodulatorThreadControlCommandQueue; - demodulatorPreThread = new DemodulatorPreThread(threadQueueDemod, threadQueuePostDemod, threadQueueControl, threadQueueNotify); - demodulatorPreThread->setCommandQueue(threadQueueCommand); + demodulatorPreThread = new DemodulatorPreThread(); + demodulatorPreThread->setInputQueue("IQDataInput",threadQueueDemod); + demodulatorPreThread->setOutputQueue("IQDataOut",threadQueuePostDemod); + demodulatorPreThread->setInputQueue("ControlQueue",threadQueueControl); + demodulatorPreThread->setOutputQueue("NotifyQueue",threadQueueNotify); + demodulatorPreThread->setInputQueue("CommandQueue",threadQueueCommand); + demodulatorThread = new DemodulatorThread(threadQueuePostDemod, threadQueueControl, threadQueueNotify); audioInputQueue = new AudioThreadInputQueue; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index eb9958c..1129e01 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -8,11 +8,7 @@ #include "DemodulatorPreThread.h" #include "CubicSDR.h" -DemodulatorPreThread::DemodulatorPreThread(DemodulatorThreadInputQueue* iqInputQueue, DemodulatorThreadPostInputQueue* iqOutputQueue, - DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify) : IOThread(), - iqInputQueue(iqInputQueue), iqOutputQueue(iqOutputQueue), audioResampler(NULL), stereoResampler(NULL), iqResampleRatio( - 1), audioResampleRatio(1), firStereoRight(NULL), firStereoLeft(NULL), iirStereoPilot(NULL), iqResampler(NULL), commandQueue(NULL), threadQueueNotify(threadQueueNotify), threadQueueControl( - threadQueueControl) { +DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(1), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL) { initialized.store(false); freqShifter = nco_crcf_create(LIQUID_VCO); @@ -21,8 +17,6 @@ DemodulatorPreThread::DemodulatorPreThread(DemodulatorThreadInputQueue* iqInputQ workerQueue = new DemodulatorThreadWorkerCommandQueue; workerResults = new DemodulatorThreadWorkerResultQueue; workerThread = new DemodulatorWorkerThread(workerQueue, workerResults); - - t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread); } void DemodulatorPreThread::initialize() { @@ -93,8 +87,16 @@ void DemodulatorPreThread::run() { std::cout << "Demodulator preprocessor thread started.." << std::endl; + t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread); + ReBuffer buffers; + DemodulatorThreadInputQueue* iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput"); + DemodulatorThreadPostInputQueue* iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOut"); + DemodulatorThreadControlCommandQueue *threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue"); + DemodulatorThreadCommandQueue* threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); + DemodulatorThreadCommandQueue* commandQueue = ( DemodulatorThreadCommandQueue*)getInputQueue("CommandQueue"); + std::vector in_buf_data; std::vector out_buf_data; // liquid_float_complex carrySample; // Keep the stream count even to simplify some demod operations @@ -307,7 +309,13 @@ void DemodulatorPreThread::run() { } buffers.purge(); - + + DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue + iqInputQueue->push(inp); + workerThread->terminate(); + t_Worker->detach(); + delete t_Worker; + DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); @@ -316,9 +324,4 @@ void DemodulatorPreThread::run() { void DemodulatorPreThread::terminate() { terminated = true; - DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue - iqInputQueue->push(inp); - workerThread->terminate(); - t_Worker->detach(); - delete t_Worker; } diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index 6e3585a..5088d55 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -10,20 +10,11 @@ class DemodulatorPreThread : public IOThread { public: - DemodulatorPreThread(DemodulatorThreadInputQueue* iqInputQueue, DemodulatorThreadPostInputQueue* iqOutputQueue, - DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify); + DemodulatorPreThread(); ~DemodulatorPreThread(); void run(); - void setCommandQueue(DemodulatorThreadCommandQueue *tQueue) { - commandQueue = tQueue; - } - - void setDemodulatorControlQueue(DemodulatorThreadControlCommandQueue *tQueue) { - threadQueueControl = tQueue; - } - DemodulatorThreadParameters &getParams() { return params; } @@ -42,10 +33,6 @@ public: #endif protected: - DemodulatorThreadInputQueue* iqInputQueue; - DemodulatorThreadPostInputQueue* iqOutputQueue; - DemodulatorThreadCommandQueue* commandQueue; - msresamp_crcf iqResampler; double iqResampleRatio; std::vector resampledData; @@ -71,6 +58,4 @@ protected: DemodulatorThreadWorkerCommandQueue *workerQueue; DemodulatorThreadWorkerResultQueue *workerResults; - DemodulatorThreadCommandQueue* threadQueueNotify; - DemodulatorThreadControlCommandQueue *threadQueueControl; }; From 0a9dd7692a8734acc0bb77897ae9df1eec5c3426 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 30 Jul 2015 00:28:53 -0400 Subject: [PATCH 27/53] DemodulatorThread convert to IOThread named queues --- src/demod/DemodulatorInstance.cpp | 16 +++++++++------- src/demod/DemodulatorPreThread.cpp | 23 +++++++++++------------ src/demod/DemodulatorPreThread.h | 5 +++++ src/demod/DemodulatorThread.cpp | 20 +++++++------------- src/demod/DemodulatorThread.h | 16 +++++++--------- 5 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 75b6441..a60c232 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -1,7 +1,7 @@ #include "DemodulatorInstance.h" DemodulatorInstance::DemodulatorInstance() : - t_Demod(NULL), t_PreDemod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), currentAudioGain(1.0) { + threadQueueDemod(NULL), demodulatorThread(NULL), t_PreDemod(NULL), t_Demod(NULL), t_Audio(NULL), currentAudioGain(1.0) { terminated.store(true); audioTerminated.store(true); @@ -24,7 +24,7 @@ DemodulatorInstance::DemodulatorInstance() : threadQueueCommand = new DemodulatorThreadCommandQueue; threadQueueNotify = new DemodulatorThreadCommandQueue; threadQueueControl = new DemodulatorThreadControlCommandQueue; - + demodulatorPreThread = new DemodulatorPreThread(); demodulatorPreThread->setInputQueue("IQDataInput",threadQueueDemod); demodulatorPreThread->setOutputQueue("IQDataOut",threadQueuePostDemod); @@ -32,13 +32,15 @@ DemodulatorInstance::DemodulatorInstance() : demodulatorPreThread->setOutputQueue("NotifyQueue",threadQueueNotify); demodulatorPreThread->setInputQueue("CommandQueue",threadQueueCommand); - demodulatorThread = new DemodulatorThread(threadQueuePostDemod, threadQueueControl, threadQueueNotify); - audioInputQueue = new AudioThreadInputQueue; + + demodulatorThread = new DemodulatorThread(); + demodulatorThread->setInputQueue("IQDataInput",threadQueuePostDemod); + demodulatorThread->setInputQueue("ControlQueue",threadQueueControl); + demodulatorThread->setOutputQueue("NotifyQueue",threadQueueNotify); + demodulatorThread->setOutputQueue("AudioDataOut", audioInputQueue); + audioThread = new AudioThread(audioInputQueue, threadQueueNotify); - - demodulatorThread->setAudioOutputQueue(audioInputQueue); - currentDemodType = demodulatorThread->getDemodulatorType(); } diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 1129e01..93c1d3f 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -8,7 +8,8 @@ #include "DemodulatorPreThread.h" #include "CubicSDR.h" -DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(1), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL) { +DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(1), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL) + { initialized.store(false); freqShifter = nco_crcf_create(LIQUID_VCO); @@ -91,11 +92,10 @@ void DemodulatorPreThread::run() { ReBuffer buffers; - DemodulatorThreadInputQueue* iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput"); - DemodulatorThreadPostInputQueue* iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOut"); - DemodulatorThreadControlCommandQueue *threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue"); - DemodulatorThreadCommandQueue* threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); - DemodulatorThreadCommandQueue* commandQueue = ( DemodulatorThreadCommandQueue*)getInputQueue("CommandQueue"); + iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput"); + iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOut"); + threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); + commandQueue = ( DemodulatorThreadCommandQueue*)getInputQueue("CommandQueue"); std::vector in_buf_data; std::vector out_buf_data; @@ -310,12 +310,6 @@ void DemodulatorPreThread::run() { buffers.purge(); - DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue - iqInputQueue->push(inp); - workerThread->terminate(); - t_Worker->detach(); - delete t_Worker; - DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); @@ -324,4 +318,9 @@ void DemodulatorPreThread::run() { void DemodulatorPreThread::terminate() { terminated = true; + DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue + iqInputQueue->push(inp); + workerThread->terminate(); + t_Worker->detach(); + delete t_Worker; } diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index 5088d55..f3edc41 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -58,4 +58,9 @@ protected: DemodulatorThreadWorkerCommandQueue *workerQueue; DemodulatorThreadWorkerResultQueue *workerResults; + + DemodulatorThreadInputQueue* iqInputQueue; + DemodulatorThreadPostInputQueue* iqOutputQueue; + DemodulatorThreadCommandQueue* threadQueueNotify; + DemodulatorThreadCommandQueue* commandQueue; }; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index a52d64e..52e7424 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -11,11 +11,7 @@ #include #endif -DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, - DemodulatorThreadCommandQueue* threadQueueNotify) : IOThread(), - iqInputQueue(iqInputQueue), audioVisOutputQueue(NULL), audioOutputQueue(NULL), iqAutoGain(NULL), amOutputCeil(1), amOutputCeilMA(1), amOutputCeilMAA( - 1), threadQueueNotify(threadQueueNotify), threadQueueControl(threadQueueControl), squelchLevel(0), signalLevel( - 0), squelchEnabled(false), audioSampleRate(0) { +DemodulatorThread::DemodulatorThread() : IOThread(), iqAutoGain(NULL), amOutputCeil(1), amOutputCeilMA(1), amOutputCeilMAA(1), audioSampleRate(0), squelchLevel(0), signalLevel(0), squelchEnabled(false), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) { stereo.store(false); agcEnabled.store(false); @@ -67,6 +63,11 @@ void DemodulatorThread::run() { std::cout << "Demodulator thread started.." << std::endl; + iqInputQueue = (DemodulatorThreadPostInputQueue*)getInputQueue("IQDataInput"); + audioOutputQueue = (AudioThreadInputQueue*)getOutputQueue("AudioDataOut"); + threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue"); + threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); + switch (demodulatorType.load()) { case DEMOD_TYPE_FM: break; @@ -485,21 +486,14 @@ void DemodulatorThread::run() { DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); + std::cout << "Demodulator thread done." << std::endl; - -#ifdef __APPLE__ - return this; -#endif } void DemodulatorThread::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) { audioVisOutputQueue = tQueue; } -void DemodulatorThread::setAudioOutputQueue(AudioThreadInputQueue *tQueue) { - audioOutputQueue = tQueue; -} - void DemodulatorThread::terminate() { terminated = true; DemodulatorThreadPostIQData *inp = new DemodulatorThreadPostIQData; // push dummy to nudge queue diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 55335b0..d6b14c0 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -13,14 +13,12 @@ typedef ThreadQueue DemodulatorThreadOutputQueue; class DemodulatorThread : public IOThread { public: - DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, - DemodulatorThreadCommandQueue* threadQueueNotify); + DemodulatorThread(); ~DemodulatorThread(); void run(); void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue); - void setAudioOutputQueue(AudioThreadInputQueue *tQueue); void terminate(); @@ -53,10 +51,6 @@ protected: std::vector resampledOutputData; std::vector resampledStereoData; - DemodulatorThreadPostInputQueue* iqInputQueue; - DemodulatorThreadOutputQueue* audioVisOutputQueue; - AudioThreadInputQueue *audioOutputQueue; - freqdem demodFM; ampmodem demodAM; ampmodem demodAM_DSB_CSP; @@ -75,9 +69,13 @@ protected: std::atomic_int demodulatorType; int audioSampleRate; - DemodulatorThreadCommandQueue* threadQueueNotify; - DemodulatorThreadControlCommandQueue *threadQueueControl; std::atomic squelchLevel; std::atomic signalLevel; bool squelchEnabled; + + DemodulatorThreadPostInputQueue* iqInputQueue; + AudioThreadInputQueue *audioOutputQueue; + DemodulatorThreadOutputQueue* audioVisOutputQueue; + DemodulatorThreadControlCommandQueue *threadQueueControl; + DemodulatorThreadCommandQueue* threadQueueNotify; }; From 5bbcf7aa116de3ed13e1cbeaabec4aa649209650 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 30 Jul 2015 00:52:00 -0400 Subject: [PATCH 28/53] DemodulatorThread visual out queue /w IOThread::onBindOutput --- src/demod/DemodulatorInstance.cpp | 5 ++--- src/demod/DemodulatorThread.cpp | 10 ++++++---- src/demod/DemodulatorThread.h | 5 ++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index a60c232..a8dc922 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -23,16 +23,15 @@ DemodulatorInstance::DemodulatorInstance() : threadQueuePostDemod = new DemodulatorThreadPostInputQueue; threadQueueCommand = new DemodulatorThreadCommandQueue; threadQueueNotify = new DemodulatorThreadCommandQueue; - threadQueueControl = new DemodulatorThreadControlCommandQueue; demodulatorPreThread = new DemodulatorPreThread(); demodulatorPreThread->setInputQueue("IQDataInput",threadQueueDemod); demodulatorPreThread->setOutputQueue("IQDataOut",threadQueuePostDemod); - demodulatorPreThread->setInputQueue("ControlQueue",threadQueueControl); demodulatorPreThread->setOutputQueue("NotifyQueue",threadQueueNotify); demodulatorPreThread->setInputQueue("CommandQueue",threadQueueCommand); audioInputQueue = new AudioThreadInputQueue; + threadQueueControl = new DemodulatorThreadControlCommandQueue; demodulatorThread = new DemodulatorThread(); demodulatorThread->setInputQueue("IQDataInput",threadQueuePostDemod); @@ -57,7 +56,7 @@ DemodulatorInstance::~DemodulatorInstance() { } void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) { - demodulatorThread->setVisualOutputQueue(tQueue); + demodulatorThread->setOutputQueue("AudioVisualOutput", tQueue); } void DemodulatorInstance::run() { diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 52e7424..d3acb35 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -28,6 +28,12 @@ DemodulatorThread::DemodulatorThread() : IOThread(), iqAutoGain(NULL), amOutputC DemodulatorThread::~DemodulatorThread() { } +void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) { + if (name == "AudioVisualOutput") { + audioVisOutputQueue = (DemodulatorThreadOutputQueue *)threadQueue; + } +} + void DemodulatorThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread @@ -490,10 +496,6 @@ void DemodulatorThread::run() { std::cout << "Demodulator thread done." << std::endl; } -void DemodulatorThread::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) { - audioVisOutputQueue = tQueue; -} - void DemodulatorThread::terminate() { terminated = true; DemodulatorThreadPostIQData *inp = new DemodulatorThreadPostIQData; // push dummy to nudge queue diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index d6b14c0..eb179c5 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -16,10 +16,9 @@ public: DemodulatorThread(); ~DemodulatorThread(); + void onBindOutput(std::string name, ThreadQueueBase *threadQueue); + void run(); - - void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue); - void terminate(); void setStereo(bool state); From 10e35002f1fcf631bf612813286886351728a676 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 30 Jul 2015 19:30:46 -0400 Subject: [PATCH 29/53] AudioThread & demod worker IOThread queues, cleanup --- src/CubicSDR.cpp | 22 +++++++++++--------- src/audio/AudioThread.cpp | 11 ++++++---- src/audio/AudioThread.h | 3 +-- src/demod/DemodulatorInstance.cpp | 9 +++++--- src/demod/DemodulatorMgr.cpp | 2 +- src/demod/DemodulatorPreThread.cpp | 7 +++++-- src/demod/DemodulatorThread.cpp | 2 +- src/demod/DemodulatorWorkerThread.cpp | 9 +++++--- src/demod/DemodulatorWorkerThread.h | 2 +- src/sdr/SDRPostThread.cpp | 30 +++++++++++---------------- src/sdr/SDRPostThread.h | 10 +++------ src/visual/ModeSelectorCanvas.cpp | 2 +- 12 files changed, 56 insertions(+), 53 deletions(-) diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index e11b766..9f93747 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -51,23 +51,25 @@ bool CubicSDR::OnInit() { ppm = 0; directSamplingMode = 0; + // Visual Data + iqVisualQueue = new DemodulatorThreadInputQueue(); + iqVisualQueue->set_max_num_items(1); + audioVisualQueue = new DemodulatorThreadOutputQueue(); audioVisualQueue->set_max_num_items(1); - + + // I/Q Data + iqPostDataQueue = new SDRThreadIQDataQueue; threadCmdQueueSDR = new SDRThreadCommandQueue(); + sdrThread = new SDRThread(); + sdrThread->setInputQueue("SDRCommandQueue",threadCmdQueueSDR); + sdrThread->setOutputQueue("IQDataOutput",iqPostDataQueue); sdrPostThread = new SDRPostThread(); sdrPostThread->setNumVisSamples(16384 * 2); - - iqPostDataQueue = new SDRThreadIQDataQueue; - iqVisualQueue = new DemodulatorThreadInputQueue; - iqVisualQueue->set_max_num_items(1); - - sdrThread->setInputQueue("SDRCommandQueue",threadCmdQueueSDR); - sdrThread->setOutputQueue("IQDataOutput",iqPostDataQueue); - sdrPostThread->setIQDataInQueue(iqPostDataQueue); - sdrPostThread->setIQVisualQueue(iqVisualQueue); + sdrPostThread->setInputQueue("IQDataInput", iqPostDataQueue); + sdrPostThread->setOutputQueue("IQVisualDataOut", iqVisualQueue); std::vector::iterator devs_i; diff --git a/src/audio/AudioThread.cpp b/src/audio/AudioThread.cpp index 458d70c..0c48fbb 100644 --- a/src/audio/AudioThread.cpp +++ b/src/audio/AudioThread.cpp @@ -11,9 +11,9 @@ std::map AudioThread::deviceController; std::map AudioThread::deviceSampleRate; std::map AudioThread::deviceThread; -AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) : IOThread(), - currentInput(NULL), inputQueue(inputQueue), gain( - 1.0), threadQueueNotify(threadQueueNotify), sampleRate(0), nBufferFrames(1024) { +AudioThread::AudioThread() : IOThread(), + currentInput(NULL), inputQueue(NULL), gain( + 1.0), threadQueueNotify(NULL), sampleRate(0), nBufferFrames(1024) { audioQueuePtr.store(0); underflowCount.store(0); @@ -316,7 +316,7 @@ void AudioThread::setupDevice(int deviceId) { } if (deviceController.find(parameters.deviceId) == deviceController.end()) { - deviceController[parameters.deviceId] = new AudioThread(NULL, NULL); + deviceController[parameters.deviceId] = new AudioThread(); deviceController[parameters.deviceId]->setInitOutputDevice(parameters.deviceId, sampleRate); deviceController[parameters.deviceId]->bindThread(this); @@ -377,6 +377,9 @@ void AudioThread::run() { std::cout << "Audio thread started." << std::endl; + inputQueue = (AudioThreadInputQueue *)getInputQueue("AudioDataInput"); + threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); + while (!terminated) { AudioThreadCommand command; cmdQueue.pop(command); diff --git a/src/audio/AudioThread.h b/src/audio/AudioThread.h index 1409c49..d5dcb61 100644 --- a/src/audio/AudioThread.h +++ b/src/audio/AudioThread.h @@ -49,7 +49,6 @@ typedef ThreadQueue AudioThreadCommandQueue; class AudioThread : public IOThread { public: - AudioThreadInput *currentInput; AudioThreadInputQueue *inputQueue; std::atomic_uint audioQueuePtr; @@ -59,7 +58,7 @@ public: std::atomic_int outputDevice; std::atomic gain; - AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify); + AudioThread(); ~AudioThread(); static void enumerateDevices(std::vector &devs); diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index a8dc922..92e6af2 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -26,7 +26,7 @@ DemodulatorInstance::DemodulatorInstance() : demodulatorPreThread = new DemodulatorPreThread(); demodulatorPreThread->setInputQueue("IQDataInput",threadQueueDemod); - demodulatorPreThread->setOutputQueue("IQDataOut",threadQueuePostDemod); + demodulatorPreThread->setOutputQueue("IQDataOutput",threadQueuePostDemod); demodulatorPreThread->setOutputQueue("NotifyQueue",threadQueueNotify); demodulatorPreThread->setInputQueue("CommandQueue",threadQueueCommand); @@ -37,9 +37,12 @@ DemodulatorInstance::DemodulatorInstance() : demodulatorThread->setInputQueue("IQDataInput",threadQueuePostDemod); demodulatorThread->setInputQueue("ControlQueue",threadQueueControl); demodulatorThread->setOutputQueue("NotifyQueue",threadQueueNotify); - demodulatorThread->setOutputQueue("AudioDataOut", audioInputQueue); + demodulatorThread->setOutputQueue("AudioDataOutput", audioInputQueue); + + audioThread = new AudioThread(); + audioThread->setInputQueue("AudioDataInput", audioInputQueue); + audioThread->setOutputQueue("NotifyQueue", threadQueueNotify); - audioThread = new AudioThread(audioInputQueue, threadQueueNotify); currentDemodType = demodulatorThread->getDemodulatorType(); } diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index 7604d92..4a9a11d 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -7,7 +7,7 @@ DemodulatorMgr::DemodulatorMgr() : activeDemodulator(NULL), lastActiveDemodulator(NULL), activeVisualDemodulator(NULL), lastBandwidth(DEFAULT_DEMOD_BW), lastDemodType( - DEFAULT_DEMOD_TYPE), lastGain(1.0), lastSquelch(0), lastSquelchEnabled(false), lastStereo(false) { + DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(0), lastGain(1.0), lastStereo(false) { } diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 93c1d3f..c93df6f 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -17,7 +17,10 @@ DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iq workerQueue = new DemodulatorThreadWorkerCommandQueue; workerResults = new DemodulatorThreadWorkerResultQueue; - workerThread = new DemodulatorWorkerThread(workerQueue, workerResults); + + workerThread = new DemodulatorWorkerThread(); + workerThread->setInputQueue("WorkerCommandQueue",workerQueue); + workerThread->setOutputQueue("WorkerResultQueue",workerResults); } void DemodulatorPreThread::initialize() { @@ -93,7 +96,7 @@ void DemodulatorPreThread::run() { ReBuffer buffers; iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput"); - iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOut"); + iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOutput"); threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); commandQueue = ( DemodulatorThreadCommandQueue*)getInputQueue("CommandQueue"); diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index d3acb35..70306f2 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -70,7 +70,7 @@ void DemodulatorThread::run() { std::cout << "Demodulator thread started.." << std::endl; iqInputQueue = (DemodulatorThreadPostInputQueue*)getInputQueue("IQDataInput"); - audioOutputQueue = (AudioThreadInputQueue*)getOutputQueue("AudioDataOut"); + audioOutputQueue = (AudioThreadInputQueue*)getOutputQueue("AudioDataOutput"); threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue"); threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index d7df90b..c9c5761 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -2,8 +2,8 @@ #include "CubicSDRDefs.h" #include -DemodulatorWorkerThread::DemodulatorWorkerThread(DemodulatorThreadWorkerCommandQueue* in, DemodulatorThreadWorkerResultQueue* out) : IOThread(), - commandQueue(in), resultQueue(out) { +DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(), + commandQueue(NULL), resultQueue(NULL) { } DemodulatorWorkerThread::~DemodulatorWorkerThread() { @@ -12,7 +12,10 @@ DemodulatorWorkerThread::~DemodulatorWorkerThread() { void DemodulatorWorkerThread::run() { std::cout << "Demodulator worker thread started.." << std::endl; - + + commandQueue = (DemodulatorThreadWorkerCommandQueue *)getInputQueue("WorkerCommandQueue"); + resultQueue = (DemodulatorThreadWorkerResultQueue *)getOutputQueue("WorkerResultQueue"); + while (!terminated) { bool filterChanged = false; DemodulatorWorkerThreadCommand filterCommand; diff --git a/src/demod/DemodulatorWorkerThread.h b/src/demod/DemodulatorWorkerThread.h index 00afbcc..490ed5d 100644 --- a/src/demod/DemodulatorWorkerThread.h +++ b/src/demod/DemodulatorWorkerThread.h @@ -73,7 +73,7 @@ typedef ThreadQueue DemodulatorThreadWorkerResult class DemodulatorWorkerThread : public IOThread { public: - DemodulatorWorkerThread(DemodulatorThreadWorkerCommandQueue* in, DemodulatorThreadWorkerResultQueue* out); + DemodulatorWorkerThread(); ~DemodulatorWorkerThread(); void run(); diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index 6a52046..f395017 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -50,16 +50,6 @@ void SDRPostThread::removeDemodulator(DemodulatorInstance *demod) { busy_demod.unlock(); } -void SDRPostThread::setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue) { - iqDataInQueue = iqDataQueue; -} -void SDRPostThread::setIQDataOutQueue(DemodulatorThreadInputQueue* iqDataQueue) { - iqDataOutQueue = iqDataQueue; -} -void SDRPostThread::setIQVisualQueue(DemodulatorThreadInputQueue *iqVisQueue) { - iqVisualQueue = iqVisQueue; -} - void SDRPostThread::setNumVisSamples(int num_vis_samples_in) { num_vis_samples = num_vis_samples_in; } @@ -90,6 +80,10 @@ void SDRPostThread::run() { std::cout << "SDR post-processing thread started.." << std::endl; + iqDataInQueue = (SDRThreadIQDataQueue*)getInputQueue("IQDataInput"); + iqDataOutQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQDataOutput"); + iqVisualQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQVisualDataOut"); + ReBuffer buffers; std::vector fpData; std::vector dataOut; @@ -97,7 +91,7 @@ void SDRPostThread::run() { while (!terminated) { SDRThreadIQData *data_in; - iqDataInQueue.load()->pop(data_in); + iqDataInQueue->pop(data_in); // std::lock_guard < std::mutex > lock(data_in->m_mutex); if (data_in && data_in->data.size()) { @@ -123,16 +117,16 @@ void SDRPostThread::run() { iirfilt_crcf_execute_block(dcFilter, &fpData[0], dataSize, &dataOut[0]); - if (iqDataOutQueue.load() != NULL) { + if (iqDataOutQueue != NULL) { DemodulatorThreadIQData *pipeDataOut = new DemodulatorThreadIQData; pipeDataOut->frequency = data_in->frequency; pipeDataOut->sampleRate = data_in->sampleRate; pipeDataOut->data.assign(dataOut.begin(), dataOut.end()); - iqDataOutQueue.load()->push(pipeDataOut); + iqDataOutQueue->push(pipeDataOut); } - if (iqVisualQueue.load() != NULL && iqVisualQueue.load()->empty()) { + if (iqVisualQueue != NULL && iqVisualQueue->empty()) { visualDataOut->busy_rw.lock(); @@ -147,7 +141,7 @@ void SDRPostThread::run() { visualDataOut->sampleRate = data_in->sampleRate; visualDataOut->data.assign(dataOut.begin(), dataOut.begin() + num_vis_samples); - iqVisualQueue.load()->push(visualDataOut); + iqVisualQueue->push(visualDataOut); visualDataOut->busy_rw.unlock(); } @@ -227,9 +221,9 @@ void SDRPostThread::run() { buffers.purge(); - if (iqVisualQueue.load() && !iqVisualQueue.load()->empty()) { + if (iqVisualQueue && !iqVisualQueue->empty()) { DemodulatorThreadIQData *visualDataDummy; - iqVisualQueue.load()->pop(visualDataDummy); + iqVisualQueue->pop(visualDataDummy); } delete visualDataOut; @@ -240,5 +234,5 @@ void SDRPostThread::run() { void SDRPostThread::terminate() { terminated = true; SDRThreadIQData *dummy = new SDRThreadIQData; - iqDataInQueue.load()->push(dummy); + iqDataInQueue->push(dummy); } diff --git a/src/sdr/SDRPostThread.h b/src/sdr/SDRPostThread.h index d95e2a6..f97e24f 100644 --- a/src/sdr/SDRPostThread.h +++ b/src/sdr/SDRPostThread.h @@ -11,10 +11,6 @@ public: void bindDemodulator(DemodulatorInstance *demod); void removeDemodulator(DemodulatorInstance *demod); - void setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue); - void setIQDataOutQueue(DemodulatorThreadInputQueue* iqDataQueue); - void setIQVisualQueue(DemodulatorThreadInputQueue* iqVisQueue); - void setNumVisSamples(int num_vis_samples_in); int getNumVisSamples(); @@ -25,9 +21,9 @@ public: void terminate(); protected: - std::atomic iqDataInQueue; - std::atomic iqDataOutQueue; - std::atomic iqVisualQueue; + SDRThreadIQDataQueue *iqDataInQueue; + DemodulatorThreadInputQueue *iqDataOutQueue; + DemodulatorThreadInputQueue *iqVisualQueue; std::mutex busy_demod; std::vector demodulators; diff --git a/src/visual/ModeSelectorCanvas.cpp b/src/visual/ModeSelectorCanvas.cpp index 04bd0c1..1b859e3 100644 --- a/src/visual/ModeSelectorCanvas.cpp +++ b/src/visual/ModeSelectorCanvas.cpp @@ -25,7 +25,7 @@ EVT_ENTER_WINDOW(ModeSelectorCanvas::OnMouseEnterWindow) wxEND_EVENT_TABLE() ModeSelectorCanvas::ModeSelectorCanvas(wxWindow *parent, int *attribList) : -InteractiveCanvas(parent, attribList), currentSelection(-1), numChoices(0) { +InteractiveCanvas(parent, attribList), numChoices(0), currentSelection(-1) { glContext = new ModeSelectorContext(this, &wxGetApp().GetContext(this)); } From c1774ee96a4d2daf5195df4fa1c0bc7a5f55e68e Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 30 Jul 2015 20:36:06 -0400 Subject: [PATCH 30/53] Cleanup / refactor "pipe" names for clarity --- src/CubicSDR.cpp | 46 +++++++++++++------------- src/CubicSDR.h | 8 ++--- src/demod/DemodulatorInstance.cpp | 54 +++++++++++++++++-------------- src/demod/DemodulatorInstance.h | 20 +++++++----- src/sdr/SDRPostThread.cpp | 2 +- 5 files changed, 69 insertions(+), 61 deletions(-) diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 9f93747..49658b2 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -22,7 +22,7 @@ IMPLEMENT_APP(CubicSDR) CubicSDR::CubicSDR() : appframe(NULL), m_glContext(NULL), frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), directSamplingMode(0), - sdrThread(NULL), sdrPostThread(NULL), threadCmdQueueSDR(NULL), iqPostDataQueue(NULL), iqVisualQueue(NULL), audioVisualQueue(NULL), t_SDR(NULL), t_PostSDR(NULL) { + sdrThread(NULL), sdrPostThread(NULL), pipeSDRCommand(NULL), pipeSDRIQData(NULL), pipeIQVisualData(NULL), pipeAudioVisualData(NULL), t_SDR(NULL), t_PostSDR(NULL) { } @@ -52,24 +52,24 @@ bool CubicSDR::OnInit() { directSamplingMode = 0; // Visual Data - iqVisualQueue = new DemodulatorThreadInputQueue(); - iqVisualQueue->set_max_num_items(1); + pipeIQVisualData = new DemodulatorThreadInputQueue(); + pipeIQVisualData->set_max_num_items(1); - audioVisualQueue = new DemodulatorThreadOutputQueue(); - audioVisualQueue->set_max_num_items(1); + pipeAudioVisualData = new DemodulatorThreadOutputQueue(); + pipeAudioVisualData->set_max_num_items(1); // I/Q Data - iqPostDataQueue = new SDRThreadIQDataQueue; - threadCmdQueueSDR = new SDRThreadCommandQueue(); + pipeSDRIQData = new SDRThreadIQDataQueue; + pipeSDRCommand = new SDRThreadCommandQueue(); sdrThread = new SDRThread(); - sdrThread->setInputQueue("SDRCommandQueue",threadCmdQueueSDR); - sdrThread->setOutputQueue("IQDataOutput",iqPostDataQueue); + sdrThread->setInputQueue("SDRCommandQueue",pipeSDRCommand); + sdrThread->setOutputQueue("IQDataOutput",pipeSDRIQData); sdrPostThread = new SDRPostThread(); sdrPostThread->setNumVisSamples(16384 * 2); - sdrPostThread->setInputQueue("IQDataInput", iqPostDataQueue); - sdrPostThread->setOutputQueue("IQVisualDataOut", iqVisualQueue); + sdrPostThread->setInputQueue("IQDataInput", pipeSDRIQData); + sdrPostThread->setOutputQueue("IQVisualDataOut", pipeIQVisualData); std::vector::iterator devs_i; @@ -153,11 +153,11 @@ int CubicSDR::OnExit() { delete sdrPostThread; delete t_PostSDR; - delete threadCmdQueueSDR; + delete pipeSDRCommand; - delete iqVisualQueue; - delete audioVisualQueue; - delete iqPostDataQueue; + delete pipeIQVisualData; + delete pipeAudioVisualData; + delete pipeSDRIQData; delete m_glContext; @@ -203,7 +203,7 @@ void CubicSDR::setFrequency(long long freq) { frequency = freq; SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_TUNE); command.llong_value = freq; - threadCmdQueueSDR->push(command); + pipeSDRCommand->push(command); } long long CubicSDR::getOffset() { @@ -214,7 +214,7 @@ void CubicSDR::setOffset(long long ofs) { offset = ofs; SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_SET_OFFSET); command.llong_value = ofs; - threadCmdQueueSDR->push(command); + pipeSDRCommand->push(command); SDRDeviceInfo *dev = (*getDevices())[getDevice()]; config.getDevice(dev->getDeviceId())->setOffset(ofs); @@ -224,7 +224,7 @@ void CubicSDR::setDirectSampling(int mode) { directSamplingMode = mode; SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_SET_DIRECT_SAMPLING); command.llong_value = mode; - threadCmdQueueSDR->push(command); + pipeSDRCommand->push(command); SDRDeviceInfo *dev = (*getDevices())[getDevice()]; config.getDevice(dev->getDeviceId())->setDirectSampling(mode); @@ -249,11 +249,11 @@ long long CubicSDR::getFrequency() { } DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() { - return audioVisualQueue; + return pipeAudioVisualData; } DemodulatorThreadInputQueue* CubicSDR::getIQVisualQueue() { - return iqVisualQueue; + return pipeIQVisualData; } DemodulatorMgr &CubicSDR::getDemodMgr() { @@ -271,7 +271,7 @@ void CubicSDR::setSampleRate(long long rate_in) { sampleRate = rate_in; SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_SET_SAMPLERATE); command.llong_value = rate_in; - threadCmdQueueSDR->push(command); + pipeSDRCommand->push(command); setFrequency(frequency); } @@ -295,7 +295,7 @@ void CubicSDR::setDevice(int deviceId) { sdrThread->setDeviceId(deviceId); SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_SET_DEVICE); command.llong_value = deviceId; - threadCmdQueueSDR->push(command); + pipeSDRCommand->push(command); SDRDeviceInfo *dev = (*getDevices())[deviceId]; DeviceConfig *devConfig = config.getDevice(dev->getDeviceId()); @@ -326,7 +326,7 @@ void CubicSDR::setPPM(int ppm_in) { SDRThreadCommand command(SDRThreadCommand::SDR_THREAD_CMD_SET_PPM); command.llong_value = ppm; - threadCmdQueueSDR->push(command); + pipeSDRCommand->push(command); SDRDeviceInfo *dev = (*getDevices())[getDevice()]; diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 685f6d8..556773d 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -87,10 +87,10 @@ private: SDRThread *sdrThread; SDRPostThread *sdrPostThread; - SDRThreadCommandQueue* threadCmdQueueSDR; - SDRThreadIQDataQueue* iqPostDataQueue; - DemodulatorThreadInputQueue* iqVisualQueue; - DemodulatorThreadOutputQueue* audioVisualQueue; + SDRThreadCommandQueue* pipeSDRCommand; + SDRThreadIQDataQueue* pipeSDRIQData; + DemodulatorThreadInputQueue* pipeIQVisualData; + DemodulatorThreadOutputQueue* pipeAudioVisualData; std::thread *t_SDR; std::thread *t_PostSDR; diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 92e6af2..d39dcb4 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -1,7 +1,7 @@ #include "DemodulatorInstance.h" DemodulatorInstance::DemodulatorInstance() : - threadQueueDemod(NULL), demodulatorThread(NULL), t_PreDemod(NULL), t_Demod(NULL), t_Audio(NULL), currentAudioGain(1.0) { + pipeIQInputData(NULL), demodulatorThread(NULL), t_PreDemod(NULL), t_Demod(NULL), t_Audio(NULL), currentAudioGain(1.0) { terminated.store(true); audioTerminated.store(true); @@ -19,29 +19,29 @@ DemodulatorInstance::DemodulatorInstance() : label = new std::string("Unnamed"); - threadQueueDemod = new DemodulatorThreadInputQueue; - threadQueuePostDemod = new DemodulatorThreadPostInputQueue; - threadQueueCommand = new DemodulatorThreadCommandQueue; - threadQueueNotify = new DemodulatorThreadCommandQueue; + pipeIQInputData = new DemodulatorThreadInputQueue; + pipeIQDemodData = new DemodulatorThreadPostInputQueue; + pipeDemodCommand = new DemodulatorThreadCommandQueue; + pipeDemodNotify = new DemodulatorThreadCommandQueue; demodulatorPreThread = new DemodulatorPreThread(); - demodulatorPreThread->setInputQueue("IQDataInput",threadQueueDemod); - demodulatorPreThread->setOutputQueue("IQDataOutput",threadQueuePostDemod); - demodulatorPreThread->setOutputQueue("NotifyQueue",threadQueueNotify); - demodulatorPreThread->setInputQueue("CommandQueue",threadQueueCommand); + demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData); + demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData); + demodulatorPreThread->setOutputQueue("NotifyQueue",pipeDemodNotify); + demodulatorPreThread->setInputQueue("CommandQueue",pipeDemodCommand); audioInputQueue = new AudioThreadInputQueue; threadQueueControl = new DemodulatorThreadControlCommandQueue; demodulatorThread = new DemodulatorThread(); - demodulatorThread->setInputQueue("IQDataInput",threadQueuePostDemod); + demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData); demodulatorThread->setInputQueue("ControlQueue",threadQueueControl); - demodulatorThread->setOutputQueue("NotifyQueue",threadQueueNotify); + demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify); demodulatorThread->setOutputQueue("AudioDataOutput", audioInputQueue); audioThread = new AudioThread(); audioThread->setInputQueue("AudioDataInput", audioInputQueue); - audioThread->setOutputQueue("NotifyQueue", threadQueueNotify); + audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify); currentDemodType = demodulatorThread->getDemodulatorType(); } @@ -50,10 +50,10 @@ DemodulatorInstance::~DemodulatorInstance() { delete audioThread; delete demodulatorThread; delete demodulatorPreThread; - delete threadQueueDemod; - delete threadQueuePostDemod; - delete threadQueueCommand; - delete threadQueueNotify; + delete pipeIQInputData; + delete pipeIQDemodData; + delete pipeDemodCommand; + delete pipeDemodNotify; delete threadQueueControl; delete audioInputQueue; } @@ -113,7 +113,7 @@ void DemodulatorInstance::updateLabel(long long freq) { } DemodulatorThreadCommandQueue *DemodulatorInstance::getCommandQueue() { - return threadQueueCommand; + return pipeDemodCommand; } void DemodulatorInstance::terminate() { @@ -139,9 +139,9 @@ void DemodulatorInstance::setLabel(std::string labelStr) { } bool DemodulatorInstance::isTerminated() { - while (!threadQueueNotify->empty()) { + while (!pipeDemodNotify->empty()) { DemodulatorThreadCommand cmd; - threadQueueNotify->pop(cmd); + pipeDemodNotify->pop(cmd); switch (cmd.cmd) { case DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED: @@ -311,13 +311,13 @@ void DemodulatorInstance::setBandwidth(int bw) { currentBandwidth = bw; checkBandwidth(); demodulatorPreThread->getParams().bandwidth = currentBandwidth; - } else if (demodulatorPreThread && threadQueueCommand) { + } else if (demodulatorPreThread && pipeDemodCommand) { DemodulatorThreadCommand command; command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH; currentBandwidth = bw; checkBandwidth(); command.llong_value = currentBandwidth; - threadQueueCommand->push(command); + pipeDemodCommand->push(command); } } @@ -335,12 +335,12 @@ void DemodulatorInstance::setFrequency(long long freq) { if (!active) { currentFrequency = freq; demodulatorPreThread->getParams().frequency = currentFrequency; - } else if (demodulatorPreThread && threadQueueCommand) { + } else if (demodulatorPreThread && pipeDemodCommand) { DemodulatorThreadCommand command; command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY; currentFrequency = freq; command.llong_value = freq; - threadQueueCommand->push(command); + pipeDemodCommand->push(command); } } @@ -356,12 +356,12 @@ void DemodulatorInstance::setAudioSampleRate(int sampleRate) { if (terminated) { currentAudioSampleRate = sampleRate; demodulatorPreThread->getParams().audioSampleRate = sampleRate; - } else if (demodulatorPreThread && threadQueueCommand) { + } else if (demodulatorPreThread && pipeDemodCommand) { DemodulatorThreadCommand command; command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE; currentAudioSampleRate = sampleRate; command.llong_value = sampleRate; - threadQueueCommand->push(command); + pipeDemodCommand->push(command); } if (currentDemodType == DEMOD_TYPE_RAW) { setBandwidth(currentAudioSampleRate); @@ -411,3 +411,7 @@ bool DemodulatorInstance::isTracking() { void DemodulatorInstance::setTracking(bool tracking) { this->tracking = tracking; } + +DemodulatorThreadInputQueue *DemodulatorInstance::getIQInputDataPipe() { + return pipeIQInputData; +} diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index b0b8682..acd28ad 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -10,14 +10,6 @@ class DemodulatorInstance { public: - DemodulatorThreadInputQueue* threadQueueDemod; - DemodulatorThreadPostInputQueue* threadQueuePostDemod; - DemodulatorThreadCommandQueue* threadQueueCommand; - DemodulatorThreadCommandQueue* threadQueueNotify; - DemodulatorPreThread *demodulatorPreThread; - DemodulatorThread *demodulatorThread; - DemodulatorThreadControlCommandQueue *threadQueueControl; - #ifdef __APPLE__ pthread_t t_PreDemod; pthread_t t_Demod; @@ -82,6 +74,18 @@ public: bool isTracking(); void setTracking(bool tracking); + + DemodulatorThreadInputQueue *getIQInputDataPipe(); + +protected: + DemodulatorThreadInputQueue* pipeIQInputData; + DemodulatorThreadPostInputQueue* pipeIQDemodData; + DemodulatorThreadCommandQueue* pipeDemodCommand; + DemodulatorThreadCommandQueue* pipeDemodNotify; + DemodulatorPreThread *demodulatorPreThread; + DemodulatorThread *demodulatorThread; + DemodulatorThreadControlCommandQueue *threadQueueControl; + private: void checkBandwidth(); diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index f395017..3ceac05 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -176,7 +176,7 @@ void SDRPostThread::run() { std::vector::iterator i; for (i = demodulators.begin(); i != demodulators.end(); i++) { DemodulatorInstance *demod = *i; - DemodulatorThreadInputQueue *demodQueue = demod->threadQueueDemod; + DemodulatorThreadInputQueue *demodQueue = demod->getIQInputDataPipe(); if (abs(data_in->frequency - demod->getFrequency()) > (wxGetApp().getSampleRate() / 2)) { if (demod->isActive() && !demod->isFollow() && !demod->isTracking()) { From 3fbb1def49021da48d4192e286a24fa93eec6fd8 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 31 Jul 2015 18:21:30 -0400 Subject: [PATCH 31/53] MSVC and TDMGCC fixes --- external/cubicvr2/math/cubic_types.h | 5 + external/cubicvr2/math/frustum.h | 11 +- external/cubicvr2/math/mat3.h | 1 + external/cubicvr2/math/mat4.h | 8 +- src/process/VisualProcessor.h | 1 + src/ui/GLPanel.cpp | 16 +- src/ui/GLPanel.h | 10 +- src/ui/UITestContext.cpp | 12 +- src/visual/ColorTheme.cpp | 280 +++++++++++++-------------- src/visual/ColorTheme.h | 54 +++--- src/visual/PrimaryGLContext.cpp | 8 +- src/visual/PrimaryGLContext.h | 8 +- src/visual/TuningCanvas.cpp | 8 +- src/visual/TuningContext.cpp | 4 +- src/visual/TuningContext.h | 4 +- 15 files changed, 219 insertions(+), 211 deletions(-) diff --git a/external/cubicvr2/math/cubic_types.h b/external/cubicvr2/math/cubic_types.h index bc4ddc7..060fc6f 100644 --- a/external/cubicvr2/math/cubic_types.h +++ b/external/cubicvr2/math/cubic_types.h @@ -38,4 +38,9 @@ namespace CubicVR { } +#include +#ifndef M_PI + #define M_PI 3.14159265358979323846 +#endif + #endif diff --git a/external/cubicvr2/math/frustum.h b/external/cubicvr2/math/frustum.h index 5da030f..2d983fe 100644 --- a/external/cubicvr2/math/frustum.h +++ b/external/cubicvr2/math/frustum.h @@ -10,6 +10,7 @@ #define CubicVR2_frustum_h #include +#include "cubic_types.h" #include "mat4.h" #include "vec3.h" #include "vec4.h" @@ -75,14 +76,14 @@ namespace CubicVR { //Sphere __float fov = 1 / pMatrix[5]; - __float near = -planes[PLANE_NEAR][3]; - __float far = planes[PLANE_FAR][3]; - __float view_length = far - near; + __float znear = -planes[PLANE_NEAR][3]; + __float zfar = planes[PLANE_FAR][3]; + __float view_length = zfar - znear; __float height = view_length * fov; __float width = height; - vec3 P(0, 0, near + view_length * 0.5f); - vec3 Q(width, height, near + view_length); + vec3 P(0, 0, znear + view_length * 0.5f); + vec3 Q(width, height, znear + view_length); vec3 diff = vec3::subtract(P, Q); __float diff_mag = vec3::length(diff); diff --git a/external/cubicvr2/math/mat3.h b/external/cubicvr2/math/mat3.h index 90553c4..e96b0db 100644 --- a/external/cubicvr2/math/mat3.h +++ b/external/cubicvr2/math/mat3.h @@ -11,6 +11,7 @@ #include #include "vec3.h" +#include namespace CubicVR { diff --git a/external/cubicvr2/math/mat4.h b/external/cubicvr2/math/mat4.h index b54029b..b46409c 100644 --- a/external/cubicvr2/math/mat4.h +++ b/external/cubicvr2/math/mat4.h @@ -72,15 +72,15 @@ namespace CubicVR { return mOut; } - static mat4 perspective(__float fovy, __float aspect, __float near, __float far) { + static mat4 perspective(__float fovy, __float aspect, __float znear, __float zfar) { __float yFac = tan(fovy * (float)M_PI / 360.0f); __float xFac = yFac * aspect; return mat4( - 1.0f / xFac, 0, 0, 0, 0, 1.0f / yFac, 0, 0, 0, 0, -(far + near) / (far - near), -1, 0, 0, -(2.0f * far * near) / (far - near), 0); + 1.0f / xFac, 0, 0, 0, 0, 1.0f / yFac, 0, 0, 0, 0, -(zfar + znear) / (zfar - znear), -1, 0, 0, -(2.0f * zfar * znear) / (zfar - znear), 0); }; - static mat4 ortho(__float left,__float right,__float bottom,__float top,__float near,__float far) { - return mat4(2.0f / (right - left), 0, 0, 0, 0, 2.0f / (top - bottom), 0, 0, 0, 0, -2.0f / (far - near), 0, -(left + right) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1); + static mat4 ortho(__float left,__float right,__float bottom,__float top,__float znear,__float zfar) { + return mat4(2.0f / (right - left), 0, 0, 0, 0, 2.0f / (top - bottom), 0, 0, 0, 0, -2.0f / (zfar - znear), 0, -(left + right) / (right - left), -(top + bottom) / (top - bottom), -(zfar + znear) / (zfar - znear), 1); }; static __float determinant(mat4 m) { diff --git a/src/process/VisualProcessor.h b/src/process/VisualProcessor.h index c27dbb1..5ca4b7d 100644 --- a/src/process/VisualProcessor.h +++ b/src/process/VisualProcessor.h @@ -3,6 +3,7 @@ #include "CubicSDRDefs.h" #include "ThreadQueue.h" #include "IOThread.h" +#include typedef ThreadQueue VisualDataQueue; diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index e0d24ed..5de9387 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -9,9 +9,9 @@ GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transf pos[1] = 0.0f; size[0] = 1.0f; size[1] = 1.0f; - fill[0] = RGB(0.5,0.5,0.5); - fill[1] = RGB(0.1,0.1,0.1); - borderColor = RGB(0.8, 0.8, 0.8); + fill[0] = RGB3f(0.5,0.5,0.5); + fill[1] = RGB3f(0.1,0.1,0.1); + borderColor = RGB3f(0.8, 0.8, 0.8); setCoordinateSystem(GLPANEL_Y_UP); } @@ -31,7 +31,7 @@ void GLPanel::genArrays() { max, min }; - RGB c[4]; + RGB3f c[4]; if (fillType == GLPANEL_FILL_SOLID) { c[0] = c[1] = c[2] = c[3] = fill[0]; @@ -58,7 +58,7 @@ void GLPanel::genArrays() { glColors.reserve(3 * 8); glColors.resize(3 * 8); - RGB c[8]; + RGB3f c[8]; if (fillType == GLPANEL_FILL_GRAD_BAR_X) { float pts[2 * 8] = { @@ -173,12 +173,12 @@ void GLPanel::setFill(GLPanelFillType fill_mode) { genArrays(); } -void GLPanel::setFillColor(RGB color1) { +void GLPanel::setFillColor(RGB3f color1) { fill[0] = color1; genArrays(); } -void GLPanel::setFillColor(RGB color1, RGB color2) { +void GLPanel::setFillColor(RGB3f color1, RGB3f color2) { fill[0] = color1; fill[1] = color2; genArrays(); @@ -189,7 +189,7 @@ void GLPanel::setMarginPx(float marg) { } -void GLPanel::setBorderColor(RGB clr) { +void GLPanel::setBorderColor(RGB3f clr) { borderColor = clr; } diff --git a/src/ui/GLPanel.h b/src/ui/GLPanel.h index d03a60d..db16fe2 100644 --- a/src/ui/GLPanel.h +++ b/src/ui/GLPanel.h @@ -42,8 +42,8 @@ public: GLPanelCoordinateSystem coord; float marginPx; GLPanelEdges borderPx; - RGB fill[2]; - RGB borderColor; + RGB3f fill[2]; + RGB3f borderColor; bool contentsVisible; CubicVR::mat4 transform; CubicVR::mat4 localTransform; @@ -68,11 +68,11 @@ public: void setCoordinateSystem(GLPanelCoordinateSystem coord); void setFill(GLPanelFillType fill_mode); - void setFillColor(RGB color1); - void setFillColor(RGB color1, RGB color2); + void setFillColor(RGB3f color1); + void setFillColor(RGB3f color1, RGB3f color2); void setMarginPx(float marg); - void setBorderColor(RGB clr); + void setBorderColor(RGB3f clr); void setBorderPx(float bord); void setBorderPx(float bordl, float bordr, float bordt, float bordb); diff --git a/src/ui/UITestContext.cpp b/src/ui/UITestContext.cpp index 8042981..ec2722d 100644 --- a/src/ui/UITestContext.cpp +++ b/src/ui/UITestContext.cpp @@ -9,30 +9,30 @@ PrimaryGLContext(canvas, sharedContext) { testPanel.setSize(1.0, 1.0); testPanel.setMarginPx(10); testPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_Y); - testPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); + testPanel.setFillColor(RGB3f(0.0,0.0,1.0), RGB3f(0.0,1.0,0.0)); testChildPanel.setPosition(0.0, 0.0); testChildPanel.setMarginPx(5); testChildPanel.setSize(1.0, 0.33); testChildPanel.setCoordinateSystem(GLPanel::GLPANEL_Y_DOWN_ZERO_ONE); testChildPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X); - testChildPanel.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); + testChildPanel.setFillColor(RGB3f(0.0,0.0,1.0), RGB3f(0.0,1.0,0.0)); testChildPanel.setBorderPx(1); testChildPanel2.setPosition(0.0, -0.66); testChildPanel2.setSize(1.0, 0.33); testChildPanel2.setMarginPx(5); testChildPanel2.setFill(GLPanel::GLPANEL_FILL_GRAD_X); - testChildPanel2.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); - testChildPanel2.setBorderColor(RGB(1.0,0.0,0.0)); + testChildPanel2.setFillColor(RGB3f(0.0,0.0,1.0), RGB3f(0.0,1.0,0.0)); + testChildPanel2.setBorderColor(RGB3f(1.0,0.0,0.0)); testChildPanel2.setBorderPx(1); testChildPanel3.setPosition(0.0, 0.66); testChildPanel3.setSize(1.0, 0.33); testChildPanel3.setMarginPx(5); testChildPanel3.setFill(GLPanel::GLPANEL_FILL_GRAD_X); - testChildPanel3.setFillColor(RGB(0.0,0.0,1.0), RGB(0.0,1.0,0.0)); - testChildPanel3.setBorderColor(RGB(1.0,0.0,0.0)); + testChildPanel3.setFillColor(RGB3f(0.0,0.0,1.0), RGB3f(0.0,1.0,0.0)); + testChildPanel3.setBorderColor(RGB3f(1.0,0.0,0.0)); testChildPanel3.setBorderPx(1); testText1.setText("Testing 123.."); diff --git a/src/visual/ColorTheme.cpp b/src/visual/ColorTheme.cpp index 4038a1e..7c0b5ef 100644 --- a/src/visual/ColorTheme.cpp +++ b/src/visual/ColorTheme.cpp @@ -41,27 +41,27 @@ DefaultColorTheme::DefaultColorTheme() { waterfallGradient.addColor(GradientColor(1.0, 1.0, 0)); waterfallGradient.addColor(GradientColor(1.0, 0.2, 0.0)); waterfallGradient.generate(256); - waterfallHighlight = RGB(1, 1, 1); - waterfallNew = RGB(0, 1, 0); - waterfallHover = RGB(1, 1, 0); - waterfallDestroy = RGB(1, 0, 0); - fftLine = RGB(0.9, 0.9, 0.9); - fftHighlight = RGB(1, 1, 1); - scopeLine = RGB(0.9, 0.9, 0.9); - tuningBarLight = RGB(0.2, 0.2, 0.9); - tuningBarDark = RGB(0.0, 0.0, 0.35); - tuningBarUp = RGB(1.0, 139.0/255.0, 96.0/255.0); - tuningBarDown = RGB(148.0/255.0, 148.0/255.0, 1.0); - meterLevel = RGB(0.1, 0.75, 0.1); - meterValue = RGB(0.75, 0.1, 0.1); - text = RGB(1, 1, 1); - freqLine = RGB(1, 1, 1); - button = RGB(0.65, 0.65, 0.65); - buttonHighlight = RGB(1, 1, 0); + waterfallHighlight = RGB3f(1, 1, 1); + waterfallNew = RGB3f(0, 1, 0); + waterfallHover = RGB3f(1, 1, 0); + waterfallDestroy = RGB3f(1, 0, 0); + fftLine = RGB3f(0.9, 0.9, 0.9); + fftHighlight = RGB3f(1, 1, 1); + scopeLine = RGB3f(0.9, 0.9, 0.9); + tuningBarLight = RGB3f(0.2, 0.2, 0.9); + tuningBarDark = RGB3f(0.0, 0.0, 0.35); + tuningBarUp = RGB3f(1.0, 139.0/255.0, 96.0/255.0); + tuningBarDown = RGB3f(148.0/255.0, 148.0/255.0, 1.0); + meterLevel = RGB3f(0.1, 0.75, 0.1); + meterValue = RGB3f(0.75, 0.1, 0.1); + text = RGB3f(1, 1, 1); + freqLine = RGB3f(1, 1, 1); + button = RGB3f(0.65, 0.65, 0.65); + buttonHighlight = RGB3f(1, 1, 0); - scopeBackground = RGB(0.1, 0.1, 0.1); - fftBackground = RGB(0.1, 0.1, 0.1); - generalBackground = RGB(0.1, 0.1, 0.1); + scopeBackground = RGB3f(0.1, 0.1, 0.1); + fftBackground = RGB3f(0.1, 0.1, 0.1); + generalBackground = RGB3f(0.1, 0.1, 0.1); } @@ -72,27 +72,27 @@ RadarColorTheme::RadarColorTheme() { waterfallGradient.addColor(GradientColor(40.0 / 255.0, 240.0 / 255.0, 60.0 / 255.0)); waterfallGradient.addColor(GradientColor(250.0 / 255.0, 250.0 / 255.0, 250.0 / 255.0)); waterfallGradient.generate(256); - waterfallHighlight = RGB(1, 1, 1); - waterfallNew = RGB(0, 1, 0); - waterfallHover = RGB(1, 1, 0); - waterfallDestroy = RGB(1, 0, 0); - fftLine = RGB(0.8, 1.0, 0.8); - fftHighlight = RGB(1, 1, 1); - scopeLine = RGB(0.8, 1.0, 0.8); - tuningBarLight = RGB(0.0, 0.45, 0.0); - tuningBarDark = RGB(0.0, 0.1, 0.0); - tuningBarUp = RGB(1.0, 139.0/255.0, 96.0/255.0); - tuningBarDown = RGB(148.0/255.0, 0.0, 0.0); - meterLevel = RGB(0, 0.5, 0); - meterValue = RGB(0, 0.5, 0); - text = RGB(0.8, 1.0, 0.8); - freqLine = RGB(1, 1, 1); - button = RGB(0.65, 0.75, 0.65); - buttonHighlight = RGB(0.65, 1.0, 0.65); + waterfallHighlight = RGB3f(1, 1, 1); + waterfallNew = RGB3f(0, 1, 0); + waterfallHover = RGB3f(1, 1, 0); + waterfallDestroy = RGB3f(1, 0, 0); + fftLine = RGB3f(0.8, 1.0, 0.8); + fftHighlight = RGB3f(1, 1, 1); + scopeLine = RGB3f(0.8, 1.0, 0.8); + tuningBarLight = RGB3f(0.0, 0.45, 0.0); + tuningBarDark = RGB3f(0.0, 0.1, 0.0); + tuningBarUp = RGB3f(1.0, 139.0/255.0, 96.0/255.0); + tuningBarDown = RGB3f(148.0/255.0, 0.0, 0.0); + meterLevel = RGB3f(0, 0.5, 0); + meterValue = RGB3f(0, 0.5, 0); + text = RGB3f(0.8, 1.0, 0.8); + freqLine = RGB3f(1, 1, 1); + button = RGB3f(0.65, 0.75, 0.65); + buttonHighlight = RGB3f(0.65, 1.0, 0.65); - scopeBackground = RGB(0.05, 0.1, 0.05); - fftBackground = RGB(0.05, 0.1, 0.05); - generalBackground = RGB(0.05, 0.1, 0.05); + scopeBackground = RGB3f(0.05, 0.1, 0.05); + fftBackground = RGB3f(0.05, 0.1, 0.05); + generalBackground = RGB3f(0.05, 0.1, 0.05); } BlackAndWhiteColorTheme::BlackAndWhiteColorTheme() { @@ -101,27 +101,27 @@ BlackAndWhiteColorTheme::BlackAndWhiteColorTheme() { waterfallGradient.addColor(GradientColor(0.75, 0.75, 0.75)); waterfallGradient.addColor(GradientColor(1.0, 1.0, 1.0)); waterfallGradient.generate(256); - waterfallHighlight = RGB(1, 1, 0.9); - waterfallNew = RGB(0, 1, 0); - waterfallHover = RGB(1, 1, 0); - waterfallDestroy = RGB(1, 0, 0); - fftLine = RGB(0.9, 0.9, 0.9); - fftHighlight = RGB(1, 1, 0.9); - scopeLine = RGB(0.9, 0.9, 0.9); - tuningBarLight = RGB(0.4, 0.4, 0.4); - tuningBarDark = RGB(0.1, 0.1, 0.1); - tuningBarUp = RGB(0.8, 0.8, 0.8); - tuningBarDown = RGB(0.4, 0.4, 0.4); - meterLevel = RGB(0.5, 0.5, 0.5); - meterValue = RGB(0.5, 0.5, 0.5); - text = RGB(1, 1, 1); - freqLine = RGB(1, 1, 1); - button = RGB(0.65, 0.65, 0.65); - buttonHighlight = RGB(1, 1, 1); + waterfallHighlight = RGB3f(1, 1, 0.9); + waterfallNew = RGB3f(0, 1, 0); + waterfallHover = RGB3f(1, 1, 0); + waterfallDestroy = RGB3f(1, 0, 0); + fftLine = RGB3f(0.9, 0.9, 0.9); + fftHighlight = RGB3f(1, 1, 0.9); + scopeLine = RGB3f(0.9, 0.9, 0.9); + tuningBarLight = RGB3f(0.4, 0.4, 0.4); + tuningBarDark = RGB3f(0.1, 0.1, 0.1); + tuningBarUp = RGB3f(0.8, 0.8, 0.8); + tuningBarDown = RGB3f(0.4, 0.4, 0.4); + meterLevel = RGB3f(0.5, 0.5, 0.5); + meterValue = RGB3f(0.5, 0.5, 0.5); + text = RGB3f(1, 1, 1); + freqLine = RGB3f(1, 1, 1); + button = RGB3f(0.65, 0.65, 0.65); + buttonHighlight = RGB3f(1, 1, 1); - scopeBackground = RGB(0.1, 0.1, 0.1); - fftBackground = RGB(0.1, 0.1, 0.1); - generalBackground = RGB(0.1, 0.1, 0.1); + scopeBackground = RGB3f(0.1, 0.1, 0.1); + fftBackground = RGB3f(0.1, 0.1, 0.1); + generalBackground = RGB3f(0.1, 0.1, 0.1); } @@ -139,27 +139,27 @@ SharpColorTheme::SharpColorTheme() { waterfallGradient.addColor(GradientColor(1.0, 0.25, 0.0)); waterfallGradient.addColor(GradientColor(0.5, 0.1, 0.0)); waterfallGradient.generate(256); - waterfallHighlight = RGB(0.9, 0.9, 1.0); - waterfallNew = RGB(0, 1, 0); - waterfallHover = RGB(1, 1, 0); - waterfallDestroy = RGB(1, 0, 0); - fftLine = RGB(0.9, 0.9, 1.0); - fftHighlight = RGB(0.9, 0.9, 1.0); - scopeLine = RGB(0.85, 0.85, 1.0); - tuningBarLight = RGB(28.0 / 255.0, 106.0 / 255.0, 179.0 / 255.0); - tuningBarDark = RGB(14.0 / 255.0, 53.0 / 255.0, 89.5 / 255.0); - tuningBarUp = RGB(0.7, 0.7, 0.7); - tuningBarDown = RGB(1.0, 0.0, 0.0); - meterLevel = RGB(28.0 / 255.0, 106.0 / 255.0, 179.0 / 255.0); - meterValue = RGB(190.0 / 255.0, 190.0 / 255.0, 60.0 / 255.0); - text = RGB(0.9, 0.9, 1); - freqLine = RGB(0.85, 0.85, 1.0); - button = RGB(217.0 / 255.0, 218.0 / 255.0, 228.0 / 255.0); - buttonHighlight = RGB(208.0 / 255.0, 249.0 / 255.0, 255.0 / 255.0); + waterfallHighlight = RGB3f(0.9, 0.9, 1.0); + waterfallNew = RGB3f(0, 1, 0); + waterfallHover = RGB3f(1, 1, 0); + waterfallDestroy = RGB3f(1, 0, 0); + fftLine = RGB3f(0.9, 0.9, 1.0); + fftHighlight = RGB3f(0.9, 0.9, 1.0); + scopeLine = RGB3f(0.85, 0.85, 1.0); + tuningBarLight = RGB3f(28.0 / 255.0, 106.0 / 255.0, 179.0 / 255.0); + tuningBarDark = RGB3f(14.0 / 255.0, 53.0 / 255.0, 89.5 / 255.0); + tuningBarUp = RGB3f(0.7, 0.7, 0.7); + tuningBarDown = RGB3f(1.0, 0.0, 0.0); + meterLevel = RGB3f(28.0 / 255.0, 106.0 / 255.0, 179.0 / 255.0); + meterValue = RGB3f(190.0 / 255.0, 190.0 / 255.0, 60.0 / 255.0); + text = RGB3f(0.9, 0.9, 1); + freqLine = RGB3f(0.85, 0.85, 1.0); + button = RGB3f(217.0 / 255.0, 218.0 / 255.0, 228.0 / 255.0); + buttonHighlight = RGB3f(208.0 / 255.0, 249.0 / 255.0, 255.0 / 255.0); - scopeBackground = RGB(0.05, 0.05, 0.15); - fftBackground = RGB(0.05, 0.05, 0.15); - generalBackground = RGB(0.05, 0.05, 0.15); + scopeBackground = RGB3f(0.05, 0.05, 0.15); + fftBackground = RGB3f(0.05, 0.05, 0.15); + generalBackground = RGB3f(0.05, 0.05, 0.15); } RadColorTheme::RadColorTheme() { @@ -170,27 +170,27 @@ RadColorTheme::RadColorTheme() { waterfallGradient.addColor(GradientColor(1.0, 40.0 / 255.0, 40.0 / 255.0)); waterfallGradient.addColor(GradientColor(1.0, 1.0, 1.0)); waterfallGradient.generate(256); - waterfallHighlight = RGB(1, 1, 1); - waterfallNew = RGB(0, 1, 0); - waterfallHover = RGB(1, 1, 0); - waterfallDestroy = RGB(1, 0, 0); - fftLine = RGB(1.0, 0.9, 0.9); - fftHighlight = RGB(1, 1, 1); - scopeLine = RGB(1.0, 0.9, 0.9); - tuningBarLight = RGB(0.0, 0.45, 0.0); - tuningBarDark = RGB(0.0, 0.1, 0.0); - tuningBarUp = RGB(1.0, 0.0, 0.0); - tuningBarDown = RGB(0.0, 0.5, 1.0); - meterLevel = RGB(0, 0.5, 0); - meterValue = RGB(0.5, 0, 0); - text = RGB(1, 1, 1); - freqLine = RGB(1, 1, 1); - button = RGB(0.65, 0.65, 0.65); - buttonHighlight = RGB(0.76, 0.65, 0); + waterfallHighlight = RGB3f(1, 1, 1); + waterfallNew = RGB3f(0, 1, 0); + waterfallHover = RGB3f(1, 1, 0); + waterfallDestroy = RGB3f(1, 0, 0); + fftLine = RGB3f(1.0, 0.9, 0.9); + fftHighlight = RGB3f(1, 1, 1); + scopeLine = RGB3f(1.0, 0.9, 0.9); + tuningBarLight = RGB3f(0.0, 0.45, 0.0); + tuningBarDark = RGB3f(0.0, 0.1, 0.0); + tuningBarUp = RGB3f(1.0, 0.0, 0.0); + tuningBarDown = RGB3f(0.0, 0.5, 1.0); + meterLevel = RGB3f(0, 0.5, 0); + meterValue = RGB3f(0.5, 0, 0); + text = RGB3f(1, 1, 1); + freqLine = RGB3f(1, 1, 1); + button = RGB3f(0.65, 0.65, 0.65); + buttonHighlight = RGB3f(0.76, 0.65, 0); - scopeBackground = RGB(13.0 / 255.0, 47.0 / 255.0, 9.0 / 255.0); - fftBackground = RGB(0, 0, 50.0 / 255.0); - generalBackground = RGB(13.0 / 255.0, 47.0 / 255.0, 9.0 / 255.0); + scopeBackground = RGB3f(13.0 / 255.0, 47.0 / 255.0, 9.0 / 255.0); + fftBackground = RGB3f(0, 0, 50.0 / 255.0); + generalBackground = RGB3f(13.0 / 255.0, 47.0 / 255.0, 9.0 / 255.0); } TouchColorTheme::TouchColorTheme() { @@ -204,27 +204,27 @@ TouchColorTheme::TouchColorTheme() { waterfallGradient.addColor(GradientColor(255.0 / 255.0, 0.0 / 255.0, 0.0 / 255.0)); waterfallGradient.addColor(GradientColor(255.0 / 255.0, 255.0 / 255.0, 255.0 / 255.0)); waterfallGradient.generate(256); - waterfallHighlight = RGB(1, 1, 1); - waterfallNew = RGB(0, 1, 0); - waterfallHover = RGB(1, 1, 0); - waterfallDestroy = RGB(1, 0, 0); - fftLine = RGB(234.0 / 255.0, 232.0 / 255.0, 247.0 / 255.0); - fftHighlight = RGB(1.0, 1.0, 1.0); - scopeLine = RGB(234.0 / 255.0, 232.0 / 255.0, 247.0 / 255.0); - tuningBarLight = RGB(0.2, 0.2, 0.7); - tuningBarDark = RGB(0.1, 0.1, 0.45); - tuningBarUp = RGB(0.5, 139.0/255.0, 96.0/255.0); - tuningBarDown = RGB(0.6, 108.0/255.0, 1.0); - meterLevel = RGB(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); - meterValue = RGB(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); - text = RGB(1, 1, 1); - freqLine = RGB(1, 1, 1); - button = RGB(1.0, 1.0, 1.0); - buttonHighlight = RGB(208.0 / 255.0, 202.0 / 255.0, 247.0 / 255.0); + waterfallHighlight = RGB3f(1, 1, 1); + waterfallNew = RGB3f(0, 1, 0); + waterfallHover = RGB3f(1, 1, 0); + waterfallDestroy = RGB3f(1, 0, 0); + fftLine = RGB3f(234.0 / 255.0, 232.0 / 255.0, 247.0 / 255.0); + fftHighlight = RGB3f(1.0, 1.0, 1.0); + scopeLine = RGB3f(234.0 / 255.0, 232.0 / 255.0, 247.0 / 255.0); + tuningBarLight = RGB3f(0.2, 0.2, 0.7); + tuningBarDark = RGB3f(0.1, 0.1, 0.45); + tuningBarUp = RGB3f(0.5, 139.0/255.0, 96.0/255.0); + tuningBarDown = RGB3f(0.6, 108.0/255.0, 1.0); + meterLevel = RGB3f(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); + meterValue = RGB3f(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); + text = RGB3f(1, 1, 1); + freqLine = RGB3f(1, 1, 1); + button = RGB3f(1.0, 1.0, 1.0); + buttonHighlight = RGB3f(208.0 / 255.0, 202.0 / 255.0, 247.0 / 255.0); - scopeBackground = RGB(39.0 / 255.0, 36.0 / 255.0, 56.0 / 255.0); - fftBackground = RGB(39.0 / 255.0, 36.0 / 255.0, 56.0 / 255.0); - generalBackground = RGB(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); + scopeBackground = RGB3f(39.0 / 255.0, 36.0 / 255.0, 56.0 / 255.0); + fftBackground = RGB3f(39.0 / 255.0, 36.0 / 255.0, 56.0 / 255.0); + generalBackground = RGB3f(61.0 / 255.0, 57.0 / 255.0, 88.0 / 255.0); } @@ -239,27 +239,27 @@ HDColorTheme::HDColorTheme() { waterfallGradient.addColor(GradientColor(255.0 / 255.0, 235.0 / 255.0, 100.0 / 255.0)); waterfallGradient.addColor(GradientColor(250.0 / 255.0, 250.0 / 255.0, 250.0 / 255.0)); waterfallGradient.generate(256); - waterfallHighlight = RGB(1, 1, 1); - waterfallNew = RGB(0, 1, 0); - waterfallHover = RGB(1, 1, 0); - waterfallDestroy = RGB(1, 0, 0); - fftLine = RGB(0.9, 0.9, 0.9); - fftHighlight = RGB(1, 1, 1); - scopeLine = RGB(0.9, 0.9, 0.9); - tuningBarLight = RGB(0.4, 0.4, 1.0); - tuningBarDark = RGB(0.1, 0.1, 0.45); - tuningBarUp = RGB(1.0, 139.0/255.0, 96.0/255.0); - tuningBarDown = RGB(148.0/255.0, 148.0/255.0, 1.0); - meterLevel = RGB(0, 0.5, 0); - meterValue = RGB(0.0, 0.0, 1.0); - text = RGB(1, 1, 1); - freqLine = RGB(1, 1, 1); - button = RGB(0, 0.7, 0.7); - buttonHighlight = RGB(1, 1, 1); + waterfallHighlight = RGB3f(1, 1, 1); + waterfallNew = RGB3f(0, 1, 0); + waterfallHover = RGB3f(1, 1, 0); + waterfallDestroy = RGB3f(1, 0, 0); + fftLine = RGB3f(0.9, 0.9, 0.9); + fftHighlight = RGB3f(1, 1, 1); + scopeLine = RGB3f(0.9, 0.9, 0.9); + tuningBarLight = RGB3f(0.4, 0.4, 1.0); + tuningBarDark = RGB3f(0.1, 0.1, 0.45); + tuningBarUp = RGB3f(1.0, 139.0/255.0, 96.0/255.0); + tuningBarDown = RGB3f(148.0/255.0, 148.0/255.0, 1.0); + meterLevel = RGB3f(0, 0.5, 0); + meterValue = RGB3f(0.0, 0.0, 1.0); + text = RGB3f(1, 1, 1); + freqLine = RGB3f(1, 1, 1); + button = RGB3f(0, 0.7, 0.7); + buttonHighlight = RGB3f(1, 1, 1); - scopeBackground = RGB(0.0, 0.0, 48.0 / 255.0); - fftBackground = RGB(0.0, 0.0, 48.0 / 255.0); - generalBackground = RGB(0.0, 0.0, 0.0); + scopeBackground = RGB3f(0.0, 0.0, 48.0 / 255.0); + fftBackground = RGB3f(0.0, 0.0, 48.0 / 255.0); + generalBackground = RGB3f(0.0, 0.0, 0.0); } diff --git a/src/visual/ColorTheme.h b/src/visual/ColorTheme.h index 971863d..1318ac6 100644 --- a/src/visual/ColorTheme.h +++ b/src/visual/ColorTheme.h @@ -15,21 +15,21 @@ #define COLOR_THEME_RADAR 6 #define COLOR_THEME_MAX 7 -class RGB { +class RGB3f { public: float r, g, b; - RGB(float r, float g, float b) : + RGB3f(float r, float g, float b) : r(r), g(g), b(b) { } - RGB() : - RGB(0, 0, 0) { + RGB3f() : + RGB3f(0, 0, 0) { } - ~RGB() { + ~RGB3f() { } - RGB & operator=(const RGB &other) { + RGB3f & operator=(const RGB3f &other) { r = other.r; g = other.g; b = other.b; @@ -39,28 +39,28 @@ public: class ColorTheme { public: - RGB waterfallHighlight; - RGB waterfallNew; - RGB wfHighlight; - RGB waterfallHover; - RGB waterfallDestroy; - RGB fftLine; - RGB fftHighlight; - RGB scopeLine; - RGB tuningBarLight; - RGB tuningBarDark; - RGB tuningBarUp; - RGB tuningBarDown; - RGB meterLevel; - RGB meterValue; - RGB text; - RGB freqLine; - RGB button; - RGB buttonHighlight; + RGB3f waterfallHighlight; + RGB3f waterfallNew; + RGB3f wfHighlight; + RGB3f waterfallHover; + RGB3f waterfallDestroy; + RGB3f fftLine; + RGB3f fftHighlight; + RGB3f scopeLine; + RGB3f tuningBarLight; + RGB3f tuningBarDark; + RGB3f tuningBarUp; + RGB3f tuningBarDown; + RGB3f meterLevel; + RGB3f meterValue; + RGB3f text; + RGB3f freqLine; + RGB3f button; + RGB3f buttonHighlight; - RGB scopeBackground; - RGB fftBackground; - RGB generalBackground; + RGB3f scopeBackground; + RGB3f fftBackground; + RGB3f generalBackground; Gradient waterfallGradient; diff --git a/src/visual/PrimaryGLContext.cpp b/src/visual/PrimaryGLContext.cpp index 8bd1bf7..0ff82dc 100644 --- a/src/visual/PrimaryGLContext.cpp +++ b/src/visual/PrimaryGLContext.cpp @@ -59,7 +59,7 @@ PrimaryGLContext::PrimaryGLContext(wxGLCanvas *canvas, wxGLContext *sharedContex //#endif } -void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGB color, long long center_freq, long long srate) { +void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGB3f color, long long center_freq, long long srate) { if (!demod) { return; } @@ -140,7 +140,7 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGB color, long } -void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGB color, long long center_freq, long long srate) { +void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGB3f color, long long center_freq, long long srate) { if (!demod) { return; } @@ -237,7 +237,7 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGB color, long lon } -void PrimaryGLContext::DrawFreqSelector(float uxPos, RGB color, float w, long long center_freq, long long srate) { +void PrimaryGLContext::DrawFreqSelector(float uxPos, RGB3f color, float w, long long center_freq, long long srate) { DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); long long bw = 0; @@ -288,7 +288,7 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, RGB color, float w, long lo } -void PrimaryGLContext::DrawRangeSelector(float uxPos1, float uxPos2, RGB color) { +void PrimaryGLContext::DrawRangeSelector(float uxPos1, float uxPos2, RGB3f color) { if (uxPos2 < uxPos1) { float temp = uxPos2; uxPos2=uxPos1; diff --git a/src/visual/PrimaryGLContext.h b/src/visual/PrimaryGLContext.h index 353f563..4f87e4d 100644 --- a/src/visual/PrimaryGLContext.h +++ b/src/visual/PrimaryGLContext.h @@ -21,10 +21,10 @@ public: void BeginDraw(float r, float g, float b); void EndDraw(); - void DrawFreqSelector(float uxPos, RGB color, float w = 0, long long center_freq = -1, long long srate = 0); - void DrawRangeSelector(float uxPos1, float uxPos2, RGB color); - void DrawDemod(DemodulatorInstance *demod, RGB color, long long center_freq = -1, long long srate = 0); - void DrawDemodInfo(DemodulatorInstance *demod, RGB color, long long center_freq = -1, long long srate = 0); + void DrawFreqSelector(float uxPos, RGB3f color, float w = 0, long long center_freq = -1, long long srate = 0); + void DrawRangeSelector(float uxPos1, float uxPos2, RGB3f color); + void DrawDemod(DemodulatorInstance *demod, RGB3f color, long long center_freq = -1, long long srate = 0); + void DrawDemodInfo(DemodulatorInstance *demod, RGB3f color, long long center_freq = -1, long long srate = 0); void setHoverAlpha(float hoverAlpha); diff --git a/src/visual/TuningCanvas.cpp b/src/visual/TuningCanvas.cpp index d64edbd..5582f30 100644 --- a/src/visual/TuningCanvas.cpp +++ b/src/visual/TuningCanvas.cpp @@ -84,10 +84,10 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { 0.75, mouseTracker.getOriginMouseX(), mouseTracker.getMouseX()); } - RGB clr = top ? ThemeMgr::mgr.currentTheme->tuningBarUp : ThemeMgr::mgr.currentTheme->tuningBarDown; + RGB3f clr = top ? ThemeMgr::mgr.currentTheme->tuningBarUp : ThemeMgr::mgr.currentTheme->tuningBarDown; - RGB clrDark = ThemeMgr::mgr.currentTheme->tuningBarDark; - RGB clrMid = ThemeMgr::mgr.currentTheme->tuningBarLight; + RGB3f clrDark = ThemeMgr::mgr.currentTheme->tuningBarDark; + RGB3f clrMid = ThemeMgr::mgr.currentTheme->tuningBarLight; glContext->DrawTunerBarIndexed(1, 3, 11, freqDP, freqW, clrMid, 0.25, true, true); // freq glContext->DrawTunerBarIndexed(4, 6, 11, freqDP, freqW, clrDark, 0.25, true, true); @@ -129,7 +129,7 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glContext->DrawTuner(freq, 11, freqDP, freqW); int snap = wxGetApp().getFrequencySnap(); if (snap != 1) { - glContext->DrawTunerDigitBox((int)log10(snap), 11, freqDP, freqW, RGB(1.0,0.0,0.0)); + glContext->DrawTunerDigitBox((int)log10(snap), 11, freqDP, freqW, RGB3f(1.0,0.0,0.0)); } } glContext->DrawTuner(bw, 7, bwDP, bwW); diff --git a/src/visual/TuningContext.cpp b/src/visual/TuningContext.cpp index e055cb4..bd9ca4a 100644 --- a/src/visual/TuningContext.cpp +++ b/src/visual/TuningContext.cpp @@ -112,7 +112,7 @@ void TuningContext::DrawTuner(long long freq, int count, float displayPos, float } -void TuningContext::DrawTunerDigitBox(int index, int count, float displayPos, float displayWidth, RGB c) { +void TuningContext::DrawTunerDigitBox(int index, int count, float displayPos, float displayWidth, RGB3f c) { GLint vp[4]; glGetIntegerv( GL_VIEWPORT, vp); @@ -152,7 +152,7 @@ int TuningContext::GetTunerDigitIndex(float mPos, int count, float displayPos, f return count - index; } -void TuningContext::DrawTunerBarIndexed(int start, int end, int count, float displayPos, float displayWidth, RGB color, float alpha, bool top, +void TuningContext::DrawTunerBarIndexed(int start, int end, int count, float displayPos, float displayWidth, RGB3f color, float alpha, bool top, bool bottom) { float ofs = (displayWidth / (float) count); float p2 = displayPos + ofs * (float) (count - start + 1); diff --git a/src/visual/TuningContext.h b/src/visual/TuningContext.h index ee88a37..61dc9f3 100644 --- a/src/visual/TuningContext.h +++ b/src/visual/TuningContext.h @@ -14,9 +14,9 @@ public: void DrawBegin(); void Draw(float r, float g, float b, float a, float p1, float p2); void DrawTuner(long long freq, int count, float displayPos, float displayWidth); - void DrawTunerDigitBox(int index, int count, float displayPos, float displayWidth, RGB c); + void DrawTunerDigitBox(int index, int count, float displayPos, float displayWidth, RGB3f c); int GetTunerDigitIndex(float mPos, int count, float displayPos, float displayWidth); - void DrawTunerBarIndexed(int start, int end, int count, float displayPos, float displayWidth, RGB color, float alpha, bool top, bool bottom); + void DrawTunerBarIndexed(int start, int end, int count, float displayPos, float displayWidth, RGB3f color, float alpha, bool top, bool bottom); void DrawDemodFreqBw(long long freq, unsigned int bw, long long center); void DrawEnd(); From 61add8ae09d13d3e0115fc7291e8816d99fdb436 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 31 Jul 2015 21:03:17 -0400 Subject: [PATCH 32/53] VisualProcessor now a template base, more tweaking needed --- src/process/ScopeVisualProcessor.h | 49 ++++++++++++++------- src/process/SpectrumVisualProcessor.h | 9 +++- src/process/VisualProcessor.h | 61 +++++++++++++++++++------- src/process/WaterfallVisualProcessor.h | 8 +++- src/util/ThreadQueue.h | 9 ++++ 5 files changed, 99 insertions(+), 37 deletions(-) diff --git a/src/process/ScopeVisualProcessor.h b/src/process/ScopeVisualProcessor.h index e5dd56c..e8d411b 100644 --- a/src/process/ScopeVisualProcessor.h +++ b/src/process/ScopeVisualProcessor.h @@ -3,35 +3,54 @@ #include "VisualProcessor.h" #include "AudioThread.h" -class ScopeVisualProcessor : public VisualProcessor { -protected: - std::vector waveform_points; +class ScopeRenderData: public ReferenceCounter { +public: + std::vector waveform_points; + int channels; +}; +typedef ThreadQueue ScopeRenderDataQueue; + +class ScopeVisualProcessor : public VisualProcessor { +protected: virtual void process() { + if (isOutputEmpty()) { + return; + } if (!input->empty()) { - ReferenceCounter *ati_ref; - input->pop(ati_ref); - - AudioThreadInput *ati = (AudioThreadInput *)ati_ref; - if (!ati) { + AudioThreadInput *audioInputData; + input->pop(audioInputData); + + if (!audioInputData) { return; } - int iMax = ati->data.size(); + int iMax = audioInputData->data.size(); if (!iMax) { - ati->decRefCount(); + audioInputData->decRefCount(); return; } - if (waveform_points.size() != iMax * 2) { - waveform_points.resize(iMax * 2); + + ScopeRenderData *renderData = outputBuffers.getBuffer(); + renderData->channels = audioInputData->channels; + + if (renderData->waveform_points.size() != iMax * 2) { + renderData->waveform_points.resize(iMax * 2); } for (int i = 0; i < iMax; i++) { - waveform_points[i * 2 + 1] = ati->data[i] * 0.5f; - waveform_points[i * 2] = ((double) i / (double) iMax); + renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] * 0.5f; + renderData->waveform_points[i * 2] = ((double) i / (double) iMax); } + distribute(renderData); // ati->channels } + } + + ReBuffer outputBuffers; +}; + + /* if (!wxGetApp().getAudioVisualQueue()->empty()) { AudioThreadInput *demodAudioData; @@ -59,5 +78,3 @@ protected: } } */ - } -}; \ No newline at end of file diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h index 20fa627..76d0789 100644 --- a/src/process/SpectrumVisualProcessor.h +++ b/src/process/SpectrumVisualProcessor.h @@ -1,8 +1,13 @@ #pragma once #include "VisualProcessor.h" +#include "SpectrumCanvas.h" -class SpectrumVisualProcessor : public VisualProcessor { +class SpectrumVisualData : public ReferenceCounter { + +}; + +class SpectrumVisualProcessor : public VisualProcessor { protected: virtual void process() { /* @@ -82,4 +87,4 @@ protected: } */ } -}; \ No newline at end of file +}; diff --git a/src/process/VisualProcessor.h b/src/process/VisualProcessor.h index 5ca4b7d..f6c876e 100644 --- a/src/process/VisualProcessor.h +++ b/src/process/VisualProcessor.h @@ -5,27 +5,30 @@ #include "IOThread.h" #include -typedef ThreadQueue VisualDataQueue; - +template class VisualProcessor { public: - void setInput(VisualDataQueue *vis_in) { + virtual ~VisualProcessor() { + + } + + void setInput(InputQueueType *vis_in) { busy_update.lock(); input = vis_in; busy_update.unlock(); } - void attachOutput(VisualDataQueue *vis_out) { + void attachOutput(OutputQueueType *vis_out) { // attach an output queue busy_update.lock(); outputs.push_back(vis_out); busy_update.unlock(); } - void removeOutput(VisualDataQueue *vis_out) { + void removeOutput(OutputQueueType *vis_out) { // remove an output queue busy_update.lock(); - std::vector::iterator i = std::find(outputs.begin(), outputs.end(), vis_out); + typename std::vector::iterator i = std::find(outputs.begin(), outputs.end(), vis_out); if (i != outputs.end()) { outputs.erase(i); } @@ -46,29 +49,53 @@ protected: // distribute(output); } - void distribute(ReferenceCounter *output) { + void distribute(OutputDataType *output) { // distribute outputs output->setRefCount(outputs.size()); - std::vector::iterator outputs_i; for (outputs_i = outputs.begin(); outputs_i != outputs.begin(); outputs_i++) { - (*outputs_i)->push(output); + if ((*outputs_i)->full()) { + output->decRefCount(); + } else { + (*outputs_i)->push(output); + } } } - VisualDataQueue * input; - std::vector outputs; + bool isOutputEmpty() { + for (outputs_i = outputs.begin(); outputs_i != outputs.begin(); outputs_i++) { + if (!(*outputs_i)->empty()) { + return false; + } + } + return true; + } + + bool isAnyOutputEmpty() { + for (outputs_i = outputs.begin(); outputs_i != outputs.begin(); outputs_i++) { + if ((*outputs_i)->empty()) { + return true; + } + } + return false; + } + + InputQueueType *input; + std::vector outputs; + typename std::vector::iterator outputs_i; std::mutex busy_update; }; -class VisualDataDistributor : public VisualProcessor { +template +class VisualDataDistributor : public VisualProcessor { protected: - virtual void process() { - while (!input->empty()) { - ReferenceCounter *inp; - input->pop(inp); + void process() { + + while (!VisualProcessor::input->empty()) { + ReferenceCounter *inp; + VisualProcessor::input->pop(inp); if (inp) { - distribute(inp); + VisualProcessor::distribute(inp); } } } diff --git a/src/process/WaterfallVisualProcessor.h b/src/process/WaterfallVisualProcessor.h index b33c37e..2fabeba 100644 --- a/src/process/WaterfallVisualProcessor.h +++ b/src/process/WaterfallVisualProcessor.h @@ -1,9 +1,13 @@ #pragma once #include "VisualProcessor.h" +#include "WaterfallCanvas.h" +class WaterfallVisualData : public ReferenceCounter { -class WaterfallVisualProcessor : public VisualProcessor { +}; + +class WaterfallVisualProcessor : public VisualProcessor { protected: virtual void process() { /* @@ -278,4 +282,4 @@ protected: } */ } -}; \ No newline at end of file +}; diff --git a/src/util/ThreadQueue.h b/src/util/ThreadQueue.h index 6ef108a..67247a6 100644 --- a/src/util/ThreadQueue.h +++ b/src/util/ThreadQueue.h @@ -211,6 +211,15 @@ public: return m_queue.empty(); } + /** + * Check if the queue is empty. + * \return true if queue is empty. + */ + bool full() const { + std::lock_guard < std::mutex > lock(m_mutex); + return m_queue.size() >= m_max_num_items; + } + /** * Remove any items in the queue. */ From 6f3d9a6c82678d7052010b81fbcf223144062244 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 31 Jul 2015 21:28:14 -0400 Subject: [PATCH 33/53] visual process template tweaks, full() logic error fix --- src/process/ScopeVisualProcessor.h | 2 +- src/process/VisualProcessor.h | 26 +++++++++++++------------- src/util/ThreadQueue.h | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/process/ScopeVisualProcessor.h b/src/process/ScopeVisualProcessor.h index e8d411b..44262ab 100644 --- a/src/process/ScopeVisualProcessor.h +++ b/src/process/ScopeVisualProcessor.h @@ -11,7 +11,7 @@ public: typedef ThreadQueue ScopeRenderDataQueue; -class ScopeVisualProcessor : public VisualProcessor { +class ScopeVisualProcessor : public VisualProcessor { protected: virtual void process() { if (isOutputEmpty()) { diff --git a/src/process/VisualProcessor.h b/src/process/VisualProcessor.h index f6c876e..f84c32d 100644 --- a/src/process/VisualProcessor.h +++ b/src/process/VisualProcessor.h @@ -5,30 +5,30 @@ #include "IOThread.h" #include -template +template class VisualProcessor { public: virtual ~VisualProcessor() { } - void setInput(InputQueueType *vis_in) { + void setInput(ThreadQueue *vis_in) { busy_update.lock(); input = vis_in; busy_update.unlock(); } - void attachOutput(OutputQueueType *vis_out) { + void attachOutput(ThreadQueue *vis_out) { // attach an output queue busy_update.lock(); outputs.push_back(vis_out); busy_update.unlock(); } - void removeOutput(OutputQueueType *vis_out) { + void removeOutput(ThreadQueue *vis_out) { // remove an output queue busy_update.lock(); - typename std::vector::iterator i = std::find(outputs.begin(), outputs.end(), vis_out); + typename std::vector *>::iterator i = std::find(outputs.begin(), outputs.end(), vis_out); if (i != outputs.end()) { outputs.erase(i); } @@ -79,23 +79,23 @@ protected: return false; } - InputQueueType *input; - std::vector outputs; - typename std::vector::iterator outputs_i; + ThreadQueue *input; + std::vector *> outputs; + typename std::vector *>::iterator outputs_i; std::mutex busy_update; }; -template -class VisualDataDistributor : public VisualProcessor { +template +class VisualDataDistributor : public VisualProcessor { protected: void process() { - while (!VisualProcessor::input->empty()) { + while (!VisualProcessor::input->empty()) { ReferenceCounter *inp; - VisualProcessor::input->pop(inp); + VisualProcessor::input->pop(inp); if (inp) { - VisualProcessor::distribute(inp); + VisualProcessor::distribute(inp); } } } diff --git a/src/util/ThreadQueue.h b/src/util/ThreadQueue.h index 67247a6..8ba5e0a 100644 --- a/src/util/ThreadQueue.h +++ b/src/util/ThreadQueue.h @@ -212,12 +212,12 @@ public: } /** - * Check if the queue is empty. - * \return true if queue is empty. + * Check if the queue is full. + * \return true if queue is full. */ bool full() const { std::lock_guard < std::mutex > lock(m_mutex); - return m_queue.size() >= m_max_num_items; + return (m_max_num_items != 0) && (m_queue.size() >= m_max_num_items); } /** From 8dfd94df8dd893dc70a4948f3955399df904a0c3 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 31 Jul 2015 21:33:31 -0400 Subject: [PATCH 34/53] ScopeVisualProcessor cleanup --- src/process/ScopeVisualProcessor.cpp | 35 +++++++++++- src/process/ScopeVisualProcessor.h | 80 ---------------------------- 2 files changed, 34 insertions(+), 81 deletions(-) delete mode 100644 src/process/ScopeVisualProcessor.h diff --git a/src/process/ScopeVisualProcessor.cpp b/src/process/ScopeVisualProcessor.cpp index 89af21c..c3ffbc9 100644 --- a/src/process/ScopeVisualProcessor.cpp +++ b/src/process/ScopeVisualProcessor.cpp @@ -1 +1,34 @@ -#include "ScopeVisualProcessor.h" \ No newline at end of file +#include "ScopeVisualProcessor.h" + +void ScopeVisualProcessor::process() { + if (isOutputEmpty()) { + return; + } + if (!input->empty()) { + AudioThreadInput *audioInputData; + input->pop(audioInputData); + + if (!audioInputData) { + return; + } + int iMax = audioInputData->data.size(); + if (!iMax) { + audioInputData->decRefCount(); + return; + } + + ScopeRenderData *renderData = outputBuffers.getBuffer(); + renderData->channels = audioInputData->channels; + + if (renderData->waveform_points.size() != iMax * 2) { + renderData->waveform_points.resize(iMax * 2); + } + + for (int i = 0; i < iMax; i++) { + renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] * 0.5f; + renderData->waveform_points[i * 2] = ((double) i / (double) iMax); + } + + distribute(renderData); + } +} diff --git a/src/process/ScopeVisualProcessor.h b/src/process/ScopeVisualProcessor.h deleted file mode 100644 index 44262ab..0000000 --- a/src/process/ScopeVisualProcessor.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include "VisualProcessor.h" -#include "AudioThread.h" - -class ScopeRenderData: public ReferenceCounter { -public: - std::vector waveform_points; - int channels; -}; - -typedef ThreadQueue ScopeRenderDataQueue; - -class ScopeVisualProcessor : public VisualProcessor { -protected: - virtual void process() { - if (isOutputEmpty()) { - return; - } - if (!input->empty()) { - AudioThreadInput *audioInputData; - input->pop(audioInputData); - - if (!audioInputData) { - return; - } - int iMax = audioInputData->data.size(); - if (!iMax) { - audioInputData->decRefCount(); - return; - } - - ScopeRenderData *renderData = outputBuffers.getBuffer(); - renderData->channels = audioInputData->channels; - - if (renderData->waveform_points.size() != iMax * 2) { - renderData->waveform_points.resize(iMax * 2); - } - - for (int i = 0; i < iMax; i++) { - renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] * 0.5f; - renderData->waveform_points[i * 2] = ((double) i / (double) iMax); - } - - distribute(renderData); - // ati->channels - } - } - - ReBuffer outputBuffers; -}; - - -/* - if (!wxGetApp().getAudioVisualQueue()->empty()) { - AudioThreadInput *demodAudioData; - wxGetApp().getAudioVisualQueue()->pop(demodAudioData); - - int iMax = demodAudioData?demodAudioData->data.size():0; - - if (demodAudioData && iMax) { - if (waveform_points.size() != iMax * 2) { - waveform_points.resize(iMax * 2); - } - - demodAudioData->busy_update.lock(); - - for (int i = 0; i < iMax; i++) { - waveform_points[i * 2 + 1] = demodAudioData->data[i] * 0.5f; - waveform_points[i * 2] = ((double) i / (double) iMax); - } - - demodAudioData->busy_update.unlock(); - - setStereo(demodAudioData->channels == 2); - } else { - std::cout << "Incoming Demodulator data empty?" << std::endl; - } - } -*/ From e616ae1ebb1b25c33d2d67e7e097b9bfdfabcc48 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 31 Jul 2015 21:44:25 -0400 Subject: [PATCH 35/53] ScopeVisualProcessor header.. --- src/process/ScopeVisualProcessor.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/process/ScopeVisualProcessor.h diff --git a/src/process/ScopeVisualProcessor.h b/src/process/ScopeVisualProcessor.h new file mode 100644 index 0000000..08ce3bb --- /dev/null +++ b/src/process/ScopeVisualProcessor.h @@ -0,0 +1,18 @@ +#pragma once + +#include "VisualProcessor.h" +#include "AudioThread.h" + +class ScopeRenderData: public ReferenceCounter { +public: + std::vector waveform_points; + int channels; +}; + +typedef ThreadQueue ScopeRenderDataQueue; + +class ScopeVisualProcessor : public VisualProcessor { +protected: + void process(); + ReBuffer outputBuffers; +}; From 77f172027e4a7996103f940cbbe721b5388ebbef Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 31 Jul 2015 21:47:21 -0400 Subject: [PATCH 36/53] Spectrum, Waterfall processor prep --- src/process/SpectrumVisualProcessor.cpp | 81 ++++++- src/process/SpectrumVisualProcessor.h | 90 ------- src/process/WaterfallVisualProcessor.cpp | 276 +++++++++++++++++++++- src/process/WaterfallVisualProcessor.h | 285 ----------------------- 4 files changed, 355 insertions(+), 377 deletions(-) delete mode 100644 src/process/SpectrumVisualProcessor.h delete mode 100644 src/process/WaterfallVisualProcessor.h diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index dd69858..dcd99b7 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -1 +1,80 @@ -#include "SpectrumVisualProcessor.h" \ No newline at end of file +#include "SpectrumVisualProcessor.h" + +void SpectrumVisualProcessor::process() { + /* + std::vector *data = &input->data; + if (data && data->size()) { + if (fft_size != data->size()) { + setup(data->size()); + } + if (spectrum_points.size() < fft_size * 2) { + if (spectrum_points.capacity() < fft_size * 2) { + spectrum_points.reserve(fft_size * 2); + } + spectrum_points.resize(fft_size * 2); + } + + for (int i = 0; i < fft_size; i++) { + in[i][0] = (*data)[i].real; + in[i][1] = (*data)[i].imag; + } + + fftwf_execute(plan); + + float fft_ceil = 0, fft_floor = 1; + + if (fft_result.size() != fft_size) { + if (fft_result.capacity() < fft_size) { + fft_result.reserve(fft_size); + fft_result_ma.reserve(fft_size); + fft_result_maa.reserve(fft_size); + } + fft_result.resize(fft_size); + fft_result_ma.resize(fft_size); + fft_result_maa.resize(fft_size); + } + + int n; + for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { + float a = out[i][0]; + float b = out[i][1]; + float c = sqrt(a * a + b * b); + + float x = out[fft_size / 2 + i][0]; + float y = out[fft_size / 2 + i][1]; + float z = sqrt(x * x + y * y); + + fft_result[i] = (z); + fft_result[fft_size / 2 + i] = (c); + } + + for (int i = 0, iMax = fft_size; i < iMax; i++) { + fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; + fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; + + if (fft_result_maa[i] > fft_ceil) { + fft_ceil = fft_result_maa[i]; + } + if (fft_result_maa[i] < fft_floor) { + fft_floor = fft_result_maa[i]; + } + } + + fft_ceil += 1; + fft_floor -= 1; + + fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.01; + fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.01; + + fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.01; + fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.01; + + for (int i = 0, iMax = fft_size; i < iMax; i++) { + float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); + spectrum_points[i * 2] = ((float) i / (float) iMax); + spectrum_points[i * 2 + 1] = v; + } + + } + */ +} \ No newline at end of file diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h deleted file mode 100644 index 76d0789..0000000 --- a/src/process/SpectrumVisualProcessor.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -#include "VisualProcessor.h" -#include "SpectrumCanvas.h" - -class SpectrumVisualData : public ReferenceCounter { - -}; - -class SpectrumVisualProcessor : public VisualProcessor { -protected: - virtual void process() { - /* - std::vector *data = &input->data; - if (data && data->size()) { - if (fft_size != data->size()) { - setup(data->size()); - } - if (spectrum_points.size() < fft_size * 2) { - if (spectrum_points.capacity() < fft_size * 2) { - spectrum_points.reserve(fft_size * 2); - } - spectrum_points.resize(fft_size * 2); - } - - for (int i = 0; i < fft_size; i++) { - in[i][0] = (*data)[i].real; - in[i][1] = (*data)[i].imag; - } - - fftwf_execute(plan); - - float fft_ceil = 0, fft_floor = 1; - - if (fft_result.size() != fft_size) { - if (fft_result.capacity() < fft_size) { - fft_result.reserve(fft_size); - fft_result_ma.reserve(fft_size); - fft_result_maa.reserve(fft_size); - } - fft_result.resize(fft_size); - fft_result_ma.resize(fft_size); - fft_result_maa.resize(fft_size); - } - - int n; - for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { - float a = out[i][0]; - float b = out[i][1]; - float c = sqrt(a * a + b * b); - - float x = out[fft_size / 2 + i][0]; - float y = out[fft_size / 2 + i][1]; - float z = sqrt(x * x + y * y); - - fft_result[i] = (z); - fft_result[fft_size / 2 + i] = (c); - } - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; - - if (fft_result_maa[i] > fft_ceil) { - fft_ceil = fft_result_maa[i]; - } - if (fft_result_maa[i] < fft_floor) { - fft_floor = fft_result_maa[i]; - } - } - - fft_ceil += 1; - fft_floor -= 1; - - fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.01; - fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.01; - - fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.01; - fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.01; - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); - spectrum_points[i * 2] = ((float) i / (float) iMax); - spectrum_points[i * 2 + 1] = v; - } - - } -*/ - } -}; diff --git a/src/process/WaterfallVisualProcessor.cpp b/src/process/WaterfallVisualProcessor.cpp index 2b8a46e..153e489 100644 --- a/src/process/WaterfallVisualProcessor.cpp +++ b/src/process/WaterfallVisualProcessor.cpp @@ -1 +1,275 @@ -#include "WaterfallVisualProcessor.h" \ No newline at end of file +#include "WaterfallVisualProcessor.h" + +void WaterfallVisualProcessor::process() { + /* + long double currentZoom = zoom; + + if (mouseZoom != 1) { + currentZoom = mouseZoom; + mouseZoom = mouseZoom + (1.0 - mouseZoom) * 0.2; + if (fabs(mouseZoom-1.0)<0.01) { + mouseZoom = 1; + } + } + + long long bw; + if (currentZoom != 1) { + long long freq = wxGetApp().getFrequency(); + + if (currentZoom < 1) { + centerFreq = getCenterFrequency(); + bw = getBandwidth(); + bw = (long long) ceil((long double) bw * currentZoom); + if (bw < 100000) { + bw = 100000; + } + if (mouseTracker.mouseInView()) { + long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); + setBandwidth(bw); + long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); + centerFreq += mfreqA - mfreqB; + } + + setView(centerFreq, bw); + if (spectrumCanvas) { + spectrumCanvas->setView(centerFreq, bw); + } + } else { + if (isView) { + bw = getBandwidth(); + bw = (long long) ceil((long double) bw * currentZoom); + if (bw >= wxGetApp().getSampleRate()) { + disableView(); + if (spectrumCanvas) { + spectrumCanvas->disableView(); + } + } else { + if (mouseTracker.mouseInView()) { + long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); + setBandwidth(bw); + long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); + centerFreq += mfreqA - mfreqB; + } + + setView(getCenterFrequency(), bw); + if (spectrumCanvas) { + spectrumCanvas->setView(centerFreq, bw); + } + } + } + } + if (centerFreq < freq && (centerFreq - bandwidth / 2) < (freq - wxGetApp().getSampleRate() / 2)) { + centerFreq = (freq - wxGetApp().getSampleRate() / 2) + bandwidth / 2; + } + if (centerFreq > freq && (centerFreq + bandwidth / 2) > (freq + wxGetApp().getSampleRate() / 2)) { + centerFreq = (freq + wxGetApp().getSampleRate() / 2) - bandwidth / 2; + } + } + + std::vector *data = &input->data; + + if (data && data->size()) { + // if (fft_size != data->size() && !isView) { + // Setup(data->size(), waterfall_lines); + // } + + // if (last_bandwidth != bandwidth && !isView) { + // Setup(bandwidth, waterfall_lines); + // } + + if (spectrum_points.size() < fft_size * 2) { + spectrum_points.resize(fft_size * 2); + } + + unsigned int num_written; + + if (isView) { + if (!input->frequency || !input->sampleRate) { + return; + } + + resamplerRatio = (double) (bandwidth) / (double) input->sampleRate; + + int desired_input_size = fft_size / resamplerRatio; + + if (input->data.size() < desired_input_size) { + // std::cout << "fft underflow, desired: " << desired_input_size << " actual:" << input->data.size() << std::endl; + desired_input_size = input->data.size(); + } + + if (centerFreq != input->frequency) { + if ((centerFreq - input->frequency) != shiftFrequency || lastInputBandwidth != input->sampleRate) { + if (abs(input->frequency - centerFreq) < (wxGetApp().getSampleRate() / 2)) { + shiftFrequency = centerFreq - input->frequency; + nco_crcf_reset(freqShifter); + nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) input->sampleRate))); + } + } + + if (shiftBuffer.size() != desired_input_size) { + if (shiftBuffer.capacity() < desired_input_size) { + shiftBuffer.reserve(desired_input_size); + } + shiftBuffer.resize(desired_input_size); + } + + if (shiftFrequency < 0) { + nco_crcf_mix_block_up(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); + } else { + nco_crcf_mix_block_down(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); + } + } else { + shiftBuffer.assign(input->data.begin(), input->data.end()); + } + + if (!resampler || bandwidth != lastBandwidth || lastInputBandwidth != input->sampleRate) { + float As = 60.0f; + + if (resampler) { + msresamp_crcf_destroy(resampler); + } + resampler = msresamp_crcf_create(resamplerRatio, As); + + lastBandwidth = bandwidth; + lastInputBandwidth = input->sampleRate; + } + + + int out_size = ceil((double) (desired_input_size) * resamplerRatio) + 512; + + if (resampleBuffer.size() != out_size) { + if (resampleBuffer.capacity() < out_size) { + resampleBuffer.reserve(out_size); + } + resampleBuffer.resize(out_size); + } + + + msresamp_crcf_execute(resampler, &shiftBuffer[0], desired_input_size, &resampleBuffer[0], &num_written); + + resampleBuffer.resize(fft_size); + + if (num_written < fft_size) { + for (int i = 0; i < num_written; i++) { + fft_in_data[i][0] = resampleBuffer[i].real; + fft_in_data[i][1] = resampleBuffer[i].imag; + } + for (int i = num_written; i < fft_size; i++) { + fft_in_data[i][0] = 0; + fft_in_data[i][1] = 0; + } + } else { + for (int i = 0; i < fft_size; i++) { + fft_in_data[i][0] = resampleBuffer[i].real; + fft_in_data[i][1] = resampleBuffer[i].imag; + } + } + } else { + num_written = data->size(); + if (data->size() < fft_size) { + for (int i = 0, iMax = data->size(); i < iMax; i++) { + fft_in_data[i][0] = (*data)[i].real; + fft_in_data[i][1] = (*data)[i].imag; + } + for (int i = data->size(); i < fft_size; i++) { + fft_in_data[i][0] = 0; + fft_in_data[i][1] = 0; + } + } else { + for (int i = 0; i < fft_size; i++) { + fft_in_data[i][0] = (*data)[i].real; + fft_in_data[i][1] = (*data)[i].imag; + } + } + } + + bool execute = false; + + if (num_written >= fft_size) { + execute = true; + memcpy(in, fft_in_data, fft_size * sizeof(fftwf_complex)); + memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); + + } else { + if (last_data_size + num_written < fft_size) { // priming + unsigned int num_copy = fft_size - last_data_size; + if (num_written > num_copy) { + num_copy = num_written; + } + memcpy(fft_last_data, fft_in_data, num_copy * sizeof(fftwf_complex)); + last_data_size += num_copy; + } else { + unsigned int num_last = (fft_size - num_written); + memcpy(in, fft_last_data + (last_data_size - num_last), num_last * sizeof(fftwf_complex)); + memcpy(in + num_last, fft_in_data, num_written * sizeof(fftwf_complex)); + memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); + execute = true; + } + } + + if (execute) { + fftwf_execute(plan); + + float fft_ceil = 0, fft_floor = 1; + + if (fft_result.size() < fft_size) { + fft_result.resize(fft_size); + fft_result_ma.resize(fft_size); + fft_result_maa.resize(fft_size); + } + + int n; + for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { + float a = out[i][0]; + float b = out[i][1]; + float c = sqrt(a * a + b * b); + + float x = out[fft_size / 2 + i][0]; + float y = out[fft_size / 2 + i][1]; + float z = sqrt(x * x + y * y); + + fft_result[i] = (z); + fft_result[fft_size / 2 + i] = (c); + } + + for (int i = 0, iMax = fft_size; i < iMax; i++) { + if (isView) { + fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; + fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; + } else { + fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; + fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; + } + + if (fft_result_maa[i] > fft_ceil) { + fft_ceil = fft_result_maa[i]; + } + if (fft_result_maa[i] < fft_floor) { + fft_floor = fft_result_maa[i]; + } + } + + fft_ceil += 0.25; + fft_floor -= 1; + + fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05; + fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.05; + + fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.05; + fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05; + + for (int i = 0, iMax = fft_size; i < iMax; i++) { + float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); + spectrum_points[i * 2] = ((float) i / (float) iMax); + spectrum_points[i * 2 + 1] = v; + } + + if (spectrumCanvas) { + spectrumCanvas->spectrum_points.assign(spectrum_points.begin(), spectrum_points.end()); + spectrumCanvas->getSpectrumContext()->setCeilValue(fft_ceil_maa); + spectrumCanvas->getSpectrumContext()->setFloorValue(fft_floor_maa); + } + } + } + */ +} \ No newline at end of file diff --git a/src/process/WaterfallVisualProcessor.h b/src/process/WaterfallVisualProcessor.h deleted file mode 100644 index 2fabeba..0000000 --- a/src/process/WaterfallVisualProcessor.h +++ /dev/null @@ -1,285 +0,0 @@ -#pragma once - -#include "VisualProcessor.h" -#include "WaterfallCanvas.h" - -class WaterfallVisualData : public ReferenceCounter { - -}; - -class WaterfallVisualProcessor : public VisualProcessor { -protected: - virtual void process() { -/* - long double currentZoom = zoom; - - if (mouseZoom != 1) { - currentZoom = mouseZoom; - mouseZoom = mouseZoom + (1.0 - mouseZoom) * 0.2; - if (fabs(mouseZoom-1.0)<0.01) { - mouseZoom = 1; - } - } - - long long bw; - if (currentZoom != 1) { - long long freq = wxGetApp().getFrequency(); - - if (currentZoom < 1) { - centerFreq = getCenterFrequency(); - bw = getBandwidth(); - bw = (long long) ceil((long double) bw * currentZoom); - if (bw < 100000) { - bw = 100000; - } - if (mouseTracker.mouseInView()) { - long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); - setBandwidth(bw); - long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); - centerFreq += mfreqA - mfreqB; - } - - setView(centerFreq, bw); - if (spectrumCanvas) { - spectrumCanvas->setView(centerFreq, bw); - } - } else { - if (isView) { - bw = getBandwidth(); - bw = (long long) ceil((long double) bw * currentZoom); - if (bw >= wxGetApp().getSampleRate()) { - disableView(); - if (spectrumCanvas) { - spectrumCanvas->disableView(); - } - } else { - if (mouseTracker.mouseInView()) { - long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); - setBandwidth(bw); - long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); - centerFreq += mfreqA - mfreqB; - } - - setView(getCenterFrequency(), bw); - if (spectrumCanvas) { - spectrumCanvas->setView(centerFreq, bw); - } - } - } - } - if (centerFreq < freq && (centerFreq - bandwidth / 2) < (freq - wxGetApp().getSampleRate() / 2)) { - centerFreq = (freq - wxGetApp().getSampleRate() / 2) + bandwidth / 2; - } - if (centerFreq > freq && (centerFreq + bandwidth / 2) > (freq + wxGetApp().getSampleRate() / 2)) { - centerFreq = (freq + wxGetApp().getSampleRate() / 2) - bandwidth / 2; - } - } - - std::vector *data = &input->data; - - if (data && data->size()) { - // if (fft_size != data->size() && !isView) { - // Setup(data->size(), waterfall_lines); - // } - - // if (last_bandwidth != bandwidth && !isView) { - // Setup(bandwidth, waterfall_lines); - // } - - if (spectrum_points.size() < fft_size * 2) { - spectrum_points.resize(fft_size * 2); - } - - unsigned int num_written; - - if (isView) { - if (!input->frequency || !input->sampleRate) { - return; - } - - resamplerRatio = (double) (bandwidth) / (double) input->sampleRate; - - int desired_input_size = fft_size / resamplerRatio; - - if (input->data.size() < desired_input_size) { - // std::cout << "fft underflow, desired: " << desired_input_size << " actual:" << input->data.size() << std::endl; - desired_input_size = input->data.size(); - } - - if (centerFreq != input->frequency) { - if ((centerFreq - input->frequency) != shiftFrequency || lastInputBandwidth != input->sampleRate) { - if (abs(input->frequency - centerFreq) < (wxGetApp().getSampleRate() / 2)) { - shiftFrequency = centerFreq - input->frequency; - nco_crcf_reset(freqShifter); - nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) input->sampleRate))); - } - } - - if (shiftBuffer.size() != desired_input_size) { - if (shiftBuffer.capacity() < desired_input_size) { - shiftBuffer.reserve(desired_input_size); - } - shiftBuffer.resize(desired_input_size); - } - - if (shiftFrequency < 0) { - nco_crcf_mix_block_up(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); - } else { - nco_crcf_mix_block_down(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); - } - } else { - shiftBuffer.assign(input->data.begin(), input->data.end()); - } - - if (!resampler || bandwidth != lastBandwidth || lastInputBandwidth != input->sampleRate) { - float As = 60.0f; - - if (resampler) { - msresamp_crcf_destroy(resampler); - } - resampler = msresamp_crcf_create(resamplerRatio, As); - - lastBandwidth = bandwidth; - lastInputBandwidth = input->sampleRate; - } - - - int out_size = ceil((double) (desired_input_size) * resamplerRatio) + 512; - - if (resampleBuffer.size() != out_size) { - if (resampleBuffer.capacity() < out_size) { - resampleBuffer.reserve(out_size); - } - resampleBuffer.resize(out_size); - } - - - msresamp_crcf_execute(resampler, &shiftBuffer[0], desired_input_size, &resampleBuffer[0], &num_written); - - resampleBuffer.resize(fft_size); - - if (num_written < fft_size) { - for (int i = 0; i < num_written; i++) { - fft_in_data[i][0] = resampleBuffer[i].real; - fft_in_data[i][1] = resampleBuffer[i].imag; - } - for (int i = num_written; i < fft_size; i++) { - fft_in_data[i][0] = 0; - fft_in_data[i][1] = 0; - } - } else { - for (int i = 0; i < fft_size; i++) { - fft_in_data[i][0] = resampleBuffer[i].real; - fft_in_data[i][1] = resampleBuffer[i].imag; - } - } - } else { - num_written = data->size(); - if (data->size() < fft_size) { - for (int i = 0, iMax = data->size(); i < iMax; i++) { - fft_in_data[i][0] = (*data)[i].real; - fft_in_data[i][1] = (*data)[i].imag; - } - for (int i = data->size(); i < fft_size; i++) { - fft_in_data[i][0] = 0; - fft_in_data[i][1] = 0; - } - } else { - for (int i = 0; i < fft_size; i++) { - fft_in_data[i][0] = (*data)[i].real; - fft_in_data[i][1] = (*data)[i].imag; - } - } - } - - bool execute = false; - - if (num_written >= fft_size) { - execute = true; - memcpy(in, fft_in_data, fft_size * sizeof(fftwf_complex)); - memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); - - } else { - if (last_data_size + num_written < fft_size) { // priming - unsigned int num_copy = fft_size - last_data_size; - if (num_written > num_copy) { - num_copy = num_written; - } - memcpy(fft_last_data, fft_in_data, num_copy * sizeof(fftwf_complex)); - last_data_size += num_copy; - } else { - unsigned int num_last = (fft_size - num_written); - memcpy(in, fft_last_data + (last_data_size - num_last), num_last * sizeof(fftwf_complex)); - memcpy(in + num_last, fft_in_data, num_written * sizeof(fftwf_complex)); - memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); - execute = true; - } - } - - if (execute) { - fftwf_execute(plan); - - float fft_ceil = 0, fft_floor = 1; - - if (fft_result.size() < fft_size) { - fft_result.resize(fft_size); - fft_result_ma.resize(fft_size); - fft_result_maa.resize(fft_size); - } - - int n; - for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { - float a = out[i][0]; - float b = out[i][1]; - float c = sqrt(a * a + b * b); - - float x = out[fft_size / 2 + i][0]; - float y = out[fft_size / 2 + i][1]; - float z = sqrt(x * x + y * y); - - fft_result[i] = (z); - fft_result[fft_size / 2 + i] = (c); - } - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - if (isView) { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; - } else { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; - } - - if (fft_result_maa[i] > fft_ceil) { - fft_ceil = fft_result_maa[i]; - } - if (fft_result_maa[i] < fft_floor) { - fft_floor = fft_result_maa[i]; - } - } - - fft_ceil += 0.25; - fft_floor -= 1; - - fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05; - fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.05; - - fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.05; - fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05; - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); - spectrum_points[i * 2] = ((float) i / (float) iMax); - spectrum_points[i * 2 + 1] = v; - } - - if (spectrumCanvas) { - spectrumCanvas->spectrum_points.assign(spectrum_points.begin(), spectrum_points.end()); - spectrumCanvas->getSpectrumContext()->setCeilValue(fft_ceil_maa); - spectrumCanvas->getSpectrumContext()->setFloorValue(fft_floor_maa); - } - } - } -*/ - } -}; From c448070319e08156631ab9375179fd1e699cf22a Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 31 Jul 2015 21:47:44 -0400 Subject: [PATCH 37/53] Spectrum, Waterfall new headers --- src/process/SpectrumVisualProcessor.h | 13 +++++++++++++ src/process/WaterfallVisualProcessor.h | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/process/SpectrumVisualProcessor.h create mode 100644 src/process/WaterfallVisualProcessor.h diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h new file mode 100644 index 0000000..3fcc0ff --- /dev/null +++ b/src/process/SpectrumVisualProcessor.h @@ -0,0 +1,13 @@ +#pragma once + +#include "VisualProcessor.h" +#include "SpectrumCanvas.h" + +class SpectrumVisualData : public ReferenceCounter { + +}; + +class SpectrumVisualProcessor : public VisualProcessor { +protected: + void process(); +}; diff --git a/src/process/WaterfallVisualProcessor.h b/src/process/WaterfallVisualProcessor.h new file mode 100644 index 0000000..76cca22 --- /dev/null +++ b/src/process/WaterfallVisualProcessor.h @@ -0,0 +1,15 @@ +#pragma once + +#include "VisualProcessor.h" +#include "WaterfallCanvas.h" + +class WaterfallVisualData : public ReferenceCounter { + +}; + +class WaterfallVisualProcessor : public VisualProcessor { +protected: + void process() { + + } +}; From cd0adb0339506028b2bd8fce3b7cdbd0d4f05b6b Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 31 Jul 2015 21:48:49 -0400 Subject: [PATCH 38/53] Bad header def.. --- src/process/WaterfallVisualProcessor.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/process/WaterfallVisualProcessor.h b/src/process/WaterfallVisualProcessor.h index 76cca22..5c2aa62 100644 --- a/src/process/WaterfallVisualProcessor.h +++ b/src/process/WaterfallVisualProcessor.h @@ -9,7 +9,5 @@ class WaterfallVisualData : public ReferenceCounter { class WaterfallVisualProcessor : public VisualProcessor { protected: - void process() { - - } + void process(); }; From 560eec1336e032c6ef2dfc37c84b0ecc7b18d01a Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 1 Aug 2015 11:03:00 -0400 Subject: [PATCH 39/53] ScopeVisualProcessor now working --- src/AppFrame.cpp | 1 + src/CubicSDR.cpp | 6 ++++ src/CubicSDR.h | 5 +++ src/demod/DemodulatorInstance.cpp | 10 +++--- src/demod/DemodulatorInstance.h | 2 +- src/process/ScopeVisualProcessor.cpp | 2 +- src/process/VisualProcessor.h | 6 ++-- src/visual/ScopeCanvas.cpp | 51 +++++++++++++--------------- src/visual/ScopeCanvas.h | 8 ++--- 9 files changed, 50 insertions(+), 41 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index e345bba..ea7910f 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -91,6 +91,7 @@ AppFrame::AppFrame() : scopeCanvas = new ScopeCanvas(this, attribList); demodScopeTray->Add(scopeCanvas, 8, wxEXPAND | wxALL, 0); + wxGetApp().getScopeProcessor()->attachOutput(scopeCanvas->getInputQueue()); demodScopeTray->AddSpacer(1); diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 49658b2..f17cec3 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -58,6 +58,8 @@ bool CubicSDR::OnInit() { pipeAudioVisualData = new DemodulatorThreadOutputQueue(); pipeAudioVisualData->set_max_num_items(1); + scopeProcessor.setInput(pipeAudioVisualData); + // I/Q Data pipeSDRIQData = new SDRThreadIQDataQueue; pipeSDRCommand = new SDRThreadCommandQueue(); @@ -248,6 +250,10 @@ long long CubicSDR::getFrequency() { return frequency; } +ScopeVisualProcessor *CubicSDR::getScopeProcessor() { + return &scopeProcessor; +} + DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() { return pipeAudioVisualData; } diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 556773d..6d4c4c8 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -16,6 +16,7 @@ #include "DemodulatorMgr.h" #include "AppConfig.h" #include "AppFrame.h" +#include "ScopeVisualProcessor.h" #include @@ -52,6 +53,8 @@ public: void setDevice(int deviceId); int getDevice(); + ScopeVisualProcessor *getScopeProcessor(); + DemodulatorThreadOutputQueue* getAudioVisualQueue(); DemodulatorThreadInputQueue* getIQVisualQueue(); DemodulatorMgr &getDemodMgr(); @@ -92,6 +95,8 @@ private: DemodulatorThreadInputQueue* pipeIQVisualData; DemodulatorThreadOutputQueue* pipeAudioVisualData; + ScopeVisualProcessor scopeProcessor; + std::thread *t_SDR; std::thread *t_PostSDR; }; diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index d39dcb4..c92f5b5 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -1,7 +1,7 @@ #include "DemodulatorInstance.h" DemodulatorInstance::DemodulatorInstance() : - pipeIQInputData(NULL), demodulatorThread(NULL), t_PreDemod(NULL), t_Demod(NULL), t_Audio(NULL), currentAudioGain(1.0) { + t_PreDemod(NULL), pipeIQInputData(NULL), demodulatorThread(NULL), t_Demod(NULL), t_Audio(NULL), currentAudioGain(1.0) { terminated.store(true); audioTerminated.store(true); @@ -30,17 +30,17 @@ DemodulatorInstance::DemodulatorInstance() : demodulatorPreThread->setOutputQueue("NotifyQueue",pipeDemodNotify); demodulatorPreThread->setInputQueue("CommandQueue",pipeDemodCommand); - audioInputQueue = new AudioThreadInputQueue; + pipeAudioData = new AudioThreadInputQueue; threadQueueControl = new DemodulatorThreadControlCommandQueue; demodulatorThread = new DemodulatorThread(); demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData); demodulatorThread->setInputQueue("ControlQueue",threadQueueControl); demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify); - demodulatorThread->setOutputQueue("AudioDataOutput", audioInputQueue); + demodulatorThread->setOutputQueue("AudioDataOutput", pipeAudioData); audioThread = new AudioThread(); - audioThread->setInputQueue("AudioDataInput", audioInputQueue); + audioThread->setInputQueue("AudioDataInput", pipeAudioData); audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify); currentDemodType = demodulatorThread->getDemodulatorType(); @@ -55,7 +55,7 @@ DemodulatorInstance::~DemodulatorInstance() { delete pipeDemodCommand; delete pipeDemodNotify; delete threadQueueControl; - delete audioInputQueue; + delete pipeAudioData; } void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) { diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index acd28ad..d211746 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -18,7 +18,6 @@ public: std::thread *t_Demod; #endif - AudioThreadInputQueue *audioInputQueue; AudioThread *audioThread; std::thread *t_Audio; @@ -80,6 +79,7 @@ public: protected: DemodulatorThreadInputQueue* pipeIQInputData; DemodulatorThreadPostInputQueue* pipeIQDemodData; + AudioThreadInputQueue *pipeAudioData; DemodulatorThreadCommandQueue* pipeDemodCommand; DemodulatorThreadCommandQueue* pipeDemodNotify; DemodulatorPreThread *demodulatorPreThread; diff --git a/src/process/ScopeVisualProcessor.cpp b/src/process/ScopeVisualProcessor.cpp index c3ffbc9..4eff90d 100644 --- a/src/process/ScopeVisualProcessor.cpp +++ b/src/process/ScopeVisualProcessor.cpp @@ -1,7 +1,7 @@ #include "ScopeVisualProcessor.h" void ScopeVisualProcessor::process() { - if (isOutputEmpty()) { + if (!isOutputEmpty()) { return; } if (!input->empty()) { diff --git a/src/process/VisualProcessor.h b/src/process/VisualProcessor.h index f84c32d..4f8c898 100644 --- a/src/process/VisualProcessor.h +++ b/src/process/VisualProcessor.h @@ -52,7 +52,7 @@ protected: void distribute(OutputDataType *output) { // distribute outputs output->setRefCount(outputs.size()); - for (outputs_i = outputs.begin(); outputs_i != outputs.begin(); outputs_i++) { + for (outputs_i = outputs.begin(); outputs_i != outputs.end(); outputs_i++) { if ((*outputs_i)->full()) { output->decRefCount(); } else { @@ -62,7 +62,7 @@ protected: } bool isOutputEmpty() { - for (outputs_i = outputs.begin(); outputs_i != outputs.begin(); outputs_i++) { + for (outputs_i = outputs.begin(); outputs_i != outputs.end(); outputs_i++) { if (!(*outputs_i)->empty()) { return false; } @@ -71,7 +71,7 @@ protected: } bool isAnyOutputEmpty() { - for (outputs_i = outputs.begin(); outputs_i != outputs.begin(); outputs_i++) { + for (outputs_i = outputs.begin(); outputs_i != outputs.end(); outputs_i++) { if ((*outputs_i)->empty()) { return true; } diff --git a/src/visual/ScopeCanvas.cpp b/src/visual/ScopeCanvas.cpp index c80cc54..5c6bd54 100644 --- a/src/visual/ScopeCanvas.cpp +++ b/src/visual/ScopeCanvas.cpp @@ -21,19 +21,16 @@ wxEND_EVENT_TABLE() ScopeCanvas::ScopeCanvas(wxWindow *parent, int *attribList) : wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, - wxFULL_REPAINT_ON_RESIZE), parent(parent), stereo(false), ppmMode(false) { + wxFULL_REPAINT_ON_RESIZE), stereo(false), ppmMode(false) { glContext = new ScopeContext(this, &wxGetApp().GetContext(this)); + inputData.set_max_num_items(1); } ScopeCanvas::~ScopeCanvas() { } -void ScopeCanvas::setWaveformPoints(std::vector &waveform_points_in) { - waveform_points = waveform_points_in; -} - void ScopeCanvas::setStereo(bool state) { stereo = state; } @@ -58,30 +55,26 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { #endif const wxSize ClientSize = GetClientSize(); - if (!wxGetApp().getAudioVisualQueue()->empty()) { - AudioThreadInput *demodAudioData; - wxGetApp().getAudioVisualQueue()->pop(demodAudioData); + wxGetApp().getScopeProcessor()->run(); + if (!inputData.empty()) { + ScopeRenderData *avData; + inputData.pop(avData); - int iMax = demodAudioData?demodAudioData->data.size():0; - - if (demodAudioData && iMax) { - if (waveform_points.size() != iMax * 2) { - waveform_points.resize(iMax * 2); - } - - demodAudioData->busy_update.lock(); - - for (int i = 0; i < iMax; i++) { - waveform_points[i * 2 + 1] = demodAudioData->data[i] * 0.5f; - waveform_points[i * 2] = ((double) i / (double) iMax); - } - - demodAudioData->busy_update.unlock(); - - setStereo(demodAudioData->channels == 2); - } else { - std::cout << "Incoming Demodulator data empty?" << std::endl; + if (!avData) { + return; } + + int iMax = avData->waveform_points.size(); + + if (!iMax) { + avData->decRefCount(); + return; + } + + waveform_points.assign(avData->waveform_points.begin(),avData->waveform_points.end()); + setStereo(avData->channels == 2); + + avData->decRefCount(); } glContext->SetCurrent(*this); @@ -103,3 +96,7 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { void ScopeCanvas::OnIdle(wxIdleEvent &event) { Refresh(false); } + +ScopeRenderDataQueue *ScopeCanvas::getInputQueue() { + return &inputData; +} diff --git a/src/visual/ScopeCanvas.h b/src/visual/ScopeCanvas.h index cb24fee..23203b7 100644 --- a/src/visual/ScopeCanvas.h +++ b/src/visual/ScopeCanvas.h @@ -7,6 +7,7 @@ #include #include "ScopeContext.h" +#include "ScopeVisualProcessor.h" #include "fftw3.h" class ScopeCanvas: public wxGLCanvas { @@ -16,19 +17,18 @@ public: ScopeCanvas(wxWindow *parent, int *attribList = NULL); ~ScopeCanvas(); - void setWaveformPoints(std::vector &waveform_points_in); void setStereo(bool state); void setDeviceName(std::string device_name); void setPPMMode(bool ppmMode); bool getPPMMode(); + ScopeRenderDataQueue *getInputQueue(); + private: void OnPaint(wxPaintEvent& event); - void OnIdle(wxIdleEvent &event); - wxWindow *parent; - + ScopeRenderDataQueue inputData; ScopeContext *glContext; std::string deviceName; bool stereo; From 2cff389d6be3825c5adfc871a337e85e71a9fa15 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 3 Aug 2015 01:38:38 -0400 Subject: [PATCH 40/53] SpectrumVisualProcessor now working, cleanup, refactoring --- CMakeLists.txt | 2 - src/AppFrame.cpp | 33 +- src/CubicSDR.cpp | 27 ++ src/CubicSDR.h | 11 + src/demod/DemodulatorInstance.cpp | 4 +- src/process/SpectrumVisualProcessor.cpp | 358 +++++++++++++++---- src/process/SpectrumVisualProcessor.h | 53 ++- src/process/VisualProcessor.h | 16 +- src/process/WaterfallVisualProcessor.cpp | 275 --------------- src/process/WaterfallVisualProcessor.h | 13 - src/visual/SpectrumCanvas.cpp | 128 ++----- src/visual/SpectrumCanvas.h | 28 +- src/visual/WaterfallCanvas.cpp | 424 +++++------------------ src/visual/WaterfallCanvas.h | 32 +- 14 files changed, 539 insertions(+), 865 deletions(-) delete mode 100644 src/process/WaterfallVisualProcessor.cpp delete mode 100644 src/process/WaterfallVisualProcessor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f2f72e9..209f2a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -262,7 +262,6 @@ SET (cubicsdr_sources src/process/VisualProcessor.cpp src/process/ScopeVisualProcessor.cpp src/process/SpectrumVisualProcessor.cpp - src/process/WaterfallVisualProcessor.cpp src/ui/GLPanel.cpp external/rtaudio/RtAudio.cpp external/lodepng/lodepng.cpp @@ -315,7 +314,6 @@ SET (cubicsdr_headers src/process/VisualProcessor.h src/process/ScopeVisualProcessor.h src/process/SpectrumVisualProcessor.h - src/process/WaterfallVisualProcessor.h src/ui/GLPanel.h src/ui/UITestCanvas.cpp src/ui/UITestCanvas.h diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index ea7910f..d758322 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -64,10 +64,11 @@ AppFrame::AppFrame() : // demodTray->AddSpacer(2); + wxGetApp().getDemodSpectrumProcesor()->setup(1024); demodSpectrumCanvas = new SpectrumCanvas(this, attribList); - demodSpectrumCanvas->setup(1024); demodSpectrumCanvas->setView(wxGetApp().getConfig()->getCenterFreq(), 300000); demodVisuals->Add(demodSpectrumCanvas, 3, wxEXPAND | wxALL, 0); + wxGetApp().getDemodSpectrumProcesor()->attachOutput(demodSpectrumCanvas->getVisualDataQueue()); demodVisuals->AddSpacer(1); @@ -77,6 +78,7 @@ AppFrame::AppFrame() : demodWaterfallCanvas->attachSpectrumCanvas(demodSpectrumCanvas); demodSpectrumCanvas->attachWaterfallCanvas(demodWaterfallCanvas); demodVisuals->Add(demodWaterfallCanvas, 6, wxEXPAND | wxALL, 0); + wxGetApp().getDemodSpectrumProcesor()->attachOutput(demodWaterfallCanvas->getVisualDataQueue()); demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0); @@ -110,17 +112,19 @@ AppFrame::AppFrame() : vbox->Add(demodTray, 12, wxEXPAND | wxALL, 0); vbox->AddSpacer(1); + + wxGetApp().getSpectrumProcesor()->setup(2048); spectrumCanvas = new SpectrumCanvas(this, attribList); - spectrumCanvas->setup(2048); vbox->Add(spectrumCanvas, 5, wxEXPAND | wxALL, 0); vbox->AddSpacer(1); + wxGetApp().getSpectrumProcesor()->attachOutput(spectrumCanvas->getVisualDataQueue()); + waterfallCanvas = new WaterfallCanvas(this, attribList); waterfallCanvas->setup(2048, 512); waterfallCanvas->attachSpectrumCanvas(spectrumCanvas); - waterfallCanvas->attachWaterfallCanvas(demodWaterfallCanvas); spectrumCanvas->attachWaterfallCanvas(waterfallCanvas); vbox->Add(waterfallCanvas, 20, wxEXPAND | wxALL, 0); - + wxGetApp().getSpectrumProcesor()->attachOutput(waterfallCanvas->getVisualDataQueue()); /* vbox->AddSpacer(1); testCanvas = new UITestCanvas(this, attribList); @@ -674,7 +678,26 @@ void AppFrame::OnIdle(wxIdleEvent& event) { } scopeCanvas->setPPMMode(demodTuner->isAltDown()); - + + + wxGetApp().getSpectrumDistributor()->run(); + + SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcesor(); + + proc->setView(waterfallCanvas->getViewState()); + proc->setBandwidth(waterfallCanvas->getBandwidth()); + proc->setCenterFrequency(waterfallCanvas->getCenterFrequency()); + + proc->run(); + + SpectrumVisualProcessor *dproc = wxGetApp().getDemodSpectrumProcesor(); + + dproc->setView(demodWaterfallCanvas->getViewState()); + dproc->setBandwidth(demodWaterfallCanvas->getBandwidth()); + dproc->setCenterFrequency(demodWaterfallCanvas->getCenterFrequency()); + + dproc->run(); + event.Skip(); } diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index f17cec3..3033b6e 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -54,6 +54,20 @@ bool CubicSDR::OnInit() { // Visual Data pipeIQVisualData = new DemodulatorThreadInputQueue(); pipeIQVisualData->set_max_num_items(1); + + spectrumDistributor.setInput(pipeIQVisualData); + + pipeDemodIQVisualData = new DemodulatorThreadInputQueue(); + pipeIQVisualData->set_max_num_items(1); + + pipeSpectrumIQVisualData = new DemodulatorThreadInputQueue(); + pipeIQVisualData->set_max_num_items(1); + + spectrumDistributor.attachOutput(pipeDemodIQVisualData); + spectrumDistributor.attachOutput(pipeSpectrumIQVisualData); + + demodSpectrumProcessor.setInput(pipeDemodIQVisualData); + spectrumProcessor.setInput(pipeSpectrumIQVisualData); pipeAudioVisualData = new DemodulatorThreadOutputQueue(); pipeAudioVisualData->set_max_num_items(1); @@ -254,6 +268,19 @@ ScopeVisualProcessor *CubicSDR::getScopeProcessor() { return &scopeProcessor; } +SpectrumVisualProcessor *CubicSDR::getSpectrumProcesor() { + return &spectrumProcessor; +} + +SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcesor() { + return &demodSpectrumProcessor; +} + +VisualDataDistributor *CubicSDR::getSpectrumDistributor() { + return &spectrumDistributor; +} + + DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() { return pipeAudioVisualData; } diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 6d4c4c8..c20d522 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -16,7 +16,9 @@ #include "DemodulatorMgr.h" #include "AppConfig.h" #include "AppFrame.h" + #include "ScopeVisualProcessor.h" +#include "SpectrumVisualProcessor.h" #include @@ -54,6 +56,9 @@ public: int getDevice(); ScopeVisualProcessor *getScopeProcessor(); + SpectrumVisualProcessor *getSpectrumProcesor(); + SpectrumVisualProcessor *getDemodSpectrumProcesor(); + VisualDataDistributor *getSpectrumDistributor(); DemodulatorThreadOutputQueue* getAudioVisualQueue(); DemodulatorThreadInputQueue* getIQVisualQueue(); @@ -94,8 +99,14 @@ private: SDRThreadIQDataQueue* pipeSDRIQData; DemodulatorThreadInputQueue* pipeIQVisualData; DemodulatorThreadOutputQueue* pipeAudioVisualData; + DemodulatorThreadInputQueue* pipeDemodIQVisualData; + DemodulatorThreadInputQueue* pipeSpectrumIQVisualData; ScopeVisualProcessor scopeProcessor; + SpectrumVisualProcessor spectrumProcessor; + SpectrumVisualProcessor demodSpectrumProcessor; + + VisualDataDistributor spectrumDistributor; std::thread *t_SDR; std::thread *t_PostSDR; diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index c92f5b5..d308327 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -1,7 +1,7 @@ #include "DemodulatorInstance.h" DemodulatorInstance::DemodulatorInstance() : - t_PreDemod(NULL), pipeIQInputData(NULL), demodulatorThread(NULL), t_Demod(NULL), t_Audio(NULL), currentAudioGain(1.0) { + t_PreDemod(NULL), t_Demod(NULL), t_Audio(NULL) { terminated.store(true); audioTerminated.store(true); @@ -16,7 +16,7 @@ DemodulatorInstance::DemodulatorInstance() : currentFrequency.store(0); currentBandwidth.store(0); currentOutputDevice.store(-1); - + currentAudioGain.store(1.0); label = new std::string("Unnamed"); pipeIQInputData = new DemodulatorThreadInputQueue; diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index dcd99b7..8defddc 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -1,80 +1,284 @@ #include "SpectrumVisualProcessor.h" +#include "CubicSDR.h" + + +SpectrumVisualProcessor::SpectrumVisualProcessor() : lastInputBandwidth(0), lastBandwidth(0), fftwInput(NULL), fftwOutput(NULL), fftInData(NULL), fftLastData(NULL), lastDataSize(0), fftw_plan(NULL), resampler(NULL), resamplerRatio(0) { + + is_view.store(false); + fftSize.store(0); + centerFreq.store(0); + bandwidth.store(0); + + freqShifter = nco_crcf_create(LIQUID_NCO); + shiftFrequency = 0; + + fft_ceil_ma = fft_ceil_maa = 100.0; + fft_floor_ma = fft_floor_maa = 0.0; +} + +SpectrumVisualProcessor::~SpectrumVisualProcessor() { + nco_crcf_destroy(freqShifter); +} + +bool SpectrumVisualProcessor::isView() { + return is_view.load(); +} + +void SpectrumVisualProcessor::setView(bool bView) { + is_view.store(bView); +} + + +void SpectrumVisualProcessor::setCenterFrequency(long long centerFreq_in) { + centerFreq.store(centerFreq_in); +} + +long long SpectrumVisualProcessor::getCenterFrequency() { + return centerFreq.load(); +} + +void SpectrumVisualProcessor::setBandwidth(long bandwidth_in) { + bandwidth.store(bandwidth_in); +} + +long SpectrumVisualProcessor::getBandwidth() { + return bandwidth.load(); +} + +void SpectrumVisualProcessor::setup(int fftSize_in) { + fftSize = fftSize_in; + + if (fftwInput) { + free(fftwInput); + } + fftwInput = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); + if (fftInData) { + free(fftInData); + } + fftInData = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); + if (fftLastData) { + free(fftLastData); + } + fftLastData = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); + if (fftwOutput) { + free(fftwOutput); + } + fftwOutput = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); + if (fftw_plan) { + fftwf_destroy_plan(fftw_plan); + } + fftw_plan = fftwf_plan_dft_1d(fftSize, fftwInput, fftwOutput, FFTW_FORWARD, FFTW_ESTIMATE); + +} void SpectrumVisualProcessor::process() { - /* - std::vector *data = &input->data; - if (data && data->size()) { - if (fft_size != data->size()) { - setup(data->size()); - } - if (spectrum_points.size() < fft_size * 2) { - if (spectrum_points.capacity() < fft_size * 2) { - spectrum_points.reserve(fft_size * 2); - } - spectrum_points.resize(fft_size * 2); - } - - for (int i = 0; i < fft_size; i++) { - in[i][0] = (*data)[i].real; - in[i][1] = (*data)[i].imag; - } - - fftwf_execute(plan); - - float fft_ceil = 0, fft_floor = 1; - - if (fft_result.size() != fft_size) { - if (fft_result.capacity() < fft_size) { - fft_result.reserve(fft_size); - fft_result_ma.reserve(fft_size); - fft_result_maa.reserve(fft_size); - } - fft_result.resize(fft_size); - fft_result_ma.resize(fft_size); - fft_result_maa.resize(fft_size); - } - - int n; - for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { - float a = out[i][0]; - float b = out[i][1]; - float c = sqrt(a * a + b * b); - - float x = out[fft_size / 2 + i][0]; - float y = out[fft_size / 2 + i][1]; - float z = sqrt(x * x + y * y); - - fft_result[i] = (z); - fft_result[fft_size / 2 + i] = (c); - } - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; - - if (fft_result_maa[i] > fft_ceil) { - fft_ceil = fft_result_maa[i]; - } - if (fft_result_maa[i] < fft_floor) { - fft_floor = fft_result_maa[i]; - } - } - - fft_ceil += 1; - fft_floor -= 1; - - fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.01; - fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.01; - - fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.01; - fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.01; - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); - spectrum_points[i * 2] = ((float) i / (float) iMax); - spectrum_points[i * 2 + 1] = v; - } - - } - */ -} \ No newline at end of file + if (!isOutputEmpty()) { + return; + } + if (!input || input->empty()) { + return; + } + + DemodulatorThreadIQData *iqData; + + input->pop(iqData); + + std::vector *data = &iqData->data; + + if (data && data->size()) { + SpectrumVisualData *output = outputBuffers.getBuffer(); + + if (output->spectrum_points.size() < fftSize * 2) { + output->spectrum_points.resize(fftSize * 2); + } + + unsigned int num_written; + + if (is_view.load()) { + if (!iqData->frequency || !iqData->sampleRate) { + return; + } + + resamplerRatio = (double) (bandwidth) / (double) iqData->sampleRate; + + int desired_input_size = fftSize / resamplerRatio; + + if (iqData->data.size() < desired_input_size) { + // std::cout << "fft underflow, desired: " << desired_input_size << " actual:" << input->data.size() << std::endl; + desired_input_size = iqData->data.size(); + } + + if (centerFreq != iqData->frequency) { + if ((centerFreq - iqData->frequency) != shiftFrequency || lastInputBandwidth != iqData->sampleRate) { + if (abs(iqData->frequency - centerFreq) < (wxGetApp().getSampleRate() / 2)) { + shiftFrequency = centerFreq - iqData->frequency; + nco_crcf_reset(freqShifter); + nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) iqData->sampleRate))); + } + } + + if (shiftBuffer.size() != desired_input_size) { + if (shiftBuffer.capacity() < desired_input_size) { + shiftBuffer.reserve(desired_input_size); + } + shiftBuffer.resize(desired_input_size); + } + + if (shiftFrequency < 0) { + nco_crcf_mix_block_up(freqShifter, &iqData->data[0], &shiftBuffer[0], desired_input_size); + } else { + nco_crcf_mix_block_down(freqShifter, &iqData->data[0], &shiftBuffer[0], desired_input_size); + } + } else { + shiftBuffer.assign(iqData->data.begin(), iqData->data.end()); + } + + if (!resampler || bandwidth != lastBandwidth || lastInputBandwidth != iqData->sampleRate) { + float As = 60.0f; + + if (resampler) { + msresamp_crcf_destroy(resampler); + } + resampler = msresamp_crcf_create(resamplerRatio, As); + + lastBandwidth = bandwidth; + lastInputBandwidth = iqData->sampleRate; + } + + + int out_size = ceil((double) (desired_input_size) * resamplerRatio) + 512; + + if (resampleBuffer.size() != out_size) { + if (resampleBuffer.capacity() < out_size) { + resampleBuffer.reserve(out_size); + } + resampleBuffer.resize(out_size); + } + + + msresamp_crcf_execute(resampler, &shiftBuffer[0], desired_input_size, &resampleBuffer[0], &num_written); + + resampleBuffer.resize(fftSize); + + if (num_written < fftSize) { + for (int i = 0; i < num_written; i++) { + fftInData[i][0] = resampleBuffer[i].real; + fftInData[i][1] = resampleBuffer[i].imag; + } + for (int i = num_written; i < fftSize; i++) { + fftInData[i][0] = 0; + fftInData[i][1] = 0; + } + } else { + for (int i = 0; i < fftSize; i++) { + fftInData[i][0] = resampleBuffer[i].real; + fftInData[i][1] = resampleBuffer[i].imag; + } + } + } else { + num_written = data->size(); + if (data->size() < fftSize) { + for (int i = 0, iMax = data->size(); i < iMax; i++) { + fftInData[i][0] = (*data)[i].real; + fftInData[i][1] = (*data)[i].imag; + } + for (int i = data->size(); i < fftSize; i++) { + fftInData[i][0] = 0; + fftInData[i][1] = 0; + } + } else { + for (int i = 0; i < fftSize; i++) { + fftInData[i][0] = (*data)[i].real; + fftInData[i][1] = (*data)[i].imag; + } + } + } + + bool execute = false; + + if (num_written >= fftSize) { + execute = true; + memcpy(fftwInput, fftInData, fftSize * sizeof(fftwf_complex)); + memcpy(fftLastData, fftwInput, fftSize * sizeof(fftwf_complex)); + + } else { + if (lastDataSize + num_written < fftSize) { // priming + unsigned int num_copy = fftSize - lastDataSize; + if (num_written > num_copy) { + num_copy = num_written; + } + memcpy(fftLastData, fftInData, num_copy * sizeof(fftwf_complex)); + lastDataSize += num_copy; + } else { + unsigned int num_last = (fftSize - num_written); + memcpy(fftwInput, fftLastData + (lastDataSize - num_last), num_last * sizeof(fftwf_complex)); + memcpy(fftwInput + num_last, fftInData, num_written * sizeof(fftwf_complex)); + memcpy(fftLastData, fftwInput, fftSize * sizeof(fftwf_complex)); + execute = true; + } + } + + if (execute) { + fftwf_execute(fftw_plan); + + float fft_ceil = 0, fft_floor = 1; + + if (fft_result.size() < fftSize) { + fft_result.resize(fftSize); + fft_result_ma.resize(fftSize); + fft_result_maa.resize(fftSize); + } + + for (int i = 0, iMax = fftSize / 2; i < iMax; i++) { + float a = fftwOutput[i][0]; + float b = fftwOutput[i][1]; + float c = sqrt(a * a + b * b); + + float x = fftwOutput[fftSize / 2 + i][0]; + float y = fftwOutput[fftSize / 2 + i][1]; + float z = sqrt(x * x + y * y); + + fft_result[i] = (z); + fft_result[fftSize / 2 + i] = (c); + } + + for (int i = 0, iMax = fftSize; i < iMax; i++) { + if (is_view.load()) { + fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; + fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; + } else { + fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; + fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; + } + + if (fft_result_maa[i] > fft_ceil) { + fft_ceil = fft_result_maa[i]; + } + if (fft_result_maa[i] < fft_floor) { + fft_floor = fft_result_maa[i]; + } + } + + fft_ceil += 0.25; + fft_floor -= 1; + + fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05; + fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.05; + + fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.05; + fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05; + + for (int i = 0, iMax = fftSize; i < iMax; i++) { + float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); + output->spectrum_points[i * 2] = ((float) i / (float) iMax); + output->spectrum_points[i * 2 + 1] = v; + } + + output->fft_ceiling = fft_ceil_maa; + output->fft_floor = fft_floor_maa; + } + + distribute(output); + } + +} diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h index 3fcc0ff..6ffe848 100644 --- a/src/process/SpectrumVisualProcessor.h +++ b/src/process/SpectrumVisualProcessor.h @@ -1,13 +1,62 @@ #pragma once #include "VisualProcessor.h" -#include "SpectrumCanvas.h" +#include "DemodDefs.h" +#include "fftw3.h" class SpectrumVisualData : public ReferenceCounter { - +public: + std::vector spectrum_points; + double fft_ceiling, fft_floor; }; +typedef ThreadQueue SpectrumVisualDataQueue; + class SpectrumVisualProcessor : public VisualProcessor { +public: + SpectrumVisualProcessor(); + ~SpectrumVisualProcessor(); + + bool isView(); + void setView(bool bView); + + void setCenterFrequency(long long centerFreq_in); + long long getCenterFrequency(); + + void setBandwidth(long bandwidth_in); + long getBandwidth(); + + void setup(int fftSize); + protected: void process(); + + ReBuffer outputBuffers; + std::atomic_bool is_view; + std::atomic_int fftSize; + std::atomic_llong centerFreq; + std::atomic_long bandwidth; + +private: + long lastInputBandwidth; + long lastBandwidth; + + fftwf_complex *fftwInput, *fftwOutput, *fftInData, *fftLastData; + unsigned int lastDataSize; + fftwf_plan fftw_plan; + + float fft_ceil_ma, fft_ceil_maa; + float fft_floor_ma, fft_floor_maa; + + std::vector fft_result; + std::vector fft_result_ma; + std::vector fft_result_maa; + + msresamp_crcf resampler; + double resamplerRatio; + nco_crcf freqShifter; + long shiftFrequency; + + std::vector shiftBuffer; + std::vector resampleBuffer; }; diff --git a/src/process/VisualProcessor.h b/src/process/VisualProcessor.h index 4f8c898..1f02bbe 100644 --- a/src/process/VisualProcessor.h +++ b/src/process/VisualProcessor.h @@ -86,16 +86,18 @@ protected: }; -template -class VisualDataDistributor : public VisualProcessor { +template +class VisualDataDistributor : public VisualProcessor { protected: void process() { - - while (!VisualProcessor::input->empty()) { - ReferenceCounter *inp; - VisualProcessor::input->pop(inp); + if (!VisualProcessor::isOutputEmpty()) { + return; + } + while (!VisualProcessor::input->empty()) { + OutputDataType *inp; + VisualProcessor::input->pop(inp); if (inp) { - VisualProcessor::distribute(inp); + VisualProcessor::distribute(inp); } } } diff --git a/src/process/WaterfallVisualProcessor.cpp b/src/process/WaterfallVisualProcessor.cpp deleted file mode 100644 index 153e489..0000000 --- a/src/process/WaterfallVisualProcessor.cpp +++ /dev/null @@ -1,275 +0,0 @@ -#include "WaterfallVisualProcessor.h" - -void WaterfallVisualProcessor::process() { - /* - long double currentZoom = zoom; - - if (mouseZoom != 1) { - currentZoom = mouseZoom; - mouseZoom = mouseZoom + (1.0 - mouseZoom) * 0.2; - if (fabs(mouseZoom-1.0)<0.01) { - mouseZoom = 1; - } - } - - long long bw; - if (currentZoom != 1) { - long long freq = wxGetApp().getFrequency(); - - if (currentZoom < 1) { - centerFreq = getCenterFrequency(); - bw = getBandwidth(); - bw = (long long) ceil((long double) bw * currentZoom); - if (bw < 100000) { - bw = 100000; - } - if (mouseTracker.mouseInView()) { - long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); - setBandwidth(bw); - long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); - centerFreq += mfreqA - mfreqB; - } - - setView(centerFreq, bw); - if (spectrumCanvas) { - spectrumCanvas->setView(centerFreq, bw); - } - } else { - if (isView) { - bw = getBandwidth(); - bw = (long long) ceil((long double) bw * currentZoom); - if (bw >= wxGetApp().getSampleRate()) { - disableView(); - if (spectrumCanvas) { - spectrumCanvas->disableView(); - } - } else { - if (mouseTracker.mouseInView()) { - long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); - setBandwidth(bw); - long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); - centerFreq += mfreqA - mfreqB; - } - - setView(getCenterFrequency(), bw); - if (spectrumCanvas) { - spectrumCanvas->setView(centerFreq, bw); - } - } - } - } - if (centerFreq < freq && (centerFreq - bandwidth / 2) < (freq - wxGetApp().getSampleRate() / 2)) { - centerFreq = (freq - wxGetApp().getSampleRate() / 2) + bandwidth / 2; - } - if (centerFreq > freq && (centerFreq + bandwidth / 2) > (freq + wxGetApp().getSampleRate() / 2)) { - centerFreq = (freq + wxGetApp().getSampleRate() / 2) - bandwidth / 2; - } - } - - std::vector *data = &input->data; - - if (data && data->size()) { - // if (fft_size != data->size() && !isView) { - // Setup(data->size(), waterfall_lines); - // } - - // if (last_bandwidth != bandwidth && !isView) { - // Setup(bandwidth, waterfall_lines); - // } - - if (spectrum_points.size() < fft_size * 2) { - spectrum_points.resize(fft_size * 2); - } - - unsigned int num_written; - - if (isView) { - if (!input->frequency || !input->sampleRate) { - return; - } - - resamplerRatio = (double) (bandwidth) / (double) input->sampleRate; - - int desired_input_size = fft_size / resamplerRatio; - - if (input->data.size() < desired_input_size) { - // std::cout << "fft underflow, desired: " << desired_input_size << " actual:" << input->data.size() << std::endl; - desired_input_size = input->data.size(); - } - - if (centerFreq != input->frequency) { - if ((centerFreq - input->frequency) != shiftFrequency || lastInputBandwidth != input->sampleRate) { - if (abs(input->frequency - centerFreq) < (wxGetApp().getSampleRate() / 2)) { - shiftFrequency = centerFreq - input->frequency; - nco_crcf_reset(freqShifter); - nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) input->sampleRate))); - } - } - - if (shiftBuffer.size() != desired_input_size) { - if (shiftBuffer.capacity() < desired_input_size) { - shiftBuffer.reserve(desired_input_size); - } - shiftBuffer.resize(desired_input_size); - } - - if (shiftFrequency < 0) { - nco_crcf_mix_block_up(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); - } else { - nco_crcf_mix_block_down(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); - } - } else { - shiftBuffer.assign(input->data.begin(), input->data.end()); - } - - if (!resampler || bandwidth != lastBandwidth || lastInputBandwidth != input->sampleRate) { - float As = 60.0f; - - if (resampler) { - msresamp_crcf_destroy(resampler); - } - resampler = msresamp_crcf_create(resamplerRatio, As); - - lastBandwidth = bandwidth; - lastInputBandwidth = input->sampleRate; - } - - - int out_size = ceil((double) (desired_input_size) * resamplerRatio) + 512; - - if (resampleBuffer.size() != out_size) { - if (resampleBuffer.capacity() < out_size) { - resampleBuffer.reserve(out_size); - } - resampleBuffer.resize(out_size); - } - - - msresamp_crcf_execute(resampler, &shiftBuffer[0], desired_input_size, &resampleBuffer[0], &num_written); - - resampleBuffer.resize(fft_size); - - if (num_written < fft_size) { - for (int i = 0; i < num_written; i++) { - fft_in_data[i][0] = resampleBuffer[i].real; - fft_in_data[i][1] = resampleBuffer[i].imag; - } - for (int i = num_written; i < fft_size; i++) { - fft_in_data[i][0] = 0; - fft_in_data[i][1] = 0; - } - } else { - for (int i = 0; i < fft_size; i++) { - fft_in_data[i][0] = resampleBuffer[i].real; - fft_in_data[i][1] = resampleBuffer[i].imag; - } - } - } else { - num_written = data->size(); - if (data->size() < fft_size) { - for (int i = 0, iMax = data->size(); i < iMax; i++) { - fft_in_data[i][0] = (*data)[i].real; - fft_in_data[i][1] = (*data)[i].imag; - } - for (int i = data->size(); i < fft_size; i++) { - fft_in_data[i][0] = 0; - fft_in_data[i][1] = 0; - } - } else { - for (int i = 0; i < fft_size; i++) { - fft_in_data[i][0] = (*data)[i].real; - fft_in_data[i][1] = (*data)[i].imag; - } - } - } - - bool execute = false; - - if (num_written >= fft_size) { - execute = true; - memcpy(in, fft_in_data, fft_size * sizeof(fftwf_complex)); - memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); - - } else { - if (last_data_size + num_written < fft_size) { // priming - unsigned int num_copy = fft_size - last_data_size; - if (num_written > num_copy) { - num_copy = num_written; - } - memcpy(fft_last_data, fft_in_data, num_copy * sizeof(fftwf_complex)); - last_data_size += num_copy; - } else { - unsigned int num_last = (fft_size - num_written); - memcpy(in, fft_last_data + (last_data_size - num_last), num_last * sizeof(fftwf_complex)); - memcpy(in + num_last, fft_in_data, num_written * sizeof(fftwf_complex)); - memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); - execute = true; - } - } - - if (execute) { - fftwf_execute(plan); - - float fft_ceil = 0, fft_floor = 1; - - if (fft_result.size() < fft_size) { - fft_result.resize(fft_size); - fft_result_ma.resize(fft_size); - fft_result_maa.resize(fft_size); - } - - int n; - for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { - float a = out[i][0]; - float b = out[i][1]; - float c = sqrt(a * a + b * b); - - float x = out[fft_size / 2 + i][0]; - float y = out[fft_size / 2 + i][1]; - float z = sqrt(x * x + y * y); - - fft_result[i] = (z); - fft_result[fft_size / 2 + i] = (c); - } - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - if (isView) { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; - } else { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; - } - - if (fft_result_maa[i] > fft_ceil) { - fft_ceil = fft_result_maa[i]; - } - if (fft_result_maa[i] < fft_floor) { - fft_floor = fft_result_maa[i]; - } - } - - fft_ceil += 0.25; - fft_floor -= 1; - - fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05; - fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.05; - - fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.05; - fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05; - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); - spectrum_points[i * 2] = ((float) i / (float) iMax); - spectrum_points[i * 2 + 1] = v; - } - - if (spectrumCanvas) { - spectrumCanvas->spectrum_points.assign(spectrum_points.begin(), spectrum_points.end()); - spectrumCanvas->getSpectrumContext()->setCeilValue(fft_ceil_maa); - spectrumCanvas->getSpectrumContext()->setFloorValue(fft_floor_maa); - } - } - } - */ -} \ No newline at end of file diff --git a/src/process/WaterfallVisualProcessor.h b/src/process/WaterfallVisualProcessor.h deleted file mode 100644 index 5c2aa62..0000000 --- a/src/process/WaterfallVisualProcessor.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "VisualProcessor.h" -#include "WaterfallCanvas.h" - -class WaterfallVisualData : public ReferenceCounter { - -}; - -class WaterfallVisualProcessor : public VisualProcessor { -protected: - void process(); -}; diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index 776b89a..65a52b2 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -27,8 +27,7 @@ EVT_MOUSEWHEEL(SpectrumCanvas::OnMouseWheelMoved) wxEND_EVENT_TABLE() SpectrumCanvas::SpectrumCanvas(wxWindow *parent, int *attribList) : - InteractiveCanvas(parent, attribList), fft_size(0), in(NULL), out(NULL), plan(NULL), fft_ceil_ma(1), fft_ceil_maa(1), fft_floor_ma(0), fft_floor_maa( - 0), waterfallCanvas(NULL), trackingRate(0) { + InteractiveCanvas(parent, attribList), fft_size(0), waterfallCanvas(NULL), trackingRate(0) { glContext = new SpectrumContext(this, &wxGetApp().GetContext(this)); @@ -37,30 +36,6 @@ SpectrumCanvas::SpectrumCanvas(wxWindow *parent, int *attribList) : SetCursor(wxCURSOR_SIZEWE); } -void SpectrumCanvas::setup(int fft_size_in) { - if (fft_size == fft_size_in) { - return; - } - - fft_size = fft_size_in; - - if (in) { - free(in); - } - in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size); - if (out) { - free(out); - } - out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size); - if (plan) { - fftwf_destroy_plan(plan); - } - plan = fftwf_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_MEASURE); - - fft_ceil_ma = fft_ceil_maa = 100.0; - fft_floor_ma = fft_floor_maa = 0.0; -} - SpectrumCanvas::~SpectrumCanvas() { } @@ -71,7 +46,23 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glFinish(); #endif const wxSize ClientSize = GetClientSize(); - + + if (visualDataQueue.empty()) { + return; + } + + SpectrumVisualData *vData; + + visualDataQueue.pop(vData); + + if (!vData) { + return; + } + + spectrum_points.assign(vData->spectrum_points.begin(),vData->spectrum_points.end()); + + vData->decRefCount(); + glContext->SetCurrent(*this); initGLExtensions(); @@ -91,85 +82,6 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { SwapBuffers(); } -void SpectrumCanvas::setData(DemodulatorThreadIQData *input) { - if (!input) { - return; - } - std::vector *data = &input->data; - if (data && data->size()) { - if (fft_size != data->size()) { - setup(data->size()); - } - if (spectrum_points.size() < fft_size * 2) { - if (spectrum_points.capacity() < fft_size * 2) { - spectrum_points.reserve(fft_size * 2); - } - spectrum_points.resize(fft_size * 2); - } - - for (int i = 0; i < fft_size; i++) { - in[i][0] = (*data)[i].real; - in[i][1] = (*data)[i].imag; - } - - fftwf_execute(plan); - - float fft_ceil = 0, fft_floor = 1; - - if (fft_result.size() != fft_size) { - if (fft_result.capacity() < fft_size) { - fft_result.reserve(fft_size); - fft_result_ma.reserve(fft_size); - fft_result_maa.reserve(fft_size); - } - fft_result.resize(fft_size); - fft_result_ma.resize(fft_size); - fft_result_maa.resize(fft_size); - } - - int n; - for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { - float a = out[i][0]; - float b = out[i][1]; - float c = sqrt(a * a + b * b); - - float x = out[fft_size / 2 + i][0]; - float y = out[fft_size / 2 + i][1]; - float z = sqrt(x * x + y * y); - - fft_result[i] = (z); - fft_result[fft_size / 2 + i] = (c); - } - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; - - if (fft_result_maa[i] > fft_ceil) { - fft_ceil = fft_result_maa[i]; - } - if (fft_result_maa[i] < fft_floor) { - fft_floor = fft_result_maa[i]; - } - } - - fft_ceil += 1; - fft_floor -= 1; - - fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.01; - fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.01; - - fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.01; - fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.01; - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); - spectrum_points[i * 2] = ((float) i / (float) iMax); - spectrum_points[i * 2 + 1] = v; - } - - } -} void SpectrumCanvas::OnIdle(wxIdleEvent &event) { Refresh(false); @@ -250,3 +162,7 @@ void SpectrumCanvas::attachWaterfallCanvas(WaterfallCanvas* canvas_in) { SpectrumContext* SpectrumCanvas::getSpectrumContext() { return glContext; } + +SpectrumVisualDataQueue *SpectrumCanvas::getVisualDataQueue() { + return &visualDataQueue; +} \ No newline at end of file diff --git a/src/visual/SpectrumCanvas.h b/src/visual/SpectrumCanvas.h index f1469a2..636296d 100644 --- a/src/visual/SpectrumCanvas.h +++ b/src/visual/SpectrumCanvas.h @@ -11,6 +11,7 @@ #include "fftw3.h" #include "MouseTracker.h" +#include "SpectrumVisualProcessor.h" class WaterfallCanvas; @@ -19,15 +20,15 @@ public: std::vector spectrum_points; SpectrumCanvas(wxWindow *parent, int *attribList = NULL); - void setup(int fft_size_in); +// void setup(int fft_size_in); ~SpectrumCanvas(); - void setData(DemodulatorThreadIQData *input); void attachWaterfallCanvas(WaterfallCanvas *canvas_in); void moveCenterFrequency(long long freqChange); SpectrumContext* getSpectrumContext(); - + SpectrumVisualDataQueue *getVisualDataQueue(); + private: void OnPaint(wxPaintEvent& event); @@ -39,20 +40,23 @@ private: void OnMouseReleased(wxMouseEvent& event); void OnMouseLeftWindow(wxMouseEvent& event); - fftwf_complex *in, *out; - fftwf_plan plan; - - float fft_ceil_ma, fft_ceil_maa; - float fft_floor_ma, fft_floor_maa; - - std::vector fft_result; - std::vector fft_result_ma; - std::vector fft_result_maa; +// fftwf_complex *in, *out; +// fftwf_plan plan; +// +// float fft_ceil_ma, fft_ceil_maa; +// float fft_floor_ma, fft_floor_maa; +// +// std::vector fft_result; +// std::vector fft_result_ma; +// std::vector fft_result_maa; SpectrumContext *glContext; WaterfallCanvas *waterfallCanvas; int fft_size; int trackingRate; + + SpectrumVisualDataQueue visualDataQueue; + // event table wxDECLARE_EVENT_TABLE(); }; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index abbcf0e..c928d89 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -35,23 +35,15 @@ EVT_MOUSEWHEEL(WaterfallCanvas::OnMouseWheelMoved) wxEND_EVENT_TABLE() WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : - InteractiveCanvas(parent, attribList), spectrumCanvas(NULL), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines( - 0), plan( - NULL), in(NULL), out(NULL), resampler(NULL), resamplerRatio(0), lastInputBandwidth(0), zoom(1), mouseZoom(1), otherWaterfallCanvas(NULL), polling(true), last_data_size(0), fft_in_data(NULL), fft_last_data(NULL), hoverAlpha(1.0), dragOfs(0) { + InteractiveCanvas(parent, attribList), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines( + 0), zoom(1), mouseZoom(1), hoverAlpha(1.0), dragOfs(0) { glContext = new WaterfallContext(this, &wxGetApp().GetContext(this)); - freqShifter = nco_crcf_create(LIQUID_NCO); - shiftFrequency = 0; - - fft_ceil_ma = fft_ceil_maa = 100.0; - fft_floor_ma = fft_floor_maa = 0.0; - SetCursor(wxCURSOR_CROSS); } WaterfallCanvas::~WaterfallCanvas() { - nco_crcf_destroy(freqShifter); } void WaterfallCanvas::setup(int fft_size_in, int waterfall_lines_in) { @@ -61,27 +53,6 @@ void WaterfallCanvas::setup(int fft_size_in, int waterfall_lines_in) { fft_size = fft_size_in; waterfall_lines = waterfall_lines_in; - if (in) { - free(in); - } - in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size); - if (fft_in_data) { - free(fft_in_data); - } - fft_in_data = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size); - if (fft_last_data) { - free(fft_last_data); - } - fft_last_data = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size); - if (out) { - free(out); - } - out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size); - if (plan) { - fftwf_destroy_plan(plan); - } - plan = fftwf_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_ESTIMATE); - glContext->Setup(fft_size, waterfall_lines); } @@ -104,29 +75,89 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { #endif const wxSize ClientSize = GetClientSize(); - - - if (polling && !wxGetApp().getIQVisualQueue()->empty()) { - DemodulatorThreadIQData *iqData; - wxGetApp().getIQVisualQueue()->pop(iqData); - - iqData->busy_rw.lock(); - - if (iqData && iqData->data.size()) { - setData(iqData); - if (otherWaterfallCanvas) { - otherWaterfallCanvas->setData(iqData); + long double currentZoom = zoom; + + if (mouseZoom != 1) { + currentZoom = mouseZoom; + mouseZoom = mouseZoom + (1.0 - mouseZoom) * 0.2; + if (fabs(mouseZoom-1.0)<0.01) { + mouseZoom = 1; + } + } + + long long bw; + if (currentZoom != 1) { + long long freq = wxGetApp().getFrequency(); + + if (currentZoom < 1) { + centerFreq = getCenterFrequency(); + bw = getBandwidth(); + bw = (long long) ceil((long double) bw * currentZoom); + if (bw < 100000) { + bw = 100000; + } + if (mouseTracker.mouseInView()) { + long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); + setBandwidth(bw); + long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); + centerFreq += mfreqA - mfreqB; + } + + setView(centerFreq, bw); + if (spectrumCanvas) { + spectrumCanvas->setView(centerFreq, bw); } } else { - std::cout << "Incoming IQ data empty?" << std::endl; + if (isView) { + bw = getBandwidth(); + bw = (long long) ceil((long double) bw * currentZoom); + if (bw >= wxGetApp().getSampleRate()) { + disableView(); + if (spectrumCanvas) { + spectrumCanvas->disableView(); + } + } else { + if (mouseTracker.mouseInView()) { + long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); + setBandwidth(bw); + long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); + centerFreq += mfreqA - mfreqB; + } + + setView(getCenterFrequency(), bw); + if (spectrumCanvas) { + spectrumCanvas->setView(centerFreq, bw); + } + } + } + } + if (centerFreq < freq && (centerFreq - bandwidth / 2) < (freq - wxGetApp().getSampleRate() / 2)) { + centerFreq = (freq - wxGetApp().getSampleRate() / 2) + bandwidth / 2; + } + if (centerFreq > freq && (centerFreq + bandwidth / 2) > (freq + wxGetApp().getSampleRate() / 2)) { + centerFreq = (freq + wxGetApp().getSampleRate() / 2) - bandwidth / 2; } - - iqData->busy_rw.unlock(); } + if (visualDataQueue.empty()) { + return; + } + + SpectrumVisualData *vData; + + visualDataQueue.pop(vData); + + if (!vData) { + return; + } + + spectrum_points.assign(vData->spectrum_points.begin(),vData->spectrum_points.end()); + + vData->decRefCount(); + glContext->SetCurrent(*this); initGLExtensions(); - glViewport(0, 0, ClientSize.x, ClientSize.y); + glViewport(0, 0, ClientSize.x, ClientSize.y); glContext->BeginDraw(0,0,0); glContext->Draw(spectrum_points); @@ -323,283 +354,6 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { return; } } - -void WaterfallCanvas::setData(DemodulatorThreadIQData *input) { - if (!input) { - return; - } - - long double currentZoom = zoom; - - if (mouseZoom != 1) { - currentZoom = mouseZoom; - mouseZoom = mouseZoom + (1.0 - mouseZoom) * 0.2; - if (fabs(mouseZoom-1.0)<0.01) { - mouseZoom = 1; - } - } - - long long bw; - if (currentZoom != 1) { - long long freq = wxGetApp().getFrequency(); - - if (currentZoom < 1) { - centerFreq = getCenterFrequency(); - bw = getBandwidth(); - bw = (long long) ceil((long double) bw * currentZoom); - if (bw < 100000) { - bw = 100000; - } - if (mouseTracker.mouseInView()) { - long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); - setBandwidth(bw); - long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); - centerFreq += mfreqA - mfreqB; - } - - setView(centerFreq, bw); - if (spectrumCanvas) { - spectrumCanvas->setView(centerFreq, bw); - } - } else { - if (isView) { - bw = getBandwidth(); - bw = (long long) ceil((long double) bw * currentZoom); - if (bw >= wxGetApp().getSampleRate()) { - disableView(); - if (spectrumCanvas) { - spectrumCanvas->disableView(); - } - } else { - if (mouseTracker.mouseInView()) { - long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); - setBandwidth(bw); - long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); - centerFreq += mfreqA - mfreqB; - } - - setView(getCenterFrequency(), bw); - if (spectrumCanvas) { - spectrumCanvas->setView(centerFreq, bw); - } - } - } - } - if (centerFreq < freq && (centerFreq - bandwidth / 2) < (freq - wxGetApp().getSampleRate() / 2)) { - centerFreq = (freq - wxGetApp().getSampleRate() / 2) + bandwidth / 2; - } - if (centerFreq > freq && (centerFreq + bandwidth / 2) > (freq + wxGetApp().getSampleRate() / 2)) { - centerFreq = (freq + wxGetApp().getSampleRate() / 2) - bandwidth / 2; - } - } - - std::vector *data = &input->data; - - if (data && data->size()) { -// if (fft_size != data->size() && !isView) { -// Setup(data->size(), waterfall_lines); -// } - -// if (last_bandwidth != bandwidth && !isView) { -// Setup(bandwidth, waterfall_lines); -// } - - if (spectrum_points.size() < fft_size * 2) { - spectrum_points.resize(fft_size * 2); - } - - unsigned int num_written; - - if (isView) { - if (!input->frequency || !input->sampleRate) { - return; - } - - resamplerRatio = (double) (bandwidth) / (double) input->sampleRate; - - int desired_input_size = fft_size / resamplerRatio; - - if (input->data.size() < desired_input_size) { -// std::cout << "fft underflow, desired: " << desired_input_size << " actual:" << input->data.size() << std::endl; - desired_input_size = input->data.size(); - } - - if (centerFreq != input->frequency) { - if ((centerFreq - input->frequency) != shiftFrequency || lastInputBandwidth != input->sampleRate) { - if (abs(input->frequency - centerFreq) < (wxGetApp().getSampleRate() / 2)) { - shiftFrequency = centerFreq - input->frequency; - nco_crcf_reset(freqShifter); - nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) input->sampleRate))); - } - } - - if (shiftBuffer.size() != desired_input_size) { - if (shiftBuffer.capacity() < desired_input_size) { - shiftBuffer.reserve(desired_input_size); - } - shiftBuffer.resize(desired_input_size); - } - - if (shiftFrequency < 0) { - nco_crcf_mix_block_up(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); - } else { - nco_crcf_mix_block_down(freqShifter, &input->data[0], &shiftBuffer[0], desired_input_size); - } - } else { - shiftBuffer.assign(input->data.begin(), input->data.end()); - } - - if (!resampler || bandwidth != lastBandwidth || lastInputBandwidth != input->sampleRate) { - float As = 60.0f; - - if (resampler) { - msresamp_crcf_destroy(resampler); - } - resampler = msresamp_crcf_create(resamplerRatio, As); - - lastBandwidth = bandwidth; - lastInputBandwidth = input->sampleRate; - } - - - int out_size = ceil((double) (desired_input_size) * resamplerRatio) + 512; - - if (resampleBuffer.size() != out_size) { - if (resampleBuffer.capacity() < out_size) { - resampleBuffer.reserve(out_size); - } - resampleBuffer.resize(out_size); - } - - - msresamp_crcf_execute(resampler, &shiftBuffer[0], desired_input_size, &resampleBuffer[0], &num_written); - - resampleBuffer.resize(fft_size); - - if (num_written < fft_size) { - for (int i = 0; i < num_written; i++) { - fft_in_data[i][0] = resampleBuffer[i].real; - fft_in_data[i][1] = resampleBuffer[i].imag; - } - for (int i = num_written; i < fft_size; i++) { - fft_in_data[i][0] = 0; - fft_in_data[i][1] = 0; - } - } else { - for (int i = 0; i < fft_size; i++) { - fft_in_data[i][0] = resampleBuffer[i].real; - fft_in_data[i][1] = resampleBuffer[i].imag; - } - } - } else { - num_written = data->size(); - if (data->size() < fft_size) { - for (int i = 0, iMax = data->size(); i < iMax; i++) { - fft_in_data[i][0] = (*data)[i].real; - fft_in_data[i][1] = (*data)[i].imag; - } - for (int i = data->size(); i < fft_size; i++) { - fft_in_data[i][0] = 0; - fft_in_data[i][1] = 0; - } - } else { - for (int i = 0; i < fft_size; i++) { - fft_in_data[i][0] = (*data)[i].real; - fft_in_data[i][1] = (*data)[i].imag; - } - } - } - - bool execute = false; - - if (num_written >= fft_size) { - execute = true; - memcpy(in, fft_in_data, fft_size * sizeof(fftwf_complex)); - memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); - - } else { - if (last_data_size + num_written < fft_size) { // priming - unsigned int num_copy = fft_size - last_data_size; - if (num_written > num_copy) { - num_copy = num_written; - } - memcpy(fft_last_data, fft_in_data, num_copy * sizeof(fftwf_complex)); - last_data_size += num_copy; - } else { - unsigned int num_last = (fft_size - num_written); - memcpy(in, fft_last_data + (last_data_size - num_last), num_last * sizeof(fftwf_complex)); - memcpy(in + num_last, fft_in_data, num_written * sizeof(fftwf_complex)); - memcpy(fft_last_data, in, fft_size * sizeof(fftwf_complex)); - execute = true; - } - } - - if (execute) { - fftwf_execute(plan); - - float fft_ceil = 0, fft_floor = 1; - - if (fft_result.size() < fft_size) { - fft_result.resize(fft_size); - fft_result_ma.resize(fft_size); - fft_result_maa.resize(fft_size); - } - - int n; - for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { - float a = out[i][0]; - float b = out[i][1]; - float c = sqrt(a * a + b * b); - - float x = out[fft_size / 2 + i][0]; - float y = out[fft_size / 2 + i][1]; - float z = sqrt(x * x + y * y); - - fft_result[i] = (z); - fft_result[fft_size / 2 + i] = (c); - } - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - if (isView) { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; - } else { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; - } - - if (fft_result_maa[i] > fft_ceil) { - fft_ceil = fft_result_maa[i]; - } - if (fft_result_maa[i] < fft_floor) { - fft_floor = fft_result_maa[i]; - } - } - - fft_ceil += 0.25; - fft_floor -= 1; - - fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05; - fft_ceil_maa = fft_ceil_maa + (fft_ceil_ma - fft_ceil_maa) * 0.05; - - fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.05; - fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05; - - for (int i = 0, iMax = fft_size; i < iMax; i++) { - float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); - spectrum_points[i * 2] = ((float) i / (float) iMax); - spectrum_points[i * 2 + 1] = v; - } - - if (spectrumCanvas) { - spectrumCanvas->spectrum_points.assign(spectrum_points.begin(), spectrum_points.end()); - spectrumCanvas->getSpectrumContext()->setCeilValue(fft_ceil_maa); - spectrumCanvas->getSpectrumContext()->setFloorValue(fft_floor_maa); - } - } - } -} - void WaterfallCanvas::OnIdle(wxIdleEvent &event) { Refresh(false); } @@ -963,16 +717,16 @@ void WaterfallCanvas::OnMouseRightReleased(wxMouseEvent& event) { mouseZoom = 1.0; } -void WaterfallCanvas::attachWaterfallCanvas(WaterfallCanvas* canvas_in) { - otherWaterfallCanvas = canvas_in; - otherWaterfallCanvas->setPolling(false); -} +// +//bool WaterfallCanvas::isPolling() { +// return polling; +//} +// +//void WaterfallCanvas::setPolling(bool polling) { +// this->polling = polling; +//} -bool WaterfallCanvas::isPolling() { - return polling; -} - -void WaterfallCanvas::setPolling(bool polling) { - this->polling = polling; -} +SpectrumVisualDataQueue *WaterfallCanvas::getVisualDataQueue() { + return &visualDataQueue; +} \ No newline at end of file diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index 7c06271..5c80c27 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -11,7 +11,6 @@ #include "MouseTracker.h" #include "SpectrumCanvas.h" -#include "fftw3.h" class WaterfallCanvas: public InteractiveCanvas { public: @@ -23,16 +22,11 @@ public: void setup(int fft_size_in, int waterfall_lines_in); ~WaterfallCanvas(); - void setData(DemodulatorThreadIQData *input); - DragState getDragState(); DragState getNextDragState(); - + void attachSpectrumCanvas(SpectrumCanvas *canvas_in); - void attachWaterfallCanvas(WaterfallCanvas *canvas_in); - - bool isPolling(); - void setPolling(bool polling); + SpectrumVisualDataQueue *getVisualDataQueue(); private: void OnPaint(wxPaintEvent& event); @@ -53,19 +47,6 @@ private: std::vector spectrum_points; SpectrumCanvas *spectrumCanvas; - WaterfallCanvas *otherWaterfallCanvas; - bool polling; - - fftwf_complex *in, *out, *fft_in_data, *fft_last_data; - unsigned int last_data_size; - fftwf_plan plan; - - float fft_ceil_ma, fft_ceil_maa; - float fft_floor_ma, fft_floor_maa; - - std::vector fft_result; - std::vector fft_result_ma; - std::vector fft_result_maa; WaterfallContext *glContext; @@ -76,18 +57,11 @@ private: int waterfall_lines; int dragOfs; - msresamp_crcf resampler; - double resamplerRatio; - nco_crcf freqShifter; - long shiftFrequency; - int lastInputBandwidth; float mouseZoom, zoom; float hoverAlpha; - std::vector shiftBuffer; - std::vector resampleBuffer; - + SpectrumVisualDataQueue visualDataQueue; // event table wxDECLARE_EVENT_TABLE(); From 00713c0259004eb01b254521280ac61476cf85af Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 3 Aug 2015 02:12:11 -0400 Subject: [PATCH 41/53] unused var, comment cleanup --- src/visual/SpectrumCanvas.cpp | 2 +- src/visual/SpectrumCanvas.h | 13 ------------- src/visual/WaterfallCanvas.cpp | 10 ---------- 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index 65a52b2..e618cc5 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -27,7 +27,7 @@ EVT_MOUSEWHEEL(SpectrumCanvas::OnMouseWheelMoved) wxEND_EVENT_TABLE() SpectrumCanvas::SpectrumCanvas(wxWindow *parent, int *attribList) : - InteractiveCanvas(parent, attribList), fft_size(0), waterfallCanvas(NULL), trackingRate(0) { + InteractiveCanvas(parent, attribList), waterfallCanvas(NULL) { glContext = new SpectrumContext(this, &wxGetApp().GetContext(this)); diff --git a/src/visual/SpectrumCanvas.h b/src/visual/SpectrumCanvas.h index 636296d..eb05e79 100644 --- a/src/visual/SpectrumCanvas.h +++ b/src/visual/SpectrumCanvas.h @@ -20,7 +20,6 @@ public: std::vector spectrum_points; SpectrumCanvas(wxWindow *parent, int *attribList = NULL); -// void setup(int fft_size_in); ~SpectrumCanvas(); void attachWaterfallCanvas(WaterfallCanvas *canvas_in); @@ -40,20 +39,8 @@ private: void OnMouseReleased(wxMouseEvent& event); void OnMouseLeftWindow(wxMouseEvent& event); -// fftwf_complex *in, *out; -// fftwf_plan plan; -// -// float fft_ceil_ma, fft_ceil_maa; -// float fft_floor_ma, fft_floor_maa; -// -// std::vector fft_result; -// std::vector fft_result_ma; -// std::vector fft_result_maa; - SpectrumContext *glContext; WaterfallCanvas *waterfallCanvas; - int fft_size; - int trackingRate; SpectrumVisualDataQueue visualDataQueue; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index c928d89..4efa1e6 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -717,16 +717,6 @@ void WaterfallCanvas::OnMouseRightReleased(wxMouseEvent& event) { mouseZoom = 1.0; } - -// -//bool WaterfallCanvas::isPolling() { -// return polling; -//} -// -//void WaterfallCanvas::setPolling(bool polling) { -// this->polling = polling; -//} - SpectrumVisualDataQueue *WaterfallCanvas::getVisualDataQueue() { return &visualDataQueue; } \ No newline at end of file From bab2ad3780f838f9a6223289f61da316a1b248f2 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 3 Aug 2015 23:41:37 -0400 Subject: [PATCH 42/53] cleanup --- src/AppFrame.cpp | 6 ------ src/audio/AudioThread.cpp | 4 ++-- src/demod/DemodulatorThread.cpp | 1 - src/util/DataTree.cpp | 2 +- src/util/GLExt.cpp | 2 -- src/util/GLFont.cpp | 2 +- src/util/GLFont.h | 1 - src/visual/SpectrumContext.cpp | 2 +- src/visual/SpectrumContext.h | 1 - src/visual/TuningCanvas.cpp | 2 +- src/visual/WaterfallCanvas.cpp | 6 +----- src/visual/WaterfallCanvas.h | 1 - src/visual/WaterfallContext.cpp | 2 +- 13 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index d758322..4463da5 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -561,12 +561,6 @@ void AppFrame::OnThread(wxCommandEvent& event) { } void AppFrame::OnIdle(wxIdleEvent& event) { - bool work_done = false; - -//#ifdef __APPLE__ -// std::this_thread::sleep_for(std::chrono::milliseconds(4)); -// std::this_thread::yield(); -//#endif DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); diff --git a/src/audio/AudioThread.cpp b/src/audio/AudioThread.cpp index 0c48fbb..789e016 100644 --- a/src/audio/AudioThread.cpp +++ b/src/audio/AudioThread.cpp @@ -12,13 +12,13 @@ std::map AudioThread::deviceSampleRate; std::map AudioThread::deviceThread; AudioThread::AudioThread() : IOThread(), - currentInput(NULL), inputQueue(NULL), gain( - 1.0), threadQueueNotify(NULL), sampleRate(0), nBufferFrames(1024) { + currentInput(NULL), inputQueue(NULL), nBufferFrames(1024), threadQueueNotify(NULL), sampleRate(0) { audioQueuePtr.store(0); underflowCount.store(0); active.store(false); outputDevice.store(-1); + gain.store(1.0); boundThreads = new std::vector; } diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 70306f2..d987a15 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -188,7 +188,6 @@ void DemodulatorThread::run() { } else if (demodulatorType == DEMOD_TYPE_RAW) { // do nothing here.. } else { - float p; switch (demodulatorType.load()) { case DEMOD_TYPE_LSB: for (int i = 0; i < bufSize; i++) { // Reject upper band diff --git a/src/util/DataTree.cpp b/src/util/DataTree.cpp index 1a17ec7..e150307 100755 --- a/src/util/DataTree.cpp +++ b/src/util/DataTree.cpp @@ -1598,8 +1598,8 @@ bool DataTree::LoadFromFile(const std::string& filename) { string compressionType(*header->getNext("compression")); dataSize = *header->getNext("uncompressed_size"); - bool uncompress = false; #if USE_FASTLZ + bool uncompress = false; if (compressionType == "FastLZ") { uncompress = true; } diff --git a/src/util/GLExt.cpp b/src/util/GLExt.cpp index f3a50a0..1de46d8 100644 --- a/src/util/GLExt.cpp +++ b/src/util/GLExt.cpp @@ -36,8 +36,6 @@ void initGLExtensions() { std::cout << std::endl << "Supported GL Extensions: " << std::endl << extensions << std::endl << std::endl; - int interval = 2; - #ifdef _WIN32 if (GLExtSupported("WGL_EXT_swap_control")) { std::cout << "Initializing WGL swap control extensions.." << std::endl; diff --git a/src/util/GLFont.cpp b/src/util/GLFont.cpp index d922e33..75109ae 100644 --- a/src/util/GLFont.cpp +++ b/src/util/GLFont.cpp @@ -103,7 +103,7 @@ int GLFontChar::getIndex() { } GLFont::GLFont() : - numCharacters(0), lineHeight(0), base(0), imageWidth(0), imageHeight(0), loaded(false), texId(0) { + lineHeight(0), base(0), imageWidth(0), imageHeight(0), loaded(false), texId(0) { } diff --git a/src/util/GLFont.h b/src/util/GLFont.h index 825459b..048095a 100644 --- a/src/util/GLFont.h +++ b/src/util/GLFont.h @@ -76,7 +76,6 @@ private: std::string getParamKey(std::string param_str); std::string getParamValue(std::string param_str); - int numCharacters; int lineHeight; int base; int imageWidth, imageHeight; diff --git a/src/visual/SpectrumContext.cpp b/src/visual/SpectrumContext.cpp index 8ee8cd7..22b78b7 100644 --- a/src/visual/SpectrumContext.cpp +++ b/src/visual/SpectrumContext.cpp @@ -7,7 +7,7 @@ #include "ColorTheme.h" SpectrumContext::SpectrumContext(SpectrumCanvas *canvas, wxGLContext *sharedContext) : - PrimaryGLContext(canvas, sharedContext), fft_size(0), floorValue(0), ceilValue(1) { + PrimaryGLContext(canvas, sharedContext), floorValue(0), ceilValue(1) { glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); diff --git a/src/visual/SpectrumContext.h b/src/visual/SpectrumContext.h index 13e3f98..03cc82a 100644 --- a/src/visual/SpectrumContext.h +++ b/src/visual/SpectrumContext.h @@ -19,6 +19,5 @@ public: void setCeilValue(float ceilValue); private: - int fft_size; float floorValue, ceilValue; }; diff --git a/src/visual/TuningCanvas.cpp b/src/visual/TuningCanvas.cpp index 5582f30..daed27e 100644 --- a/src/visual/TuningCanvas.cpp +++ b/src/visual/TuningCanvas.cpp @@ -31,7 +31,7 @@ EVT_KEY_UP(TuningCanvas::OnKeyUp) wxEND_EVENT_TABLE() TuningCanvas::TuningCanvas(wxWindow *parent, int *attribList) : - InteractiveCanvas(parent, attribList), dragAccum(0), top(false), bottom(false), uxDown(0) { + InteractiveCanvas(parent, attribList), dragAccum(0), uxDown(0), top(false), bottom(false) { glContext = new TuningContext(this, &wxGetApp().GetContext(this)); diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 4efa1e6..7fe2011 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -36,7 +36,7 @@ wxEND_EVENT_TABLE() WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : InteractiveCanvas(parent, attribList), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines( - 0), zoom(1), mouseZoom(1), hoverAlpha(1.0), dragOfs(0) { + 0), mouseZoom(1), zoom(1), hoverAlpha(1.0), dragOfs(0) { glContext = new WaterfallContext(this, &wxGetApp().GetContext(this)); @@ -173,7 +173,6 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { int currentBandwidth = getBandwidth(); long long currentCenterFreq = getCenterFrequency(); - float demodColor, selectorColor; ColorTheme *currentTheme = ThemeMgr::mgr.currentTheme; int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType(); @@ -260,13 +259,11 @@ void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) { void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { InteractiveCanvas::OnKeyDown(event); - float angle = 5.0; DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); long long freq; long long originalFreq; - unsigned int bw; switch (event.GetKeyCode()) { case 'A': zoom = 0.95; @@ -425,7 +422,6 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { setStatusText("Click and drag to set the current demodulator range."); } } else if (demodsHover->size() && !shiftDown) { - int hovered = -1; long near_dist = getBandwidth(); DemodulatorInstance *activeDemodulator = NULL; diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index 5c80c27..e7f3384 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -57,7 +57,6 @@ private: int waterfall_lines; int dragOfs; - int lastInputBandwidth; float mouseZoom, zoom; float hoverAlpha; diff --git a/src/visual/WaterfallContext.cpp b/src/visual/WaterfallContext.cpp index 3ff3e30..733cfc9 100644 --- a/src/visual/WaterfallContext.cpp +++ b/src/visual/WaterfallContext.cpp @@ -3,7 +3,7 @@ #include "CubicSDR.h" WaterfallContext::WaterfallContext(WaterfallCanvas *canvas, wxGLContext *sharedContext) : - PrimaryGLContext(canvas, sharedContext), waterfall_lines(0), waterfall_slice(NULL), fft_size(0), activeTheme(NULL) { + PrimaryGLContext(canvas, sharedContext), fft_size(0), waterfall_lines(0), waterfall_slice(NULL), activeTheme(NULL) { for (int i = 0; i < 2; i++) { waterfall[i] = 0; } From 9d4f9337588e98e1cbc0a69aef320ab929cf4c18 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 8 Aug 2015 13:26:53 -0400 Subject: [PATCH 43/53] synchronized refresh timer at 30fps, remove osx frame limiter hack - Tuning, Gain and Mode selector canvases no longer refresh unless necessary - Hopefully resolves refresh issues on El Capitan and others --- src/AppFrame.cpp | 28 ++++++++++++++++++++++++- src/AppFrame.h | 6 ++++-- src/ui/UITestCanvas.cpp | 3 --- src/visual/MeterCanvas.cpp | 6 ++---- src/visual/ModeSelectorCanvas.cpp | 8 +++---- src/visual/ScopeCanvas.cpp | 5 +---- src/visual/SpectrumCanvas.cpp | 30 ++++++++++++-------------- src/visual/TuningCanvas.cpp | 35 +++++++++++++++++++++---------- src/visual/TuningCanvas.h | 4 +++- src/visual/WaterfallCanvas.cpp | 34 ++++++++++++++---------------- src/visual/WaterfallContext.cpp | 2 +- src/visual/WaterfallContext.h | 2 +- 12 files changed, 95 insertions(+), 68 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 4463da5..66291dd 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -35,10 +35,11 @@ EVT_CLOSE(AppFrame::OnClose) EVT_MENU(wxID_ANY, AppFrame::OnMenu) EVT_COMMAND(wxID_ANY, wxEVT_THREAD, AppFrame::OnThread) EVT_IDLE(AppFrame::OnIdle) +EVT_TIMER(FRAME_TIMER_ID, AppFrame::OnTimer) wxEND_EVENT_TABLE() AppFrame::AppFrame() : - wxFrame(NULL, wxID_ANY, CUBICSDR_TITLE), activeDemodulator(NULL) { + wxFrame(NULL, wxID_ANY, CUBICSDR_TITLE), activeDemodulator(NULL), frame_timer(this, FRAME_TIMER_ID) { #ifdef __linux__ SetIcon(wxICON(cubicsdr)); @@ -350,6 +351,7 @@ AppFrame::AppFrame() : wxAcceleratorTable accel(3, entries); SetAcceleratorTable(accel); + frame_timer.Start(30); // static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 }; // wxLogStatus("Double-buffered display %s supported", wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not"); // ShowFullScreen(true); @@ -561,6 +563,10 @@ void AppFrame::OnThread(wxCommandEvent& event) { } void AppFrame::OnIdle(wxIdleEvent& event) { + event.Skip(); +} + +void AppFrame::OnTimer(wxTimerEvent& event) { DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); @@ -691,6 +697,26 @@ void AppFrame::OnIdle(wxIdleEvent& event) { dproc->setCenterFrequency(demodWaterfallCanvas->getCenterFrequency()); dproc->run(); + + scopeCanvas->Refresh(); + + waterfallCanvas->Refresh(); + spectrumCanvas->Refresh(); + + demodWaterfallCanvas->Refresh(); + demodSpectrumCanvas->Refresh(); + + demodSignalMeter->Refresh(); + + if (demodTuner->getMouseTracker()->mouseInView() || demodTuner->changed()) { + demodTuner->Refresh(); + } + if (demodModeSelector->getMouseTracker()->mouseInView()) { + demodModeSelector->Refresh(); + } + if (demodGainMeter->getMouseTracker()->mouseInView()) { + demodGainMeter->Refresh(); + } event.Skip(); } diff --git a/src/AppFrame.h b/src/AppFrame.h index 4d335a0..de90215 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -50,7 +50,7 @@ #define wxID_AUDIO_BANDWIDTH_BASE 9000 #define wxID_AUDIO_DEVICE_MULTIPLIER 50 - +#define FRAME_TIMER_ID 1000 // Define a new frame type class AppFrame: public wxFrame { @@ -69,6 +69,7 @@ private: void OnClose(wxCloseEvent& event); void OnNewWindow(wxCommandEvent& event); void OnIdle(wxIdleEvent& event); + void OnTimer(wxTimerEvent& event); ScopeCanvas *scopeCanvas; SpectrumCanvas *spectrumCanvas; @@ -93,6 +94,7 @@ private: wxMenuItem *iqSwapMenuItem; std::string currentSessionFile; - + wxTimer frame_timer; + wxDECLARE_EVENT_TABLE(); }; diff --git a/src/ui/UITestCanvas.cpp b/src/ui/UITestCanvas.cpp index e94a993..e3bf7d2 100644 --- a/src/ui/UITestCanvas.cpp +++ b/src/ui/UITestCanvas.cpp @@ -36,9 +36,6 @@ UITestCanvas::~UITestCanvas() { void UITestCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); -#ifdef __APPLE__ // force half-rate? - glFinish(); -#endif const wxSize ClientSize = GetClientSize(); glContext->SetCurrent(*this); diff --git a/src/visual/MeterCanvas.cpp b/src/visual/MeterCanvas.cpp index bb3c20b..423fc20 100644 --- a/src/visual/MeterCanvas.cpp +++ b/src/visual/MeterCanvas.cpp @@ -60,9 +60,6 @@ float MeterCanvas::getInputValue() { void MeterCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); -#ifdef __APPLE__ // force half-rate? - glFinish(); -#endif const wxSize ClientSize = GetClientSize(); glContext->SetCurrent(*this); @@ -82,7 +79,7 @@ void MeterCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { } void MeterCanvas::OnIdle(wxIdleEvent &event) { - Refresh(false); + event.Skip(); } void MeterCanvas::OnMouseMoved(wxMouseEvent& event) { @@ -115,6 +112,7 @@ void MeterCanvas::OnMouseReleased(wxMouseEvent& event) { void MeterCanvas::OnMouseLeftWindow(wxMouseEvent& event) { InteractiveCanvas::OnMouseLeftWindow(event); SetCursor(wxCURSOR_CROSS); + Refresh(); } void MeterCanvas::OnMouseEnterWindow(wxMouseEvent& event) { diff --git a/src/visual/ModeSelectorCanvas.cpp b/src/visual/ModeSelectorCanvas.cpp index 1b859e3..98172b5 100644 --- a/src/visual/ModeSelectorCanvas.cpp +++ b/src/visual/ModeSelectorCanvas.cpp @@ -47,10 +47,7 @@ int ModeSelectorCanvas::getHoveredSelection() { void ModeSelectorCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); -#ifdef __APPLE__ // force half-rate? - glFinish(); -#endif - const wxSize ClientSize = GetClientSize(); + const wxSize ClientSize = GetClientSize(); glContext->SetCurrent(*this); initGLExtensions(); @@ -75,7 +72,7 @@ void ModeSelectorCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { } void ModeSelectorCanvas::OnIdle(wxIdleEvent &event) { - Refresh(false); + event.Skip(); } void ModeSelectorCanvas::OnMouseMoved(wxMouseEvent& event) { @@ -109,6 +106,7 @@ void ModeSelectorCanvas::OnMouseReleased(wxMouseEvent& event) { void ModeSelectorCanvas::OnMouseLeftWindow(wxMouseEvent& event) { InteractiveCanvas::OnMouseLeftWindow(event); SetCursor (wxCURSOR_CROSS); + Refresh(); } void ModeSelectorCanvas::OnMouseEnterWindow(wxMouseEvent& event) { diff --git a/src/visual/ScopeCanvas.cpp b/src/visual/ScopeCanvas.cpp index 5c6bd54..88d6a33 100644 --- a/src/visual/ScopeCanvas.cpp +++ b/src/visual/ScopeCanvas.cpp @@ -50,9 +50,6 @@ bool ScopeCanvas::getPPMMode() { void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); -#ifdef __APPLE__ // force half-rate? - glFinish(); -#endif const wxSize ClientSize = GetClientSize(); wxGetApp().getScopeProcessor()->run(); @@ -94,7 +91,7 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { } void ScopeCanvas::OnIdle(wxIdleEvent &event) { - Refresh(false); + event.Skip(); } ScopeRenderDataQueue *ScopeCanvas::getInputQueue() { diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index e618cc5..5052f24 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -42,26 +42,22 @@ SpectrumCanvas::~SpectrumCanvas() { void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); -#ifdef __APPLE__ // force half-rate? - glFinish(); -#endif const wxSize ClientSize = GetClientSize(); - if (visualDataQueue.empty()) { - return; + if (!visualDataQueue.empty()) { + SpectrumVisualData *vData; + + visualDataQueue.pop(vData); + + if (!vData) { + return; + } + + spectrum_points.assign(vData->spectrum_points.begin(),vData->spectrum_points.end()); + + vData->decRefCount(); } - SpectrumVisualData *vData; - - visualDataQueue.pop(vData); - - if (!vData) { - return; - } - - spectrum_points.assign(vData->spectrum_points.begin(),vData->spectrum_points.end()); - - vData->decRefCount(); glContext->SetCurrent(*this); initGLExtensions(); @@ -84,7 +80,7 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { void SpectrumCanvas::OnIdle(wxIdleEvent &event) { - Refresh(false); + event.Skip(); } diff --git a/src/visual/TuningCanvas.cpp b/src/visual/TuningCanvas.cpp index daed27e..cb618f6 100644 --- a/src/visual/TuningCanvas.cpp +++ b/src/visual/TuningCanvas.cpp @@ -31,7 +31,7 @@ EVT_KEY_UP(TuningCanvas::OnKeyUp) wxEND_EVENT_TABLE() TuningCanvas::TuningCanvas(wxWindow *parent, int *attribList) : - InteractiveCanvas(parent, attribList), dragAccum(0), uxDown(0), top(false), bottom(false) { + InteractiveCanvas(parent, attribList), dragAccum(0), uxDown(0), top(false), bottom(false), freq(-1), bw(-1), center(-1) { glContext = new TuningContext(this, &wxGetApp().GetContext(this)); @@ -57,13 +57,27 @@ TuningCanvas::~TuningCanvas() { } +bool TuningCanvas::changed() { + DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + + long long current_freq = 0; + if (activeDemod != NULL) { + freq = activeDemod->getFrequency(); + } + long long current_bw = wxGetApp().getDemodMgr().getLastBandwidth(); + long long current_center = wxGetApp().getFrequency(); + + if (current_freq != freq || current_bw != bw || current_center != center) { + return true; + } + + return false; +} + void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); -#ifdef __APPLE__ // force half-rate? - glFinish(); -#endif const wxSize ClientSize = GetClientSize(); - + glContext->SetCurrent(*this); initGLExtensions(); glViewport(0, 0, ClientSize.x, ClientSize.y); @@ -71,13 +85,13 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glContext->DrawBegin(); DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); - - long long freq = 0; + + freq = 0; if (activeDemod != NULL) { freq = activeDemod->getFrequency(); } - long long bw = wxGetApp().getDemodMgr().getLastBandwidth(); - long long center = wxGetApp().getFrequency(); + bw = wxGetApp().getDemodMgr().getLastBandwidth(); + center = wxGetApp().getFrequency(); if (mouseTracker.mouseDown()) { glContext->Draw(ThemeMgr::mgr.currentTheme->tuningBarDark.r, ThemeMgr::mgr.currentTheme->tuningBarDark.g, ThemeMgr::mgr.currentTheme->tuningBarDark.b, @@ -238,8 +252,6 @@ void TuningCanvas::OnIdle(wxIdleEvent &event) { dragging = false; } } - - Refresh(false); } void TuningCanvas::OnMouseMoved(wxMouseEvent& event) { @@ -373,6 +385,7 @@ void TuningCanvas::OnMouseLeftWindow(wxMouseEvent& event) { if (currentPPM != lastPPM) { wxGetApp().saveConfig(); } + Refresh(); } void TuningCanvas::OnMouseEnterWindow(wxMouseEvent& event) { diff --git a/src/visual/TuningCanvas.h b/src/visual/TuningCanvas.h index 1fea2e2..2826363 100644 --- a/src/visual/TuningCanvas.h +++ b/src/visual/TuningCanvas.h @@ -22,7 +22,8 @@ public: ~TuningCanvas(); void setHelpTip(std::string tip); - + bool changed(); + private: void OnPaint(wxPaintEvent& event); void OnIdle(wxIdleEvent &event); @@ -66,6 +67,7 @@ private: int currentPPM; int lastPPM; + long long freq, bw, center; // wxDECLARE_EVENT_TABLE(); }; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 7fe2011..be6639e 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -70,9 +70,6 @@ void WaterfallCanvas::attachSpectrumCanvas(SpectrumCanvas *canvas_in) { void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); -#ifdef __APPLE__ // force half-rate? - glFinish(); -#endif const wxSize ClientSize = GetClientSize(); long double currentZoom = zoom; @@ -139,28 +136,29 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { } } - if (visualDataQueue.empty()) { - return; + bool step = false; + if (!visualDataQueue.empty()) { + SpectrumVisualData *vData; + + visualDataQueue.pop(vData); + + if (!vData) { + return; + } + + spectrum_points.assign(vData->spectrum_points.begin(),vData->spectrum_points.end()); + + vData->decRefCount(); + step = true; } - SpectrumVisualData *vData; - - visualDataQueue.pop(vData); - - if (!vData) { - return; - } - - spectrum_points.assign(vData->spectrum_points.begin(),vData->spectrum_points.end()); - - vData->decRefCount(); glContext->SetCurrent(*this); initGLExtensions(); glViewport(0, 0, ClientSize.x, ClientSize.y); glContext->BeginDraw(0,0,0); - glContext->Draw(spectrum_points); + glContext->Draw(spectrum_points, step); std::vector &demods = wxGetApp().getDemodMgr().getDemodulators(); @@ -352,7 +350,7 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { } } void WaterfallCanvas::OnIdle(wxIdleEvent &event) { - Refresh(false); + event.Skip(); } void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { diff --git a/src/visual/WaterfallContext.cpp b/src/visual/WaterfallContext.cpp index 733cfc9..8ba0f45 100644 --- a/src/visual/WaterfallContext.cpp +++ b/src/visual/WaterfallContext.cpp @@ -36,7 +36,7 @@ void WaterfallContext::refreshTheme() { } } -void WaterfallContext::Draw(std::vector &points) { +void WaterfallContext::Draw(std::vector &points, bool step) { int half_fft_size = fft_size / 2; diff --git a/src/visual/WaterfallContext.h b/src/visual/WaterfallContext.h index f42b5f9..e993747 100644 --- a/src/visual/WaterfallContext.h +++ b/src/visual/WaterfallContext.h @@ -10,7 +10,7 @@ class WaterfallContext: public PrimaryGLContext { public: WaterfallContext(WaterfallCanvas *canvas, wxGLContext *sharedContext); - void Draw(std::vector &points); + void Draw(std::vector &points, bool step); void Setup(int fft_size_in, int num_waterfall_lines_in); void refreshTheme(); From 8a0034d24abd8ee4502f439ca7591a3c794aa46b Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 8 Aug 2015 14:15:57 -0400 Subject: [PATCH 44/53] Add source groups --- CMakeLists.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 209f2a0..841d5cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -339,6 +339,21 @@ SET (cubicsdr_headers external/cubicvr2/math/vec4.h ) +set(REG_EXT "[^/]*([.]cpp|[.]c|[.]h|[.]hpp)$") + +SOURCE_GROUP("Base" REGULAR_EXPRESSION src/${REG_EXT}) +SOURCE_GROUP("SDR" REGULAR_EXPRESSION src/sdr/${REG_EXT}) +SOURCE_GROUP("Demodulator" REGULAR_EXPRESSION src/demod/${REG_EXT}) +SOURCE_GROUP("Audio" REGULAR_EXPRESSION src/audio/${REG_EXT}) +SOURCE_GROUP("Utility" REGULAR_EXPRESSION src/util/${REG_EXT}) +SOURCE_GROUP("Visual" REGULAR_EXPRESSION src/visual/${REG_EXT}) +SOURCE_GROUP("Process" REGULAR_EXPRESSION src/process/${REG_EXT}) +SOURCE_GROUP("UI" REGULAR_EXPRESSION src/ui/${REG_EXT}) +SOURCE_GROUP("_ext-RTAudio" REGULAR_EXPRESSION external/rtaudio/.*${REG_EXT}) +SOURCE_GROUP("_ext-LodePNG" REGULAR_EXPRESSION external/lodepng/.*${REG_EXT}) +SOURCE_GROUP("_ext-TinyXML" REGULAR_EXPRESSION external/tinyxml/.*${REG_EXT}) +SOURCE_GROUP("_ext-CubicVR2" REGULAR_EXPRESSION external/cubicvr2/.*${REG_EXT}) + include_directories ( ${PROJECT_SOURCE_DIR}/src/sdr ${PROJECT_SOURCE_DIR}/src/demod From 8b48b4e44954c0cee5d7ea13775cdf679e6cedaa Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 8 Aug 2015 14:31:23 -0400 Subject: [PATCH 45/53] set swap interval down to 1; frames are timed instead of throttled now --- src/util/GLExt.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util/GLExt.cpp b/src/util/GLExt.cpp index 1de46d8..47ccfdf 100644 --- a/src/util/GLExt.cpp +++ b/src/util/GLExt.cpp @@ -36,6 +36,8 @@ void initGLExtensions() { std::cout << std::endl << "Supported GL Extensions: " << std::endl << extensions << std::endl << std::endl; + const GLint interval = 1; + #ifdef _WIN32 if (GLExtSupported("WGL_EXT_swap_control")) { std::cout << "Initializing WGL swap control extensions.." << std::endl; @@ -48,8 +50,7 @@ void initGLExtensions() { #ifdef __APPLE__ // OSX is just ON / OFF - const GLint gl_interval = 1; - CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, &gl_interval); + CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, &interval); #endif #ifdef __linux__ From aa6e612d6a674b2f868074d34dc91fad2fe754c4 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 8 Aug 2015 14:52:01 -0400 Subject: [PATCH 46/53] Move processor call out of scope canvas --- src/AppFrame.cpp | 2 +- src/visual/ScopeCanvas.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 66291dd..842267c 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -679,7 +679,7 @@ void AppFrame::OnTimer(wxTimerEvent& event) { scopeCanvas->setPPMMode(demodTuner->isAltDown()); - + wxGetApp().getScopeProcessor()->run(); wxGetApp().getSpectrumDistributor()->run(); SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcesor(); diff --git a/src/visual/ScopeCanvas.cpp b/src/visual/ScopeCanvas.cpp index 88d6a33..268fe7b 100644 --- a/src/visual/ScopeCanvas.cpp +++ b/src/visual/ScopeCanvas.cpp @@ -52,7 +52,6 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); const wxSize ClientSize = GetClientSize(); - wxGetApp().getScopeProcessor()->run(); if (!inputData.empty()) { ScopeRenderData *avData; inputData.pop(avData); From db8e7a68d0f018ce77eea8a58dd2874245f72c5c Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 9 Aug 2015 12:51:01 -0400 Subject: [PATCH 47/53] Re-usable ScopePanel to replace ScopeContext Plot --- CMakeLists.txt | 4 + src/AppFrame.cpp | 4 +- src/panel/ScopePanel.cpp | 91 ++++++++++++++++++++++ src/panel/ScopePanel.h | 20 +++++ src/process/ScopeVisualProcessor.cpp | 19 ++++- src/ui/GLPanel.cpp | 6 +- src/visual/ColorTheme.h | 3 + src/visual/ScopeCanvas.cpp | 11 ++- src/visual/ScopeCanvas.h | 4 +- src/visual/ScopeContext.cpp | 110 +-------------------------- src/visual/ScopeContext.h | 2 +- 11 files changed, 152 insertions(+), 122 deletions(-) create mode 100644 src/panel/ScopePanel.cpp create mode 100644 src/panel/ScopePanel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 841d5cd..0d16cd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,6 +244,7 @@ SET (cubicsdr_sources src/util/GLExt.cpp src/util/GLFont.cpp src/util/DataTree.cpp + src/panel/ScopePanel.cpp src/visual/ColorTheme.cpp src/visual/PrimaryGLContext.cpp src/visual/InteractiveCanvas.cpp @@ -296,6 +297,7 @@ SET (cubicsdr_headers src/util/GLExt.h src/util/GLFont.h src/util/DataTree.h + src/panel/ScopePanel.h src/visual/ColorTheme.h src/visual/PrimaryGLContext.h src/visual/InteractiveCanvas.h @@ -346,6 +348,7 @@ SOURCE_GROUP("SDR" REGULAR_EXPRESSION src/sdr/${REG_EXT}) SOURCE_GROUP("Demodulator" REGULAR_EXPRESSION src/demod/${REG_EXT}) SOURCE_GROUP("Audio" REGULAR_EXPRESSION src/audio/${REG_EXT}) SOURCE_GROUP("Utility" REGULAR_EXPRESSION src/util/${REG_EXT}) +SOURCE_GROUP("Panel" REGULAR_EXPRESSION src/panel/${REG_EXT}) SOURCE_GROUP("Visual" REGULAR_EXPRESSION src/visual/${REG_EXT}) SOURCE_GROUP("Process" REGULAR_EXPRESSION src/process/${REG_EXT}) SOURCE_GROUP("UI" REGULAR_EXPRESSION src/ui/${REG_EXT}) @@ -359,6 +362,7 @@ include_directories ( ${PROJECT_SOURCE_DIR}/src/demod ${PROJECT_SOURCE_DIR}/src/audio ${PROJECT_SOURCE_DIR}/src/util + ${PROJECT_SOURCE_DIR}/src/panel ${PROJECT_SOURCE_DIR}/src/visual ${PROJECT_SOURCE_DIR}/src/process ${PROJECT_SOURCE_DIR}/src/ui diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 842267c..85ecdfa 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -707,6 +707,7 @@ void AppFrame::OnTimer(wxTimerEvent& event) { demodSpectrumCanvas->Refresh(); demodSignalMeter->Refresh(); + demodGainMeter->Refresh(); if (demodTuner->getMouseTracker()->mouseInView() || demodTuner->changed()) { demodTuner->Refresh(); @@ -714,9 +715,6 @@ void AppFrame::OnTimer(wxTimerEvent& event) { if (demodModeSelector->getMouseTracker()->mouseInView()) { demodModeSelector->Refresh(); } - if (demodGainMeter->getMouseTracker()->mouseInView()) { - demodGainMeter->Refresh(); - } event.Skip(); } diff --git a/src/panel/ScopePanel.cpp b/src/panel/ScopePanel.cpp new file mode 100644 index 0000000..7f60597 --- /dev/null +++ b/src/panel/ScopePanel.cpp @@ -0,0 +1,91 @@ +#include "ScopePanel.h" +#include "ColorTheme.h" + +ScopePanel::ScopePanel() : GLPanel(), scopeMode(SCOPE_MODE_Y) { + bgPanel.setFill(GLPanelFillType::GLPANEL_FILL_GRAD_BAR_Y); + bgPanelStereo[0].setFill(GLPanelFillType::GLPANEL_FILL_GRAD_BAR_Y); + bgPanelStereo[0].setPosition(0, 0.5); + bgPanelStereo[0].setSize(1, 0.5); + bgPanelStereo[1].setFill(GLPanelFillType::GLPANEL_FILL_GRAD_BAR_Y); + bgPanelStereo[1].setPosition(0, -0.5); + bgPanelStereo[1].setSize(1, 0.5); +} + +void ScopePanel::setMode(ScopeMode scopeMode) { + this->scopeMode = scopeMode; +} + + +void ScopePanel::setPoints(std::vector &points) { + this->points.assign(points.begin(),points.end()); +} + +void ScopePanel::drawPanelContents() { + + glLineWidth(1.0); + + if (scopeMode == SCOPE_MODE_Y) { + bgPanel.setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground, ThemeMgr::mgr.currentTheme->scopeBackground * 2.0); + bgPanel.calcTransform(transform); + bgPanel.draw(); + + glLoadIdentity(); + glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r * 0.35, ThemeMgr::mgr.currentTheme->scopeLine.g * 0.35, + ThemeMgr::mgr.currentTheme->scopeLine.b * 0.35); + glBegin (GL_LINES); + glVertex2f(-1.0, 0.0); + glVertex2f(1.0, 0.0); + glEnd(); + } else if (scopeMode == SCOPE_MODE_2Y) { + bgPanelStereo[0].setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground, ThemeMgr::mgr.currentTheme->scopeBackground * 2.0); + bgPanelStereo[1].setFillColor(ThemeMgr::mgr.currentTheme->scopeBackground, ThemeMgr::mgr.currentTheme->scopeBackground * 2.0); + + bgPanelStereo[0].calcTransform(transform); + bgPanelStereo[0].draw(); + bgPanelStereo[1].calcTransform(transform); + bgPanelStereo[1].draw(); + + glLoadIdentity(); + glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r, ThemeMgr::mgr.currentTheme->scopeLine.g, ThemeMgr::mgr.currentTheme->scopeLine.b); + glBegin (GL_LINES); + glVertex2f(-1.0, 0.0); + glVertex2f(1.0, 0.0); + glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r * 0.35, ThemeMgr::mgr.currentTheme->scopeLine.g * 0.35, + ThemeMgr::mgr.currentTheme->scopeLine.b * 0.35); + glVertex2f(-1.0, 0.5); + glVertex2f(1.0, 0.5); + glVertex2f(-1.0, -0.5); + glVertex2f(1.0, -0.5); + glEnd(); + + } else if (scopeMode == SCOPE_MODE_XY) { + // ... + } + + if (points.size()) { + glEnable (GL_BLEND); + glEnable (GL_LINE_SMOOTH); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(ThemeMgr::mgr.currentTheme->scopeLine.r, ThemeMgr::mgr.currentTheme->scopeLine.g, ThemeMgr::mgr.currentTheme->scopeLine.b, 1.0); + glEnableClientState (GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, &points[0]); + glLineWidth(1.5); + if (scopeMode == SCOPE_MODE_Y) { + glLoadMatrixf(bgPanel.transform); + glDrawArrays(GL_LINE_STRIP, 0, points.size() / 2); + } else if (scopeMode == SCOPE_MODE_2Y) { + glLoadMatrixf(bgPanelStereo[0].transform); + glDrawArrays(GL_LINE_STRIP, 0, points.size() / 4); + + glLoadMatrixf(bgPanelStereo[1].transform); + glDrawArrays(GL_LINE_STRIP, points.size() / 4, points.size() / 4); + } else if (scopeMode == SCOPE_MODE_XY) { + // ... + } + glLineWidth(1.0); + glDisableClientState(GL_VERTEX_ARRAY); + glDisable(GL_BLEND); + } +} + diff --git a/src/panel/ScopePanel.h b/src/panel/ScopePanel.h new file mode 100644 index 0000000..2907448 --- /dev/null +++ b/src/panel/ScopePanel.h @@ -0,0 +1,20 @@ +#pragma once + +#include "GLPanel.h" + +class ScopePanel : public GLPanel { + +public: + typedef enum ScopeMode { SCOPE_MODE_Y, SCOPE_MODE_2Y, SCOPE_MODE_XY } ScopeMode; + + ScopePanel(); + + void setMode(ScopeMode scopeMode); + void setPoints(std::vector &points); + void drawPanelContents(); + + std::vector points; + ScopeMode scopeMode; + GLPanel bgPanel; + GLPanel bgPanelStereo[2]; +}; \ No newline at end of file diff --git a/src/process/ScopeVisualProcessor.cpp b/src/process/ScopeVisualProcessor.cpp index 4eff90d..7439977 100644 --- a/src/process/ScopeVisualProcessor.cpp +++ b/src/process/ScopeVisualProcessor.cpp @@ -23,12 +23,27 @@ void ScopeVisualProcessor::process() { if (renderData->waveform_points.size() != iMax * 2) { renderData->waveform_points.resize(iMax * 2); } + + float peak = 1.0f; for (int i = 0; i < iMax; i++) { - renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] * 0.5f; - renderData->waveform_points[i * 2] = ((double) i / (double) iMax); + float p = fabs(audioInputData->data[i]); + if (p > peak) { + peak = p; + } } + if (audioInputData->channels == 2) { + for (int i = 0; i < iMax; i++) { + renderData->waveform_points[i * 2] = (((double) (i % (iMax/2)) / (double) iMax) * 2.0 - 0.5) * 2.0; + renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] / peak; + } + } else { + for (int i = 0; i < iMax; i++) { + renderData->waveform_points[i * 2] = (((double) i / (double) iMax) - 0.5) * 2.0; + renderData->waveform_points[i * 2 + 1] = audioInputData->data[i] / peak; + } + } distribute(renderData); } } diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index 5de9387..ae44400 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -225,7 +225,7 @@ void GLPanel::drawPanelContents() { void GLPanel::calcTransform(mat4 transform_in) { // compute local transform - localTransform = mat4::translate(pos[0], pos[1], 0) * mat4::scale(size[0], size[1], 0); + localTransform = mat4::translate(pos[0], pos[1], 0) * mat4::scale(size[0], size[1], 1); // compute global transform transform = transform_in * localTransform; @@ -250,10 +250,10 @@ void GLPanel::calcTransform(mat4 transform_in) { pdim = vec2((vmax.x - vmin.x) / 2.0 * view[0], (vmax.y - vmin.y) / 2.0 * view[1]); pvec = vec2(((vmax.x - vmin.x) / 2.0) / pdim.x, ((vmax.y - vmin.y) / 2.0) / pdim.y); - std::cout << umin << " :: " << ucenter << " :: " << pdim << " :: " << pvec << std::endl; +// std::cout << umin << " :: " << ucenter << " :: " << pdim << " :: " << pvec << std::endl; if (marginPx) { - transform *= mat4::scale(1.0 - marginPx * 2.0 * pvec.x / size[0], 1.0 - marginPx * 2.0 * pvec.y / size[1], 0); + transform *= mat4::scale(1.0 - marginPx * 2.0 * pvec.x / size[0], 1.0 - marginPx * 2.0 * pvec.y / size[1], 1); } } diff --git a/src/visual/ColorTheme.h b/src/visual/ColorTheme.h index 1318ac6..52b431a 100644 --- a/src/visual/ColorTheme.h +++ b/src/visual/ColorTheme.h @@ -35,6 +35,9 @@ public: b = other.b; return *this; } + + RGB3f operator*(float v) { return RGB3f(r*v, g*v, b*v); } + }; class ColorTheme { diff --git a/src/visual/ScopeCanvas.cpp b/src/visual/ScopeCanvas.cpp index 268fe7b..febc3b5 100644 --- a/src/visual/ScopeCanvas.cpp +++ b/src/visual/ScopeCanvas.cpp @@ -15,6 +15,7 @@ #include "AppFrame.h" #include + wxBEGIN_EVENT_TABLE(ScopeCanvas, wxGLCanvas) EVT_PAINT(ScopeCanvas::OnPaint) EVT_IDLE(ScopeCanvas::OnIdle) wxEND_EVENT_TABLE() @@ -66,8 +67,9 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { avData->decRefCount(); return; } - - waveform_points.assign(avData->waveform_points.begin(),avData->waveform_points.end()); + + scopePanel.setPoints(avData->waveform_points); +// waveform_points.assign(avData->waveform_points.begin(),avData->waveform_points.end()); setStereo(avData->channels == 2); avData->decRefCount(); @@ -79,7 +81,10 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glViewport(0, 0, ClientSize.x, ClientSize.y); glContext->DrawBegin(); - glContext->Plot(waveform_points, stereo, ppmMode); + scopePanel.setMode(stereo?ScopePanel::SCOPE_MODE_2Y:ScopePanel::SCOPE_MODE_Y); + scopePanel.calcTransform(CubicVR::mat4::identity()); + scopePanel.draw(); + glContext->DrawTunerTitles(ppmMode); if (!deviceName.empty()) { glContext->DrawDeviceName(deviceName); } diff --git a/src/visual/ScopeCanvas.h b/src/visual/ScopeCanvas.h index 23203b7..6cdff03 100644 --- a/src/visual/ScopeCanvas.h +++ b/src/visual/ScopeCanvas.h @@ -8,12 +8,11 @@ #include "ScopeContext.h" #include "ScopeVisualProcessor.h" +#include "ScopePanel.h" #include "fftw3.h" class ScopeCanvas: public wxGLCanvas { public: - std::vector waveform_points; - ScopeCanvas(wxWindow *parent, int *attribList = NULL); ~ScopeCanvas(); @@ -29,6 +28,7 @@ private: void OnIdle(wxIdleEvent &event); ScopeRenderDataQueue inputData; + ScopePanel scopePanel; ScopeContext *glContext; std::string deviceName; bool stereo; diff --git a/src/visual/ScopeContext.cpp b/src/visual/ScopeContext.cpp index 267b038..8c4a889 100644 --- a/src/visual/ScopeContext.cpp +++ b/src/visual/ScopeContext.cpp @@ -23,56 +23,8 @@ void ScopeContext::DrawBegin() { glDisable (GL_TEXTURE_2D); } -void ScopeContext::Plot(std::vector &points, bool stereo, bool ppmMode) { - if (stereo) { - glBegin(GL_QUADS); - glColor3f(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g, ThemeMgr::mgr.currentTheme->scopeBackground.b); - glVertex2f(1, 1); - glVertex2f(-1, 1); - glColor3f(ThemeMgr::mgr.currentTheme->scopeBackground.r*2.0, ThemeMgr::mgr.currentTheme->scopeBackground.g*2.0, ThemeMgr::mgr.currentTheme->scopeBackground.b*2.0); - glVertex2f(-1, 0.5); - glVertex2f(1, 0.5); - - glVertex2f(-1, 0.5); - glVertex2f(1, 0.5); - glColor3f(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g, ThemeMgr::mgr.currentTheme->scopeBackground.b); - glVertex2f(1, 0.0); - glVertex2f(-1, 0.0); - - glColor3f(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g, ThemeMgr::mgr.currentTheme->scopeBackground.b); - glVertex2f(1, 0); - glVertex2f(-1, 0); - glColor3f(ThemeMgr::mgr.currentTheme->scopeBackground.r*2.0, ThemeMgr::mgr.currentTheme->scopeBackground.g*2.0, ThemeMgr::mgr.currentTheme->scopeBackground.b*2.0); - glVertex2f(-1, -0.5); - glVertex2f(1, -0.5); - - glVertex2f(-1, -0.5); - glVertex2f(1, -0.5); - glColor3f(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g, ThemeMgr::mgr.currentTheme->scopeBackground.b); - glVertex2f(1, -1.0); - glVertex2f(-1, -1.0); - glEnd(); - } else { - glBegin (GL_QUADS); - glColor3f(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g, - ThemeMgr::mgr.currentTheme->scopeBackground.b); - glVertex2f(1, 1); - glVertex2f(-1, 1); - glColor3f(ThemeMgr::mgr.currentTheme->scopeBackground.r * 2.0, ThemeMgr::mgr.currentTheme->scopeBackground.g * 2.0, - ThemeMgr::mgr.currentTheme->scopeBackground.b * 2.0); - glVertex2f(-1, 0); - glVertex2f(1, 0); - - glVertex2f(-1, 0); - glVertex2f(1, 0); - glColor3f(ThemeMgr::mgr.currentTheme->scopeBackground.r, ThemeMgr::mgr.currentTheme->scopeBackground.g, - ThemeMgr::mgr.currentTheme->scopeBackground.b); - glVertex2f(1, -1); - glVertex2f(-1, -1); - glEnd(); - } - glLineWidth(1.0); - +void ScopeContext::DrawTunerTitles(bool ppmMode) { + glLoadIdentity(); GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp); @@ -84,64 +36,6 @@ void ScopeContext::Plot(std::vector &points, bool stereo, bool ppmMode) { GLFont::getFont(GLFont::GLFONT_SIZE12).drawString(ppmMode?"Device PPM":"Frequency", -0.66, -1.0+hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); GLFont::getFont(GLFont::GLFONT_SIZE12).drawString("Bandwidth", 0.0, -1.0+hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); GLFont::getFont(GLFont::GLFONT_SIZE12).drawString("Center Frequency", 0.66, -1.0+hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); - - - if (stereo) { - glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r, ThemeMgr::mgr.currentTheme->scopeLine.g, ThemeMgr::mgr.currentTheme->scopeLine.b); - glBegin (GL_LINES); - glVertex2f(-1.0, 0.0); - glVertex2f(1.0, 0.0); - glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r * 0.35, ThemeMgr::mgr.currentTheme->scopeLine.g * 0.35, - ThemeMgr::mgr.currentTheme->scopeLine.b * 0.35); - glVertex2f(-1.0, 0.5); - glVertex2f(1.0, 0.5); - glVertex2f(-1.0, -0.5); - glVertex2f(1.0, -0.5); - glEnd(); - } else { - glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r * 0.35, ThemeMgr::mgr.currentTheme->scopeLine.g * 0.35, - ThemeMgr::mgr.currentTheme->scopeLine.b * 0.35); - glBegin (GL_LINES); - glVertex2f(-1.0, 0.0); - glVertex2f(1.0, 0.0); - glEnd(); - } - - if (points.size()) { - glEnable (GL_BLEND); - glEnable (GL_LINE_SMOOTH); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(ThemeMgr::mgr.currentTheme->scopeLine.r, ThemeMgr::mgr.currentTheme->scopeLine.g, ThemeMgr::mgr.currentTheme->scopeLine.b, 1.0); - glEnableClientState (GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, &points[0]); - if (stereo) { - glLineWidth(1.5); - glPushMatrix(); - glTranslatef(-1.0f, 0.5f, 0.0f); - glScalef(4.0f, 0.92f, 1.0f); - glDrawArrays(GL_LINE_STRIP, 0, points.size() / 4); - glPopMatrix(); - - glPushMatrix(); - glTranslatef(-3.0f, -0.5f, 0.0f); - glPushMatrix(); - glScalef(4.0f, 0.92f, 1.0f); - glDrawArrays(GL_LINE_STRIP, points.size() / 4, points.size() / 4); - glPopMatrix(); - glPopMatrix(); - } else { - glLineWidth(1.5); - glPushMatrix(); - glTranslatef(-1.0f, 0.0f, 0.0f); - glScalef(2.0f, 2.0f, 1.0f); - glDrawArrays(GL_LINE_STRIP, 0, points.size() / 2); - glPopMatrix(); - } - glLineWidth(1.0); - glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_BLEND); - } } void ScopeContext::DrawDeviceName(std::string deviceName) { diff --git a/src/visual/ScopeContext.h b/src/visual/ScopeContext.h index 4afc6ad..c962429 100644 --- a/src/visual/ScopeContext.h +++ b/src/visual/ScopeContext.h @@ -12,7 +12,7 @@ public: ScopeContext(ScopeCanvas *canvas, wxGLContext *sharedContext); void DrawBegin(); - void Plot(std::vector &points, bool stereo=false, bool ppmMode=false); + void DrawTunerTitles(bool ppmMode=false); void DrawDeviceName(std::string deviceName); void DrawDivider(); void DrawEnd(); From c970f8d5db0668174d270b2409bb5dbd4f519842 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 9 Aug 2015 13:23:58 -0400 Subject: [PATCH 48/53] Transform error for scope divider / center line --- src/panel/ScopePanel.cpp | 4 ++-- src/visual/ScopeCanvas.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/panel/ScopePanel.cpp b/src/panel/ScopePanel.cpp index 7f60597..c50fa08 100644 --- a/src/panel/ScopePanel.cpp +++ b/src/panel/ScopePanel.cpp @@ -29,7 +29,7 @@ void ScopePanel::drawPanelContents() { bgPanel.calcTransform(transform); bgPanel.draw(); - glLoadIdentity(); + glLoadMatrixf(transform); glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r * 0.35, ThemeMgr::mgr.currentTheme->scopeLine.g * 0.35, ThemeMgr::mgr.currentTheme->scopeLine.b * 0.35); glBegin (GL_LINES); @@ -45,7 +45,7 @@ void ScopePanel::drawPanelContents() { bgPanelStereo[1].calcTransform(transform); bgPanelStereo[1].draw(); - glLoadIdentity(); + glLoadMatrixf(transform); glColor3f(ThemeMgr::mgr.currentTheme->scopeLine.r, ThemeMgr::mgr.currentTheme->scopeLine.g, ThemeMgr::mgr.currentTheme->scopeLine.b); glBegin (GL_LINES); glVertex2f(-1.0, 0.0); diff --git a/src/visual/ScopeCanvas.cpp b/src/visual/ScopeCanvas.cpp index febc3b5..f27d355 100644 --- a/src/visual/ScopeCanvas.cpp +++ b/src/visual/ScopeCanvas.cpp @@ -69,7 +69,6 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { } scopePanel.setPoints(avData->waveform_points); -// waveform_points.assign(avData->waveform_points.begin(),avData->waveform_points.end()); setStereo(avData->channels == 2); avData->decRefCount(); From 2f0d6b9c75f87a9c3e81ccfe25028823358a48ff Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 9 Aug 2015 23:00:51 -0400 Subject: [PATCH 49/53] Re-usable WaterfallPanel to replace WaterfallContext --- CMakeLists.txt | 6 +- src/panel/SpectrumPanel.cpp | 2 + src/panel/SpectrumPanel.h | 7 + .../WaterfallPanel.cpp} | 132 ++++++++++-------- src/panel/WaterfallPanel.h | 25 ++++ src/ui/GLPanel.cpp | 2 + src/visual/WaterfallCanvas.cpp | 42 +++--- src/visual/WaterfallCanvas.h | 6 +- src/visual/WaterfallContext.h | 25 ---- 9 files changed, 139 insertions(+), 108 deletions(-) create mode 100644 src/panel/SpectrumPanel.cpp create mode 100644 src/panel/SpectrumPanel.h rename src/{visual/WaterfallContext.cpp => panel/WaterfallPanel.cpp} (76%) create mode 100644 src/panel/WaterfallPanel.h delete mode 100644 src/visual/WaterfallContext.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d16cd6..e0e0db1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,6 +245,8 @@ SET (cubicsdr_sources src/util/GLFont.cpp src/util/DataTree.cpp src/panel/ScopePanel.cpp + src/panel/SpectrumPanel.cpp + src/panel/WaterfallPanel.cpp src/visual/ColorTheme.cpp src/visual/PrimaryGLContext.cpp src/visual/InteractiveCanvas.cpp @@ -259,7 +261,6 @@ SET (cubicsdr_sources src/visual/SpectrumCanvas.cpp src/visual/SpectrumContext.cpp src/visual/WaterfallCanvas.cpp - src/visual/WaterfallContext.cpp src/process/VisualProcessor.cpp src/process/ScopeVisualProcessor.cpp src/process/SpectrumVisualProcessor.cpp @@ -298,6 +299,8 @@ SET (cubicsdr_headers src/util/GLFont.h src/util/DataTree.h src/panel/ScopePanel.h + src/panel/SpectrumPanel.h + src/panel/WaterfallPanel.h src/visual/ColorTheme.h src/visual/PrimaryGLContext.h src/visual/InteractiveCanvas.h @@ -312,7 +315,6 @@ SET (cubicsdr_headers src/visual/SpectrumCanvas.h src/visual/SpectrumContext.h src/visual/WaterfallCanvas.h - src/visual/WaterfallContext.h src/process/VisualProcessor.h src/process/ScopeVisualProcessor.h src/process/SpectrumVisualProcessor.h diff --git a/src/panel/SpectrumPanel.cpp b/src/panel/SpectrumPanel.cpp new file mode 100644 index 0000000..853a805 --- /dev/null +++ b/src/panel/SpectrumPanel.cpp @@ -0,0 +1,2 @@ +#include "SpectrumPanel.h" + diff --git a/src/panel/SpectrumPanel.h b/src/panel/SpectrumPanel.h new file mode 100644 index 0000000..a72c79f --- /dev/null +++ b/src/panel/SpectrumPanel.h @@ -0,0 +1,7 @@ +#pragma once + +#include "GLPanel.h" + +class SpectrumPanel : public GLPanel { + +}; \ No newline at end of file diff --git a/src/visual/WaterfallContext.cpp b/src/panel/WaterfallPanel.cpp similarity index 76% rename from src/visual/WaterfallContext.cpp rename to src/panel/WaterfallPanel.cpp index 8ba0f45..b018736 100644 --- a/src/visual/WaterfallContext.cpp +++ b/src/panel/WaterfallPanel.cpp @@ -1,34 +1,35 @@ -#include "WaterfallContext.h" -#include "WaterfallCanvas.h" -#include "CubicSDR.h" +#include "WaterfallPanel.h" -WaterfallContext::WaterfallContext(WaterfallCanvas *canvas, wxGLContext *sharedContext) : - PrimaryGLContext(canvas, sharedContext), fft_size(0), waterfall_lines(0), waterfall_slice(NULL), activeTheme(NULL) { +WaterfallPanel::WaterfallPanel() : GLPanel(), fft_size(0), waterfall_lines(0), waterfall_slice(NULL), activeTheme(NULL) { for (int i = 0; i < 2; i++) { waterfall[i] = 0; } } -void WaterfallContext::Setup(int fft_size_in, int num_waterfall_lines_in) { +void WaterfallPanel::setup(int fft_size_in, int num_waterfall_lines_in) { waterfall_lines = num_waterfall_lines_in; fft_size = fft_size_in; - + + if (points.size() != fft_size) { + points.resize(fft_size); + } + for (int i = 0; i < 2; i++) { if (waterfall[i]) { glDeleteTextures(1, &waterfall[i]); waterfall[i] = 0; } - + waterfall_ofs[i] = waterfall_lines - 1; } } -void WaterfallContext::refreshTheme() { +void WaterfallPanel::refreshTheme() { glEnable (GL_TEXTURE_2D); - + for (int i = 0; i < 2; i++) { glBindTexture(GL_TEXTURE_2D, waterfall[i]); - + glPixelTransferi(GL_MAP_COLOR, GL_TRUE); glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, &(ThemeMgr::mgr.currentTheme->waterfallGradient.getRed())[0]); glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, &(ThemeMgr::mgr.currentTheme->waterfallGradient.getGreen())[0]); @@ -36,81 +37,100 @@ void WaterfallContext::refreshTheme() { } } -void WaterfallContext::Draw(std::vector &points, bool step) { +void WaterfallPanel::setPoints(std::vector &points) { + int halfPts = points.size()/2; + if (halfPts == fft_size) { + for (int i = 0; i < fft_size; i++) { + this->points[i] = points[i*2+1]; + } + } else { + this->points.assign(points.begin(), points.end()); + } +} +void WaterfallPanel::step() { int half_fft_size = fft_size / 2; - glEnable (GL_TEXTURE_2D); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); - if (!waterfall[0]) { glGenTextures(2, waterfall); - + unsigned char *waterfall_tex; - + waterfall_tex = new unsigned char[half_fft_size * waterfall_lines]; memset(waterfall_tex, 0, half_fft_size * waterfall_lines); - + for (int i = 0; i < 2; i++) { glBindTexture(GL_TEXTURE_2D, waterfall[i]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - + glBindTexture(GL_TEXTURE_2D, waterfall[i]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, half_fft_size, waterfall_lines, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, (GLvoid *) waterfall_tex); } - - if (waterfall_slice != NULL) { - delete waterfall_slice; - } - waterfall_slice = new unsigned char[half_fft_size]; - + + if (waterfall_slice != NULL) { + delete waterfall_slice; + } + waterfall_slice = new unsigned char[half_fft_size]; + delete[] waterfall_tex; } + + if (points.size()) { + for (int j = 0; j < 2; j++) { + for (int i = 0, iMax = half_fft_size; i < iMax; i++) { + float v = points[j * half_fft_size + i]; + + float wv = v < 0 ? 0 : (v > 0.99 ? 0.99 : v); + + waterfall_slice[i] = (unsigned char) floor(wv * 255.0); + } + + glBindTexture(GL_TEXTURE_2D, waterfall[j]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, waterfall_ofs[j], half_fft_size, 1, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, (GLvoid *) waterfall_slice); + + if (waterfall_ofs[j] == 0) { + waterfall_ofs[j] = waterfall_lines; + } + + waterfall_ofs[j]--; + } + } +} +void WaterfallPanel::drawPanelContents() { + if (!waterfall[0]) { + return; + } + + int half_fft_size = fft_size / 2; + + glLoadMatrixf(transform); + + glEnable (GL_TEXTURE_2D); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + if (activeTheme != ThemeMgr::mgr.currentTheme) { refreshTheme(); activeTheme = ThemeMgr::mgr.currentTheme; } - - if (points.size()) { - for (int j = 0; j < 2; j++) { - for (int i = 0, iMax = half_fft_size; i < iMax; i++) { - float v = points[(j * half_fft_size + i) * 2 + 1]; - - float wv = v < 0 ? 0 : (v > 0.99 ? 0.99 : v); - - waterfall_slice[i] = (unsigned char) floor(wv * 255.0); - } - - glBindTexture(GL_TEXTURE_2D, waterfall[j]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, waterfall_ofs[j], half_fft_size, 1, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, (GLvoid *) waterfall_slice); - - if (waterfall_ofs[j] == 0) { - waterfall_ofs[j] = waterfall_lines; - } - - waterfall_ofs[j]--; - } - } - glColor3f(1.0, 1.0, 1.0); - + GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp); - + float viewWidth = (float) vp[2]; - + // some bias to prevent seams at odd scales float half_pixel = 1.0 / viewWidth; float half_texel = 1.0 / (float) half_fft_size; float vtexel = 1.0 / (float) waterfall_lines; float vofs = (float) (waterfall_ofs[0] + 1) * vtexel; - + glBindTexture(GL_TEXTURE_2D, waterfall[0]); glBegin (GL_QUADS); glTexCoord2f(0.0 + half_texel, 1.0 + vofs); @@ -122,7 +142,7 @@ void WaterfallContext::Draw(std::vector &points, bool step) { glTexCoord2f(0.0 + half_texel, 0.0 + vofs); glVertex3f(-1.0, 1.0, 0.0); glEnd(); - + vofs = (float) (waterfall_ofs[1] + 1) * vtexel; glBindTexture(GL_TEXTURE_2D, waterfall[1]); glBegin(GL_QUADS); @@ -135,9 +155,9 @@ void WaterfallContext::Draw(std::vector &points, bool step) { glTexCoord2f(0.0 + half_texel, 0.0 + vofs); glVertex3f(0.0 - half_pixel, 1.0, 0.0); glEnd(); - + glBindTexture(GL_TEXTURE_2D, 0); - + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_TEXTURE_2D); -} +} \ No newline at end of file diff --git a/src/panel/WaterfallPanel.h b/src/panel/WaterfallPanel.h new file mode 100644 index 0000000..b172635 --- /dev/null +++ b/src/panel/WaterfallPanel.h @@ -0,0 +1,25 @@ +#pragma once + +#include "GLPanel.h" + +class WaterfallPanel : public GLPanel { +public: + WaterfallPanel(); + void setup(int fft_size_in, int num_waterfall_lines_in); + void refreshTheme(); + void setPoints(std::vector &points); + void step(); + void drawPanelContents(); + + std::vector points; + bool needsUpdate; + +private: + GLuint waterfall[2]; + int waterfall_ofs[2]; + int fft_size; + int waterfall_lines; + unsigned char *waterfall_slice; + + ColorTheme *activeTheme; +}; \ No newline at end of file diff --git a/src/ui/GLPanel.cpp b/src/ui/GLPanel.cpp index ae44400..c7e2bca 100644 --- a/src/ui/GLPanel.cpp +++ b/src/ui/GLPanel.cpp @@ -13,6 +13,8 @@ GLPanel::GLPanel() : fillType(GLPANEL_FILL_SOLID), contentsVisible(true), transf fill[1] = RGB3f(0.1,0.1,0.1); borderColor = RGB3f(0.8, 0.8, 0.8); setCoordinateSystem(GLPANEL_Y_UP); + setMarginPx(0); + setBorderPx(0); } void GLPanel::genArrays() { diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index be6639e..e9a93ff 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -35,10 +35,10 @@ EVT_MOUSEWHEEL(WaterfallCanvas::OnMouseWheelMoved) wxEND_EVENT_TABLE() WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : - InteractiveCanvas(parent, attribList), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines( - 0), mouseZoom(1), zoom(1), hoverAlpha(1.0), dragOfs(0) { + InteractiveCanvas(parent, attribList), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines(0), + dragOfs(0), mouseZoom(1), zoom(1), hoverAlpha(1.0) { - glContext = new WaterfallContext(this, &wxGetApp().GetContext(this)); + glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this)); SetCursor(wxCURSOR_CROSS); } @@ -53,7 +53,7 @@ void WaterfallCanvas::setup(int fft_size_in, int waterfall_lines_in) { fft_size = fft_size_in; waterfall_lines = waterfall_lines_in; - glContext->Setup(fft_size, waterfall_lines); + waterfallPanel.setup(fft_size, waterfall_lines); } WaterfallCanvas::DragState WaterfallCanvas::getDragState() { @@ -135,30 +135,28 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { centerFreq = (freq + wxGetApp().getSampleRate() / 2) - bandwidth / 2; } } - - bool step = false; - if (!visualDataQueue.empty()) { - SpectrumVisualData *vData; - - visualDataQueue.pop(vData); - - if (!vData) { - return; - } - - spectrum_points.assign(vData->spectrum_points.begin(),vData->spectrum_points.end()); - - vData->decRefCount(); - step = true; - } - glContext->SetCurrent(*this); initGLExtensions(); glViewport(0, 0, ClientSize.x, ClientSize.y); + if (!visualDataQueue.empty()) { + SpectrumVisualData *vData; + + visualDataQueue.pop(vData); + + if (vData) { + waterfallPanel.setPoints(vData->spectrum_points); + waterfallPanel.step(); + } + + vData->decRefCount(); + } + glContext->BeginDraw(0,0,0); - glContext->Draw(spectrum_points, step); + + waterfallPanel.calcTransform(CubicVR::mat4::identity()); + waterfallPanel.draw(); std::vector &demods = wxGetApp().getDemodMgr().getDemodulators(); diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index e7f3384..b570ffb 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -7,9 +7,9 @@ #include #include "InteractiveCanvas.h" -#include "WaterfallContext.h" #include "MouseTracker.h" #include "SpectrumCanvas.h" +#include "WaterfallPanel.h" class WaterfallCanvas: public InteractiveCanvas { @@ -47,8 +47,8 @@ private: std::vector spectrum_points; SpectrumCanvas *spectrumCanvas; - - WaterfallContext *glContext; + PrimaryGLContext *glContext; + WaterfallPanel waterfallPanel; DragState dragState; DragState nextDragState; diff --git a/src/visual/WaterfallContext.h b/src/visual/WaterfallContext.h deleted file mode 100644 index e993747..0000000 --- a/src/visual/WaterfallContext.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "PrimaryGLContext.h" -#include "Gradient.h" -#include "ColorTheme.h" - -class WaterfallCanvas; - -class WaterfallContext: public PrimaryGLContext { -public: - WaterfallContext(WaterfallCanvas *canvas, wxGLContext *sharedContext); - - void Draw(std::vector &points, bool step); - void Setup(int fft_size_in, int num_waterfall_lines_in); - void refreshTheme(); - -private: - GLuint waterfall[2]; - int waterfall_ofs[2]; - int fft_size; - int waterfall_lines; - unsigned char *waterfall_slice; - - ColorTheme *activeTheme; -}; From 1fd380d2fb297bcdb10b8d153ffcf746fe378a2c Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 10 Aug 2015 00:33:31 -0400 Subject: [PATCH 50/53] Re-usable SpectrumPanel to replace SpectrumContext --- CMakeLists.txt | 2 - src/panel/ScopePanel.h | 5 +- src/panel/SpectrumPanel.cpp | 158 ++++++++++++++++++++++++++++++++ src/panel/SpectrumPanel.h | 24 +++++ src/panel/WaterfallPanel.h | 4 +- src/visual/ScopeCanvas.cpp | 19 ++-- src/visual/SpectrumCanvas.cpp | 26 +++--- src/visual/SpectrumCanvas.h | 14 +-- src/visual/SpectrumContext.cpp | 161 --------------------------------- src/visual/SpectrumContext.h | 23 ----- src/visual/WaterfallCanvas.cpp | 5 +- 11 files changed, 214 insertions(+), 227 deletions(-) delete mode 100644 src/visual/SpectrumContext.cpp delete mode 100644 src/visual/SpectrumContext.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e0e0db1..340b728 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -259,7 +259,6 @@ SET (cubicsdr_sources src/visual/ScopeCanvas.cpp src/visual/ScopeContext.cpp src/visual/SpectrumCanvas.cpp - src/visual/SpectrumContext.cpp src/visual/WaterfallCanvas.cpp src/process/VisualProcessor.cpp src/process/ScopeVisualProcessor.cpp @@ -313,7 +312,6 @@ SET (cubicsdr_headers src/visual/ScopeCanvas.h src/visual/ScopeContext.h src/visual/SpectrumCanvas.h - src/visual/SpectrumContext.h src/visual/WaterfallCanvas.h src/process/VisualProcessor.h src/process/ScopeVisualProcessor.h diff --git a/src/panel/ScopePanel.h b/src/panel/ScopePanel.h index 2907448..7d72756 100644 --- a/src/panel/ScopePanel.h +++ b/src/panel/ScopePanel.h @@ -11,8 +11,11 @@ public: void setMode(ScopeMode scopeMode); void setPoints(std::vector &points); - void drawPanelContents(); +protected: + void drawPanelContents(); + +private: std::vector points; ScopeMode scopeMode; GLPanel bgPanel; diff --git a/src/panel/SpectrumPanel.cpp b/src/panel/SpectrumPanel.cpp index 853a805..4e33087 100644 --- a/src/panel/SpectrumPanel.cpp +++ b/src/panel/SpectrumPanel.cpp @@ -1,2 +1,160 @@ #include "SpectrumPanel.h" +#include +#include +#include "ColorTheme.h" + +SpectrumPanel::SpectrumPanel() : floorValue(0), ceilValue(1) { + setFill(GLPANEL_FILL_GRAD_Y); + setFillColor(ThemeMgr::mgr.currentTheme->fftBackground * 2.0, ThemeMgr::mgr.currentTheme->fftBackground); +} + + +float SpectrumPanel::getFloorValue() const { + return floorValue; +} + +void SpectrumPanel::setFloorValue(float floorValue) { + this->floorValue = floorValue; +} + +float SpectrumPanel::getCeilValue() const { + return ceilValue; +} + +void SpectrumPanel::setCeilValue(float ceilValue) { + this->ceilValue = ceilValue; +} + +void SpectrumPanel::setFreq(long long freq) { + this->freq = freq; +} + +long long SpectrumPanel::getFreq() { + return freq; +} + +void SpectrumPanel::setBandwidth(long long bandwidth) { + this->bandwidth = bandwidth; +} + +long long SpectrumPanel::getBandwidth() { + return bandwidth; +} + +void SpectrumPanel::setPoints(std::vector &points) { + this->points.assign(points.begin(), points.end()); +} + + +void SpectrumPanel::drawPanelContents() { + glDisable(GL_TEXTURE_2D); + + glEnable(GL_BLEND); + glEnable(GL_LINE_SMOOTH); + glHint( GL_LINE_SMOOTH_HINT, GL_NICEST ); + + glLoadMatrixf(transform * (CubicVR::mat4::translate(-1.0f, -0.75f, 0.0f) * CubicVR::mat4::scale(2.0f, 1.5f, 1.0f))); + + if (points.size()) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + float range = ceilValue-floorValue; + float ranges[3][4] = { { 90.0, 5000.0, 10.0, 100.0 }, { 20.0, 150.0, 10.0, 10.0 }, { -20.0, 30.0, 10.0, 1.0 } }; + + for (int i = 0; i < 3; i++) { + float p = 0; + float rangeMin = ranges[i][0]; + float rangeMax = ranges[i][1]; + float rangeTrans = ranges[i][2]; + float rangeStep = ranges[i][3]; + + if (range >= rangeMin && range <= rangeMax) { + float a = 1.0; + + if (range <= rangeMin+rangeTrans) { + a *= (range-rangeMin)/rangeTrans; + } + if (range >= rangeMax-rangeTrans) { + a *= (rangeTrans-(range-(rangeMax-rangeTrans)))/rangeTrans; + } + + glColor4f(0.12, 0.12, 0.12, a); + glBegin(GL_LINES); + for (float l = floorValue; l<=ceilValue+rangeStep; l+=rangeStep) { + p += rangeStep/range; + glVertex2f(0,p); glVertex2f(1,p); + } + glEnd(); + } + } + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor3f(ThemeMgr::mgr.currentTheme->fftLine.r, ThemeMgr::mgr.currentTheme->fftLine.g, ThemeMgr::mgr.currentTheme->fftLine.b); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, &points[0]); + glDrawArrays(GL_LINE_STRIP, 0, points.size() / 2); + glDisableClientState(GL_VERTEX_ARRAY); + } + + glLoadMatrixf(transform); + + GLint vp[4]; + glGetIntegerv( GL_VIEWPORT, vp); + + float viewHeight = (float) vp[3]; + float viewWidth = (float) vp[2]; + + long long leftFreq = (float) freq - ((float) bandwidth / 2.0); + long long rightFreq = leftFreq + (float) bandwidth; + + long long firstMhz = (leftFreq / 1000000) * 1000000; + long double mhzStart = ((long double) (firstMhz - leftFreq) / (long double) (rightFreq - leftFreq)) * 2.0; + + long double mhzStep = (100000.0 / (long double) (rightFreq - leftFreq)) * 2.0; + float mhzVisualStep = 0.1f; + + if (mhzStep * 0.5 * viewWidth > 400) { + mhzStep = (10000.0 / (long double) (rightFreq - leftFreq)) * 2.0; + mhzVisualStep = 0.01f; + } + + long double currentMhz = trunc(floor(firstMhz / 1000000.0)); + + std::stringstream label; + label.precision(2); + + float hPos = 1.0 - (16.0 / viewHeight); + float lMhzPos = 1.0 - (5.0 / viewHeight); + + for (float m = -1.0 + mhzStart, mMax = 1.0 + ((mhzStart>0)?mhzStart:-mhzStart); m <= mMax; m += mhzStep) { + label << std::fixed << currentMhz; + + double fractpart, intpart; + + fractpart = modf(currentMhz, &intpart); + + if (fractpart < 0.001) { + glLineWidth(4.0); + glColor3f(ThemeMgr::mgr.currentTheme->freqLine.r, ThemeMgr::mgr.currentTheme->freqLine.g, ThemeMgr::mgr.currentTheme->freqLine.b); + } else { + glLineWidth(1.0); + glColor3f(ThemeMgr::mgr.currentTheme->freqLine.r * 0.65, ThemeMgr::mgr.currentTheme->freqLine.g * 0.65, + ThemeMgr::mgr.currentTheme->freqLine.b * 0.65); + } + + glDisable(GL_TEXTURE_2D); + glBegin(GL_LINES); + glVertex2f(m, lMhzPos); + glVertex2f(m, 1); + glEnd(); + + glColor4f(ThemeMgr::mgr.currentTheme->text.r, ThemeMgr::mgr.currentTheme->text.g, ThemeMgr::mgr.currentTheme->text.b,1.0); + GLFont::getFont(GLFont::GLFONT_SIZE12).drawString(label.str(), m, hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); + + label.str(std::string()); + + currentMhz += mhzVisualStep; + } + + glLineWidth(1.0); +} diff --git a/src/panel/SpectrumPanel.h b/src/panel/SpectrumPanel.h index a72c79f..af2d2f7 100644 --- a/src/panel/SpectrumPanel.h +++ b/src/panel/SpectrumPanel.h @@ -3,5 +3,29 @@ #include "GLPanel.h" class SpectrumPanel : public GLPanel { +public: + SpectrumPanel(); + void setPoints(std::vector &points); + + float getFloorValue() const; + void setFloorValue(float floorValue); + + float getCeilValue() const; + void setCeilValue(float ceilValue); + + void setFreq(long long freq); + long long getFreq(); + + void setBandwidth(long long bandwidth); + long long getBandwidth(); + +protected: + void drawPanelContents(); + +private: + float floorValue, ceilValue; + long long freq; + long long bandwidth; + std::vector points; }; \ No newline at end of file diff --git a/src/panel/WaterfallPanel.h b/src/panel/WaterfallPanel.h index b172635..3d44d6b 100644 --- a/src/panel/WaterfallPanel.h +++ b/src/panel/WaterfallPanel.h @@ -9,11 +9,13 @@ public: void refreshTheme(); void setPoints(std::vector &points); void step(); - void drawPanelContents(); std::vector points; bool needsUpdate; +protected: + void drawPanelContents(); + private: GLuint waterfall[2]; int waterfall_ofs[2]; diff --git a/src/visual/ScopeCanvas.cpp b/src/visual/ScopeCanvas.cpp index f27d355..1063c16 100644 --- a/src/visual/ScopeCanvas.cpp +++ b/src/visual/ScopeCanvas.cpp @@ -57,21 +57,14 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { ScopeRenderData *avData; inputData.pop(avData); - if (!avData) { - return; - } - - int iMax = avData->waveform_points.size(); - - if (!iMax) { + if (avData) { + if (avData->waveform_points.size()) { + scopePanel.setPoints(avData->waveform_points); + setStereo(avData->channels == 2); + } + avData->decRefCount(); - return; } - - scopePanel.setPoints(avData->waveform_points); - setStereo(avData->channels == 2); - - avData->decRefCount(); } glContext->SetCurrent(*this); diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index 5052f24..c9df1f0 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -29,7 +29,7 @@ wxEND_EVENT_TABLE() SpectrumCanvas::SpectrumCanvas(wxWindow *parent, int *attribList) : InteractiveCanvas(parent, attribList), waterfallCanvas(NULL) { - glContext = new SpectrumContext(this, &wxGetApp().GetContext(this)); + glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this)); mouseTracker.setVertDragLock(true); @@ -49,13 +49,12 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { visualDataQueue.pop(vData); - if (!vData) { - return; + if (vData) { + spectrumPanel.setPoints(vData->spectrum_points); + spectrumPanel.setFloorValue(vData->fft_floor); + spectrumPanel.setCeilValue(vData->fft_ceiling); + vData->decRefCount(); } - - spectrum_points.assign(vData->spectrum_points.begin(),vData->spectrum_points.end()); - - vData->decRefCount(); } @@ -64,9 +63,14 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glViewport(0, 0, ClientSize.x, ClientSize.y); - glContext->BeginDraw(ThemeMgr::mgr.currentTheme->fftBackground.r, ThemeMgr::mgr.currentTheme->fftBackground.g, ThemeMgr::mgr.currentTheme->fftBackground.b); - glContext->Draw(spectrum_points, getCenterFrequency(), getBandwidth()); + glContext->BeginDraw(0,0,0); + spectrumPanel.setFreq(getCenterFrequency()); + spectrumPanel.setBandwidth(getBandwidth()); + + spectrumPanel.calcTransform(CubicVR::mat4::identity()); + spectrumPanel.draw(); + std::vector &demods = wxGetApp().getDemodMgr().getDemodulators(); for (int i = 0, iMax = demods.size(); i < iMax; i++) { @@ -155,10 +159,6 @@ void SpectrumCanvas::attachWaterfallCanvas(WaterfallCanvas* canvas_in) { waterfallCanvas = canvas_in; } -SpectrumContext* SpectrumCanvas::getSpectrumContext() { - return glContext; -} - SpectrumVisualDataQueue *SpectrumCanvas::getVisualDataQueue() { return &visualDataQueue; } \ No newline at end of file diff --git a/src/visual/SpectrumCanvas.h b/src/visual/SpectrumCanvas.h index eb05e79..6c891ae 100644 --- a/src/visual/SpectrumCanvas.h +++ b/src/visual/SpectrumCanvas.h @@ -1,31 +1,24 @@ #pragma once -#include "wx/glcanvas.h" -#include "wx/timer.h" - #include #include #include "InteractiveCanvas.h" -#include "SpectrumContext.h" - -#include "fftw3.h" +#include "PrimaryGLContext.h" #include "MouseTracker.h" #include "SpectrumVisualProcessor.h" +#include "SpectrumPanel.h" class WaterfallCanvas; class SpectrumCanvas: public InteractiveCanvas { public: - std::vector spectrum_points; - SpectrumCanvas(wxWindow *parent, int *attribList = NULL); ~SpectrumCanvas(); void attachWaterfallCanvas(WaterfallCanvas *canvas_in); void moveCenterFrequency(long long freqChange); - SpectrumContext* getSpectrumContext(); SpectrumVisualDataQueue *getVisualDataQueue(); private: @@ -39,8 +32,9 @@ private: void OnMouseReleased(wxMouseEvent& event); void OnMouseLeftWindow(wxMouseEvent& event); - SpectrumContext *glContext; + PrimaryGLContext *glContext; WaterfallCanvas *waterfallCanvas; + SpectrumPanel spectrumPanel; SpectrumVisualDataQueue visualDataQueue; diff --git a/src/visual/SpectrumContext.cpp b/src/visual/SpectrumContext.cpp deleted file mode 100644 index 22b78b7..0000000 --- a/src/visual/SpectrumContext.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "SpectrumContext.h" - -#include "SpectrumCanvas.h" -#include "CubicSDR.h" -#include -#include -#include "ColorTheme.h" - -SpectrumContext::SpectrumContext(SpectrumCanvas *canvas, wxGLContext *sharedContext) : - PrimaryGLContext(canvas, sharedContext), floorValue(0), ceilValue(1) { - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - -} - - -float SpectrumContext::getFloorValue() const { - return floorValue; -} - -void SpectrumContext::setFloorValue(float floorValue) { - this->floorValue = floorValue; -} - -float SpectrumContext::getCeilValue() const { - return ceilValue; -} - -void SpectrumContext::setCeilValue(float ceilValue) { - this->ceilValue = ceilValue; -} - -void SpectrumContext::Draw(std::vector &points, long long freq, int bandwidth) { - - glBegin(GL_QUADS); - glColor3f(ThemeMgr::mgr.currentTheme->fftBackground.r, ThemeMgr::mgr.currentTheme->fftBackground.g, ThemeMgr::mgr.currentTheme->fftBackground.b); - glVertex2f(1, 0.5); - glVertex2f(-1, 0.5); - glColor3f(ThemeMgr::mgr.currentTheme->fftBackground.r*2.0, ThemeMgr::mgr.currentTheme->fftBackground.g*2.0, ThemeMgr::mgr.currentTheme->fftBackground.b*2.0); - glVertex2f(-1, -1); - glVertex2f(1, -1); - glEnd(); - - - glDisable(GL_TEXTURE_2D); - - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - glHint( GL_LINE_SMOOTH_HINT, GL_NICEST ); - if (points.size()) { - glPushMatrix(); - glTranslatef(-1.0f, -0.75f, 0.0f); - glScalef(2.0f, 1.5f, 1.0f); - - - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - float range = ceilValue-floorValue; - float ranges[3][4] = { { 90.0, 5000.0, 10.0, 100.0 }, { 20.0, 150.0, 10.0, 10.0 }, { -20.0, 30.0, 10.0, 1.0 } }; - - for (int i = 0; i < 3; i++) { - float p = 0; - float rangeMin = ranges[i][0]; - float rangeMax = ranges[i][1]; - float rangeTrans = ranges[i][2]; - float rangeStep = ranges[i][3]; - - if (range >= rangeMin && range <= rangeMax) { - float a = 1.0; - - if (range <= rangeMin+rangeTrans) { - a *= (range-rangeMin)/rangeTrans; - } - if (range >= rangeMax-rangeTrans) { - a *= (rangeTrans-(range-(rangeMax-rangeTrans)))/rangeTrans; - } - - glColor4f(0.12, 0.12, 0.12, a); - glBegin(GL_LINES); - for (float l = floorValue; l<=ceilValue+rangeStep; l+=rangeStep) { - p += rangeStep/range; - glVertex2f(0,p); glVertex2f(1,p); - } - glEnd(); - } - } - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor3f(ThemeMgr::mgr.currentTheme->fftLine.r, ThemeMgr::mgr.currentTheme->fftLine.g, ThemeMgr::mgr.currentTheme->fftLine.b); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, &points[0]); - glDrawArrays(GL_LINE_STRIP, 0, points.size() / 2); - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); - } - - GLint vp[4]; - glGetIntegerv( GL_VIEWPORT, vp); - - float viewHeight = (float) vp[3]; - float viewWidth = (float) vp[2]; - - long long leftFreq = (float) freq - ((float) bandwidth / 2.0); - long long rightFreq = leftFreq + (float) bandwidth; - - long long firstMhz = (leftFreq / 1000000) * 1000000; - long double mhzStart = ((long double) (firstMhz - leftFreq) / (long double) (rightFreq - leftFreq)) * 2.0; - - long double mhzStep = (100000.0 / (long double) (rightFreq - leftFreq)) * 2.0; - float mhzVisualStep = 0.1f; - - if (mhzStep * 0.5 * viewWidth > 400) { - mhzStep = (10000.0 / (long double) (rightFreq - leftFreq)) * 2.0; - mhzVisualStep = 0.01f; - } - - long double currentMhz = trunc(floor(firstMhz / 1000000.0)); - - std::stringstream label; - label.precision(2); - - float hPos = 1.0 - (16.0 / viewHeight); - float lMhzPos = 1.0 - (5.0 / viewHeight); - - for (float m = -1.0 + mhzStart, mMax = 1.0 + fabs(mhzStart); m <= mMax; m += mhzStep) { - label << std::fixed << currentMhz; - - double fractpart, intpart; - - fractpart = modf(currentMhz, &intpart); - - if (fractpart < 0.001) { - glLineWidth(4.0); - glColor3f(ThemeMgr::mgr.currentTheme->freqLine.r, ThemeMgr::mgr.currentTheme->freqLine.g, ThemeMgr::mgr.currentTheme->freqLine.b); - } else { - glLineWidth(1.0); - glColor3f(ThemeMgr::mgr.currentTheme->freqLine.r * 0.65, ThemeMgr::mgr.currentTheme->freqLine.g * 0.65, - ThemeMgr::mgr.currentTheme->freqLine.b * 0.65); - } - - glDisable(GL_TEXTURE_2D); - glBegin(GL_LINES); - glVertex2f(m, lMhzPos); - glVertex2f(m, 1); - glEnd(); - - glColor4f(ThemeMgr::mgr.currentTheme->text.r, ThemeMgr::mgr.currentTheme->text.g, ThemeMgr::mgr.currentTheme->text.b,1.0); - GLFont::getFont(GLFont::GLFONT_SIZE12).drawString(label.str(), m, hPos, 12, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER); - - label.str(std::string()); - - currentMhz += mhzVisualStep; - } - - glLineWidth(1.0); - -// getFont(PrimaryGLContext::GLFONT_SIZE16).drawString("Welcome to CubicSDR -- This is a test string. 01234567890!@#$%^&*()_[]",0.0,0.0,16,GLFont::GLFONT_ALIGN_CENTER,GLFont::GLFONT_ALIGN_CENTER); - CheckGLError(); -} diff --git a/src/visual/SpectrumContext.h b/src/visual/SpectrumContext.h deleted file mode 100644 index 03cc82a..0000000 --- a/src/visual/SpectrumContext.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "PrimaryGLContext.h" -#include "Gradient.h" - -#define NUM_WATERFALL_LINES 512 - -class SpectrumCanvas; - -class SpectrumContext: public PrimaryGLContext { -public: - SpectrumContext(SpectrumCanvas *canvas, wxGLContext *sharedContext); - - void Draw(std::vector &points, long long freq, int bandwidth); - - float getFloorValue() const; - void setFloorValue(float floorValue); - float getCeilValue() const; - void setCeilValue(float ceilValue); - -private: - float floorValue, ceilValue; -}; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index e9a93ff..3f13d9b 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -139,7 +139,7 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glContext->SetCurrent(*this); initGLExtensions(); glViewport(0, 0, ClientSize.x, ClientSize.y); - + if (!visualDataQueue.empty()) { SpectrumVisualData *vData; @@ -148,9 +148,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { if (vData) { waterfallPanel.setPoints(vData->spectrum_points); waterfallPanel.step(); + vData->decRefCount(); } - - vData->decRefCount(); } glContext->BeginDraw(0,0,0); From e1016e5cc5bff2b24df80ea84a48a99987c3a5a9 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 10 Aug 2015 17:27:48 -0400 Subject: [PATCH 51/53] MSVC fix-up --- external/cubicvr2/math/mat3.h | 2 ++ external/cubicvr2/math/mat4.h | 3 +++ external/cubicvr2/math/vec2.h | 5 +++-- external/cubicvr2/math/vec3.h | 2 ++ external/cubicvr2/math/vec4.h | 4 +++- 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/external/cubicvr2/math/mat3.h b/external/cubicvr2/math/mat3.h index e96b0db..8f5ab22 100644 --- a/external/cubicvr2/math/mat3.h +++ b/external/cubicvr2/math/mat3.h @@ -23,7 +23,9 @@ namespace CubicVR { __float a,b,c,d,e,f,g,h,i; // __float operator [] (unsigned i) const { return ((__float *)this)[i]; } +#ifndef _WIN32 __float& operator [] (unsigned i) { return ((__float *)this)[i]; } +#endif operator __float*() const { return (__float *)this; } mat3(__float ai,__float bi,__float ci,__float di,__float ei,__float fi,__float gi,__float hi,__float ii) { diff --git a/external/cubicvr2/math/mat4.h b/external/cubicvr2/math/mat4.h index b46409c..0059cd8 100644 --- a/external/cubicvr2/math/mat4.h +++ b/external/cubicvr2/math/mat4.h @@ -25,7 +25,10 @@ namespace CubicVR { __float a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p; // __float operator [] (unsigned i) const { return ((__float *)this)[i]; } +#ifndef _WIN32 __float& operator [] (unsigned i) { return ((__float *)this)[i]; } +#endif + operator __float*() const { return (__float *)this; } mat4(__float ai,__float bi,__float ci,__float di,__float ei,__float fi,__float gi,__float hi,__float ii,__float ji,__float ki,__float li,__float mi,__float ni,__float oi,__float pi) { a = ai; b = bi; c = ci; d = di; e = ei; f = fi; g = gi; h = hi; i = ii; j = ji; k = ki; l = li; m = mi; n = ni; o = oi; p = pi; diff --git a/external/cubicvr2/math/vec2.h b/external/cubicvr2/math/vec2.h index d7a7aad..24011c7 100644 --- a/external/cubicvr2/math/vec2.h +++ b/external/cubicvr2/math/vec2.h @@ -25,8 +25,9 @@ namespace CubicVR { __float& v() { return y; } // __float operator [] (unsigned i) const { return ((__float *)this)[i]; } - __float& operator [] (unsigned i) { return ((__float *)this)[i]; } - +#ifndef _WIN32 + __float& operator [] (unsigned i) { return ((__float *)this)[i]; } +#endif vec2 (__float xi,__float yi) { x = xi; y = yi; } vec2 () { x = y = 0.0f; } diff --git a/external/cubicvr2/math/vec3.h b/external/cubicvr2/math/vec3.h index 9dcdca6..220bf60 100644 --- a/external/cubicvr2/math/vec3.h +++ b/external/cubicvr2/math/vec3.h @@ -29,7 +29,9 @@ namespace CubicVR { __float& g() { return y; } __float& b() { return z; } +#ifndef _WIN32 __float& operator [] (unsigned i) { return ((__float *)this)[i]; } +#endif vec3 (__float xi,__float yi,__float zi) { x = xi; y = yi; z = zi; } vec3 () { x = y = z = 0.0f; } diff --git a/external/cubicvr2/math/vec4.h b/external/cubicvr2/math/vec4.h index 5975079..ad795c1 100644 --- a/external/cubicvr2/math/vec4.h +++ b/external/cubicvr2/math/vec4.h @@ -28,8 +28,10 @@ namespace CubicVR { __float& a() { return w; } // __float operator [] (unsigned i) const { return ((__float *)this)[i]; } +#ifndef _WIN32 __float& operator [] (unsigned i) { return ((__float *)this)[i]; } - +#endif + vec4 (__float xi,__float yi,__float zi,__float wi) { x = xi; y = yi; z = zi; w = wi; } vec4 () { x = y = z = w = 0.0f; } From c60a5aa019399f8f5eb9bfb75494246828394e11 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 10 Aug 2015 18:30:22 -0400 Subject: [PATCH 52/53] frame timing adjustment --- src/AppFrame.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 85ecdfa..5e06c38 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -351,7 +351,8 @@ AppFrame::AppFrame() : wxAcceleratorTable accel(3, entries); SetAcceleratorTable(accel); - frame_timer.Start(30); + // frame rate = 1000 / 30 = 33ms + frame_timer.Start(33); // static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 }; // wxLogStatus("Double-buffered display %s supported", wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not"); // ShowFullScreen(true); From c4cde423f9f885e70358bc76456b13c5d99fdfef Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 10 Aug 2015 18:45:46 -0400 Subject: [PATCH 53/53] theme refresh fix, set waterfall panel bg --- src/AppFrame.cpp | 5 +++++ src/panel/WaterfallPanel.cpp | 5 +++-- src/panel/WaterfallPanel.h | 7 +++---- src/visual/WaterfallCanvas.cpp | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 5e06c38..826e40a 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -456,6 +456,11 @@ void AppFrame::OnMenu(wxCommandEvent& event) { ThemeMgr::mgr.setTheme(COLOR_THEME_RADAR); } + if (event.GetId() >= wxID_THEME_DEFAULT && event.GetId() <= wxID_THEME_RADAR) { + demodTuner->Refresh(); + demodModeSelector->Refresh(); + } + switch (event.GetId()) { case wxID_BANDWIDTH_250K: wxGetApp().setSampleRate(250000); diff --git a/src/panel/WaterfallPanel.cpp b/src/panel/WaterfallPanel.cpp index b018736..d3b0224 100644 --- a/src/panel/WaterfallPanel.cpp +++ b/src/panel/WaterfallPanel.cpp @@ -1,6 +1,7 @@ #include "WaterfallPanel.h" WaterfallPanel::WaterfallPanel() : GLPanel(), fft_size(0), waterfall_lines(0), waterfall_slice(NULL), activeTheme(NULL) { + setFillColor(RGB3f(0,0,0)); for (int i = 0; i < 2; i++) { waterfall[i] = 0; } @@ -106,7 +107,7 @@ void WaterfallPanel::drawPanelContents() { if (!waterfall[0]) { return; } - + int half_fft_size = fft_size / 2; glLoadMatrixf(transform); @@ -160,4 +161,4 @@ void WaterfallPanel::drawPanelContents() { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_TEXTURE_2D); -} \ No newline at end of file +} diff --git a/src/panel/WaterfallPanel.h b/src/panel/WaterfallPanel.h index 3d44d6b..65c664a 100644 --- a/src/panel/WaterfallPanel.h +++ b/src/panel/WaterfallPanel.h @@ -9,14 +9,13 @@ public: void refreshTheme(); void setPoints(std::vector &points); void step(); - - std::vector points; - bool needsUpdate; protected: void drawPanelContents(); private: + std::vector points; + GLuint waterfall[2]; int waterfall_ofs[2]; int fft_size; @@ -24,4 +23,4 @@ private: unsigned char *waterfall_slice; ColorTheme *activeTheme; -}; \ No newline at end of file +}; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 3f13d9b..a5269e2 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -710,4 +710,4 @@ void WaterfallCanvas::OnMouseRightReleased(wxMouseEvent& event) { SpectrumVisualDataQueue *WaterfallCanvas::getVisualDataQueue() { return &visualDataQueue; -} \ No newline at end of file +}