2017-01-02 21:07:43 -05:00
// Copyright (c) Charles J. Cliffe
// SPDX-License-Identifier: GPL-2.0+
2014-11-15 23:41:41 -05:00
# include "SpectrumCanvas.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 <algorithm>
2014-11-25 00:35:06 -05:00
# include <wx/numformatter.h>
2015-01-01 21:10:54 -05:00
# include "WaterfallCanvas.h"
2014-11-15 23:41:41 -05:00
wxBEGIN_EVENT_TABLE ( SpectrumCanvas , wxGLCanvas ) EVT_PAINT ( SpectrumCanvas : : OnPaint )
EVT_IDLE ( SpectrumCanvas : : OnIdle )
2015-01-03 17:07:39 -05:00
EVT_MOTION ( SpectrumCanvas : : OnMouseMoved )
EVT_LEFT_DOWN ( SpectrumCanvas : : OnMouseDown )
EVT_LEFT_UP ( SpectrumCanvas : : OnMouseReleased )
2015-08-16 19:47:49 -04:00
EVT_ENTER_WINDOW ( SpectrumCanvas : : OnMouseEnterWindow )
2015-01-03 17:07:39 -05:00
EVT_LEAVE_WINDOW ( SpectrumCanvas : : OnMouseLeftWindow )
EVT_MOUSEWHEEL ( SpectrumCanvas : : OnMouseWheelMoved )
2015-10-25 00:07:01 -04:00
EVT_RIGHT_DOWN ( SpectrumCanvas : : OnMouseRightDown )
EVT_RIGHT_UP ( SpectrumCanvas : : OnMouseRightReleased )
2014-11-15 23:41:41 -05:00
wxEND_EVENT_TABLE ( )
2016-04-07 20:00:59 -04:00
SpectrumCanvas : : SpectrumCanvas ( wxWindow * parent , int * dispAttrs ) :
2016-03-22 20:49:15 -04:00
InteractiveCanvas ( parent , dispAttrs ) , waterfallCanvas ( NULL ) {
2014-11-15 23:41:41 -05:00
2015-08-10 00:33:31 -04:00
glContext = new PrimaryGLContext ( this , & wxGetApp ( ) . GetContext ( this ) ) ;
2014-11-25 00:35:06 -05:00
2015-08-11 20:37:46 -04:00
visualDataQueue . set_max_num_items ( 1 ) ;
2014-11-25 00:35:06 -05:00
SetCursor ( wxCURSOR_SIZEWE ) ;
2015-10-25 00:07:01 -04:00
scaleFactor = 1.0 ;
resetScaleFactor = false ;
2015-10-25 14:09:59 -04:00
scaleFactorEnabled = false ;
2015-10-25 00:07:01 -04:00
bwChange = 0.0 ;
2014-11-15 23:41:41 -05:00
}
SpectrumCanvas : : ~ SpectrumCanvas ( ) {
}
void SpectrumCanvas : : OnPaint ( wxPaintEvent & WXUNUSED ( event ) ) {
wxPaintDC dc ( this ) ;
const wxSize ClientSize = GetClientSize ( ) ;
2015-08-03 01:38:38 -04:00
2016-07-05 15:43:45 -04:00
SpectrumVisualData * vData ;
if ( visualDataQueue . try_pop ( vData ) ) {
2015-08-10 00:33:31 -04:00
if ( vData ) {
spectrumPanel . setPoints ( vData - > spectrum_points ) ;
2015-12-31 20:44:39 -05:00
spectrumPanel . setPeakPoints ( vData - > spectrum_hold_points ) ;
2015-08-10 00:33:31 -04:00
spectrumPanel . setFloorValue ( vData - > fft_floor ) ;
spectrumPanel . setCeilValue ( vData - > fft_ceiling ) ;
vData - > decRefCount ( ) ;
2015-08-08 13:26:53 -04:00
}
2015-08-03 01:38:38 -04:00
}
2015-10-25 00:07:01 -04:00
if ( resetScaleFactor ) {
scaleFactor + = ( 1.0 - scaleFactor ) * 0.05 ;
if ( fabs ( scaleFactor - 1.0 ) < 0.01 ) {
scaleFactor = 1.0 ;
resetScaleFactor = false ;
}
updateScaleFactor ( scaleFactor ) ;
}
2015-08-03 01:38:38 -04:00
2014-11-15 23:41:41 -05:00
glContext - > SetCurrent ( * this ) ;
2015-02-09 20:49:21 -05:00
initGLExtensions ( ) ;
2014-11-15 23:41:41 -05:00
glViewport ( 0 , 0 , ClientSize . x , ClientSize . y ) ;
2015-08-10 00:33:31 -04:00
glContext - > BeginDraw ( 0 , 0 , 0 ) ;
2014-11-15 23:41:41 -05:00
2015-08-10 00:33:31 -04:00
spectrumPanel . setFreq ( getCenterFrequency ( ) ) ;
spectrumPanel . setBandwidth ( getBandwidth ( ) ) ;
spectrumPanel . calcTransform ( CubicVR : : mat4 : : identity ( ) ) ;
spectrumPanel . draw ( ) ;
2015-08-17 21:52:38 -04:00
glLoadIdentity ( ) ;
2014-12-08 21:08:03 -05:00
std : : vector < DemodulatorInstance * > & demods = wxGetApp ( ) . getDemodMgr ( ) . getDemodulators ( ) ;
2016-03-07 19:25:12 -05:00
DemodulatorInstance * activeDemodulator = wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) ;
2014-12-08 21:08:03 -05:00
for ( int i = 0 , iMax = demods . size ( ) ; i < iMax ; i + + ) {
2016-03-07 19:25:12 -05:00
if ( ! demods [ i ] - > isActive ( ) ) {
continue ;
}
glContext - > DrawDemodInfo ( demods [ i ] , ThemeMgr : : mgr . currentTheme - > fftHighlight , getCenterFrequency ( ) , getBandwidth ( ) , activeDemodulator = = demods [ i ] ) ;
2014-12-08 21:08:03 -05:00
}
2016-03-07 19:25:12 -05:00
if ( waterfallCanvas & & ! activeDemodulator ) {
2016-01-13 00:07:42 -05:00
MouseTracker * wfmt = waterfallCanvas - > getMouseTracker ( ) ;
2016-03-07 19:25:12 -05:00
if ( wfmt - > mouseInView ( ) ) {
2016-01-13 00:07:42 -05:00
int snap = wxGetApp ( ) . getFrequencySnap ( ) ;
long long freq = getFrequencyAt ( wfmt - > getMouseX ( ) ) ;
if ( snap > 1 ) {
freq = roundf ( ( float ) freq / ( float ) snap ) * snap ;
}
2016-01-13 21:29:26 -05:00
DemodulatorInstance * lastActiveDemodulator = wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) ;
bool isNew = ( ( ( waterfallCanvas - > isShiftDown ( ) | | ( lastActiveDemodulator & & ! lastActiveDemodulator - > isActive ( ) ) ) & & lastActiveDemodulator ) | | ( ! lastActiveDemodulator ) ) ;
2016-03-07 19:25:12 -05:00
glContext - > DrawFreqBwInfo ( freq , wxGetApp ( ) . getDemodMgr ( ) . getLastBandwidth ( ) , isNew ? ThemeMgr : : mgr . currentTheme - > waterfallNew : ThemeMgr : : mgr . currentTheme - > waterfallHover , getCenterFrequency ( ) , getBandwidth ( ) , true , true ) ;
2016-01-13 00:07:42 -05:00
}
}
2014-12-08 21:08:03 -05:00
glContext - > EndDraw ( ) ;
2015-08-17 21:52:38 -04:00
spectrumPanel . drawChildren ( ) ;
2014-11-15 23:41:41 -05:00
SwapBuffers ( ) ;
}
void SpectrumCanvas : : OnIdle ( wxIdleEvent & event ) {
2015-08-12 18:07:06 -04:00
Refresh ( ) ;
event . RequestMore ( ) ;
2014-11-15 23:41:41 -05:00
}
2014-11-25 00:35:06 -05:00
2015-04-23 19:38:44 -04:00
void SpectrumCanvas : : moveCenterFrequency ( long long freqChange ) {
long long freq = wxGetApp ( ) . getFrequency ( ) ;
if ( isView ) {
if ( centerFreq - freqChange < bandwidth / 2 ) {
centerFreq = bandwidth / 2 ;
} else {
centerFreq - = freqChange ;
}
if ( waterfallCanvas ) {
waterfallCanvas - > setCenterFrequency ( centerFreq ) ;
}
long long bwOfs = ( centerFreq > freq ) ? ( ( long long ) bandwidth / 2 ) : ( - ( long long ) bandwidth / 2 ) ;
long long freqEdge = centerFreq + bwOfs ;
if ( abs ( freq - freqEdge ) > ( wxGetApp ( ) . getSampleRate ( ) / 2 ) ) {
freqChange = - ( ( centerFreq > freq ) ? ( freqEdge - freq - ( wxGetApp ( ) . getSampleRate ( ) / 2 ) ) : ( freqEdge - freq + ( wxGetApp ( ) . getSampleRate ( ) / 2 ) ) ) ;
} else {
freqChange = 0 ;
}
}
if ( freqChange ) {
if ( freq - freqChange < wxGetApp ( ) . getSampleRate ( ) / 2 ) {
freq = wxGetApp ( ) . getSampleRate ( ) / 2 ;
} else {
freq - = freqChange ;
}
wxGetApp ( ) . setFrequency ( freq ) ;
}
}
2015-08-17 21:52:38 -04:00
void SpectrumCanvas : : setShowDb ( bool showDb ) {
spectrumPanel . setShowDb ( showDb ) ;
}
2015-08-17 23:31:22 -04:00
bool SpectrumCanvas : : getShowDb ( ) {
return spectrumPanel . getShowDb ( ) ;
}
2016-10-20 21:44:33 -04:00
void SpectrumCanvas : : setUseDBOfs ( bool showDb ) {
spectrumPanel . setUseDBOffset ( showDb ) ;
}
bool SpectrumCanvas : : getUseDBOfs ( ) {
return spectrumPanel . getUseDBOffset ( ) ;
}
2015-10-25 00:07:01 -04:00
void SpectrumCanvas : : setView ( long long center_freq_in , int bandwidth_in ) {
bwChange + = bandwidth_in - bandwidth ;
# define BW_RESET_TH 400000
if ( bwChange > BW_RESET_TH | | bwChange < - BW_RESET_TH ) {
resetScaleFactor = true ;
bwChange = 0 ;
}
InteractiveCanvas : : setView ( center_freq_in , bandwidth_in ) ;
}
void SpectrumCanvas : : disableView ( ) {
InteractiveCanvas : : disableView ( ) ;
}
2015-10-25 14:09:59 -04:00
void SpectrumCanvas : : setScaleFactorEnabled ( bool en ) {
scaleFactorEnabled = en ;
}
2015-12-29 20:52:49 -05:00
void SpectrumCanvas : : setFFTSize ( int fftSize ) {
spectrumPanel . setFFTSize ( fftSize ) ;
}
2015-10-25 14:09:59 -04:00
2015-10-25 00:07:01 -04:00
void SpectrumCanvas : : updateScaleFactor ( float factor ) {
SpectrumVisualProcessor * sp = wxGetApp ( ) . getSpectrumProcessor ( ) ;
FFTVisualDataThread * wdt = wxGetApp ( ) . getAppFrame ( ) - > getWaterfallDataThread ( ) ;
SpectrumVisualProcessor * wp = wdt - > getProcessor ( ) ;
scaleFactor = factor ;
sp - > setScaleFactor ( factor ) ;
wp - > setScaleFactor ( factor ) ;
}
2015-08-17 21:52:38 -04:00
2015-01-03 17:07:39 -05:00
void SpectrumCanvas : : OnMouseMoved ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseMoved ( event ) ;
if ( mouseTracker . mouseDown ( ) ) {
int freqChange = mouseTracker . getDeltaMouseX ( ) * getBandwidth ( ) ;
2014-11-25 22:51:14 -05:00
if ( freqChange ! = 0 ) {
2015-04-23 19:38:44 -04:00
moveCenterFrequency ( freqChange ) ;
2014-11-25 00:35:06 -05:00
}
2015-10-25 00:07:01 -04:00
}
2015-10-25 14:09:59 -04:00
else if ( scaleFactorEnabled & & mouseTracker . mouseRightDown ( ) ) {
2015-10-25 00:07:01 -04:00
float yDelta = mouseTracker . getDeltaMouseY ( ) ;
scaleFactor + = yDelta * 2.0 ;
if ( scaleFactor < 0.25 ) {
scaleFactor = 0.25 ;
}
if ( scaleFactor > 10.0 ) {
scaleFactor = 10.0 ;
}
resetScaleFactor = false ;
updateScaleFactor ( scaleFactor ) ;
2015-01-02 22:44:09 -05:00
} else {
2015-10-25 14:09:59 -04:00
if ( scaleFactorEnabled ) {
2015-10-25 14:31:56 -04:00
setStatusText ( " Drag horizontal to adjust center frequency. Right-drag or SHIFT+UP/DOWN to adjust vertical scale; right-click to reset. 'B' to toggle decibels display. " ) ;
2015-10-25 14:09:59 -04:00
} else {
setStatusText ( " Displaying spectrum of active demodulator. " ) ;
}
2014-11-25 00:35:06 -05:00
}
}
2015-01-03 17:07:39 -05:00
void SpectrumCanvas : : OnMouseDown ( wxMouseEvent & event ) {
2015-11-01 12:41:13 -05:00
mouseTracker . setVertDragLock ( true ) ;
2015-01-03 17:07:39 -05:00
InteractiveCanvas : : OnMouseDown ( event ) ;
2014-11-25 00:35:06 -05:00
SetCursor ( wxCURSOR_CROSS ) ;
}
2015-01-03 17:07:39 -05:00
void SpectrumCanvas : : OnMouseWheelMoved ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseWheelMoved ( event ) ;
2016-05-30 19:45:38 -04:00
if ( waterfallCanvas ) {
waterfallCanvas - > OnMouseWheelMoved ( event ) ;
}
2014-11-25 00:35:06 -05:00
}
2015-01-03 17:07:39 -05:00
void SpectrumCanvas : : OnMouseReleased ( wxMouseEvent & event ) {
2015-11-01 12:41:13 -05:00
mouseTracker . setVertDragLock ( false ) ;
InteractiveCanvas : : OnMouseReleased ( event ) ;
2014-11-25 00:35:06 -05:00
SetCursor ( wxCURSOR_SIZEWE ) ;
}
2015-08-16 19:47:49 -04:00
void SpectrumCanvas : : OnMouseEnterWindow ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseEnterWindow ( event ) ;
SetCursor ( wxCURSOR_SIZEWE ) ;
2016-05-30 00:17:08 -04:00
# ifdef _WIN32
2016-05-30 19:25:46 -04:00
if ( wxGetApp ( ) . getAppFrame ( ) - > canFocus ( ) ) {
this - > SetFocus ( ) ;
}
2016-05-30 00:17:08 -04:00
# endif
2015-08-16 19:47:49 -04:00
}
2015-01-03 17:07:39 -05:00
void SpectrumCanvas : : OnMouseLeftWindow ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseLeftWindow ( event ) ;
2014-11-25 00:35:06 -05:00
SetCursor ( wxCURSOR_SIZEWE ) ;
}
2015-01-01 21:10:54 -05:00
void SpectrumCanvas : : attachWaterfallCanvas ( WaterfallCanvas * canvas_in ) {
waterfallCanvas = canvas_in ;
}
2014-11-25 00:35:06 -05:00
2015-08-03 01:38:38 -04:00
SpectrumVisualDataQueue * SpectrumCanvas : : getVisualDataQueue ( ) {
return & visualDataQueue ;
2015-08-16 19:47:49 -04:00
}
2015-10-25 00:07:01 -04:00
void SpectrumCanvas : : OnMouseRightDown ( wxMouseEvent & event ) {
2015-11-01 12:41:13 -05:00
mouseTracker . setHorizDragLock ( true ) ;
2015-10-25 00:07:01 -04:00
mouseTracker . OnMouseRightDown ( event ) ;
2015-10-25 14:31:56 -04:00
scaleFactor = wxGetApp ( ) . getSpectrumProcessor ( ) - > getScaleFactor ( ) ;
2015-10-25 00:07:01 -04:00
}
void SpectrumCanvas : : OnMouseRightReleased ( wxMouseEvent & event ) {
2015-11-01 12:41:13 -05:00
mouseTracker . setHorizDragLock ( false ) ;
2015-10-25 00:07:01 -04:00
if ( ! mouseTracker . getOriginDeltaMouseY ( ) ) {
resetScaleFactor = true ;
2016-01-02 01:38:17 -05:00
wxGetApp ( ) . getSpectrumProcessor ( ) - > setPeakHold ( wxGetApp ( ) . getSpectrumProcessor ( ) - > getPeakHold ( ) ) ;
2016-06-09 13:33:52 -04:00
//make the peak hold act on the current dmod also, like a zoomed-in version.
2016-10-20 21:44:33 -04:00
if ( wxGetApp ( ) . getDemodSpectrumProcessor ( ) ) {
wxGetApp ( ) . getDemodSpectrumProcessor ( ) - > setPeakHold ( wxGetApp ( ) . getSpectrumProcessor ( ) - > getPeakHold ( ) ) ;
}
2015-10-25 00:07:01 -04:00
}
mouseTracker . OnMouseRightReleased ( event ) ;
}
2017-01-27 15:38:48 -05:00
void SpectrumCanvas : : OnKeyDown ( wxKeyEvent & event ) {
InteractiveCanvas : : OnKeyDown ( event ) ;
switch ( event . GetKeyCode ( ) ) {
case ' B ' :
setShowDb ( ! getShowDb ( ) ) ;
break ;
default :
event . Skip ( ) ;
}
}
void SpectrumCanvas : : OnKeyUp ( wxKeyEvent & event ) {
InteractiveCanvas : : OnKeyUp ( event ) ;
}