2014-11-15 23:41:41 -05:00
# include "WaterfallCanvas.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 22:51:14 -05:00
# include <wx/numformatter.h>
2015-01-01 18:08:54 -05:00
# define MIN_BANDWIDTH 1500
2014-12-29 00:24:10 -05:00
2015-05-11 20:25:31 -04:00
wxBEGIN_EVENT_TABLE ( WaterfallCanvas , wxGLCanvas )
EVT_PAINT ( WaterfallCanvas : : OnPaint )
2014-11-15 23:41:41 -05:00
EVT_KEY_DOWN ( WaterfallCanvas : : OnKeyDown )
2014-12-10 00:34:27 -05:00
EVT_KEY_UP ( WaterfallCanvas : : OnKeyUp )
2014-11-15 23:41:41 -05:00
EVT_IDLE ( WaterfallCanvas : : OnIdle )
2015-01-03 17:07:39 -05:00
EVT_MOTION ( WaterfallCanvas : : OnMouseMoved )
EVT_LEFT_DOWN ( WaterfallCanvas : : OnMouseDown )
EVT_LEFT_UP ( WaterfallCanvas : : OnMouseReleased )
EVT_RIGHT_DOWN ( WaterfallCanvas : : OnMouseRightDown )
EVT_RIGHT_UP ( WaterfallCanvas : : OnMouseRightReleased )
EVT_LEAVE_WINDOW ( WaterfallCanvas : : OnMouseLeftWindow )
EVT_ENTER_WINDOW ( WaterfallCanvas : : OnMouseEnterWindow )
2015-01-07 20:23:15 -05:00
EVT_MOUSEWHEEL ( WaterfallCanvas : : OnMouseWheelMoved )
2014-11-15 23:41:41 -05:00
wxEND_EVENT_TABLE ( )
WaterfallCanvas : : WaterfallCanvas ( wxWindow * parent , int * attribList ) :
2015-08-09 23:00:51 -04:00
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 ) {
2014-11-15 23:41:41 -05:00
2015-08-09 23:00:51 -04:00
glContext = new PrimaryGLContext ( this , & wxGetApp ( ) . GetContext ( this ) ) ;
2014-12-28 05:13:46 -05:00
2014-11-25 00:35:06 -05:00
SetCursor ( wxCURSOR_CROSS ) ;
2014-11-15 23:41:41 -05:00
}
WaterfallCanvas : : ~ WaterfallCanvas ( ) {
2014-12-28 05:13:46 -05:00
}
2014-11-15 23:41:41 -05:00
2015-01-03 17:07:39 -05:00
void WaterfallCanvas : : setup ( int fft_size_in , int waterfall_lines_in ) {
2014-12-28 05:13:46 -05:00
if ( fft_size = = fft_size_in & & waterfall_lines_in = = waterfall_lines ) {
return ;
}
fft_size = fft_size_in ;
waterfall_lines = waterfall_lines_in ;
2014-11-30 18:54:13 -05:00
2015-08-09 23:00:51 -04:00
waterfallPanel . setup ( fft_size , waterfall_lines ) ;
2014-12-28 05:13:46 -05:00
}
2014-12-28 20:55:05 -05:00
WaterfallCanvas : : DragState WaterfallCanvas : : getDragState ( ) {
return dragState ;
}
WaterfallCanvas : : DragState WaterfallCanvas : : getNextDragState ( ) {
return nextDragState ;
}
2014-12-29 00:24:10 -05:00
void WaterfallCanvas : : attachSpectrumCanvas ( SpectrumCanvas * canvas_in ) {
spectrumCanvas = canvas_in ;
}
2015-08-12 19:39:11 -04:00
void WaterfallCanvas : : processInputQueue ( ) {
if ( ! glContext ) {
return ;
}
glContext - > SetCurrent ( * this ) ;
while ( ! visualDataQueue . empty ( ) ) {
SpectrumVisualData * vData ;
visualDataQueue . pop ( vData ) ;
if ( vData ) {
waterfallPanel . setPoints ( vData - > spectrum_points ) ;
waterfallPanel . step ( ) ;
vData - > decRefCount ( ) ;
}
}
}
2014-11-15 23:41:41 -05:00
void WaterfallCanvas : : OnPaint ( wxPaintEvent & WXUNUSED ( event ) ) {
2015-08-14 19:17:43 -04:00
// wxClientDC dc(this);
wxPaintDC dc ( this ) ;
2015-02-10 23:49:34 -05:00
2014-11-15 23:41:41 -05:00
const wxSize ClientSize = GetClientSize ( ) ;
2015-08-03 01:38:38 -04:00
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 ( ) ;
2015-08-16 19:47:49 -04:00
bw = getBandwidth ( ) ;
double mpos = 0 ;
float mouseInView = false ;
if ( mouseTracker . mouseInView ( ) ) {
mpos = mouseTracker . getMouseX ( ) ;
mouseInView = true ;
} else if ( spectrumCanvas & & spectrumCanvas - > getMouseTracker ( ) - > mouseInView ( ) ) {
mpos = spectrumCanvas - > getMouseTracker ( ) - > getMouseX ( ) ;
mouseInView = true ;
}
2015-08-03 01:38:38 -04:00
if ( currentZoom < 1 ) {
bw = ( long long ) ceil ( ( long double ) bw * currentZoom ) ;
2015-08-11 20:37:46 -04:00
if ( bw < 30000 ) {
bw = 30000 ;
2015-08-03 01:38:38 -04:00
}
2015-08-16 19:47:49 -04:00
if ( mouseInView ) {
long long mfreqA = getFrequencyAt ( mpos ) ;
2015-08-03 01:38:38 -04:00
setBandwidth ( bw ) ;
2015-08-16 19:47:49 -04:00
long long mfreqB = getFrequencyAt ( mpos ) ;
2015-08-03 01:38:38 -04:00
centerFreq + = mfreqA - mfreqB ;
}
setView ( centerFreq , bw ) ;
2015-01-22 22:14:00 -05:00
} else {
2015-08-03 01:38:38 -04:00
if ( isView ) {
bw = ( long long ) ceil ( ( long double ) bw * currentZoom ) ;
2015-08-16 19:47:49 -04:00
2015-08-03 01:38:38 -04:00
if ( bw > = wxGetApp ( ) . getSampleRate ( ) ) {
disableView ( ) ;
if ( spectrumCanvas ) {
spectrumCanvas - > disableView ( ) ;
}
} else {
2015-08-16 19:47:49 -04:00
if ( mouseInView ) {
long long mfreqA = getFrequencyAt ( mpos ) ;
2015-08-03 01:38:38 -04:00
setBandwidth ( bw ) ;
2015-08-16 19:47:49 -04:00
long long mfreqB = getFrequencyAt ( mpos ) ;
2015-08-03 01:38:38 -04:00
centerFreq + = mfreqA - mfreqB ;
2015-08-16 19:47:49 -04:00
} else {
setBandwidth ( bw ) ;
2015-08-03 01:38:38 -04:00
}
}
}
}
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 ;
2015-01-22 22:14:00 -05:00
}
2015-08-16 19:47:49 -04:00
if ( spectrumCanvas ) {
if ( ( spectrumCanvas - > getCenterFrequency ( ) ! = centerFreq ) | | ( spectrumCanvas - > getBandwidth ( ) ! = bw ) ) {
spectrumCanvas - > setView ( centerFreq , bw ) ;
}
}
2015-01-22 22:14:00 -05:00
}
2015-08-09 23:00:51 -04:00
2015-08-16 19:47:49 -04:00
2015-08-09 23:00:51 -04:00
glContext - > SetCurrent ( * this ) ;
initGLExtensions ( ) ;
glViewport ( 0 , 0 , ClientSize . x , ClientSize . y ) ;
2014-11-15 23:41:41 -05:00
2015-01-15 00:59:33 -05:00
glContext - > BeginDraw ( 0 , 0 , 0 ) ;
2015-08-09 23:00:51 -04:00
waterfallPanel . calcTransform ( CubicVR : : mat4 : : identity ( ) ) ;
waterfallPanel . draw ( ) ;
2014-11-15 23:41:41 -05:00
2014-11-30 18:54:13 -05:00
std : : vector < DemodulatorInstance * > & demods = wxGetApp ( ) . getDemodMgr ( ) . getDemodulators ( ) ;
2014-12-10 00:34:27 -05:00
DemodulatorInstance * activeDemodulator = wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) ;
DemodulatorInstance * lastActiveDemodulator = wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) ;
2014-12-24 01:28:33 -05:00
bool isNew = shiftDown
| | ( wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) & & ! wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) - > isActive ( ) ) ;
2014-12-18 21:39:32 -05:00
2015-01-03 17:07:39 -05:00
int currentBandwidth = getBandwidth ( ) ;
2015-01-04 17:11:20 -05:00
long long currentCenterFreq = getCenterFrequency ( ) ;
2014-12-28 05:13:46 -05:00
2015-02-16 20:47:58 -05:00
ColorTheme * currentTheme = ThemeMgr : : mgr . currentTheme ;
int last_type = wxGetApp ( ) . getDemodMgr ( ) . getLastDemodulatorType ( ) ;
2015-05-10 02:30:50 -04:00
if ( mouseTracker . mouseInView ( ) | | wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) ) {
2015-03-06 21:11:14 -05:00
hoverAlpha + = ( 1.0f - hoverAlpha ) * 0.1f ;
if ( hoverAlpha > 1.5f ) {
hoverAlpha = 1.5f ;
}
glContext - > setHoverAlpha ( hoverAlpha ) ;
2014-12-11 20:50:58 -05:00
if ( nextDragState = = WF_DRAG_RANGE ) {
2015-02-16 20:47:58 -05:00
float width = ( 1.0 / ( float ) ClientSize . x ) ;
float rangeWidth = mouseTracker . getOriginDeltaMouseX ( ) ;
float centerPos ;
2014-11-26 21:05:19 -05:00
2015-02-16 20:47:58 -05:00
if ( mouseTracker . mouseDown ( ) ) {
if ( rangeWidth ) {
width = rangeWidth ;
2014-12-10 00:34:27 -05:00
}
2015-02-16 20:47:58 -05:00
centerPos = mouseTracker . getOriginMouseX ( ) + width / 2.0 ;
2014-12-10 21:22:13 -05:00
} else {
2015-02-16 20:47:58 -05:00
centerPos = mouseTracker . getMouseX ( ) ;
}
glContext - > DrawDemod ( lastActiveDemodulator , isNew ? currentTheme - > waterfallHighlight : currentTheme - > waterfallDestroy , currentCenterFreq , currentBandwidth ) ;
if ( ( last_type = = DEMOD_TYPE_LSB | | last_type = = DEMOD_TYPE_USB ) & & mouseTracker . mouseDown ( ) ) {
centerPos = mouseTracker . getMouseX ( ) ;
glContext - > DrawRangeSelector ( centerPos , centerPos - width , isNew ? currentTheme - > waterfallNew : currentTheme - > waterfallHover ) ;
} else {
glContext - > DrawFreqSelector ( centerPos , isNew ? currentTheme - > waterfallNew : currentTheme - > waterfallHover , width , currentCenterFreq , currentBandwidth ) ;
2014-12-10 00:34:27 -05:00
}
2014-11-30 18:54:13 -05:00
} else {
2015-02-16 20:47:58 -05:00
if ( lastActiveDemodulator ) {
glContext - > DrawDemod ( lastActiveDemodulator , ( ( isNew & & activeDemodulator = = NULL ) | | ( activeDemodulator ! = NULL ) ) ? currentTheme - > waterfallHighlight : currentTheme - > waterfallDestroy , currentCenterFreq , currentBandwidth ) ;
}
2014-12-11 20:50:58 -05:00
if ( activeDemodulator = = NULL ) {
2015-02-16 20:47:58 -05:00
glContext - > DrawFreqSelector ( mouseTracker . getMouseX ( ) , ( ( isNew & & lastActiveDemodulator ) | | ( ! lastActiveDemodulator ) ) ? currentTheme - > waterfallNew : currentTheme - > waterfallHover , 0 , currentCenterFreq , currentBandwidth ) ;
2014-12-11 20:50:58 -05:00
} else {
2015-02-16 20:47:58 -05:00
glContext - > DrawDemod ( activeDemodulator , currentTheme - > waterfallHover , currentCenterFreq , currentBandwidth ) ;
2014-12-10 00:34:27 -05:00
}
2014-11-30 18:54:13 -05:00
}
2014-12-10 00:34:27 -05:00
} else {
2015-03-06 21:11:14 -05:00
hoverAlpha + = ( 0.0f - hoverAlpha ) * 0.05f ;
if ( hoverAlpha < 1.0e-5 f ) {
hoverAlpha = 0 ;
}
glContext - > setHoverAlpha ( hoverAlpha ) ;
2014-12-10 00:34:27 -05:00
if ( activeDemodulator ) {
2015-02-16 20:47:58 -05:00
glContext - > DrawDemod ( activeDemodulator , currentTheme - > waterfallHighlight , currentCenterFreq , currentBandwidth ) ;
2014-12-10 00:34:27 -05:00
}
if ( lastActiveDemodulator ) {
2015-02-16 20:47:58 -05:00
glContext - > DrawDemod ( lastActiveDemodulator , currentTheme - > waterfallHighlight , currentCenterFreq , currentBandwidth ) ;
2014-12-10 00:34:27 -05:00
}
2014-11-26 21:05:19 -05:00
}
2015-05-10 20:00:48 -04:00
glContext - > setHoverAlpha ( 0 ) ;
2014-11-30 18:54:13 -05:00
for ( int i = 0 , iMax = demods . size ( ) ; i < iMax ; i + + ) {
2014-12-10 00:34:27 -05:00
if ( activeDemodulator = = demods [ i ] | | lastActiveDemodulator = = demods [ i ] ) {
2014-11-30 18:54:13 -05:00
continue ;
}
2015-02-16 20:47:58 -05:00
glContext - > DrawDemod ( demods [ i ] , currentTheme - > waterfallHighlight , currentCenterFreq , currentBandwidth ) ;
2014-11-25 22:51:14 -05:00
}
2014-11-30 18:54:13 -05:00
2014-11-25 22:51:14 -05:00
glContext - > EndDraw ( ) ;
2014-11-15 23:41:41 -05:00
SwapBuffers ( ) ;
}
2014-12-10 00:34:27 -05:00
void WaterfallCanvas : : OnKeyUp ( wxKeyEvent & event ) {
2015-01-02 21:32:24 -05:00
InteractiveCanvas : : OnKeyUp ( event ) ;
2014-12-10 21:22:13 -05:00
shiftDown = event . ShiftDown ( ) ;
2014-12-11 20:50:58 -05:00
altDown = event . AltDown ( ) ;
ctrlDown = event . ControlDown ( ) ;
2015-01-01 21:10:54 -05:00
switch ( event . GetKeyCode ( ) ) {
case ' A ' :
2015-08-15 04:47:01 -04:00
case WXK_UP :
case WXK_NUMPAD_UP :
zoom = 1.0 ;
2015-08-16 19:47:49 -04:00
mouseZoom = 0.95 ;
2015-01-01 21:10:54 -05:00
break ;
case ' Z ' :
2015-08-15 04:47:01 -04:00
case WXK_DOWN :
case WXK_NUMPAD_DOWN :
zoom = 1.0 ;
2015-08-16 19:47:49 -04:00
mouseZoom = 1.05 ;
2015-01-01 21:10:54 -05:00
break ;
}
2014-12-10 00:34:27 -05:00
}
2014-11-15 23:41:41 -05:00
void WaterfallCanvas : : OnKeyDown ( wxKeyEvent & event ) {
2015-01-02 21:32:24 -05:00
InteractiveCanvas : : OnKeyDown ( event ) ;
2014-11-15 23:41:41 -05:00
2014-12-10 21:22:13 -05:00
DemodulatorInstance * activeDemod = wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) ;
2015-08-16 16:43:19 -04:00
long long originalFreq = getCenterFrequency ( ) ;
long long freq = originalFreq ;
2015-01-01 21:10:54 -05:00
switch ( event . GetKeyCode ( ) ) {
case ' A ' :
2015-08-15 04:47:01 -04:00
case WXK_UP :
case WXK_NUMPAD_UP :
2015-08-16 19:47:49 -04:00
mouseZoom = 1.0 ;
2015-08-15 04:47:01 -04:00
zoom = 0.95 ;
2015-01-01 21:10:54 -05:00
break ;
case ' Z ' :
2015-08-15 04:47:01 -04:00
case WXK_DOWN :
case WXK_NUMPAD_DOWN :
2015-08-16 19:47:49 -04:00
mouseZoom = 1.0 ;
2015-08-15 04:47:01 -04:00
zoom = 1.05 ;
2015-01-01 21:10:54 -05:00
break ;
case WXK_RIGHT :
2015-08-15 04:47:01 -04:00
case WXK_NUMPAD_RIGHT :
2015-01-01 21:10:54 -05:00
if ( shiftDown ) {
2015-08-15 04:47:01 -04:00
freq + = getBandwidth ( ) * 10 ;
2015-01-01 21:10:54 -05:00
} else {
2015-08-15 04:47:01 -04:00
freq + = getBandwidth ( ) / 2 ;
2015-01-01 21:10:54 -05:00
}
break ;
case WXK_LEFT :
2015-08-15 04:47:01 -04:00
case WXK_NUMPAD_LEFT :
2015-01-01 21:10:54 -05:00
if ( shiftDown ) {
2015-08-16 16:43:19 -04:00
freq - = getBandwidth ( ) * 10 ;
2015-01-01 21:10:54 -05:00
} else {
2015-08-16 16:43:19 -04:00
freq - = getBandwidth ( ) / 2 ;
2015-01-01 21:10:54 -05:00
}
break ;
case ' D ' :
case WXK_DELETE :
if ( ! activeDemod ) {
2014-12-28 05:13:46 -05:00
break ;
2015-01-01 21:10:54 -05:00
}
wxGetApp ( ) . removeDemodulator ( activeDemod ) ;
wxGetApp ( ) . getDemodMgr ( ) . deleteThread ( activeDemod ) ;
break ;
2015-08-17 00:59:38 -04:00
case ' M ' :
if ( ! activeDemod ) {
break ;
}
activeDemod - > setMuted ( ! activeDemod - > isMuted ( ) ) ;
break ;
2015-01-01 21:10:54 -05:00
case ' S ' :
if ( ! activeDemod ) {
2014-12-28 05:13:46 -05:00
break ;
2014-12-21 16:08:32 -05:00
}
2015-01-01 21:10:54 -05:00
if ( activeDemod - > isStereo ( ) ) {
activeDemod - > setStereo ( false ) ;
} else {
activeDemod - > setStereo ( true ) ;
}
break ;
2015-08-17 23:31:22 -04:00
case ' B ' :
if ( spectrumCanvas ) {
spectrumCanvas - > setShowDb ( ! spectrumCanvas - > getShowDb ( ) ) ;
}
break ;
2015-05-04 19:44:03 -04:00
case WXK_SPACE :
wxGetApp ( ) . showFrequencyInput ( ) ;
break ;
2015-01-01 21:10:54 -05:00
default :
event . Skip ( ) ;
return ;
2014-11-15 23:41:41 -05:00
}
2015-08-16 16:43:19 -04:00
long long minFreq = wxGetApp ( ) . getSampleRate ( ) / 2 ;
if ( freq < minFreq ) {
freq = minFreq ;
}
if ( freq ! = originalFreq ) {
if ( isView ) {
setView ( freq , getBandwidth ( ) ) ;
if ( spectrumCanvas ) {
spectrumCanvas - > setView ( freq , getBandwidth ( ) ) ;
}
long long minFreq = wxGetApp ( ) . getFrequency ( ) - ( wxGetApp ( ) . getSampleRate ( ) / 2 ) ;
long long maxFreq = wxGetApp ( ) . getFrequency ( ) + ( wxGetApp ( ) . getSampleRate ( ) / 2 ) ;
if ( freq < minFreq ) {
wxGetApp ( ) . setFrequency ( freq + ( wxGetApp ( ) . getSampleRate ( ) / 2 ) ) ;
}
if ( freq > maxFreq ) {
wxGetApp ( ) . setFrequency ( freq - ( wxGetApp ( ) . getSampleRate ( ) / 2 ) ) ;
}
} else {
2015-08-16 19:47:49 -04:00
if ( spectrumCanvas ) {
spectrumCanvas - > setCenterFrequency ( freq ) ;
}
2015-08-16 16:43:19 -04:00
wxGetApp ( ) . setFrequency ( freq ) ;
}
}
2014-11-15 23:41:41 -05:00
}
void WaterfallCanvas : : OnIdle ( wxIdleEvent & event ) {
2015-08-14 19:17:43 -04:00
Refresh ( ) ;
event . RequestMore ( ) ;
// event.Skip();
2014-11-15 23:41:41 -05:00
}
2014-11-25 22:51:14 -05:00
2015-01-03 17:07:39 -05:00
void WaterfallCanvas : : OnMouseMoved ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseMoved ( event ) ;
2014-12-10 00:34:27 -05:00
DemodulatorInstance * demod = wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) ;
2014-11-26 21:05:19 -05:00
2015-01-03 17:07:39 -05:00
if ( mouseTracker . mouseDown ( ) ) {
2014-12-06 21:10:29 -05:00
if ( demod = = NULL ) {
return ;
}
2014-11-30 21:14:17 -05:00
if ( dragState = = WF_DRAG_BANDWIDTH_LEFT | | dragState = = WF_DRAG_BANDWIDTH_RIGHT ) {
2015-01-03 17:07:39 -05:00
int bwDiff = ( int ) ( mouseTracker . getDeltaMouseX ( ) * ( float ) getBandwidth ( ) ) * 2 ;
2014-11-25 22:51:14 -05:00
2014-11-30 21:14:17 -05:00
if ( dragState = = WF_DRAG_BANDWIDTH_LEFT ) {
bwDiff = - bwDiff ;
}
2015-01-04 13:20:31 -05:00
int currentBW = demod - > getBandwidth ( ) ;
2014-11-25 22:51:14 -05:00
2015-01-04 13:20:31 -05:00
currentBW = currentBW + bwDiff ;
2015-01-11 17:08:16 -05:00
if ( currentBW > wxGetApp ( ) . getSampleRate ( ) ) {
currentBW = wxGetApp ( ) . getSampleRate ( ) ;
2014-11-26 21:05:19 -05:00
}
2015-01-04 13:20:31 -05:00
if ( currentBW < MIN_BANDWIDTH ) {
currentBW = MIN_BANDWIDTH ;
2014-11-26 21:05:19 -05:00
}
2015-01-04 13:20:31 -05:00
demod - > setBandwidth ( currentBW ) ;
2014-11-25 22:51:14 -05:00
}
2014-11-26 21:05:19 -05:00
2014-11-30 21:14:17 -05:00
if ( dragState = = WF_DRAG_FREQUENCY ) {
2015-05-11 20:25:31 -04:00
long long bwTarget = getFrequencyAt ( mouseTracker . getMouseX ( ) ) - dragOfs ;
2015-01-04 17:11:20 -05:00
long long currentFreq = demod - > getFrequency ( ) ;
2015-05-10 21:43:03 -04:00
long long bwDiff = bwTarget - currentFreq ;
int snap = wxGetApp ( ) . getFrequencySnap ( ) ;
2014-11-30 21:14:17 -05:00
2015-05-10 21:43:03 -04:00
if ( snap > 1 ) {
bwDiff = roundf ( ( float ) bwDiff / ( float ) snap ) * snap ;
}
if ( bwDiff ) {
demod - > setFrequency ( currentFreq + bwDiff ) ;
currentFreq = demod - > getFrequency ( ) ;
demod - > updateLabel ( currentFreq ) ;
}
2014-11-30 21:14:17 -05:00
}
2015-01-03 17:07:39 -05:00
} else if ( mouseTracker . mouseRightDown ( ) ) {
2015-01-04 13:20:31 -05:00
mouseZoom = mouseZoom + ( ( 1.0 - ( mouseTracker . getDeltaMouseY ( ) * 4.0 ) ) - mouseZoom ) * 0.1 ;
2014-11-30 21:14:17 -05:00
} else {
2015-01-04 17:11:20 -05:00
long long freqPos = getFrequencyAt ( mouseTracker . getMouseX ( ) ) ;
2014-11-30 18:54:13 -05:00
std : : vector < DemodulatorInstance * > * demodsHover = wxGetApp ( ) . getDemodMgr ( ) . getDemodulatorsAt ( freqPos , 15000 ) ;
2014-12-10 00:34:27 -05:00
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( NULL ) ;
2014-12-11 20:50:58 -05:00
if ( altDown ) {
nextDragState = WF_DRAG_RANGE ;
2015-01-03 17:07:39 -05:00
mouseTracker . setVertDragLock ( true ) ;
mouseTracker . setHorizDragLock ( false ) ;
2015-01-02 22:44:09 -05:00
if ( shiftDown ) {
setStatusText ( " Click and drag to create a new demodulator by range. " ) ;
} else {
setStatusText ( " Click and drag to set the current demodulator range. " ) ;
}
2015-02-03 19:11:30 -05:00
} else if ( demodsHover - > size ( ) & & ! shiftDown ) {
2015-01-04 17:11:20 -05:00
long near_dist = getBandwidth ( ) ;
2014-11-30 21:14:17 -05:00
2014-12-10 00:34:27 -05:00
DemodulatorInstance * activeDemodulator = NULL ;
2014-11-30 18:54:13 -05:00
for ( int i = 0 , iMax = demodsHover - > size ( ) ; i < iMax ; i + + ) {
2014-11-30 21:14:17 -05:00
DemodulatorInstance * demod = ( * demodsHover ) [ i ] ;
2015-01-04 17:11:20 -05:00
long long freqDiff = demod - > getFrequency ( ) - freqPos ;
long halfBw = ( demod - > getBandwidth ( ) / 2 ) ;
2015-05-11 20:25:31 -04:00
long long currentBw = getBandwidth ( ) ;
long long globalBw = wxGetApp ( ) . getSampleRate ( ) ;
2015-01-04 17:11:20 -05:00
long dist = abs ( freqDiff ) ;
2015-05-11 20:55:54 -04:00
double bufferBw = 10000.0 * ( ( double ) currentBw / ( double ) globalBw ) ;
double maxDist = ( ( double ) halfBw + bufferBw ) ;
2014-12-06 21:47:18 -05:00
2015-05-11 20:25:31 -04:00
if ( ( double ) dist < = maxDist ) {
2015-05-11 20:55:54 -04:00
if ( ( freqDiff > 0 & & demod - > getDemodulatorType ( ) = = DEMOD_TYPE_USB ) | |
( freqDiff < 0 & & demod - > getDemodulatorType ( ) = = DEMOD_TYPE_LSB ) ) {
continue ;
}
2015-05-11 20:25:31 -04:00
if ( dist < near_dist ) {
activeDemodulator = demod ;
near_dist = dist ;
}
2015-03-12 20:50:40 -04:00
2015-01-04 17:11:20 -05:00
long edge_dist = abs ( halfBw - dist ) ;
2014-12-06 21:47:18 -05:00
if ( edge_dist < near_dist ) {
activeDemodulator = demod ;
near_dist = edge_dist ;
}
}
2014-11-30 18:54:13 -05:00
}
2014-12-10 00:34:27 -05:00
if ( activeDemodulator = = NULL ) {
2015-05-11 20:25:31 -04:00
nextDragState = WF_DRAG_NONE ;
2015-05-11 20:55:54 -04:00
SetCursor ( wxCURSOR_CROSS ) ;
2014-12-10 00:34:27 -05:00
return ;
}
2014-12-10 18:52:24 -05:00
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( activeDemodulator ) ;
2014-12-10 00:34:27 -05:00
2015-01-04 17:11:20 -05:00
long long freqDiff = activeDemodulator - > getFrequency ( ) - freqPos ;
2014-11-30 21:14:17 -05:00
2015-01-04 17:11:20 -05:00
if ( abs ( freqDiff ) > ( activeDemodulator - > getBandwidth ( ) / 3 ) ) {
2014-11-30 21:14:17 -05:00
if ( freqDiff > 0 ) {
2015-03-12 20:50:40 -04:00
if ( activeDemodulator - > getDemodulatorType ( ) ! = DEMOD_TYPE_USB ) {
nextDragState = WF_DRAG_BANDWIDTH_LEFT ;
2015-05-11 20:55:54 -04:00
SetCursor ( wxCURSOR_SIZEWE ) ;
2015-03-12 20:50:40 -04:00
}
2014-11-30 21:14:17 -05:00
} else {
2015-03-12 20:50:40 -04:00
if ( activeDemodulator - > getDemodulatorType ( ) ! = DEMOD_TYPE_LSB ) {
nextDragState = WF_DRAG_BANDWIDTH_RIGHT ;
2015-05-11 20:55:54 -04:00
SetCursor ( wxCURSOR_SIZEWE ) ;
2015-03-12 20:50:40 -04:00
}
2014-11-30 21:14:17 -05:00
}
2014-11-30 18:54:13 -05:00
2015-01-03 17:07:39 -05:00
mouseTracker . setVertDragLock ( true ) ;
mouseTracker . setHorizDragLock ( false ) ;
2015-08-17 01:07:57 -04:00
setStatusText ( " Click and drag to change demodulator bandwidth. SPACE for direct frequency input. M for mute, D to delete, S for stereo. " ) ;
2014-11-30 21:14:17 -05:00
} else {
2014-12-28 20:55:05 -05:00
SetCursor ( wxCURSOR_SIZING ) ;
2014-11-30 21:14:17 -05:00
nextDragState = WF_DRAG_FREQUENCY ;
2015-01-03 17:07:39 -05:00
mouseTracker . setVertDragLock ( true ) ;
mouseTracker . setHorizDragLock ( false ) ;
2015-08-17 01:07:57 -04:00
setStatusText ( " Click and drag to change demodulator frequency; SPACE for direct input. M for mute, D to delete, S for stereo. " ) ;
2014-11-30 21:14:17 -05:00
}
} else {
2014-12-28 20:55:05 -05:00
SetCursor ( wxCURSOR_CROSS ) ;
2014-11-30 21:14:17 -05:00
nextDragState = WF_DRAG_NONE ;
2015-01-02 22:44:09 -05:00
if ( shiftDown ) {
2015-05-10 02:30:50 -04:00
setStatusText ( " Click to create a new demodulator or hold ALT to drag range, SPACE for direct center frequency input. " ) ;
2015-01-02 22:44:09 -05:00
} else {
2015-01-04 13:20:31 -05:00
setStatusText (
2015-05-10 02:30:50 -04:00
" Click to move active demodulator frequency or hold ALT to drag range; hold SHIFT to create new. Right drag or A / Z to Zoom. Arrow keys (+SHIFT) to move center frequency; SPACE for direct input. " ) ;
2015-01-02 22:44:09 -05:00
}
2014-11-30 21:14:17 -05:00
}
2014-11-30 18:54:13 -05:00
delete demodsHover ;
2014-11-25 22:51:14 -05:00
}
}
2015-01-03 17:07:39 -05:00
void WaterfallCanvas : : OnMouseDown ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseDown ( event ) ;
2014-12-10 00:34:27 -05:00
2015-01-02 21:32:24 -05:00
dragState = nextDragState ;
2014-12-10 21:22:13 -05:00
2014-12-11 20:50:58 -05:00
if ( dragState & & dragState ! = WF_DRAG_RANGE ) {
2015-05-11 01:23:02 -04:00
DemodulatorInstance * demod = wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) ;
if ( demod ) {
dragOfs = ( long long ) ( mouseTracker . getMouseX ( ) * ( float ) getBandwidth ( ) ) + getCenterFrequency ( ) - ( getBandwidth ( ) / 2 ) - demod - > getFrequency ( ) ;
}
2014-12-10 00:34:27 -05:00
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) , false ) ;
}
2014-11-25 22:51:14 -05:00
}
2015-01-03 17:07:39 -05:00
void WaterfallCanvas : : OnMouseWheelMoved ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseWheelMoved ( event ) ;
2015-01-07 20:23:15 -05:00
float movement = ( float ) event . GetWheelRotation ( ) / ( float ) event . GetLinesPerAction ( ) ;
2015-01-07 21:25:35 -05:00
mouseZoom = 1.0f - movement / 1000.0f ;
2014-11-25 22:51:14 -05:00
}
2015-01-03 17:07:39 -05:00
void WaterfallCanvas : : OnMouseReleased ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseReleased ( event ) ;
2014-12-10 21:22:13 -05:00
2015-02-05 21:40:38 -05:00
bool isNew = shiftDown | | ( wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) = = NULL )
2014-12-24 01:28:33 -05:00
| | ( wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) & & ! wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) - > isActive ( ) ) ;
2014-12-18 21:39:32 -05:00
2015-01-03 17:07:39 -05:00
mouseTracker . setVertDragLock ( false ) ;
mouseTracker . setHorizDragLock ( false ) ;
2014-12-10 00:34:27 -05:00
2015-05-10 21:43:03 -04:00
DemodulatorInstance * demod = isNew ? NULL : wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) ;
2015-05-11 20:25:31 -04:00
DemodulatorInstance * activeDemod = isNew ? NULL : wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) ;
2015-02-02 20:10:55 -05:00
DemodulatorMgr * mgr = & wxGetApp ( ) . getDemodMgr ( ) ;
2014-12-10 00:34:27 -05:00
2015-01-03 17:07:39 -05:00
if ( mouseTracker . getOriginDeltaMouseX ( ) = = 0 & & mouseTracker . getOriginDeltaMouseY ( ) = = 0 ) {
float pos = mouseTracker . getMouseX ( ) ;
2015-01-04 17:11:20 -05:00
long long input_center_freq = getCenterFrequency ( ) ;
2015-05-10 21:43:03 -04:00
long long freqTarget = input_center_freq - ( long long ) ( 0.5 * ( float ) getBandwidth ( ) ) + ( long long ) ( ( float ) pos * ( float ) getBandwidth ( ) ) ;
long long demodFreq = demod ? demod - > getFrequency ( ) : freqTarget ;
long long bwDiff = freqTarget - demodFreq ;
long long freq = demodFreq ;
int snap = wxGetApp ( ) . getFrequencySnap ( ) ;
if ( snap > 1 ) {
if ( demod ) {
bwDiff = roundf ( ( double ) bwDiff / ( double ) snap ) * snap ;
freq + = bwDiff ;
} else {
freq = roundl ( ( long double ) freq / ( double ) snap ) * snap ;
}
} else {
freq + = bwDiff ;
}
2014-12-10 18:52:24 -05:00
2014-12-11 20:50:58 -05:00
if ( dragState = = WF_DRAG_NONE ) {
2014-12-18 21:39:32 -05:00
if ( ! isNew & & wxGetApp ( ) . getDemodMgr ( ) . getDemodulators ( ) . size ( ) ) {
2014-12-11 20:50:58 -05:00
demod = wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) ;
} else {
2015-01-04 17:11:20 -05:00
isNew = true ;
2014-12-11 20:50:58 -05:00
demod = wxGetApp ( ) . getDemodMgr ( ) . newThread ( ) ;
2015-02-02 18:24:04 -05:00
demod - > setFrequency ( freq ) ;
2014-12-06 21:10:29 -05:00
2015-02-02 20:10:55 -05:00
demod - > setDemodulatorType ( mgr - > getLastDemodulatorType ( ) ) ;
2015-07-17 22:27:38 -04:00
demod - > setBandwidth ( mgr - > getLastBandwidth ( ) ) ;
2015-02-02 20:10:55 -05:00
demod - > setSquelchLevel ( mgr - > getLastSquelchLevel ( ) ) ;
demod - > setSquelchEnabled ( mgr - > isLastSquelchEnabled ( ) ) ;
demod - > setStereo ( mgr - > isLastStereo ( ) ) ;
demod - > setGain ( mgr - > getLastGain ( ) ) ;
2014-12-10 18:52:24 -05:00
2014-12-11 20:50:58 -05:00
demod - > run ( ) ;
2014-12-10 21:22:13 -05:00
2014-12-11 20:50:58 -05:00
wxGetApp ( ) . bindDemodulator ( demod ) ;
}
2014-11-25 22:51:14 -05:00
2015-05-11 20:25:31 -04:00
if ( ! demod ) {
2014-12-11 21:37:01 -05:00
dragState = WF_DRAG_NONE ;
2014-12-10 18:52:24 -05:00
return ;
}
2014-11-25 22:51:14 -05:00
2014-12-11 20:50:58 -05:00
demod - > updateLabel ( freq ) ;
2015-01-04 17:11:20 -05:00
demod - > setFrequency ( freq ) ;
2014-12-11 20:50:58 -05:00
2015-01-04 17:11:20 -05:00
if ( isNew ) {
setStatusText ( " New demodulator at frequency: %s " , freq ) ;
} else {
setStatusText ( " Moved demodulator to frequency: %s " , freq ) ;
}
2014-11-25 22:51:14 -05:00
2015-05-11 20:25:31 -04:00
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( demod , false ) ;
2014-12-28 20:55:05 -05:00
SetCursor ( wxCURSOR_SIZING ) ;
2014-12-10 00:34:27 -05:00
nextDragState = WF_DRAG_FREQUENCY ;
2015-01-03 17:07:39 -05:00
mouseTracker . setVertDragLock ( true ) ;
mouseTracker . setHorizDragLock ( false ) ;
2014-12-10 00:34:27 -05:00
} else {
2015-05-11 20:25:31 -04:00
if ( activeDemod ) {
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( activeDemod , false ) ;
activeDemod - > setTracking ( true ) ;
nextDragState = WF_DRAG_FREQUENCY ;
} else {
nextDragState = WF_DRAG_NONE ;
}
2014-12-10 00:34:27 -05:00
}
2014-12-11 21:37:01 -05:00
} else if ( dragState = = WF_DRAG_RANGE ) {
2015-01-03 17:07:39 -05:00
float width = mouseTracker . getOriginDeltaMouseX ( ) ;
2015-02-16 20:47:58 -05:00
float pos ;
int last_type = mgr - > getLastDemodulatorType ( ) ;
if ( last_type = = DEMOD_TYPE_LSB | | last_type = = DEMOD_TYPE_USB ) {
float pos1 = mouseTracker . getOriginMouseX ( ) ;
float pos2 = mouseTracker . getMouseX ( ) ;
if ( pos2 < pos1 ) {
float tmp = pos1 ;
pos1 = pos2 ;
pos2 = tmp ;
}
pos = ( last_type = = DEMOD_TYPE_LSB ) ? pos2 : pos1 ;
width * = 2 ;
} else {
pos = mouseTracker . getOriginMouseX ( ) + width / 2.0 ;
}
2014-12-11 21:37:01 -05:00
2015-01-04 17:11:20 -05:00
long long input_center_freq = getCenterFrequency ( ) ;
long long freq = input_center_freq - ( long long ) ( 0.5 * ( float ) getBandwidth ( ) ) + ( long long ) ( ( float ) pos * ( float ) getBandwidth ( ) ) ;
2015-01-03 17:07:39 -05:00
unsigned int bw = ( unsigned int ) ( fabs ( width ) * ( float ) getBandwidth ( ) ) ;
2014-12-11 21:37:01 -05:00
2015-01-01 18:08:54 -05:00
if ( bw < MIN_BANDWIDTH ) {
bw = MIN_BANDWIDTH ;
2014-12-11 21:37:01 -05:00
}
2014-12-28 05:13:46 -05:00
if ( ! bw ) {
2014-12-11 21:37:01 -05:00
dragState = WF_DRAG_NONE ;
return ;
}
2015-05-11 21:54:31 -04:00
int snap = wxGetApp ( ) . getFrequencySnap ( ) ;
if ( snap > 1 ) {
freq = roundl ( ( long double ) freq / ( double ) snap ) * snap ;
}
2014-12-18 21:39:32 -05:00
if ( ! isNew & & wxGetApp ( ) . getDemodMgr ( ) . getDemodulators ( ) . size ( ) ) {
2014-12-11 21:37:01 -05:00
demod = wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) ;
} else {
demod = wxGetApp ( ) . getDemodMgr ( ) . newThread ( ) ;
2015-02-02 18:24:04 -05:00
demod - > setFrequency ( freq ) ;
2015-02-02 20:10:55 -05:00
demod - > setDemodulatorType ( mgr - > getLastDemodulatorType ( ) ) ;
2015-07-18 17:03:29 -04:00
demod - > setBandwidth ( bw ) ;
2015-02-02 20:10:55 -05:00
demod - > setSquelchLevel ( mgr - > getLastSquelchLevel ( ) ) ;
demod - > setSquelchEnabled ( mgr - > isLastSquelchEnabled ( ) ) ;
demod - > setStereo ( mgr - > isLastStereo ( ) ) ;
demod - > setGain ( mgr - > getLastGain ( ) ) ;
2014-12-11 21:37:01 -05:00
demod - > run ( ) ;
wxGetApp ( ) . bindDemodulator ( demod ) ;
}
if ( demod = = NULL ) {
dragState = WF_DRAG_NONE ;
return ;
}
2015-01-02 22:44:09 -05:00
setStatusText ( " New demodulator at frequency: %s " , freq ) ;
2014-12-11 21:37:01 -05:00
demod - > updateLabel ( freq ) ;
2015-01-04 17:11:20 -05:00
demod - > setFrequency ( freq ) ;
demod - > setBandwidth ( bw ) ;
2015-05-11 20:25:31 -04:00
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( demod , false ) ;
2014-11-25 22:51:14 -05:00
}
2014-11-30 21:14:17 -05:00
dragState = WF_DRAG_NONE ;
2014-11-25 22:51:14 -05:00
}
2015-01-03 17:07:39 -05:00
void WaterfallCanvas : : OnMouseLeftWindow ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseLeftWindow ( event ) ;
2014-12-28 20:55:05 -05:00
SetCursor ( wxCURSOR_CROSS ) ;
2014-12-10 00:34:27 -05:00
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( NULL ) ;
2015-01-03 17:07:39 -05:00
mouseZoom = 1.0 ;
2014-11-25 22:51:14 -05:00
}
2015-01-03 17:07:39 -05:00
void WaterfallCanvas : : OnMouseEnterWindow ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseEnterWindow ( event ) ;
2014-12-28 20:55:05 -05:00
SetCursor ( wxCURSOR_CROSS ) ;
2014-11-25 22:51:14 -05:00
}
2014-12-28 05:13:46 -05:00
2015-01-03 17:07:39 -05:00
void WaterfallCanvas : : OnMouseRightDown ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseRightDown ( event ) ;
SetCursor ( wxCURSOR_SIZENS ) ;
mouseTracker . setVertDragLock ( true ) ;
mouseTracker . setHorizDragLock ( true ) ;
}
void WaterfallCanvas : : OnMouseRightReleased ( wxMouseEvent & event ) {
InteractiveCanvas : : OnMouseRightReleased ( event ) ;
SetCursor ( wxCURSOR_CROSS ) ;
mouseTracker . setVertDragLock ( false ) ;
mouseTracker . setHorizDragLock ( false ) ;
mouseZoom = 1.0 ;
}
2015-01-22 22:14:00 -05:00
2015-08-03 01:38:38 -04:00
SpectrumVisualDataQueue * WaterfallCanvas : : getVisualDataQueue ( ) {
return & visualDataQueue ;
2015-08-10 18:45:46 -04:00
}