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
2014-11-15 23:41:41 -05:00
wxBEGIN_EVENT_TABLE ( WaterfallCanvas , wxGLCanvas ) EVT_PAINT ( WaterfallCanvas : : OnPaint )
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-01-04 17:11:20 -05:00
InteractiveCanvas ( parent , attribList ) , spectrumCanvas ( NULL ) , dragState ( WF_DRAG_NONE ) , nextDragState ( WF_DRAG_NONE ) , fft_size ( 0 ) , waterfall_lines (
0 ) , plan (
2015-01-30 19:31:32 -05:00
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 ) {
2014-11-15 23:41:41 -05:00
glContext = new WaterfallContext ( this , & wxGetApp ( ) . GetContext ( this ) ) ;
2014-12-28 05:13:46 -05:00
2015-01-03 17:07:39 -05:00
freqShifter = nco_crcf_create ( LIQUID_NCO ) ;
shiftFrequency = 0 ;
2014-11-25 00:35:06 -05:00
2014-12-31 19:45:01 -05:00
fft_ceil_ma = fft_ceil_maa = 100.0 ;
fft_floor_ma = fft_floor_maa = 0.0 ;
2014-11-25 00:35:06 -05:00
SetCursor ( wxCURSOR_CROSS ) ;
2014-11-15 23:41:41 -05:00
}
WaterfallCanvas : : ~ WaterfallCanvas ( ) {
2015-01-03 17:07:39 -05:00
nco_crcf_destroy ( freqShifter ) ;
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
2014-12-28 05:13:46 -05:00
if ( in ) {
free ( in ) ;
}
2015-01-06 19:15:27 -05:00
in = ( fftwf_complex * ) fftwf_malloc ( sizeof ( fftwf_complex ) * fft_size ) ;
2015-01-30 19:31:32 -05:00
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 ) ;
2014-12-28 05:13:46 -05:00
if ( out ) {
free ( out ) ;
}
2015-01-06 19:15:27 -05:00
out = ( fftwf_complex * ) fftwf_malloc ( sizeof ( fftwf_complex ) * fft_size ) ;
2014-12-28 05:13:46 -05:00
if ( plan ) {
2015-01-06 19:15:27 -05:00
fftwf_destroy_plan ( plan ) ;
2014-12-28 05:13:46 -05:00
}
2015-01-06 19:15:27 -05:00
plan = fftwf_plan_dft_1d ( fft_size , in , out , FFTW_FORWARD , FFTW_ESTIMATE ) ;
2014-12-28 05:13:46 -05:00
glContext - > Setup ( fft_size , waterfall_lines ) ;
}
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 ;
}
2014-11-15 23:41:41 -05:00
void WaterfallCanvas : : OnPaint ( wxPaintEvent & WXUNUSED ( event ) ) {
wxPaintDC dc ( this ) ;
const wxSize ClientSize = GetClientSize ( ) ;
2015-01-22 22:14:00 -05:00
if ( polling & & ! wxGetApp ( ) . getIQVisualQueue ( ) - > empty ( ) ) {
DemodulatorThreadIQData * iqData ;
wxGetApp ( ) . getIQVisualQueue ( ) - > pop ( iqData ) ;
if ( iqData & & iqData - > data . size ( ) ) {
setData ( iqData ) ;
if ( otherWaterfallCanvas ) {
otherWaterfallCanvas - > setData ( iqData ) ;
}
} else {
std : : cout < < " Incoming IQ data empty? " < < std : : endl ;
}
}
2014-11-15 23:41:41 -05:00
glContext - > SetCurrent ( * this ) ;
glViewport ( 0 , 0 , ClientSize . x , ClientSize . y ) ;
2015-01-15 00:59:33 -05:00
glContext - > BeginDraw ( 0 , 0 , 0 ) ;
2014-11-15 23:41:41 -05:00
glContext - > Draw ( spectrum_points ) ;
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-01-03 17:07:39 -05:00
if ( mouseTracker . mouseInView ( ) ) {
2014-12-11 20:50:58 -05:00
if ( nextDragState = = WF_DRAG_RANGE ) {
2015-01-03 17:07:39 -05:00
if ( mouseTracker . mouseDown ( ) ) {
float width = mouseTracker . getOriginDeltaMouseX ( ) ;
float centerPos = mouseTracker . getOriginMouseX ( ) + width / 2.0 ;
2014-11-26 21:05:19 -05:00
2014-12-18 21:39:32 -05:00
if ( isNew ) {
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( lastActiveDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . r , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . g , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . b , currentCenterFreq , currentBandwidth ) ;
glContext - > DrawFreqSelector ( centerPos , ThemeMgr : : mgr . currentTheme - > waterfallNew . r , ThemeMgr : : mgr . currentTheme - > waterfallNew . g , ThemeMgr : : mgr . currentTheme - > waterfallNew . b , width ? width : ( 1.0 / ( float ) ClientSize . x ) , currentCenterFreq ,
2014-12-28 05:13:46 -05:00
currentBandwidth ) ;
2014-12-10 00:34:27 -05:00
} else {
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( lastActiveDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallDestroy . r , ThemeMgr : : mgr . currentTheme - > waterfallDestroy . g , ThemeMgr : : mgr . currentTheme - > waterfallDestroy . b , currentCenterFreq , currentBandwidth ) ;
glContext - > DrawFreqSelector ( centerPos , ThemeMgr : : mgr . currentTheme - > waterfallHover . r , ThemeMgr : : mgr . currentTheme - > waterfallHover . g , ThemeMgr : : mgr . currentTheme - > waterfallHover . b , width ? width : ( 1.0 / ( float ) ClientSize . x ) , currentCenterFreq ,
2014-12-28 05:13:46 -05:00
currentBandwidth ) ;
2014-12-10 00:34:27 -05:00
}
2014-12-10 21:22:13 -05:00
} else {
2014-12-18 21:39:32 -05:00
if ( isNew ) {
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( lastActiveDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . r , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . g , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . b , currentCenterFreq , currentBandwidth ) ;
glContext - > DrawFreqSelector ( mouseTracker . getMouseX ( ) , ThemeMgr : : mgr . currentTheme - > waterfallNew . r , ThemeMgr : : mgr . currentTheme - > waterfallNew . g , ThemeMgr : : mgr . currentTheme - > waterfallNew . b , 1.0 / ( float ) ClientSize . x , currentCenterFreq , currentBandwidth ) ;
2014-12-11 20:50:58 -05:00
} else {
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( lastActiveDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallDestroy . r , ThemeMgr : : mgr . currentTheme - > waterfallDestroy . g , ThemeMgr : : mgr . currentTheme - > waterfallDestroy . b , currentCenterFreq , currentBandwidth ) ;
glContext - > DrawFreqSelector ( mouseTracker . getMouseX ( ) , ThemeMgr : : mgr . currentTheme - > waterfallHover . r , ThemeMgr : : mgr . currentTheme - > waterfallHover . g , ThemeMgr : : mgr . currentTheme - > waterfallHover . b , 1.0 / ( float ) ClientSize . x , currentCenterFreq , currentBandwidth ) ;
2014-12-11 20:50:58 -05:00
}
2014-12-10 00:34:27 -05:00
}
2014-11-30 18:54:13 -05:00
} else {
2014-12-11 20:50:58 -05:00
if ( activeDemodulator = = NULL ) {
if ( lastActiveDemodulator ) {
2014-12-18 21:39:32 -05:00
if ( isNew ) {
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( lastActiveDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . r , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . g , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . b , currentCenterFreq , currentBandwidth ) ;
glContext - > DrawFreqSelector ( mouseTracker . getMouseX ( ) , ThemeMgr : : mgr . currentTheme - > waterfallNew . r , ThemeMgr : : mgr . currentTheme - > waterfallNew . g , ThemeMgr : : mgr . currentTheme - > waterfallNew . b , 0 , currentCenterFreq , currentBandwidth ) ;
2014-12-11 20:50:58 -05:00
} else {
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( lastActiveDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallDestroy . r , ThemeMgr : : mgr . currentTheme - > waterfallDestroy . g , ThemeMgr : : mgr . currentTheme - > waterfallDestroy . b , currentCenterFreq , currentBandwidth ) ;
glContext - > DrawFreqSelector ( mouseTracker . getMouseX ( ) , ThemeMgr : : mgr . currentTheme - > waterfallHover . r , ThemeMgr : : mgr . currentTheme - > waterfallHover . g , ThemeMgr : : mgr . currentTheme - > waterfallHover . b , 0 , currentCenterFreq , currentBandwidth ) ;
2014-12-11 20:50:58 -05:00
}
} else {
2015-01-14 22:14:57 -05:00
glContext - > DrawFreqSelector ( mouseTracker . getMouseX ( ) , ThemeMgr : : mgr . currentTheme - > waterfallNew . r , ThemeMgr : : mgr . currentTheme - > waterfallNew . g , ThemeMgr : : mgr . currentTheme - > waterfallNew . b , 0 , currentCenterFreq , currentBandwidth ) ;
2014-12-11 20:50:58 -05:00
}
} else {
if ( lastActiveDemodulator ) {
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( lastActiveDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . r , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . g , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . b , currentCenterFreq , currentBandwidth ) ;
2014-12-11 20:50:58 -05:00
}
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( activeDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallHover . r , ThemeMgr : : mgr . currentTheme - > waterfallHover . g , ThemeMgr : : mgr . currentTheme - > waterfallHover . b , 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 {
if ( activeDemodulator ) {
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( activeDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . r , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . g , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . b , currentCenterFreq , currentBandwidth ) ;
2014-12-10 00:34:27 -05:00
}
if ( lastActiveDemodulator ) {
2015-01-14 22:14:57 -05:00
glContext - > DrawDemod ( lastActiveDemodulator , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . r , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . g , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . b , currentCenterFreq , currentBandwidth ) ;
2014-12-10 00:34:27 -05:00
}
2014-11-26 21:05:19 -05:00
}
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-01-14 22:14:57 -05:00
glContext - > DrawDemod ( demods [ i ] , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . r , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . g , ThemeMgr : : mgr . currentTheme - > waterfallHighlight . b , 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-01-03 17:07:39 -05:00
zoom = 1.0 ;
2015-01-01 21:10:54 -05:00
break ;
case ' Z ' :
2015-01-03 17:07:39 -05:00
zoom = 1.0 ;
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
float angle = 5.0 ;
2014-12-10 21:22:13 -05:00
DemodulatorInstance * activeDemod = wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) ;
2015-01-04 17:11:20 -05:00
long long freq ;
2015-01-06 19:15:27 -05:00
long long originalFreq ;
2015-01-01 21:10:54 -05:00
unsigned int bw ;
switch ( event . GetKeyCode ( ) ) {
case ' A ' :
2015-01-03 17:07:39 -05:00
zoom = 0.95 ;
2015-01-01 21:10:54 -05:00
break ;
case ' Z ' :
2015-01-03 17:07:39 -05:00
zoom = 1.05 ;
2015-01-01 21:10:54 -05:00
break ;
case WXK_RIGHT :
freq = wxGetApp ( ) . getFrequency ( ) ;
2015-01-06 19:15:27 -05:00
originalFreq = freq ;
2015-01-01 21:10:54 -05:00
if ( shiftDown ) {
2015-01-11 17:08:16 -05:00
freq + = wxGetApp ( ) . getSampleRate ( ) * 10 ;
2015-01-02 21:32:24 -05:00
if ( isView ) {
2015-01-06 19:15:27 -05:00
setView ( centerFreq + ( freq - originalFreq ) , getBandwidth ( ) ) ;
2015-01-02 21:32:24 -05:00
if ( spectrumCanvas ) {
2015-01-03 17:07:39 -05:00
spectrumCanvas - > setView ( getCenterFrequency ( ) , getBandwidth ( ) ) ;
2015-01-02 21:32:24 -05:00
}
}
2015-01-01 21:10:54 -05:00
} else {
2015-01-11 17:08:16 -05:00
freq + = wxGetApp ( ) . getSampleRate ( ) / 2 ;
2015-01-02 21:32:24 -05:00
if ( isView ) {
2015-01-06 19:15:27 -05:00
setView ( centerFreq + ( freq - originalFreq ) , getBandwidth ( ) ) ;
2015-01-02 21:32:24 -05:00
if ( spectrumCanvas ) {
2015-01-03 17:07:39 -05:00
spectrumCanvas - > setView ( getCenterFrequency ( ) , getBandwidth ( ) ) ;
2015-01-02 21:32:24 -05:00
}
}
2015-01-01 21:10:54 -05:00
}
wxGetApp ( ) . setFrequency ( freq ) ;
2015-01-02 22:44:09 -05:00
setStatusText ( " Set center frequency: %s " , freq ) ;
2015-01-01 21:10:54 -05:00
break ;
case WXK_LEFT :
freq = wxGetApp ( ) . getFrequency ( ) ;
2015-01-06 19:15:27 -05:00
originalFreq = freq ;
2015-01-01 21:10:54 -05:00
if ( shiftDown ) {
2015-01-11 17:08:16 -05:00
if ( ( freq - wxGetApp ( ) . getSampleRate ( ) * 10 ) < wxGetApp ( ) . getSampleRate ( ) / 2 ) {
freq = wxGetApp ( ) . getSampleRate ( ) / 2 ;
2015-01-04 13:20:31 -05:00
} else {
2015-01-11 17:08:16 -05:00
freq - = wxGetApp ( ) . getSampleRate ( ) * 10 ;
2015-01-04 13:20:31 -05:00
}
2015-01-02 21:32:24 -05:00
if ( isView ) {
2015-01-06 19:15:27 -05:00
setView ( centerFreq + ( freq - originalFreq ) , getBandwidth ( ) ) ;
2015-01-02 21:32:24 -05:00
if ( spectrumCanvas ) {
2015-01-03 17:07:39 -05:00
spectrumCanvas - > setView ( getCenterFrequency ( ) , getBandwidth ( ) ) ;
2015-01-02 21:32:24 -05:00
}
}
2015-01-01 21:10:54 -05:00
} else {
2015-01-11 17:08:16 -05:00
if ( ( freq - wxGetApp ( ) . getSampleRate ( ) / 2 ) < wxGetApp ( ) . getSampleRate ( ) / 2 ) {
freq = wxGetApp ( ) . getSampleRate ( ) / 2 ;
2015-01-04 13:20:31 -05:00
} else {
2015-01-11 17:08:16 -05:00
freq - = wxGetApp ( ) . getSampleRate ( ) / 2 ;
2015-01-04 13:20:31 -05:00
}
2015-01-02 21:32:24 -05:00
if ( isView ) {
2015-01-06 19:15:27 -05:00
setView ( centerFreq + ( freq - originalFreq ) , getBandwidth ( ) ) ;
2015-01-02 21:32:24 -05:00
if ( spectrumCanvas ) {
2015-01-03 17:07:39 -05:00
spectrumCanvas - > setView ( getCenterFrequency ( ) , getBandwidth ( ) ) ;
2015-01-02 21:32:24 -05:00
}
}
2015-01-01 21:10:54 -05:00
}
wxGetApp ( ) . setFrequency ( freq ) ;
2015-01-02 22:44:09 -05:00
setStatusText ( " Set center frequency: %s " , freq ) ;
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 ;
case ' S ' :
if ( ! activeDemod ) {
2014-12-28 05:13:46 -05:00
break ;
2015-01-01 21:10:54 -05:00
}
if ( activeDemod - > isSquelchEnabled ( ) ) {
activeDemod - > setSquelchEnabled ( false ) ;
} else {
activeDemod - > squelchAuto ( ) ;
}
break ;
case WXK_SPACE :
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 ;
default :
event . Skip ( ) ;
return ;
2014-11-15 23:41:41 -05:00
}
}
2014-12-28 05:13:46 -05:00
void WaterfallCanvas : : setData ( DemodulatorThreadIQData * input ) {
if ( ! input ) {
return ;
}
2015-01-04 17:11:20 -05:00
long double currentZoom = zoom ;
2015-01-03 17:07:39 -05:00
if ( mouseZoom ! = 1 ) {
currentZoom = mouseZoom ;
2015-01-04 13:20:31 -05:00
mouseZoom = mouseZoom + ( 1.0 - mouseZoom ) * 0.2 ;
2015-01-07 20:23:15 -05:00
if ( fabs ( mouseZoom - 1.0 ) < 0.01 ) {
mouseZoom = 1 ;
}
2015-01-03 17:07:39 -05:00
}
2015-01-04 17:11:20 -05:00
long long bw ;
2015-01-03 17:07:39 -05:00
if ( currentZoom ! = 1 ) {
2015-01-04 17:11:20 -05:00
long long freq = wxGetApp ( ) . getFrequency ( ) ;
2015-01-02 19:35:34 -05:00
2015-01-03 17:07:39 -05:00
if ( currentZoom < 1 ) {
centerFreq = getCenterFrequency ( ) ;
bw = getBandwidth ( ) ;
2015-01-04 17:11:20 -05:00
bw = ( long long ) ceil ( ( long double ) bw * currentZoom ) ;
2015-01-06 19:15:27 -05:00
if ( bw < 100000 ) {
bw = 100000 ;
2015-01-01 21:10:54 -05:00
}
2015-01-03 17:07:39 -05:00
if ( mouseTracker . mouseInView ( ) ) {
2015-01-04 17:11:20 -05:00
long long mfreqA = getFrequencyAt ( mouseTracker . getMouseX ( ) ) ;
2015-01-03 17:07:39 -05:00
setBandwidth ( bw ) ;
2015-01-04 17:11:20 -05:00
long long mfreqB = getFrequencyAt ( mouseTracker . getMouseX ( ) ) ;
2015-01-03 17:07:39 -05:00
centerFreq + = mfreqA - mfreqB ;
2015-01-02 19:35:34 -05:00
}
2015-01-03 17:07:39 -05:00
setView ( centerFreq , bw ) ;
2015-01-01 21:10:54 -05:00
if ( spectrumCanvas ) {
2015-01-03 17:07:39 -05:00
spectrumCanvas - > setView ( centerFreq , bw ) ;
2015-01-01 21:10:54 -05:00
}
} else {
if ( isView ) {
2015-01-03 17:07:39 -05:00
bw = getBandwidth ( ) ;
2015-01-04 17:11:20 -05:00
bw = ( long long ) ceil ( ( long double ) bw * currentZoom ) ;
2015-01-11 17:08:16 -05:00
if ( bw > = wxGetApp ( ) . getSampleRate ( ) ) {
bw = wxGetApp ( ) . getSampleRate ( ) ;
2015-01-03 17:07:39 -05:00
disableView ( ) ;
2015-01-01 21:10:54 -05:00
if ( spectrumCanvas ) {
2015-01-03 17:07:39 -05:00
spectrumCanvas - > disableView ( ) ;
2015-01-01 21:10:54 -05:00
}
} else {
2015-01-03 17:07:39 -05:00
if ( mouseTracker . mouseInView ( ) ) {
2015-01-04 17:11:20 -05:00
long long freq = wxGetApp ( ) . getFrequency ( ) ;
long long mfreqA = getFrequencyAt ( mouseTracker . getMouseX ( ) ) ;
2015-01-03 17:07:39 -05:00
setBandwidth ( bw ) ;
2015-01-04 17:11:20 -05:00
long long mfreqB = getFrequencyAt ( mouseTracker . getMouseX ( ) ) ;
2015-01-03 17:07:39 -05:00
centerFreq + = mfreqA - mfreqB ;
2015-01-02 19:35:34 -05:00
}
2015-01-03 17:07:39 -05:00
setView ( getCenterFrequency ( ) , bw ) ;
2015-01-01 21:10:54 -05:00
if ( spectrumCanvas ) {
2015-01-03 17:07:39 -05:00
spectrumCanvas - > setView ( centerFreq , bw ) ;
2015-01-01 21:10:54 -05:00
}
}
}
}
2015-01-11 17:08:16 -05:00
if ( centerFreq < freq & & ( centerFreq - bandwidth / 2 ) < ( freq - wxGetApp ( ) . getSampleRate ( ) / 2 ) ) {
centerFreq = ( freq - wxGetApp ( ) . getSampleRate ( ) / 2 ) + bandwidth / 2 ;
2015-01-02 19:35:34 -05:00
}
2015-01-11 17:08:16 -05:00
if ( centerFreq > freq & & ( centerFreq + bandwidth / 2 ) > ( freq + wxGetApp ( ) . getSampleRate ( ) / 2 ) ) {
centerFreq = ( freq + wxGetApp ( ) . getSampleRate ( ) / 2 ) - bandwidth / 2 ;
2015-01-02 19:35:34 -05:00
}
2015-01-01 21:10:54 -05:00
}
2014-12-28 05:13:46 -05:00
std : : vector < liquid_float_complex > * data = & input - > data ;
2014-11-15 23:41:41 -05:00
if ( data & & data - > size ( ) ) {
2015-01-01 21:10:54 -05:00
// if (fft_size != data->size() && !isView) {
// Setup(data->size(), waterfall_lines);
// }
2014-11-15 23:41:41 -05:00
2015-01-01 21:10:54 -05:00
// if (last_bandwidth != bandwidth && !isView) {
// Setup(bandwidth, waterfall_lines);
// }
2014-12-28 05:13:46 -05:00
if ( spectrum_points . size ( ) < fft_size * 2 ) {
spectrum_points . resize ( fft_size * 2 ) ;
}
2015-01-30 19:31:32 -05:00
unsigned int num_written ;
2014-12-28 05:13:46 -05:00
if ( isView ) {
2015-01-11 17:08:16 -05:00
if ( ! input - > frequency | | ! input - > sampleRate ) {
2014-12-28 05:13:46 -05:00
return ;
}
2015-01-03 17:07:39 -05:00
if ( centerFreq ! = input - > frequency ) {
2015-01-11 17:08:16 -05:00
if ( ( centerFreq - input - > frequency ) ! = shiftFrequency | | lastInputBandwidth ! = input - > sampleRate ) {
if ( abs ( input - > frequency - centerFreq ) < ( wxGetApp ( ) . getSampleRate ( ) / 2 ) ) {
2015-01-04 17:11:20 -05:00
shiftFrequency = centerFreq - input - > frequency ;
2015-01-03 17:07:39 -05:00
nco_crcf_reset ( freqShifter ) ;
2015-01-11 17:08:16 -05:00
nco_crcf_set_frequency ( freqShifter , ( 2.0 * M_PI ) * ( ( ( double ) abs ( shiftFrequency ) ) / ( ( double ) input - > sampleRate ) ) ) ;
2014-12-28 05:13:46 -05:00
}
}
2015-01-03 17:07:39 -05:00
if ( shiftBuffer . size ( ) ! = input - > data . size ( ) ) {
if ( shiftBuffer . capacity ( ) < input - > data . size ( ) ) {
shiftBuffer . reserve ( input - > data . size ( ) ) ;
2014-12-28 05:13:46 -05:00
}
2015-01-03 17:07:39 -05:00
shiftBuffer . resize ( input - > data . size ( ) ) ;
2014-12-28 05:13:46 -05:00
}
2015-01-03 17:07:39 -05:00
if ( shiftFrequency < 0 ) {
nco_crcf_mix_block_up ( freqShifter , & input - > data [ 0 ] , & shiftBuffer [ 0 ] , input - > data . size ( ) ) ;
2014-12-28 05:13:46 -05:00
} else {
2015-01-03 17:07:39 -05:00
nco_crcf_mix_block_down ( freqShifter , & input - > data [ 0 ] , & shiftBuffer [ 0 ] , input - > data . size ( ) ) ;
2014-12-28 05:13:46 -05:00
}
} else {
2015-01-03 17:07:39 -05:00
shiftBuffer . assign ( input - > data . begin ( ) , input - > data . end ( ) ) ;
2014-12-28 05:13:46 -05:00
}
2015-01-11 17:08:16 -05:00
if ( ! resampler | | bandwidth ! = lastBandwidth | | lastInputBandwidth ! = input - > sampleRate ) {
resamplerRatio = ( double ) ( bandwidth ) / ( double ) input - > sampleRate ;
2014-12-28 05:13:46 -05:00
2015-01-03 17:07:39 -05:00
float As = 120.0f ;
2014-12-28 05:13:46 -05:00
if ( resampler ) {
msresamp_crcf_destroy ( resampler ) ;
}
2015-01-03 17:07:39 -05:00
resampler = msresamp_crcf_create ( resamplerRatio , As ) ;
2014-12-28 05:13:46 -05:00
2015-01-03 17:07:39 -05:00
lastBandwidth = bandwidth ;
2015-01-11 17:08:16 -05:00
lastInputBandwidth = input - > sampleRate ;
2014-12-28 05:13:46 -05:00
}
2015-01-03 17:07:39 -05:00
int out_size = ceil ( ( double ) ( input - > data . size ( ) ) * resamplerRatio ) + 512 ;
2014-12-28 05:13:46 -05:00
2015-01-03 17:07:39 -05:00
if ( resampleBuffer . size ( ) ! = out_size ) {
if ( resampleBuffer . capacity ( ) < out_size ) {
resampleBuffer . reserve ( out_size ) ;
2014-12-28 05:13:46 -05:00
}
2015-01-03 17:07:39 -05:00
resampleBuffer . resize ( out_size ) ;
2014-12-28 05:13:46 -05:00
}
2015-01-03 17:07:39 -05:00
msresamp_crcf_execute ( resampler , & shiftBuffer [ 0 ] , input - > data . size ( ) , & resampleBuffer [ 0 ] , & num_written ) ;
2014-12-28 05:13:46 -05:00
2015-01-03 17:07:39 -05:00
resampleBuffer . resize ( fft_size ) ;
2014-12-28 05:13:46 -05:00
2015-01-01 18:08:54 -05:00
if ( num_written < fft_size ) {
for ( int i = 0 ; i < num_written ; i + + ) {
2015-01-30 19:31:32 -05:00
fft_in_data [ i ] [ 0 ] = resampleBuffer [ i ] . real ;
fft_in_data [ i ] [ 1 ] = resampleBuffer [ i ] . imag ;
2015-01-01 18:08:54 -05:00
}
for ( int i = num_written ; i < fft_size ; i + + ) {
2015-01-30 19:31:32 -05:00
fft_in_data [ i ] [ 0 ] = 0 ;
fft_in_data [ i ] [ 1 ] = 0 ;
2015-01-01 18:08:54 -05:00
}
} else {
for ( int i = 0 ; i < fft_size ; i + + ) {
2015-01-30 19:31:32 -05:00
fft_in_data [ i ] [ 0 ] = resampleBuffer [ i ] . real ;
fft_in_data [ i ] [ 1 ] = resampleBuffer [ i ] . imag ;
2015-01-01 18:08:54 -05:00
}
2014-12-28 05:13:46 -05:00
}
} else {
2015-01-30 19:31:32 -05:00
num_written = data - > size ( ) ;
2015-01-01 18:08:54 -05:00
if ( data - > size ( ) < fft_size ) {
for ( int i = 0 , iMax = data - > size ( ) ; i < iMax ; i + + ) {
2015-01-30 19:31:32 -05:00
fft_in_data [ i ] [ 0 ] = ( * data ) [ i ] . real ;
fft_in_data [ i ] [ 1 ] = ( * data ) [ i ] . imag ;
2015-01-01 18:08:54 -05:00
}
for ( int i = data - > size ( ) ; i < fft_size ; i + + ) {
2015-01-30 19:31:32 -05:00
fft_in_data [ i ] [ 0 ] = 0 ;
fft_in_data [ i ] [ 1 ] = 0 ;
2015-01-01 18:08:54 -05:00
}
} else {
for ( int i = 0 ; i < fft_size ; i + + ) {
2015-01-30 19:31:32 -05:00
fft_in_data [ i ] [ 0 ] = ( * data ) [ i ] . real ;
fft_in_data [ i ] [ 1 ] = ( * data ) [ i ] . imag ;
2015-01-01 18:08:54 -05:00
}
2014-12-28 05:13:46 -05:00
}
2014-11-15 23:41:41 -05:00
}
2015-01-30 19:31:32 -05:00
bool execute = false ;
2014-11-15 23:41:41 -05:00
2015-01-30 19:31:32 -05:00
if ( num_written > = fft_size ) {
execute = true ;
memcpy ( in , fft_in_data , sizeof ( fftwf_complex ) * fft_size * sizeof ( fftwf_complex ) ) ;
memcpy ( fft_last_data , in , fft_size * sizeof ( fftwf_complex ) ) ;
2014-11-15 23:41:41 -05:00
2015-01-30 19:31:32 -05:00
} else {
if ( last_data_size + num_written < fft_size ) { // priming
unsigned int num_copy = fft_size ;
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 ) ) ;
}
2014-11-15 23:41:41 -05:00
}
2015-01-30 19:31:32 -05:00
if ( execute ) {
fftwf_execute ( plan ) ;
2014-11-15 23:41:41 -05:00
2015-01-30 19:31:32 -05:00
float fft_ceil = 0 , fft_floor = 1 ;
2014-11-15 23:41:41 -05:00
2015-01-30 19:31:32 -05:00
if ( fft_result . size ( ) < fft_size ) {
fft_result . resize ( fft_size ) ;
fft_result_ma . resize ( fft_size ) ;
fft_result_maa . resize ( fft_size ) ;
2014-12-31 19:45:01 -05:00
}
2014-11-15 23:41:41 -05:00
2015-01-30 19:31:32 -05:00
int n ;
for ( int i = 0 , iMax = fft_size / 2 ; i < iMax ; i + + ) {
n = ( i = = 0 ) ? 1 : i ;
float a = out [ n ] [ 0 ] ;
float b = out [ n ] [ 1 ] ;
float c = sqrt ( a * a + b * b ) ;
float x = out [ fft_size / 2 + n ] [ 0 ] ;
float y = out [ fft_size / 2 + n ] [ 1 ] ;
float z = sqrt ( x * x + y * y ) ;
fft_result [ i ] = ( z ) ;
fft_result [ fft_size / 2 + i ] = ( c ) ;
2014-11-15 23:41:41 -05:00
}
2015-01-30 19:31:32 -05:00
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 ] ;
}
2014-11-15 23:41:41 -05:00
}
2015-01-30 19:31:32 -05:00
fft_ceil + = 0.25 ;
fft_floor - = 1 ;
2014-11-15 23:41:41 -05:00
2015-01-30 19:31:32 -05:00
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 ;
2014-11-15 23:41:41 -05:00
2015-01-30 19:31:32 -05:00
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 ;
2014-11-15 23:41:41 -05:00
2015-01-30 19:31:32 -05:00
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 ;
}
2014-12-29 00:24:10 -05:00
2015-01-30 19:31:32 -05:00
if ( spectrumCanvas ) {
spectrumCanvas - > spectrum_points . assign ( spectrum_points . begin ( ) , spectrum_points . end ( ) ) ;
}
2014-12-29 00:24:10 -05:00
}
2014-11-15 23:41:41 -05:00
}
}
void WaterfallCanvas : : OnIdle ( wxIdleEvent & event ) {
2014-11-25 22:51:14 -05:00
Refresh ( false ) ;
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 ) ;
setStatusText ( " Set demodulator bandwidth: %s " , demod - > getBandwidth ( ) ) ;
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-01-04 17:11:20 -05:00
long long bwDiff = ( long long ) ( mouseTracker . getDeltaMouseX ( ) * ( float ) getBandwidth ( ) ) ;
long long currentFreq = demod - > getFrequency ( ) ;
2014-11-30 21:14:17 -05:00
2015-01-04 17:11:20 -05:00
demod - > setFrequency ( currentFreq + bwDiff ) ;
currentFreq = demod - > getFrequency ( ) ;
2015-01-04 13:20:31 -05:00
demod - > updateLabel ( currentFreq ) ;
2015-01-02 22:44:09 -05:00
2015-01-04 13:20:31 -05:00
setStatusText ( " Set demodulator frequency: %s " , demod - > getFrequency ( ) ) ;
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. " ) ;
}
2014-12-11 20:50:58 -05:00
} else if ( demodsHover - > size ( ) ) {
2014-11-30 21:14:17 -05:00
int hovered = - 1 ;
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 ) ;
2014-11-30 18:54:13 -05:00
2015-01-04 17:11:20 -05:00
long dist = abs ( freqDiff ) ;
2014-11-30 18:54:13 -05:00
if ( dist < near_dist ) {
2014-11-30 21:14:17 -05:00
activeDemodulator = demod ;
near_dist = dist ;
2014-11-30 18:54:13 -05:00
}
2014-12-06 21:47:18 -05:00
2014-12-10 00:34:27 -05:00
if ( dist < = halfBw & & dist > = ( int ) ( ( float ) halfBw / ( float ) 1.5 ) ) {
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 ) {
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-12-28 20:55:05 -05:00
SetCursor ( wxCURSOR_SIZEWE ) ;
2014-11-30 21:14:17 -05:00
if ( freqDiff > 0 ) {
nextDragState = WF_DRAG_BANDWIDTH_LEFT ;
} else {
nextDragState = WF_DRAG_BANDWIDTH_RIGHT ;
}
2014-11-30 18:54:13 -05:00
2015-01-03 17:07:39 -05:00
mouseTracker . setVertDragLock ( true ) ;
mouseTracker . setHorizDragLock ( false ) ;
2015-01-02 22:44:09 -05:00
setStatusText ( " Click and drag to change demodulator bandwidth. D to delete, SPACE 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-01-02 22:44:09 -05:00
setStatusText ( " Click and drag to change demodulator frequency. D to delete, SPACE 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 ) {
setStatusText ( " Click to create a new demodulator or hold ALT to drag range. " ) ;
} else {
2015-01-04 13:20:31 -05:00
setStatusText (
" 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. " ) ;
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 ) {
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
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
mouseTracker . setVertDragLock ( false ) ;
mouseTracker . setHorizDragLock ( false ) ;
2014-12-10 00:34:27 -05:00
2014-12-11 21:37:01 -05:00
DemodulatorInstance * demod ;
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 ( ) ;
long long freq = input_center_freq - ( long long ) ( 0.5 * ( float ) getBandwidth ( ) ) + ( long long ) ( ( float ) pos * ( float ) getBandwidth ( ) ) ;
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 ( ) ;
demod - > getParams ( ) . frequency = freq ;
2014-12-06 21:10:29 -05:00
2014-12-11 20:50:58 -05:00
if ( DemodulatorInstance * last = wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) ) {
2015-01-04 17:11:20 -05:00
demod - > getParams ( ) . bandwidth = last - > getBandwidth ( ) ;
2015-01-02 19:35:34 -05:00
demod - > setDemodulatorType ( last - > getDemodulatorType ( ) ) ;
demod - > setSquelchLevel ( last - > getSquelchLevel ( ) ) ;
demod - > setSquelchEnabled ( last - > isSquelchEnabled ( ) ) ;
demod - > setStereo ( last - > isStereo ( ) ) ;
2015-01-10 20:33:30 -05:00
demod - > setGain ( last - > getGain ( ) ) ;
2014-12-11 20:50:58 -05:00
}
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-12-16 21:30:03 -05:00
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( demod , false ) ;
2014-12-11 20:50:58 -05:00
}
2014-11-25 22:51:14 -05:00
2014-12-10 18:52:24 -05:00
if ( demod = = NULL ) {
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
2014-12-10 00:34:27 -05:00
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) , 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 {
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( wxGetApp ( ) . getDemodMgr ( ) . getActiveDemodulator ( ) , false ) ;
2014-12-16 21:03:45 -05:00
nextDragState = WF_DRAG_FREQUENCY ;
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 ( ) ;
float 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 ;
}
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 ( ) ;
demod - > getParams ( ) . frequency = freq ;
2014-12-28 05:13:46 -05:00
demod - > getParams ( ) . bandwidth = bw ;
2015-01-02 19:35:34 -05:00
if ( DemodulatorInstance * last = wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) ) {
demod - > setDemodulatorType ( last - > getDemodulatorType ( ) ) ;
demod - > setSquelchLevel ( last - > getSquelchLevel ( ) ) ;
demod - > setSquelchEnabled ( last - > isSquelchEnabled ( ) ) ;
demod - > setStereo ( last - > isStereo ( ) ) ;
2015-01-10 20:33:30 -05:00
demod - > setGain ( last - > getGain ( ) ) ;
2015-01-02 19:35:34 -05:00
}
2014-12-11 21:37:01 -05:00
demod - > run ( ) ;
wxGetApp ( ) . bindDemodulator ( demod ) ;
2014-12-16 21:30:03 -05:00
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( demod , false ) ;
2014-12-11 21:37:01 -05:00
}
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
wxGetApp ( ) . getDemodMgr ( ) . setActiveDemodulator ( wxGetApp ( ) . getDemodMgr ( ) . getLastActiveDemodulator ( ) , false ) ;
demod - > updateLabel ( freq ) ;
2015-01-04 17:11:20 -05:00
demod - > setFrequency ( freq ) ;
demod - > setBandwidth ( bw ) ;
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
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 ;
}