| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | 
					
						
							|  |  |  | // written by Christian Daniel                                                   //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify          //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by          //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                  //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,               //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-05 17:08:06 +02:00
										 |  |  | #ifdef USE_SIMD
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | #include <immintrin.h>
 | 
					
						
							| 
									
										
										
										
											2015-07-05 17:08:06 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | #include <QMouseEvent>
 | 
					
						
							|  |  |  | #include "gui/glspectrum.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | #include <iostream>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | GLSpectrum::GLSpectrum(QWidget* parent) : | 
					
						
							|  |  |  | 	QGLWidget(parent), | 
					
						
							|  |  |  | 	m_cursorState(CSNormal), | 
					
						
							|  |  |  | 	m_mouseInside(false), | 
					
						
							|  |  |  | 	m_changesPending(true), | 
					
						
							|  |  |  | 	m_centerFrequency(100000000), | 
					
						
							|  |  |  | 	m_referenceLevel(0), | 
					
						
							|  |  |  | 	m_powerRange(100), | 
					
						
							|  |  |  | 	m_decay(0), | 
					
						
							|  |  |  | 	m_sampleRate(500000), | 
					
						
							|  |  |  | 	m_fftSize(512), | 
					
						
							|  |  |  | 	m_displayGrid(true), | 
					
						
							| 
									
										
										
										
											2015-05-12 15:49:03 +02:00
										 |  |  | 	m_displayGridIntensity(5), | 
					
						
							| 
									
										
										
										
											2015-07-18 17:53:57 +02:00
										 |  |  | 	m_displayTraceIntensity(50), | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	m_invertedWaterfall(false), | 
					
						
							|  |  |  | 	m_displayMaxHold(false), | 
					
						
							| 
									
										
										
										
											2015-07-16 08:38:33 +02:00
										 |  |  | 	m_currentSpectrum(0), | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	m_displayCurrent(false), | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	m_leftMarginTextureAllocated(false), | 
					
						
							|  |  |  | 	m_frequencyTextureAllocated(false), | 
					
						
							|  |  |  | 	m_waterfallBuffer(NULL), | 
					
						
							|  |  |  | 	m_waterfallTextureAllocated(false), | 
					
						
							|  |  |  | 	m_waterfallTextureHeight(-1), | 
					
						
							|  |  |  | 	m_displayWaterfall(true), | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 	m_ssbSpectrum(false), | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	m_histogramBuffer(NULL), | 
					
						
							|  |  |  | 	m_histogram(NULL), | 
					
						
							|  |  |  | 	m_histogramHoldoff(NULL), | 
					
						
							|  |  |  | 	m_histogramTextureAllocated(false), | 
					
						
							|  |  |  | 	m_displayHistogram(true), | 
					
						
							|  |  |  | 	m_displayChanged(false) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	setAutoFillBackground(false); | 
					
						
							|  |  |  | 	setAttribute(Qt::WA_OpaquePaintEvent, true); | 
					
						
							|  |  |  | 	setAttribute(Qt::WA_NoSystemBackground, true); | 
					
						
							|  |  |  | 	setMouseTracking(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	setMinimumSize(200, 200); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_waterfallShare = 0.66; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(int i = 0; i <= 239; i++) { | 
					
						
							|  |  |  | 		 QColor c; | 
					
						
							|  |  |  | 		 c.setHsv(239 - i, 255, 15 + i); | 
					
						
							|  |  |  | 		 ((quint8*)&m_waterfallPalette[i])[0] = c.red(); | 
					
						
							|  |  |  | 		 ((quint8*)&m_waterfallPalette[i])[1] = c.green(); | 
					
						
							|  |  |  | 		 ((quint8*)&m_waterfallPalette[i])[2] = c.blue(); | 
					
						
							|  |  |  | 		 ((quint8*)&m_waterfallPalette[i])[3] = c.alpha(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	m_waterfallPalette[239] = 0xffffffff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_histogramPalette[0] = m_waterfallPalette[0]; | 
					
						
							|  |  |  | 	for(int i = 1; i < 240; i++) { | 
					
						
							|  |  |  | 		 QColor c; | 
					
						
							|  |  |  | 		 c.setHsv(239 - i, 255 - ((i < 200) ? 0 : (i - 200) * 3), 150 + ((i < 100) ? i : 100)); | 
					
						
							|  |  |  | 		 ((quint8*)&m_histogramPalette[i])[0] = c.red(); | 
					
						
							|  |  |  | 		 ((quint8*)&m_histogramPalette[i])[1] = c.green(); | 
					
						
							|  |  |  | 		 ((quint8*)&m_histogramPalette[i])[2] = c.blue(); | 
					
						
							|  |  |  | 		 ((quint8*)&m_histogramPalette[i])[3] = c.alpha(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for(int i = 1; i < 16; i++) { | 
					
						
							|  |  |  | 		QColor c; | 
					
						
							|  |  |  | 		c.setHsv(270, 128, 48 + i * 4); | 
					
						
							|  |  |  | 		((quint8*)&m_histogramPalette[i])[0] = c.red(); | 
					
						
							|  |  |  | 		((quint8*)&m_histogramPalette[i])[1] = c.green(); | 
					
						
							|  |  |  | 		((quint8*)&m_histogramPalette[i])[2] = c.blue(); | 
					
						
							|  |  |  | 		((quint8*)&m_histogramPalette[i])[3] = c.alpha(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-16 08:38:33 +02:00
										 |  |  | 	m_histogramHoldoffBase = 2; // was 4
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	m_histogramHoldoffCount = m_histogramHoldoffBase; | 
					
						
							| 
									
										
										
										
											2015-07-15 08:48:02 +02:00
										 |  |  | 	m_histogramLateHoldoff = 1; // was 20
 | 
					
						
							|  |  |  | 	m_histogramStroke = 40; // was 4
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	m_timeScale.setFont(font()); | 
					
						
							|  |  |  | 	m_timeScale.setOrientation(Qt::Vertical); | 
					
						
							|  |  |  | 	m_timeScale.setRange(Unit::Time, 0, 1); | 
					
						
							|  |  |  | 	m_powerScale.setFont(font()); | 
					
						
							|  |  |  | 	m_powerScale.setOrientation(Qt::Vertical); | 
					
						
							|  |  |  | 	m_frequencyScale.setFont(font()); | 
					
						
							|  |  |  | 	m_frequencyScale.setOrientation(Qt::Horizontal); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); | 
					
						
							|  |  |  | 	m_timer.start(50); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GLSpectrum::~GLSpectrum() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(m_waterfallBuffer != NULL) { | 
					
						
							|  |  |  | 		delete m_waterfallBuffer; | 
					
						
							|  |  |  | 		m_waterfallBuffer = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(m_waterfallTextureAllocated) { | 
					
						
							|  |  |  | 		makeCurrent(); | 
					
						
							|  |  |  | 		deleteTexture(m_waterfallTexture); | 
					
						
							|  |  |  | 		m_waterfallTextureAllocated = false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(m_histogramBuffer != NULL) { | 
					
						
							|  |  |  | 		delete m_histogramBuffer; | 
					
						
							|  |  |  | 		m_histogramBuffer = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(m_histogram != NULL) { | 
					
						
							|  |  |  | 		delete[] m_histogram; | 
					
						
							|  |  |  | 		m_histogram = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(m_histogramHoldoff != NULL) { | 
					
						
							|  |  |  | 		delete[] m_histogramHoldoff; | 
					
						
							|  |  |  | 		m_histogramHoldoff = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(m_histogramTextureAllocated) { | 
					
						
							|  |  |  | 		makeCurrent(); | 
					
						
							|  |  |  | 		deleteTexture(m_histogramTexture); | 
					
						
							|  |  |  | 		m_histogramTextureAllocated = false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(m_leftMarginTextureAllocated) { | 
					
						
							|  |  |  | 		deleteTexture(m_leftMarginTexture); | 
					
						
							|  |  |  | 		m_leftMarginTextureAllocated = false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(m_frequencyTextureAllocated) { | 
					
						
							|  |  |  | 		deleteTexture(m_frequencyTexture); | 
					
						
							|  |  |  | 		m_frequencyTextureAllocated = false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setCenterFrequency(quint64 frequency) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_centerFrequency = frequency; | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setReferenceLevel(Real referenceLevel) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_referenceLevel = referenceLevel; | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setPowerRange(Real powerRange) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_powerRange = powerRange; | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setDecay(int decay) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_decay = decay; | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	if(m_decay < 0) | 
					
						
							|  |  |  | 		m_decay = 0; | 
					
						
							| 
									
										
										
										
											2015-06-12 03:21:02 +02:00
										 |  |  | 	else if(m_decay > 10) | 
					
						
							|  |  |  | 		m_decay = 10; | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | void GLSpectrum::setHistoLateHoldoff(int lateHoldoff) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_histogramLateHoldoff = lateHoldoff; | 
					
						
							|  |  |  | 	if(m_histogramLateHoldoff < 0) | 
					
						
							|  |  |  | 		m_histogramLateHoldoff = 0; | 
					
						
							|  |  |  | 	else if(m_histogramLateHoldoff > 20) | 
					
						
							|  |  |  | 		m_histogramLateHoldoff = 20; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setHistoStroke(int stroke) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_histogramStroke = stroke; | 
					
						
							|  |  |  | 	if(m_histogramStroke < 4) | 
					
						
							|  |  |  | 		m_histogramStroke = 4; | 
					
						
							|  |  |  | 	else if(m_histogramStroke > 240) | 
					
						
							|  |  |  | 		m_histogramStroke = 240; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | void GLSpectrum::setSampleRate(qint32 sampleRate) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_sampleRate = sampleRate; | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setDisplayWaterfall(bool display) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_displayWaterfall = display; | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	stopDrag(); | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | void GLSpectrum::setSsbSpectrum(bool ssbSpectrum) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_ssbSpectrum = ssbSpectrum; | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | void GLSpectrum::setInvertedWaterfall(bool inv) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_invertedWaterfall = inv; | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	stopDrag(); | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setDisplayMaxHold(bool display) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_displayMaxHold = display; | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	stopDrag(); | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | void GLSpectrum::setDisplayCurrent(bool display) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_displayCurrent = display; | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	stopDrag(); | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | void GLSpectrum::setDisplayHistogram(bool display) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_displayHistogram = display; | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	stopDrag(); | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setDisplayGrid(bool display) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_displayGrid = display; | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-12 15:49:03 +02:00
										 |  |  | void GLSpectrum::setDisplayGridIntensity(int intensity) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_displayGridIntensity = intensity; | 
					
						
							|  |  |  | 	if (m_displayGridIntensity > 100) { | 
					
						
							|  |  |  | 		m_displayGridIntensity = 100; | 
					
						
							| 
									
										
										
										
											2015-07-18 17:53:57 +02:00
										 |  |  | 	} else if (m_displayGridIntensity < 0) { | 
					
						
							|  |  |  | 		m_displayGridIntensity = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setDisplayTraceIntensity(int intensity) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_displayTraceIntensity = intensity; | 
					
						
							|  |  |  | 	if (m_displayTraceIntensity > 100) { | 
					
						
							|  |  |  | 		m_displayTraceIntensity = 100; | 
					
						
							|  |  |  | 	} else if (m_displayTraceIntensity < 0) { | 
					
						
							|  |  |  | 		m_displayTraceIntensity = 0; | 
					
						
							| 
									
										
										
										
											2015-05-12 15:49:03 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | void GLSpectrum::addChannelMarker(ChannelMarker* channelMarker) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	connect(channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged())); | 
					
						
							|  |  |  | 	connect(channelMarker, SIGNAL(destroyed(QObject*)), this, SLOT(channelMarkerDestroyed(QObject*))); | 
					
						
							|  |  |  | 	m_channelMarkerStates.append(new ChannelMarkerState(channelMarker)); | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	stopDrag(); | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::removeChannelMarker(ChannelMarker* channelMarker) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(int i = 0; i < m_channelMarkerStates.size(); ++i) { | 
					
						
							|  |  |  | 		if(m_channelMarkerStates[i]->m_channelMarker == channelMarker) { | 
					
						
							|  |  |  | 			channelMarker->disconnect(this); | 
					
						
							|  |  |  | 			delete m_channelMarkerStates.takeAt(i); | 
					
						
							|  |  |  | 			m_changesPending = true; | 
					
						
							|  |  |  | 			stopDrag(); | 
					
						
							|  |  |  | 			update(); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::newSpectrum(const std::vector<Real>& spectrum, int fftSize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_displayChanged = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(m_changesPending) { | 
					
						
							|  |  |  | 		m_fftSize = fftSize; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(fftSize != m_fftSize) { | 
					
						
							|  |  |  | 		m_fftSize = fftSize; | 
					
						
							|  |  |  | 		m_changesPending = true; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	updateWaterfall(spectrum); | 
					
						
							|  |  |  | 	updateHistogram(spectrum); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::updateWaterfall(const std::vector<Real>& spectrum) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(m_waterfallBufferPos < m_waterfallBuffer->height()) { | 
					
						
							|  |  |  | 		quint32* pix = (quint32*)m_waterfallBuffer->scanLine(m_waterfallBufferPos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(int i = 0; i < m_fftSize; i++) { | 
					
						
							| 
									
										
										
										
											2014-06-10 12:24:52 +01:00
										 |  |  | 			int v = (int)((spectrum[i] - m_referenceLevel) * 2.4 * 100.0 / m_powerRange + 240.0); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			if(v > 239) | 
					
						
							|  |  |  | 				v = 239; | 
					
						
							|  |  |  | 			else if(v < 0) | 
					
						
							|  |  |  | 				v = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			*pix++ = m_waterfallPalette[(int)v]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_waterfallBufferPos++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::updateHistogram(const std::vector<Real>& spectrum) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	quint8* b = m_histogram; | 
					
						
							|  |  |  | 	quint8* h = m_histogramHoldoff; | 
					
						
							|  |  |  | 	int sub = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(m_decay > 0) | 
					
						
							|  |  |  | 		sub += m_decay; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_histogramHoldoffCount--; | 
					
						
							|  |  |  | 	if(m_histogramHoldoffCount <= 0) { | 
					
						
							|  |  |  | 		for(int i = 0; i < 100 * m_fftSize; i++) { | 
					
						
							|  |  |  | 			if(*b > 20) { | 
					
						
							|  |  |  | 				*b = *b - sub; | 
					
						
							|  |  |  | 			} else if(*b > 0) { | 
					
						
							|  |  |  | 				if(*h >= sub) { | 
					
						
							|  |  |  | 					*h = *h - sub; | 
					
						
							|  |  |  | 				} else if(*h > 0) { | 
					
						
							|  |  |  | 					*h = *h - 1; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					*b = *b - 1; | 
					
						
							|  |  |  | 					*h = m_histogramLateHoldoff; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			b++; | 
					
						
							|  |  |  | 			h++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		m_histogramHoldoffCount = m_histogramHoldoffBase; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-16 08:53:55 +02:00
										 |  |  | 	m_currentSpectrum = &spectrum; // Store spectrum for current spectrum line display
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-05 17:08:06 +02:00
										 |  |  | #ifndef USE_SIMD
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	for(int i = 0; i < m_fftSize; i++) { | 
					
						
							|  |  |  | 		int v = (int)((spectrum[i] - m_referenceLevel) * 100.0 / m_powerRange + 100.0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-16 08:38:33 +02:00
										 |  |  | 		if ((v >= 0) && (v <= 99)) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			b = m_histogram + i * 100 + v; | 
					
						
							|  |  |  | 			if(*b < 220) | 
					
						
							| 
									
										
										
										
											2015-07-15 08:48:02 +02:00
										 |  |  | 				*b += m_histogramStroke; // was 4
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			else if(*b < 239) | 
					
						
							|  |  |  | 				*b += 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	if(m_decay >= 0) { // normal
 | 
					
						
							|  |  |  | 		const __m128 refl = {m_referenceLevel, m_referenceLevel, m_referenceLevel, m_referenceLevel}; | 
					
						
							|  |  |  | 		const __m128 power = {m_powerRange, m_powerRange, m_powerRange, m_powerRange}; | 
					
						
							|  |  |  | 		const __m128 mul = {100.0f, 100.0f, 100.0f, 100.0f}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(int i = 0; i < m_fftSize; i += 4) { | 
					
						
							|  |  |  | 			__m128 abc = _mm_loadu_ps (&spectrum[i]); | 
					
						
							|  |  |  | 			abc = _mm_sub_ps(abc, refl); | 
					
						
							|  |  |  | 			abc = _mm_mul_ps(abc, mul); | 
					
						
							|  |  |  | 			abc = _mm_div_ps(abc, power); | 
					
						
							|  |  |  | 			abc =  _mm_add_ps(abc, mul); | 
					
						
							|  |  |  | 			__m128i result = _mm_cvtps_epi32(abc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for(int j = 0; j < 4; j++) { | 
					
						
							|  |  |  | 				int v = ((int*)&result)[j]; | 
					
						
							|  |  |  | 				if((v >= 0) && (v <= 99)) { | 
					
						
							|  |  |  | 					b = m_histogram + (i + j) * 100 + v; | 
					
						
							|  |  |  | 					if(*b < 220) | 
					
						
							| 
									
										
										
										
											2015-07-20 22:51:49 +02:00
										 |  |  | 						*b += m_histogramStroke; // was 4
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 					else if(*b < 239) | 
					
						
							|  |  |  | 						*b += 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { // draw double pixels
 | 
					
						
							|  |  |  | 		int add = -m_decay * 4; | 
					
						
							|  |  |  | 		const __m128 refl = {m_referenceLevel, m_referenceLevel, m_referenceLevel, m_referenceLevel}; | 
					
						
							|  |  |  | 		const __m128 power = {m_powerRange, m_powerRange, m_powerRange, m_powerRange}; | 
					
						
							|  |  |  | 		const __m128 mul = {100.0f, 100.0f, 100.0f, 100.0f}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(int i = 0; i < m_fftSize; i += 4) { | 
					
						
							|  |  |  | 			__m128 abc = _mm_loadu_ps (&spectrum[i]); | 
					
						
							|  |  |  | 			abc = _mm_sub_ps(abc, refl); | 
					
						
							|  |  |  | 			abc = _mm_mul_ps(abc, mul); | 
					
						
							|  |  |  | 			abc = _mm_div_ps(abc, power); | 
					
						
							|  |  |  | 			abc =  _mm_add_ps(abc, mul); | 
					
						
							|  |  |  | 			__m128i result = _mm_cvtps_epi32(abc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for(int j = 0; j < 4; j++) { | 
					
						
							|  |  |  | 				int v = ((int*)&result)[j]; | 
					
						
							|  |  |  | 				if((v >= 1) && (v <= 98)) { | 
					
						
							|  |  |  | 					b = m_histogram + (i + j) * 100 + v; | 
					
						
							|  |  |  | 					if(b[-1] < 220) | 
					
						
							|  |  |  | 						b[-1] += add; | 
					
						
							|  |  |  | 					else if(b[-1] < 239) | 
					
						
							|  |  |  | 						b[-1] += 1; | 
					
						
							|  |  |  | 					if(b[0] < 220) | 
					
						
							|  |  |  | 						b[0] += add; | 
					
						
							|  |  |  | 					else if(b[0] < 239) | 
					
						
							|  |  |  | 						b[0] += 1; | 
					
						
							|  |  |  | 					if(b[1] < 220) | 
					
						
							|  |  |  | 						b[1] += add; | 
					
						
							|  |  |  | 					else if(b[1] < 239) | 
					
						
							|  |  |  | 						b[1] += 1; | 
					
						
							|  |  |  | 				} else if((v >= 0) && (v <= 99)) { | 
					
						
							|  |  |  | 					b = m_histogram + (i + j) * 100 + v; | 
					
						
							|  |  |  | 					if(*b < 220) | 
					
						
							|  |  |  | 						*b += add; | 
					
						
							|  |  |  | 					else if(*b < 239) | 
					
						
							|  |  |  | 						*b += 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::initializeGL() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	 glDisable(GL_DEPTH_TEST); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::resizeGL(int width, int height) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	glViewport(0, 0, width, height); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-24 01:09:03 +02:00
										 |  |  | void GLSpectrum::clearSpectrumHistogram() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(!m_mutex.tryLock(2)) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memset(m_histogram, 0x00, 100 * m_fftSize); | 
					
						
							|  |  |  | 	memset(m_histogramHoldoff, 0x07, 100 * m_fftSize); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_mutex.unlock(); | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | void GLSpectrum::paintGL() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(!m_mutex.tryLock(2)) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(m_changesPending) | 
					
						
							|  |  |  | 		applyChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(m_fftSize <= 0) { | 
					
						
							|  |  |  | 		m_mutex.unlock(); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | 
					
						
							|  |  |  | 	glClear(GL_COLOR_BUFFER_BIT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	glPushMatrix(); | 
					
						
							|  |  |  | 	glScalef(2.0, -2.0, 1.0); | 
					
						
							|  |  |  | 	glTranslatef(-0.50, -0.5, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// paint waterfall
 | 
					
						
							|  |  |  | 	if(m_displayWaterfall) { | 
					
						
							|  |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		glTranslatef(m_glWaterfallRect.x(), m_glWaterfallRect.y(), 0); | 
					
						
							|  |  |  | 		glScalef(m_glWaterfallRect.width(), m_glWaterfallRect.height(), 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glBindTexture(GL_TEXTURE_2D, m_waterfallTexture); | 
					
						
							|  |  |  | 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
					
						
							|  |  |  | 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
					
						
							|  |  |  | 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | 
					
						
							|  |  |  | 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | 
					
						
							|  |  |  | 		for(int i = 0; i < m_waterfallBufferPos; i++) { | 
					
						
							|  |  |  | 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, m_waterfallTexturePos, m_fftSize, 1, GL_RGBA, GL_UNSIGNED_BYTE, m_waterfallBuffer->scanLine(i)); | 
					
						
							|  |  |  | 			m_waterfallTexturePos = (m_waterfallTexturePos + 1) % m_waterfallTextureHeight; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		m_waterfallBufferPos = 0; | 
					
						
							|  |  |  | 		float prop_y = m_waterfallTexturePos / (m_waterfallTextureHeight - 1.0); | 
					
						
							|  |  |  | 		float off = 1.0 / (m_waterfallTextureHeight - 1.0); | 
					
						
							|  |  |  | 		glEnable(GL_TEXTURE_2D); | 
					
						
							|  |  |  | 		glBegin(GL_QUADS); | 
					
						
							|  |  |  | 		glTexCoord2f(0, prop_y + 1 - off); | 
					
						
							|  |  |  | 		glVertex2f(0, m_invertedWaterfall ? 0 : 1); | 
					
						
							|  |  |  | 		glTexCoord2f(1, prop_y + 1 - off); | 
					
						
							|  |  |  | 		glVertex2f(1, m_invertedWaterfall ? 0 : 1); | 
					
						
							|  |  |  | 		glTexCoord2f(1, prop_y); | 
					
						
							|  |  |  | 		glVertex2f(1, m_invertedWaterfall ? 1 : 0); | 
					
						
							|  |  |  | 		glTexCoord2f(0, prop_y); | 
					
						
							|  |  |  | 		glVertex2f(0, m_invertedWaterfall ? 1 : 0); | 
					
						
							|  |  |  | 		glEnd(); | 
					
						
							|  |  |  | 		glDisable(GL_TEXTURE_2D); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// paint channels
 | 
					
						
							|  |  |  | 		if(m_mouseInside) { | 
					
						
							|  |  |  | 			for(int i = 0; i < m_channelMarkerStates.size(); ++i) { | 
					
						
							|  |  |  | 				ChannelMarkerState* dv = m_channelMarkerStates[i]; | 
					
						
							|  |  |  | 				if(dv->m_channelMarker->getVisible()) { | 
					
						
							|  |  |  | 					glEnable(GL_BLEND); | 
					
						
							|  |  |  | 					glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 					glColor4f(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.3f); | 
					
						
							|  |  |  | 					glPushMatrix(); | 
					
						
							|  |  |  | 					glTranslatef(dv->m_glRect.x(), dv->m_glRect.y(), 0); | 
					
						
							|  |  |  | 					glScalef(dv->m_glRect.width(), dv->m_glRect.height(), 1); | 
					
						
							|  |  |  | 					glBegin(GL_QUADS); | 
					
						
							|  |  |  | 					glVertex2f(0, 0); | 
					
						
							|  |  |  | 					glVertex2f(1, 0); | 
					
						
							|  |  |  | 					glVertex2f(1, 1); | 
					
						
							|  |  |  | 					glVertex2f(0, 1); | 
					
						
							|  |  |  | 					glEnd(); | 
					
						
							|  |  |  | 					glDisable(GL_BLEND); | 
					
						
							|  |  |  | 					glPopMatrix(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// draw rect around
 | 
					
						
							|  |  |  | 		glEnable(GL_BLEND); | 
					
						
							|  |  |  | 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 		glLineWidth(1.0f); | 
					
						
							|  |  |  | 		glColor4f(1, 1, 1, 0.5); | 
					
						
							|  |  |  | 		glBegin(GL_LINE_LOOP); | 
					
						
							|  |  |  | 		glVertex2f(1, 1); | 
					
						
							|  |  |  | 		glVertex2f(0, 1); | 
					
						
							|  |  |  | 		glVertex2f(0, 0); | 
					
						
							|  |  |  | 		glVertex2f(1, 0); | 
					
						
							|  |  |  | 		glEnd(); | 
					
						
							|  |  |  | 		glDisable(GL_BLEND); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glPopMatrix(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// paint histogram
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	if(m_displayHistogram || m_displayMaxHold || m_displayCurrent) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		glTranslatef(m_glHistogramRect.x(), m_glHistogramRect.y(), 0); | 
					
						
							|  |  |  | 		glScalef(m_glHistogramRect.width(), m_glHistogramRect.height(), 1); | 
					
						
							|  |  |  | 		if(m_displayHistogram) { | 
					
						
							|  |  |  | 			// import new lines into the texture
 | 
					
						
							|  |  |  | 			quint32* pix; | 
					
						
							|  |  |  | 			quint8* bs = m_histogram; | 
					
						
							|  |  |  | 			for(int y = 0; y < 100; y++) { | 
					
						
							|  |  |  | 				quint8* b = bs; | 
					
						
							|  |  |  | 				pix = (quint32*)m_histogramBuffer->scanLine(99 - y); | 
					
						
							|  |  |  | 				for(int x = 0; x < m_fftSize; x++) { | 
					
						
							|  |  |  | 					*pix = m_histogramPalette[*b]; | 
					
						
							|  |  |  | 					pix++; | 
					
						
							|  |  |  | 					b += 100; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				bs++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// draw texture
 | 
					
						
							|  |  |  | 			glBindTexture(GL_TEXTURE_2D, m_histogramTexture); | 
					
						
							|  |  |  | 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
					
						
							|  |  |  | 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
					
						
							|  |  |  | 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); | 
					
						
							|  |  |  | 			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | 
					
						
							|  |  |  | 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_fftSize, 100, GL_RGBA, GL_UNSIGNED_BYTE, m_histogramBuffer->scanLine(0)); | 
					
						
							|  |  |  | 			glEnable(GL_TEXTURE_2D); | 
					
						
							|  |  |  | 			glBegin(GL_QUADS); | 
					
						
							|  |  |  | 			glTexCoord2f(0, 0); | 
					
						
							|  |  |  | 			glVertex2f(0, 0); | 
					
						
							|  |  |  | 			glTexCoord2f(1, 0); | 
					
						
							|  |  |  | 			glVertex2f(1, 0); | 
					
						
							|  |  |  | 			glTexCoord2f(1, 1); | 
					
						
							|  |  |  | 			glVertex2f(1, 1); | 
					
						
							|  |  |  | 			glTexCoord2f(0, 1); | 
					
						
							|  |  |  | 			glVertex2f(0, 1); | 
					
						
							|  |  |  | 			glEnd(); | 
					
						
							|  |  |  | 			glDisable(GL_TEXTURE_2D); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// paint channels
 | 
					
						
							|  |  |  | 		if(m_mouseInside) { | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 			// Effective BW overlays
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			for(int i = 0; i < m_channelMarkerStates.size(); ++i) { | 
					
						
							|  |  |  | 				ChannelMarkerState* dv = m_channelMarkerStates[i]; | 
					
						
							|  |  |  | 				if(dv->m_channelMarker->getVisible()) { | 
					
						
							|  |  |  | 					glEnable(GL_BLEND); | 
					
						
							|  |  |  | 					glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 					glColor4f(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.3f); | 
					
						
							|  |  |  | 					glPushMatrix(); | 
					
						
							|  |  |  | 					glTranslatef(dv->m_glRect.x(), dv->m_glRect.y(), 0); | 
					
						
							|  |  |  | 					glScalef(dv->m_glRect.width(), dv->m_glRect.height(), 1); | 
					
						
							|  |  |  | 					glBegin(GL_QUADS); | 
					
						
							|  |  |  | 					glVertex2f(0, 0); | 
					
						
							|  |  |  | 					glVertex2f(1, 0); | 
					
						
							|  |  |  | 					glVertex2f(1, 1); | 
					
						
							|  |  |  | 					glVertex2f(0, 1); | 
					
						
							|  |  |  | 					glEnd(); | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 					glPopMatrix(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Center line overlays based on DSB enveloppe
 | 
					
						
							|  |  |  | 			for(int i = 0; i < m_channelMarkerStates.size(); ++i) { | 
					
						
							|  |  |  | 				ChannelMarkerState* dv = m_channelMarkerStates[i]; | 
					
						
							|  |  |  | 				if(dv->m_channelMarker->getVisible()) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 					glDisable(GL_BLEND); | 
					
						
							|  |  |  | 					glColor3f(0.8f, 0.8f, 0.6f); | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 					glPushMatrix(); | 
					
						
							|  |  |  | 					glTranslatef(dv->m_glRectDsb.x(), dv->m_glRectDsb.y(), 0); | 
					
						
							|  |  |  | 					glScalef(dv->m_glRectDsb.width(), dv->m_glRectDsb.height(), 1); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 					glBegin(GL_LINE_LOOP); | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 					glVertex2f(0.5, 0); | 
					
						
							|  |  |  | 					glVertex2f(0.5, 1); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 					glEnd(); | 
					
						
							|  |  |  | 					glPopMatrix(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// draw rect around
 | 
					
						
							|  |  |  | 		glEnable(GL_BLEND); | 
					
						
							|  |  |  | 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 		glLineWidth(1.0f); | 
					
						
							|  |  |  | 		glColor4f(1, 1, 1, 0.5); | 
					
						
							|  |  |  | 		glBegin(GL_LINE_LOOP); | 
					
						
							|  |  |  | 		glVertex2f(1, 1); | 
					
						
							|  |  |  | 		glVertex2f(0, 1); | 
					
						
							|  |  |  | 		glVertex2f(0, 0); | 
					
						
							|  |  |  | 		glVertex2f(1, 0); | 
					
						
							|  |  |  | 		glEnd(); | 
					
						
							|  |  |  | 		glDisable(GL_BLEND); | 
					
						
							|  |  |  | 		glPopMatrix(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// paint left scales (time and power)
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	if(m_displayWaterfall || m_displayMaxHold || m_displayCurrent || m_displayHistogram ) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		glBindTexture(GL_TEXTURE_2D, m_leftMarginTexture); | 
					
						
							|  |  |  | 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
					
						
							|  |  |  | 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
					
						
							|  |  |  | 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | 
					
						
							|  |  |  | 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		glTranslatef(m_glLeftScaleRect.x(), m_glLeftScaleRect.y(), 0); | 
					
						
							|  |  |  | 		glScalef(m_glLeftScaleRect.width(), m_glLeftScaleRect.height(), 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glEnable(GL_TEXTURE_2D); | 
					
						
							|  |  |  | 		glBegin(GL_QUADS); | 
					
						
							|  |  |  | 		glTexCoord2f(0, 1); | 
					
						
							|  |  |  | 		glVertex2f(0, 1); | 
					
						
							|  |  |  | 		glTexCoord2f(1, 1); | 
					
						
							|  |  |  | 		glVertex2f(1, 1); | 
					
						
							|  |  |  | 		glTexCoord2f(1, 0); | 
					
						
							|  |  |  | 		glVertex2f(1, 0); | 
					
						
							|  |  |  | 		glTexCoord2f(0, 0); | 
					
						
							|  |  |  | 		glVertex2f(0, 0); | 
					
						
							|  |  |  | 		glEnd(); | 
					
						
							|  |  |  | 		glDisable(GL_TEXTURE_2D); | 
					
						
							|  |  |  | 		glPopMatrix(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// paint frequency scale
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	if(m_displayWaterfall || m_displayMaxHold || m_displayCurrent || m_displayHistogram ) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		glBindTexture(GL_TEXTURE_2D, m_frequencyTexture); | 
					
						
							|  |  |  | 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
					
						
							|  |  |  | 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
					
						
							|  |  |  | 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | 
					
						
							|  |  |  | 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | 
					
						
							|  |  |  | 		glEnable(GL_BLEND); | 
					
						
							|  |  |  | 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		glTranslatef(m_glFrequencyScaleRect.x(), m_glFrequencyScaleRect.y(), 0); | 
					
						
							|  |  |  | 		glScalef(m_glFrequencyScaleRect.width(), m_glFrequencyScaleRect.height(), 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glEnable(GL_TEXTURE_2D); | 
					
						
							|  |  |  | 		glBegin(GL_QUADS); | 
					
						
							|  |  |  | 		glTexCoord2f(0, 1); | 
					
						
							|  |  |  | 		glVertex2f(0, 1); | 
					
						
							|  |  |  | 		glTexCoord2f(1, 1); | 
					
						
							|  |  |  | 		glVertex2f(1, 1); | 
					
						
							|  |  |  | 		glTexCoord2f(1, 0); | 
					
						
							|  |  |  | 		glVertex2f(1, 0); | 
					
						
							|  |  |  | 		glTexCoord2f(0, 0); | 
					
						
							|  |  |  | 		glVertex2f(0, 0); | 
					
						
							|  |  |  | 		glEnd(); | 
					
						
							|  |  |  | 		glDisable(GL_TEXTURE_2D); | 
					
						
							|  |  |  | 		glPopMatrix(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// paint channels
 | 
					
						
							|  |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		glTranslatef(m_glWaterfallRect.x(), m_glFrequencyScaleRect.y(), 0); | 
					
						
							|  |  |  | 		glScalef(m_glWaterfallRect.width(), m_glFrequencyScaleRect.height(), 1); | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Effective bandwidth overlays
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		for(int i = 0; i < m_channelMarkerStates.size(); ++i) { | 
					
						
							|  |  |  | 			ChannelMarkerState* dv = m_channelMarkerStates[i]; | 
					
						
							|  |  |  | 			if(dv->m_channelMarker->getVisible()) { | 
					
						
							|  |  |  | 				glEnable(GL_BLEND); | 
					
						
							|  |  |  | 				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 				glColor4f(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.5f); | 
					
						
							|  |  |  | 				glPushMatrix(); | 
					
						
							|  |  |  | 				glTranslatef(dv->m_glRect.x(), dv->m_glRect.y(), 0); | 
					
						
							|  |  |  | 				glScalef(dv->m_glRect.width(), dv->m_glRect.height(), 1); | 
					
						
							|  |  |  | 				glBegin(GL_QUADS); | 
					
						
							|  |  |  | 				glVertex2f(0, 0); | 
					
						
							|  |  |  | 				glVertex2f(1, 0); | 
					
						
							| 
									
										
										
										
											2015-05-11 17:46:59 +02:00
										 |  |  | 				glVertex2f(1, 0.5); | 
					
						
							|  |  |  | 				glVertex2f(0, 0.5); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 				glEnd(); | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 				glDisable(GL_BLEND); | 
					
						
							|  |  |  | 				glPopMatrix(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-05-11 11:03:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 		// Center frequency mark on highlighted channels based on DSB enveloppe
 | 
					
						
							|  |  |  | 		for(int i = 0; i < m_channelMarkerStates.size(); ++i) { | 
					
						
							|  |  |  | 			ChannelMarkerState* dv = m_channelMarkerStates[i]; | 
					
						
							|  |  |  | 			if(dv->m_channelMarker->getVisible()) { | 
					
						
							| 
									
										
										
										
											2015-05-11 11:03:01 +02:00
										 |  |  | 				if (dv->m_channelMarker->getHighlighted()) { | 
					
						
							|  |  |  | 					glColor3f(0.8f, 0.8f, 0.6f); | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 					glPushMatrix(); | 
					
						
							|  |  |  | 					glTranslatef(dv->m_glRectDsb.x(), dv->m_glRectDsb.y(), 0); | 
					
						
							|  |  |  | 					glScalef(dv->m_glRectDsb.width(), dv->m_glRectDsb.height(), 1); | 
					
						
							| 
									
										
										
										
											2015-05-11 11:03:01 +02:00
										 |  |  | 					glBegin(GL_LINE_LOOP); | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 					glVertex2f(0.5, 0); | 
					
						
							|  |  |  | 					glVertex2f(0.5, 1); | 
					
						
							| 
									
										
										
										
											2015-05-11 11:03:01 +02:00
										 |  |  | 					glEnd(); | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 					glPopMatrix(); | 
					
						
							| 
									
										
										
										
											2015-05-11 11:03:01 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		glPopMatrix(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// paint max hold lines on top of histogram
 | 
					
						
							|  |  |  | 	if(m_displayMaxHold) { | 
					
						
							| 
									
										
										
										
											2014-11-21 15:41:58 +00:00
										 |  |  | 		if(m_maxHold.size() < (uint)m_fftSize) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			m_maxHold.resize(m_fftSize); | 
					
						
							|  |  |  | 		for(int i = 0; i < m_fftSize; i++) { | 
					
						
							|  |  |  | 			int j; | 
					
						
							|  |  |  | 			quint8* bs = m_histogram + i * 100; | 
					
						
							|  |  |  | 			for(j = 99; j > 1; j--) { | 
					
						
							|  |  |  | 				if(bs[j] > 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// TODO: ((bs[j] * (float)j) + (bs[j + 1] * (float)(j + 1))) / (bs[j] +  bs[j + 1])
 | 
					
						
							|  |  |  | 			j = j - 99; | 
					
						
							|  |  |  | 			m_maxHold[i] = (j * m_powerRange) / 99.0 + m_referenceLevel; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		glTranslatef(m_glHistogramRect.x(), m_glHistogramRect.y(), 0); | 
					
						
							|  |  |  | 		glScalef(m_glHistogramRect.width() / (float)(m_fftSize - 1), -m_glHistogramRect.height() / m_powerRange, 1); | 
					
						
							|  |  |  | 		glEnable(GL_BLEND); | 
					
						
							|  |  |  | 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 		glEnable(GL_LINE_SMOOTH); | 
					
						
							|  |  |  | 		glLineWidth(1.0f); | 
					
						
							| 
									
										
										
										
											2015-07-18 17:53:57 +02:00
										 |  |  | 		glColor4f(1, 0, 0, m_displayTraceIntensity / 100.0); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		Real bottom = -m_powerRange; | 
					
						
							|  |  |  | 		glBegin(GL_LINE_STRIP); | 
					
						
							|  |  |  | 		for(int i = 0; i < m_fftSize; i++) { | 
					
						
							|  |  |  | 			Real v = m_maxHold[i] - m_referenceLevel; | 
					
						
							|  |  |  | 			if(v > 0) | 
					
						
							|  |  |  | 				v = 0; | 
					
						
							|  |  |  | 			else if(v < bottom) | 
					
						
							|  |  |  | 				v = bottom; | 
					
						
							|  |  |  | 			glVertex2f(i, v); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		glEnd(); | 
					
						
							|  |  |  | 		glDisable(GL_LINE_SMOOTH); | 
					
						
							|  |  |  | 		glPopMatrix(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	// paint current spectrum line on top of histogram
 | 
					
						
							| 
									
										
										
										
											2015-07-16 08:38:33 +02:00
										 |  |  | 	if ((m_displayCurrent) && m_currentSpectrum) { | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		glTranslatef(m_glHistogramRect.x(), m_glHistogramRect.y(), 0); | 
					
						
							|  |  |  | 		glScalef(m_glHistogramRect.width() / (float)(m_fftSize - 1), -m_glHistogramRect.height() / m_powerRange, 1); | 
					
						
							|  |  |  | 		glEnable(GL_BLEND); | 
					
						
							|  |  |  | 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 		glEnable(GL_LINE_SMOOTH); | 
					
						
							|  |  |  | 		glLineWidth(1.0f); | 
					
						
							| 
									
										
										
										
											2015-07-18 17:53:57 +02:00
										 |  |  | 		glColor4f(1.0f, 1.0f, 0.25f, m_displayTraceIntensity / 100.0); // intense yellow
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 		Real bottom = -m_powerRange; | 
					
						
							|  |  |  | 		glBegin(GL_LINE_STRIP); | 
					
						
							|  |  |  | 		for(int i = 0; i < m_fftSize; i++) { | 
					
						
							| 
									
										
										
										
											2015-07-16 08:38:33 +02:00
										 |  |  | 			Real v = (*m_currentSpectrum)[i] - m_referenceLevel; | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 			if(v > 0) | 
					
						
							|  |  |  | 				v = 0; | 
					
						
							|  |  |  | 			else if(v < bottom) | 
					
						
							|  |  |  | 				v = bottom; | 
					
						
							|  |  |  | 			glVertex2f(i, v); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		glEnd(); | 
					
						
							|  |  |  | 		glDisable(GL_LINE_SMOOTH); | 
					
						
							|  |  |  | 		glPopMatrix(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	// paint waterfall grid
 | 
					
						
							|  |  |  | 	if(m_displayWaterfall && m_displayGrid) { | 
					
						
							|  |  |  | 		glEnable(GL_BLEND); | 
					
						
							|  |  |  | 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 		glLineWidth(1.0f); | 
					
						
							| 
									
										
										
										
											2015-05-12 15:49:03 +02:00
										 |  |  | 		//glColor4f(1, 1, 1, 0.05f);
 | 
					
						
							|  |  |  | 		glColor4f(1, 1, 1, m_displayGridIntensity / 100.0); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		glTranslatef(m_glWaterfallRect.x(), m_glWaterfallRect.y(), 0); | 
					
						
							|  |  |  | 		glScalef(m_glWaterfallRect.width(), m_glWaterfallRect.height(), 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const ScaleEngine::TickList* tickList; | 
					
						
							|  |  |  | 		const ScaleEngine::Tick* tick; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tickList = &m_timeScale.getTickList(); | 
					
						
							|  |  |  | 		for(int i= 0; i < tickList->count(); i++) { | 
					
						
							|  |  |  | 			tick = &(*tickList)[i]; | 
					
						
							|  |  |  | 			if(tick->major) { | 
					
						
							|  |  |  | 				if(tick->textSize > 0) { | 
					
						
							|  |  |  | 					float y = tick->pos / m_timeScale.getSize(); | 
					
						
							|  |  |  | 					glBegin(GL_LINE_LOOP); | 
					
						
							|  |  |  | 					glVertex2f(0, y); | 
					
						
							|  |  |  | 					glVertex2f(1, y); | 
					
						
							|  |  |  | 					glEnd(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tickList = &m_frequencyScale.getTickList(); | 
					
						
							|  |  |  | 		for(int i= 0; i < tickList->count(); i++) { | 
					
						
							|  |  |  | 			tick = &(*tickList)[i]; | 
					
						
							|  |  |  | 			if(tick->major) { | 
					
						
							|  |  |  | 				if(tick->textSize > 0) { | 
					
						
							|  |  |  | 					float x = tick->pos / m_frequencyScale.getSize(); | 
					
						
							|  |  |  | 					glBegin(GL_LINE_LOOP); | 
					
						
							|  |  |  | 					glVertex2f(x, 0); | 
					
						
							|  |  |  | 					glVertex2f(x, 1); | 
					
						
							|  |  |  | 					glEnd(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glPopMatrix(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-17 01:00:48 +02:00
										 |  |  | 	// TODO: paint histogram grid
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	if((m_displayHistogram || m_displayMaxHold || m_displayCurrent) && (m_displayGrid)) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		glEnable(GL_BLEND); | 
					
						
							|  |  |  | 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							|  |  |  | 		glLineWidth(1.0f); | 
					
						
							| 
									
										
										
										
											2015-05-12 15:49:03 +02:00
										 |  |  | 		glColor4f(1, 1, 1, m_displayGridIntensity / 100.0); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		glTranslatef(m_glHistogramRect.x(), m_glHistogramRect.y(), 0); | 
					
						
							|  |  |  | 		glScalef(m_glHistogramRect.width(), m_glHistogramRect.height(), 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const ScaleEngine::TickList* tickList; | 
					
						
							|  |  |  | 		const ScaleEngine::Tick* tick; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tickList = &m_powerScale.getTickList(); | 
					
						
							|  |  |  | 		for(int i= 0; i < tickList->count(); i++) { | 
					
						
							|  |  |  | 			tick = &(*tickList)[i]; | 
					
						
							|  |  |  | 			if(tick->major) { | 
					
						
							|  |  |  | 				if(tick->textSize > 0) { | 
					
						
							|  |  |  | 					float y = tick->pos / m_powerScale.getSize(); | 
					
						
							|  |  |  | 					glBegin(GL_LINE_LOOP); | 
					
						
							| 
									
										
										
										
											2015-07-17 01:00:48 +02:00
										 |  |  | 					glVertex2f(0, 1-y); | 
					
						
							|  |  |  | 					glVertex2f(1, 1-y); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 					glEnd(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tickList = &m_frequencyScale.getTickList(); | 
					
						
							|  |  |  | 		for(int i= 0; i < tickList->count(); i++) { | 
					
						
							|  |  |  | 			tick = &(*tickList)[i]; | 
					
						
							|  |  |  | 			if(tick->major) { | 
					
						
							|  |  |  | 				if(tick->textSize > 0) { | 
					
						
							|  |  |  | 					float x = tick->pos / m_frequencyScale.getSize(); | 
					
						
							|  |  |  | 					glBegin(GL_LINE_LOOP); | 
					
						
							|  |  |  | 					glVertex2f(x, 0); | 
					
						
							|  |  |  | 					glVertex2f(x, 1); | 
					
						
							|  |  |  | 					glEnd(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glPopMatrix(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	glPopMatrix(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_mutex.unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::stopDrag() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(m_cursorState != CSNormal) { | 
					
						
							|  |  |  | 		if((m_cursorState == CSSplitterMoving) || (m_cursorState == CSChannelMoving)) | 
					
						
							|  |  |  | 			releaseMouse(); | 
					
						
							|  |  |  | 		setCursor(Qt::ArrowCursor); | 
					
						
							|  |  |  | 		m_cursorState = CSNormal; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::applyChanges() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_changesPending = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(m_fftSize <= 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	QFontMetrics fm(font()); | 
					
						
							|  |  |  | 	int M = fm.width("-"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int topMargin = fm.ascent() * 1.5; | 
					
						
							|  |  |  | 	int bottomMargin = fm.ascent() * 1.5; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-21 15:41:58 +00:00
										 |  |  | 	int waterfallHeight = 0; | 
					
						
							|  |  |  | 	int waterfallTop = 0; | 
					
						
							| 
									
										
										
										
											2015-05-11 13:37:46 +02:00
										 |  |  | 	int frequencyScaleHeight = fm.height() * 3; // +1 line for marker frequency scale
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	int frequencyScaleTop; | 
					
						
							| 
									
										
										
										
											2014-11-21 15:41:58 +00:00
										 |  |  | 	int histogramTop = 0; | 
					
						
							|  |  |  | 	int histogramHeight = 20; | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	int leftMargin; | 
					
						
							|  |  |  | 	int rightMargin = fm.width("000"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	if(m_displayWaterfall && (m_displayHistogram | m_displayMaxHold | m_displayCurrent)) | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		waterfallHeight = height() * m_waterfallShare - 1; | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		if(waterfallHeight < 0) | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			waterfallHeight = 0; | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(!m_invertedWaterfall) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			waterfallTop = topMargin; | 
					
						
							|  |  |  | 			frequencyScaleTop = waterfallTop + waterfallHeight + 1; | 
					
						
							|  |  |  | 			histogramTop = waterfallTop + waterfallHeight + frequencyScaleHeight + 1; | 
					
						
							|  |  |  | 			histogramHeight = height() - topMargin - waterfallHeight - frequencyScaleHeight - bottomMargin; | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			histogramTop = topMargin; | 
					
						
							|  |  |  | 			histogramHeight = height() - topMargin - waterfallHeight - frequencyScaleHeight - bottomMargin; | 
					
						
							|  |  |  | 			waterfallTop = histogramTop + histogramHeight + frequencyScaleHeight + 1; | 
					
						
							|  |  |  | 			frequencyScaleTop = histogramTop + histogramHeight + 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_timeScale.setSize(waterfallHeight); | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if(m_sampleRate > 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			float scaleDiv = (float)m_sampleRate * (m_ssbSpectrum ? 2 : 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			if(!m_invertedWaterfall) | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				m_timeScale.setRange(Unit::Time, (waterfallHeight * m_fftSize) / scaleDiv, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				m_timeScale.setRange(Unit::Time, 0, (waterfallHeight * m_fftSize) / scaleDiv); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			m_timeScale.setRange(Unit::Time, 0, 1); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		m_powerScale.setSize(histogramHeight); | 
					
						
							|  |  |  | 		m_powerScale.setRange(Unit::Decibel, m_referenceLevel - m_powerRange, m_referenceLevel); | 
					
						
							|  |  |  | 		leftMargin = m_timeScale.getScaleWidth(); | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		if(m_powerScale.getScaleWidth() > leftMargin) | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			leftMargin = m_powerScale.getScaleWidth(); | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		leftMargin += 2 * M; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_frequencyScale.setSize(width() - leftMargin - rightMargin); | 
					
						
							|  |  |  | 		m_frequencyScale.setRange(Unit::Frequency, m_centerFrequency - m_sampleRate / 2, m_centerFrequency + m_sampleRate / 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_glWaterfallRect = QRectF( | 
					
						
							|  |  |  | 			(float)leftMargin / (float)width(), | 
					
						
							|  |  |  | 			(float)waterfallTop / (float)height(), | 
					
						
							|  |  |  | 			(float)(width() - leftMargin - rightMargin) / (float)width(), | 
					
						
							|  |  |  | 			(float)waterfallHeight / (float)height() | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_glHistogramRect = QRectF( | 
					
						
							|  |  |  | 			(float)leftMargin / (float)width(), | 
					
						
							|  |  |  | 			(float)histogramTop / (float)height(), | 
					
						
							|  |  |  | 			(float)(width() - leftMargin - rightMargin) / (float)width(), | 
					
						
							|  |  |  | 			(float)histogramHeight / (float)height() | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_frequencyScaleRect = QRect( | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			frequencyScaleTop, | 
					
						
							|  |  |  | 			width(), | 
					
						
							|  |  |  | 			frequencyScaleHeight | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		m_glFrequencyScaleRect = QRectF( | 
					
						
							|  |  |  | 			(float)0, | 
					
						
							|  |  |  | 			(float)frequencyScaleTop / (float)height(), | 
					
						
							|  |  |  | 			(float)1, | 
					
						
							|  |  |  | 			(float)frequencyScaleHeight / (float)height() | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_glLeftScaleRect = QRectF( | 
					
						
							|  |  |  | 			(float)0, | 
					
						
							|  |  |  | 			(float)0, | 
					
						
							|  |  |  | 			(float)(leftMargin - 1) / (float)width(), | 
					
						
							|  |  |  | 			(float)1 | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if(m_displayWaterfall) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		bottomMargin = frequencyScaleHeight; | 
					
						
							|  |  |  | 		waterfallTop = topMargin; | 
					
						
							|  |  |  | 		waterfallHeight = height() - topMargin - frequencyScaleHeight; | 
					
						
							|  |  |  | 		frequencyScaleTop = topMargin + waterfallHeight + 1; | 
					
						
							|  |  |  | 		histogramTop = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_timeScale.setSize(waterfallHeight); | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if(m_sampleRate > 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			float scaleDiv = (float)m_sampleRate * (m_ssbSpectrum ? 2 : 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			if(!m_invertedWaterfall) | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				m_timeScale.setRange(Unit::Time, (waterfallHeight * m_fftSize) / scaleDiv, 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				m_timeScale.setRange(Unit::Time, 0, (waterfallHeight * m_fftSize) / scaleDiv); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			if(!m_invertedWaterfall) | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 				m_timeScale.setRange(Unit::Time, 10, 0); | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				m_timeScale.setRange(Unit::Time, 0, 10); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		leftMargin = m_timeScale.getScaleWidth(); | 
					
						
							|  |  |  | 		leftMargin += 2 * M; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_frequencyScale.setSize(width() - leftMargin - rightMargin); | 
					
						
							|  |  |  | 		m_frequencyScale.setRange(Unit::Frequency, m_centerFrequency - m_sampleRate / 2.0, m_centerFrequency + m_sampleRate / 2.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_glWaterfallRect = QRectF( | 
					
						
							|  |  |  | 			(float)leftMargin / (float)width(), | 
					
						
							|  |  |  | 			(float)topMargin / (float)height(), | 
					
						
							|  |  |  | 			(float)(width() - leftMargin - rightMargin) / (float)width(), | 
					
						
							|  |  |  | 			(float)waterfallHeight / (float)height() | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_frequencyScaleRect = QRect( | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			frequencyScaleTop, | 
					
						
							|  |  |  | 			width(), | 
					
						
							|  |  |  | 			frequencyScaleHeight | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		m_glFrequencyScaleRect = QRectF( | 
					
						
							|  |  |  | 			(float)0, | 
					
						
							|  |  |  | 			(float)frequencyScaleTop / (float)height(), | 
					
						
							|  |  |  | 			(float)1, | 
					
						
							|  |  |  | 			(float)frequencyScaleHeight / (float)height() | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_glLeftScaleRect = QRectF( | 
					
						
							|  |  |  | 			(float)0, | 
					
						
							|  |  |  | 			(float)0, | 
					
						
							|  |  |  | 			(float)(leftMargin - 1) / (float)width(), | 
					
						
							|  |  |  | 			(float)1 | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	else if(m_displayHistogram || m_displayMaxHold || m_displayCurrent) | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		bottomMargin = frequencyScaleHeight; | 
					
						
							|  |  |  | 		frequencyScaleTop = height() - bottomMargin; | 
					
						
							|  |  |  | 		histogramTop = topMargin - 1; | 
					
						
							|  |  |  | 		waterfallHeight = 0; | 
					
						
							|  |  |  | 		histogramHeight = height() - topMargin - frequencyScaleHeight; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_powerScale.setSize(histogramHeight); | 
					
						
							|  |  |  | 		m_powerScale.setRange(Unit::Decibel, m_referenceLevel - m_powerRange, m_referenceLevel); | 
					
						
							|  |  |  | 		leftMargin = m_powerScale.getScaleWidth(); | 
					
						
							|  |  |  | 		leftMargin += 2 * M; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_frequencyScale.setSize(width() - leftMargin - rightMargin); | 
					
						
							|  |  |  | 		m_frequencyScale.setRange(Unit::Frequency, m_centerFrequency - m_sampleRate / 2, m_centerFrequency + m_sampleRate / 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_glHistogramRect = QRectF( | 
					
						
							|  |  |  | 			(float)leftMargin / (float)width(), | 
					
						
							|  |  |  | 			(float)histogramTop / (float)height(), | 
					
						
							|  |  |  | 			(float)(width() - leftMargin - rightMargin) / (float)width(), | 
					
						
							|  |  |  | 			(float)(height() - topMargin - frequencyScaleHeight) / (float)height() | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_frequencyScaleRect = QRect( | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			frequencyScaleTop, | 
					
						
							|  |  |  | 			width(), | 
					
						
							|  |  |  | 			frequencyScaleHeight | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		m_glFrequencyScaleRect = QRectF( | 
					
						
							|  |  |  | 			(float)0, | 
					
						
							|  |  |  | 			(float)frequencyScaleTop / (float)height(), | 
					
						
							|  |  |  | 			(float)1, | 
					
						
							|  |  |  | 			(float)frequencyScaleHeight / (float)height() | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_glLeftScaleRect = QRectF( | 
					
						
							|  |  |  | 			(float)0, | 
					
						
							|  |  |  | 			(float)0, | 
					
						
							|  |  |  | 			(float)(leftMargin - 1) / (float)width(), | 
					
						
							|  |  |  | 			(float)1 | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2015-06-12 02:49:29 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		leftMargin = 2; | 
					
						
							|  |  |  | 		waterfallHeight = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// channel overlays
 | 
					
						
							|  |  |  | 	for(int i = 0; i < m_channelMarkerStates.size(); ++i) { | 
					
						
							|  |  |  | 		ChannelMarkerState* dv = m_channelMarkerStates[i]; | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 		qreal xc, pw, nw, dsbw; | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 		ChannelMarker::sidebands_t sidebands = dv->m_channelMarker->getSidebands(); | 
					
						
							|  |  |  | 		xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency
 | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 		dsbw = dv->m_channelMarker->getBandwidth(); | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (sidebands == ChannelMarker::usb) { | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 			nw = dv->m_channelMarker->getLowCutoff();     // negative bandwidth
 | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 			pw = dv->m_channelMarker->getBandwidth() / 2; // positive bandwidth
 | 
					
						
							|  |  |  | 		} else if (sidebands == ChannelMarker::lsb) { | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 			pw = dv->m_channelMarker->getLowCutoff(); | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 			nw = dv->m_channelMarker->getBandwidth() / 2; | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 			pw = dsbw / 2; | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 			nw = -pw; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:02 +02:00
										 |  |  | 		// draw the DSB rectangle
 | 
					
						
							|  |  |  | 		dv->m_glRectDsb.setRect( | 
					
						
							|  |  |  | 			m_frequencyScale.getPosFromValue(xc - (dsbw/2)) / (float)(width() - leftMargin - rightMargin), | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			dsbw / (float)m_sampleRate, | 
					
						
							|  |  |  | 			1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// draw the effective BW rectangle
 | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 		dv->m_glRect.setRect( | 
					
						
							|  |  |  | 			m_frequencyScale.getPosFromValue(xc + nw) / (float)(width() - leftMargin - rightMargin), | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			(pw-nw) / (float)m_sampleRate, | 
					
						
							|  |  |  | 			1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		dv->m_glRect.setRect( | 
					
						
							|  |  |  | 			m_frequencyScale.getPosFromValue(m_centerFrequency + dv->m_channelMarker->getCenterFrequency() - dv->m_channelMarker->getBandwidth() / 2) / (float)(width() - leftMargin - rightMargin), | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			(dv->m_channelMarker->getBandwidth() / (float)m_sampleRate), | 
					
						
							|  |  |  | 			1); | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 		*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 		if(m_displayHistogram || m_displayMaxHold || m_displayCurrent || m_displayWaterfall) { | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 			dv->m_rect.setRect(m_frequencyScale.getPosFromValue(xc) + leftMargin - 1, | 
					
						
							|  |  |  | 			topMargin, | 
					
						
							|  |  |  | 			5, | 
					
						
							|  |  |  | 			height() - topMargin - bottomMargin); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		if(m_displayHistogram || m_displayMaxHold || m_displayWaterfall) { | 
					
						
							|  |  |  | 			dv->m_rect.setRect(m_frequencyScale.getPosFromValue(m_centerFrequency + dv->m_channelMarker->getCenterFrequency()) + leftMargin - 1, | 
					
						
							|  |  |  | 			topMargin, | 
					
						
							|  |  |  | 			5, | 
					
						
							|  |  |  | 			height() - topMargin - bottomMargin); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-05-11 03:27:31 +02:00
										 |  |  | 		*/ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// prepare left scales (time and power)
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		m_leftMarginPixmap = QPixmap(leftMargin - 1, height()); | 
					
						
							|  |  |  | 		m_leftMarginPixmap.fill(Qt::black); | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			QPainter painter(&m_leftMarginPixmap); | 
					
						
							|  |  |  | 			painter.setPen(QColor(0xf0, 0xf0, 0xff)); | 
					
						
							| 
									
										
										
										
											2015-07-07 02:50:26 +02:00
										 |  |  | 			painter.setFont(font()); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			const ScaleEngine::TickList* tickList; | 
					
						
							|  |  |  | 			const ScaleEngine::Tick* tick; | 
					
						
							|  |  |  | 			if(m_displayWaterfall) { | 
					
						
							|  |  |  | 				tickList = &m_timeScale.getTickList(); | 
					
						
							|  |  |  | 				for(int i = 0; i < tickList->count(); i++) { | 
					
						
							|  |  |  | 					tick = &(*tickList)[i]; | 
					
						
							|  |  |  | 					if(tick->major) { | 
					
						
							|  |  |  | 						if(tick->textSize > 0) | 
					
						
							|  |  |  | 							painter.drawText(QPointF(leftMargin - M - tick->textSize, waterfallTop + fm.ascent() + tick->textPos), tick->text); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 			if(m_displayHistogram || m_displayMaxHold || m_displayCurrent) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 				tickList = &m_powerScale.getTickList(); | 
					
						
							|  |  |  | 				for(int i = 0; i < tickList->count(); i++) { | 
					
						
							|  |  |  | 					tick = &(*tickList)[i]; | 
					
						
							|  |  |  | 					if(tick->major) { | 
					
						
							|  |  |  | 						if(tick->textSize > 0) | 
					
						
							|  |  |  | 							painter.drawText(QPointF(leftMargin - M - tick->textSize, histogramTop + histogramHeight - tick->textPos - 1), tick->text); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(m_leftMarginTextureAllocated) | 
					
						
							|  |  |  | 			deleteTexture(m_leftMarginTexture); | 
					
						
							|  |  |  | 		m_leftMarginTexture = bindTexture(m_leftMarginPixmap, | 
					
						
							|  |  |  | 			GL_TEXTURE_2D, | 
					
						
							|  |  |  | 			GL_RGBA, | 
					
						
							|  |  |  | 			QGLContext::LinearFilteringBindOption | | 
					
						
							|  |  |  | 			QGLContext::MipmapBindOption); | 
					
						
							|  |  |  | 		m_leftMarginTextureAllocated = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// prepare frequency scale
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	if(m_displayWaterfall || m_displayHistogram || m_displayMaxHold || m_displayCurrent){ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		m_frequencyPixmap = QPixmap(width(), frequencyScaleHeight); | 
					
						
							|  |  |  | 		m_frequencyPixmap.fill(Qt::transparent); | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			QPainter painter(&m_frequencyPixmap); | 
					
						
							|  |  |  | 			painter.setPen(Qt::NoPen); | 
					
						
							|  |  |  | 			painter.setBrush(Qt::black); | 
					
						
							|  |  |  | 			painter.setBrush(Qt::transparent); | 
					
						
							|  |  |  | 			painter.drawRect(leftMargin, 0, width() - leftMargin, frequencyScaleHeight); | 
					
						
							|  |  |  | 			painter.setPen(QColor(0xf0, 0xf0, 0xff)); | 
					
						
							| 
									
										
										
										
											2015-07-07 02:50:26 +02:00
										 |  |  | 			painter.setFont(font()); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			const ScaleEngine::TickList* tickList = &m_frequencyScale.getTickList(); | 
					
						
							|  |  |  | 			const ScaleEngine::Tick* tick; | 
					
						
							|  |  |  | 			for(int i = 0; i < tickList->count(); i++) { | 
					
						
							|  |  |  | 				tick = &(*tickList)[i]; | 
					
						
							|  |  |  | 				if(tick->major) { | 
					
						
							|  |  |  | 					if(tick->textSize > 0) | 
					
						
							|  |  |  | 						painter.drawText(QPointF(leftMargin + tick->textPos, fm.height() + fm.ascent() / 2 - 1), tick->text); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-11 13:37:46 +02:00
										 |  |  | 			// Frequency overlay on highlighted marker
 | 
					
						
							|  |  |  | 			for(int i = 0; i < m_channelMarkerStates.size(); ++i) { | 
					
						
							|  |  |  | 				ChannelMarkerState* dv = m_channelMarkerStates[i]; | 
					
						
							|  |  |  | 				if (dv->m_channelMarker->getHighlighted()) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					qreal xc; | 
					
						
							| 
									
										
										
										
											2015-05-11 17:46:59 +02:00
										 |  |  | 					int shift; | 
					
						
							| 
									
										
										
										
											2015-05-11 13:37:46 +02:00
										 |  |  | 					//ChannelMarker::sidebands_t sidebands = dv->m_channelMarker->getSidebands();
 | 
					
						
							|  |  |  | 					xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency
 | 
					
						
							|  |  |  | 					QString ftext = QString::number((m_centerFrequency + dv->m_channelMarker->getCenterFrequency())/1e6, 'f', 6); | 
					
						
							| 
									
										
										
										
											2015-05-11 17:46:59 +02:00
										 |  |  | 					if (dv->m_channelMarker->getCenterFrequency() < 0) { // left half of scale
 | 
					
						
							|  |  |  | 						ftext = " " + ftext; | 
					
						
							|  |  |  | 						shift = 0; | 
					
						
							|  |  |  | 					} else { // right half of scale
 | 
					
						
							|  |  |  | 						ftext = ftext + " "; | 
					
						
							|  |  |  | 						shift = - fm.width(ftext); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					painter.drawText(QPointF(leftMargin + m_frequencyScale.getPosFromValue(xc) + shift, 2*fm.height() + fm.ascent() / 2 - 1), ftext); | 
					
						
							| 
									
										
										
										
											2015-05-11 13:37:46 +02:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if(m_frequencyTextureAllocated) | 
					
						
							|  |  |  | 			deleteTexture(m_frequencyTexture); | 
					
						
							|  |  |  | 		m_frequencyTexture = bindTexture(m_frequencyPixmap, | 
					
						
							|  |  |  | 			GL_TEXTURE_2D, | 
					
						
							|  |  |  | 			GL_RGBA, | 
					
						
							|  |  |  | 			QGLContext::LinearFilteringBindOption | | 
					
						
							|  |  |  | 			QGLContext::MipmapBindOption); | 
					
						
							|  |  |  | 		m_frequencyTextureAllocated = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(!m_waterfallTextureAllocated) { | 
					
						
							|  |  |  | 		glGenTextures(1, &m_waterfallTexture); | 
					
						
							|  |  |  | 		m_waterfallTextureAllocated = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(!m_histogramTextureAllocated) { | 
					
						
							|  |  |  | 		glGenTextures(1, &m_histogramTexture); | 
					
						
							|  |  |  | 		m_histogramTextureAllocated = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool fftSizeChanged = true; | 
					
						
							|  |  |  | 	if(m_waterfallBuffer != NULL) | 
					
						
							|  |  |  | 		fftSizeChanged = m_waterfallBuffer->width() != m_fftSize; | 
					
						
							|  |  |  | 	bool windowSizeChanged = m_waterfallTextureHeight != waterfallHeight; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(fftSizeChanged) { | 
					
						
							|  |  |  | 		if(m_waterfallBuffer != NULL) { | 
					
						
							|  |  |  | 			delete m_waterfallBuffer; | 
					
						
							|  |  |  | 			m_waterfallBuffer = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		m_waterfallBuffer = new QImage(m_fftSize, 256, QImage::Format_ARGB32); | 
					
						
							|  |  |  | 		if(m_waterfallBuffer != NULL) { | 
					
						
							|  |  |  | 			m_waterfallBuffer->fill(qRgb(0x00, 0x00, 0x00)); | 
					
						
							|  |  |  | 			m_waterfallBufferPos = 0; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			m_fftSize = 0; | 
					
						
							|  |  |  | 			m_changesPending = true; | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(m_histogramBuffer != NULL) { | 
					
						
							|  |  |  | 			delete m_histogramBuffer; | 
					
						
							|  |  |  | 			m_histogramBuffer = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(m_histogram != NULL) { | 
					
						
							|  |  |  | 			delete[] m_histogram; | 
					
						
							|  |  |  | 			m_histogram = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(m_histogramHoldoff != NULL) { | 
					
						
							|  |  |  | 			delete[] m_histogramHoldoff; | 
					
						
							|  |  |  | 			m_histogramHoldoff = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_histogramBuffer = new QImage(m_fftSize, 100, QImage::Format_RGB32); | 
					
						
							|  |  |  | 		if(m_histogramBuffer != NULL) { | 
					
						
							|  |  |  | 			m_histogramBuffer->fill(qRgb(0x00, 0x00, 0x00)); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			m_fftSize = 0; | 
					
						
							|  |  |  | 			m_changesPending = true; | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m_histogram = new quint8[100 * m_fftSize]; | 
					
						
							|  |  |  | 		memset(m_histogram, 0x00, 100 * m_fftSize); | 
					
						
							|  |  |  | 		m_histogramHoldoff = new quint8[100 * m_fftSize]; | 
					
						
							|  |  |  | 		memset(m_histogramHoldoff, 0x07, 100 * m_fftSize); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		quint8* data = new quint8[m_fftSize * 100 * 4]; | 
					
						
							|  |  |  | 		memset(data, 0x00, m_fftSize * 100 * 4); | 
					
						
							|  |  |  | 		glBindTexture(GL_TEXTURE_2D, m_histogramTexture); | 
					
						
							|  |  |  | 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_fftSize, 100, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); | 
					
						
							|  |  |  | 		delete[] data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(fftSizeChanged || windowSizeChanged) { | 
					
						
							|  |  |  | 		m_waterfallTextureHeight = waterfallHeight; | 
					
						
							|  |  |  | 		quint8* data = new quint8[m_fftSize * m_waterfallTextureHeight * 4]; | 
					
						
							|  |  |  | 		memset(data, 0x00, m_fftSize * m_waterfallTextureHeight * 4); | 
					
						
							|  |  |  | 		glBindTexture(GL_TEXTURE_2D, m_waterfallTexture); | 
					
						
							|  |  |  | 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_fftSize, m_waterfallTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); | 
					
						
							|  |  |  | 		delete[] data; | 
					
						
							|  |  |  | 		m_waterfallTexturePos = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::mouseMoveEvent(QMouseEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	if(m_displayWaterfall && (m_displayWaterfall || m_displayHistogram || m_displayMaxHold || m_displayCurrent)) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		if(m_frequencyScaleRect.contains(event->pos())) { | 
					
						
							|  |  |  | 			if(m_cursorState == CSNormal) { | 
					
						
							|  |  |  | 				setCursor(Qt::SizeVerCursor); | 
					
						
							|  |  |  | 				m_cursorState = CSSplitter; | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if(m_cursorState == CSSplitter) { | 
					
						
							|  |  |  | 				setCursor(Qt::ArrowCursor); | 
					
						
							|  |  |  | 				m_cursorState = CSNormal; | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(m_cursorState == CSSplitterMoving) { | 
					
						
							|  |  |  | 		float newShare; | 
					
						
							|  |  |  | 		if(!m_invertedWaterfall) | 
					
						
							|  |  |  | 			newShare = (float)(event->y() - m_frequencyScaleRect.height()) / (float)height(); | 
					
						
							|  |  |  | 		else newShare = 1.0 - (float)(event->y() + m_frequencyScaleRect.height()) / (float)height(); | 
					
						
							|  |  |  | 		if(newShare < 0.1) | 
					
						
							|  |  |  | 			newShare = 0.1f; | 
					
						
							|  |  |  | 		else if(newShare > 0.8) | 
					
						
							|  |  |  | 			newShare = 0.8f; | 
					
						
							|  |  |  | 		m_waterfallShare = newShare; | 
					
						
							|  |  |  | 		m_changesPending = true; | 
					
						
							|  |  |  | 		update(); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} else if(m_cursorState == CSChannelMoving) { | 
					
						
							|  |  |  | 		Real freq = m_frequencyScale.getValueFromPos(event->x() - m_leftMarginPixmap.width() - 1) - m_centerFrequency; | 
					
						
							| 
									
										
										
										
											2014-06-30 23:26:21 +01:00
										 |  |  | 		if(m_channelMarkerStates[m_cursorChannel]->m_channelMarker->getColor()!=Qt::blue) | 
					
						
							|  |  |  | 			m_channelMarkerStates[m_cursorChannel]->m_channelMarker->setCenterFrequency(freq); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-16 04:55:14 +02:00
										 |  |  | 	if(m_displayWaterfall || m_displayHistogram || m_displayMaxHold || m_displayCurrent) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		for(int i = 0; i < m_channelMarkerStates.size(); ++i) { | 
					
						
							|  |  |  | 			if(m_channelMarkerStates[i]->m_rect.contains(event->pos())) { | 
					
						
							|  |  |  | 				if(m_cursorState == CSNormal) { | 
					
						
							|  |  |  | 					setCursor(Qt::SizeHorCursor); | 
					
						
							|  |  |  | 					m_cursorState = CSChannel; | 
					
						
							|  |  |  | 					m_cursorChannel = i; | 
					
						
							| 
									
										
										
										
											2015-06-20 11:09:08 +02:00
										 |  |  | 					m_channelMarkerStates[i]->m_channelMarker->setHighlighted(true); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 					return; | 
					
						
							|  |  |  | 				} else if(m_cursorState == CSChannel) { | 
					
						
							|  |  |  | 					return; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-06-20 11:09:08 +02:00
										 |  |  | 			} else if (m_channelMarkerStates[i]->m_channelMarker->getHighlighted()) { | 
					
						
							|  |  |  | 				m_channelMarkerStates[i]->m_channelMarker->setHighlighted(false); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(m_cursorState == CSChannel) { | 
					
						
							|  |  |  | 		setCursor(Qt::ArrowCursor); | 
					
						
							|  |  |  | 		m_cursorState = CSNormal; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::mousePressEvent(QMouseEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(event->button() != 1) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(m_cursorState == CSSplitter) { | 
					
						
							|  |  |  | 		grabMouse(); | 
					
						
							|  |  |  | 		m_cursorState = CSSplitterMoving; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} else if(m_cursorState == CSChannel) { | 
					
						
							|  |  |  | 		grabMouse(); | 
					
						
							|  |  |  | 		m_cursorState = CSChannelMoving; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} else if((m_cursorState == CSNormal) && (m_channelMarkerStates.size() == 1)) { | 
					
						
							|  |  |  | 		grabMouse(); | 
					
						
							|  |  |  | 		setCursor(Qt::SizeHorCursor); | 
					
						
							|  |  |  | 		m_cursorState = CSChannelMoving; | 
					
						
							|  |  |  | 		m_cursorChannel = 0; | 
					
						
							|  |  |  | 		Real freq = m_frequencyScale.getValueFromPos(event->x() - m_leftMarginPixmap.width() - 1) - m_centerFrequency; | 
					
						
							| 
									
										
										
										
											2014-06-30 23:26:21 +01:00
										 |  |  | 		if(m_channelMarkerStates[m_cursorChannel]->m_channelMarker->getColor()!=Qt::blue) | 
					
						
							|  |  |  | 			m_channelMarkerStates[m_cursorChannel]->m_channelMarker->setCenterFrequency(freq); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::mouseReleaseEvent(QMouseEvent*) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(m_cursorState == CSSplitterMoving) { | 
					
						
							|  |  |  | 		releaseMouse(); | 
					
						
							|  |  |  | 		m_cursorState = CSSplitter; | 
					
						
							|  |  |  | 	} else if(m_cursorState == CSChannelMoving) { | 
					
						
							|  |  |  | 		releaseMouse(); | 
					
						
							|  |  |  | 		m_cursorState = CSChannel; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::enterEvent(QEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_mouseInside = true; | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | 	QGLWidget::enterEvent(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::leaveEvent(QEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_mouseInside = false; | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | 	QGLWidget::enterEvent(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::tick() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(m_displayChanged) { | 
					
						
							|  |  |  | 		m_displayChanged = false; | 
					
						
							|  |  |  | 		update(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::channelMarkerChanged() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | 	update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::channelMarkerDestroyed(QObject* object) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	removeChannelMarker((ChannelMarker*)object); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-07-24 01:30:00 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void GLSpectrum::setWaterfallShare(Real waterfallShare) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (waterfallShare < 0.1f) { | 
					
						
							|  |  |  | 		m_waterfallShare = 0.1f; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (waterfallShare > 0.8f) { | 
					
						
							|  |  |  | 		m_waterfallShare = 0.8f; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		m_waterfallShare = waterfallShare; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	m_changesPending = true; | 
					
						
							|  |  |  | } |