From de8f64063f979a915f05ac7cb5478b48fa9733a7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 21 Jan 2022 00:18:41 +0100 Subject: [PATCH] Spectrum Annotations. Implements #887 --- scriptsapi/config.py | 3 + sdrbase/dsp/spectrummarkers.cpp | 48 + sdrbase/dsp/spectrummarkers.h | 45 + sdrbase/dsp/spectrumsettings.cpp | 73 + sdrbase/dsp/spectrumsettings.h | 4 +- sdrbase/resources/webapi/doc/html2/index.html | 32 +- .../doc/swagger/include/GLSpectrum.yaml | 26 +- sdrgui/gui/glspectrum.cpp | 3277 +++++++++-------- sdrgui/gui/glspectrum.h | 278 +- sdrgui/gui/glspectrumgui.cpp | 197 +- sdrgui/gui/glspectrumgui.h | 2 + sdrgui/gui/spectrummarkersdialog.cpp | 357 +- sdrgui/gui/spectrummarkersdialog.h | 28 + sdrgui/gui/spectrummarkersdialog.ui | 684 +++- sdrgui/mainwindow.cpp | 1 - sdrgui/resources/res.qrc | 1 + sdrgui/resources/sort.png | Bin 0 -> 975 bytes .../api/swagger/include/GLSpectrum.yaml | 26 +- swagger/sdrangel/code/html2/index.html | 32 +- .../code/qt5/client/SWGGLSpectrum.cpp | 29 + .../sdrangel/code/qt5/client/SWGGLSpectrum.h | 7 + .../code/qt5/client/SWGModelFactory.h | 6 + .../client/SWGSpectrumAnnotationMarker.cpp | 177 + .../qt5/client/SWGSpectrumAnnotationMarker.h | 76 + 24 files changed, 3614 insertions(+), 1795 deletions(-) create mode 100644 sdrgui/resources/sort.png create mode 100644 swagger/sdrangel/code/qt5/client/SWGSpectrumAnnotationMarker.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGSpectrumAnnotationMarker.h diff --git a/scriptsapi/config.py b/scriptsapi/config.py index ed8232cc2..6c430ff14 100755 --- a/scriptsapi/config.py +++ b/scriptsapi/config.py @@ -36,6 +36,7 @@ def getInputOptions(): parser.add_option("-j", "--json-file", dest="json_file", help="JSON file containing commands. Mandatory", metavar="FILE", type="string") parser.add_option("-i", "--init", dest="initialize", help="Initialize instance before running script", action="store_true") parser.add_option("-1", "--ignore-first-posts", dest="ignore_first_posts", help="Ignore first deviceset or featureset post in sequence", action="store_true") + parser.add_option("-d", "--delay", dest="delay_ms", help="force delay after each command (ms)", metavar="TIME", type="int") (options, args) = parser.parse_args() @@ -134,6 +135,8 @@ def main(): delay = command.get('delay', None) if delay is not None and isinstance(delay, int): time.sleep(delay/1000) + elif options.delay_ms is not None: + time.sleep(options.delay_ms/1000) print("All done!") diff --git a/sdrbase/dsp/spectrummarkers.cpp b/sdrbase/dsp/spectrummarkers.cpp index 5a497c694..702ed031d 100644 --- a/sdrbase/dsp/spectrummarkers.cpp +++ b/sdrbase/dsp/spectrummarkers.cpp @@ -113,3 +113,51 @@ bool SpectrumWaterfallMarker::deserialize(const QByteArray& data) return false; } } + +QByteArray SpectrumAnnotationMarker::serialize() const +{ + SimpleSerializer s(1); + + s.writeS64(1, m_startFrequency); + s.writeU32(2, m_bandwidth); + int r, g, b; + m_markerColor.getRgb(&r, &g, &b); + s.writeS32(4, r); + s.writeS32(5, g); + s.writeS32(6, b); + s.writeBool(7, m_show); + s.writeString(8, m_text); + + return s.final(); +} + +bool SpectrumAnnotationMarker::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) { + return false; + } + + if (d.getVersion() == 1) + { + d.readS64(1, &m_startFrequency, 0); + d.readU32(2, &m_bandwidth, 0); + int r, g, b; + d.readS32(4, &r, 255); + m_markerColor.setRed(r); + d.readS32(5, &g, 255); + m_markerColor.setGreen(g); + d.readS32(6, &b, 255); + m_markerColor.setBlue(b); + d.readBool(7, &m_show, true); + d.readString(8, &m_text); + + return true; + } + else + { + return false; + } + +} diff --git a/sdrbase/dsp/spectrummarkers.h b/sdrbase/dsp/spectrummarkers.h index 00b90f2ca..05e955317 100644 --- a/sdrbase/dsp/spectrummarkers.h +++ b/sdrbase/dsp/spectrummarkers.h @@ -155,4 +155,49 @@ struct SDRBASE_API SpectrumWaterfallMarker bool deserialize(const QByteArray& data); }; +struct SDRBASE_API SpectrumAnnotationMarker +{ + qint64 m_startFrequency; + uint32_t m_bandwidth; + QColor m_markerColor; + bool m_show; + QString m_text; + bool m_selected; + float m_startPos; + float m_stopPos; + + SpectrumAnnotationMarker() : + m_startFrequency(0), + m_bandwidth(0), + m_markerColor("white"), + m_show(true), + m_text("Text"), + m_selected(false), + m_startPos(0.0f), + m_stopPos(1.0f) + {} + + SpectrumAnnotationMarker( + qint64 startFrequency, + uint32_t bandwidth, + QColor markerColor, + bool show, + const QString& text + ) : + m_startFrequency(startFrequency), + m_bandwidth(bandwidth), + m_markerColor(markerColor), + m_show(show), + m_text(text), + m_startPos(0.0f), + m_stopPos(1.0f) + {} + + SpectrumAnnotationMarker(const SpectrumAnnotationMarker& other) = default; + SpectrumAnnotationMarker& operator=(const SpectrumAnnotationMarker&) = default; + + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + #endif // INCLUDE_SPECTRUMMARKERS_H diff --git a/sdrbase/dsp/spectrumsettings.cpp b/sdrbase/dsp/spectrumsettings.cpp index 1792d0f0f..3c605fe9b 100644 --- a/sdrbase/dsp/spectrumsettings.cpp +++ b/sdrbase/dsp/spectrumsettings.cpp @@ -15,6 +15,9 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include +#include + #include "SWGGLSpectrum.h" #include "util/simpleserializer.h" @@ -102,9 +105,25 @@ QByteArray SpectrumSettings::serialize() const s.writeBlob(111+i, m_waterfallMarkers[i].serialize()); } + QByteArray data; + QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly); + (*stream) << m_annoationMarkers; + delete stream; + s.writeBlob(40, data); + return s.final(); } +QDataStream& operator<<(QDataStream& out, const SpectrumAnnotationMarker& marker) +{ + out << marker.m_startFrequency; + out << marker.m_bandwidth; + out << marker.m_markerColor; + out << marker.m_show; + out << marker.m_text; + return out; +} + bool SpectrumSettings::deserialize(const QByteArray& data) { SimpleDeserializer d(data); @@ -182,6 +201,11 @@ bool SpectrumSettings::deserialize(const QByteArray& data) m_waterfallMarkers.back().deserialize(bytetmp); } + d.readBlob(40, &bytetmp); + QDataStream *stream = new QDataStream(bytetmp); + (*stream) >> m_annoationMarkers; + delete stream; + return true; } else @@ -191,6 +215,16 @@ bool SpectrumSettings::deserialize(const QByteArray& data) } } +QDataStream& operator>>(QDataStream& in, SpectrumAnnotationMarker& marker) +{ + in >> marker.m_startFrequency; + in >> marker.m_bandwidth; + in >> marker.m_markerColor; + in >> marker.m_show; + in >> marker.m_text; + return in; +} + void SpectrumSettings::formatTo(SWGSDRangel::SWGObject *swgObject) const { SWGSDRangel::SWGGLSpectrum *swgSpectrum = static_cast(swgObject); @@ -256,6 +290,20 @@ void SpectrumSettings::formatTo(SWGSDRangel::SWGObject *swgObject) const swgSpectrum->getWaterfallMarkers()->back()->setShow(marker.m_show ? 1 : 0); } } + + if (m_annoationMarkers.size() > 0) + { + swgSpectrum->setAnnotationMarkers(new QList); + + for (const auto &marker : m_annoationMarkers) + { + swgSpectrum->getAnnotationMarkers()->append(new SWGSDRangel::SWGSpectrumAnnotationMarker); + swgSpectrum->getAnnotationMarkers()->back()->setStartFrequency(marker.m_startFrequency); + swgSpectrum->getAnnotationMarkers()->back()->setBandwidth(marker.m_bandwidth); + swgSpectrum->getAnnotationMarkers()->back()->setMarkerColor(qColorToInt(marker.m_markerColor)); + swgSpectrum->getAnnotationMarkers()->back()->setShow(marker.m_show ? 1 : 0); + } + } } void SpectrumSettings::updateFrom(const QStringList& keys, const SWGSDRangel::SWGObject *swgObject) @@ -351,6 +399,7 @@ void SpectrumSettings::updateFrom(const QStringList& keys, const SWGSDRangel::SW { QList *swgHistogramMarkers = swgSpectrum->getHistogramMarkers(); m_histogramMarkers.clear(); + int i = 0; for (const auto &swgHistogramMarker : *swgHistogramMarkers) { @@ -360,6 +409,10 @@ void SpectrumSettings::updateFrom(const QStringList& keys, const SWGSDRangel::SW m_histogramMarkers.back().m_markerType = (SpectrumHistogramMarker::SpectrumMarkerType) swgHistogramMarker->getMarkerType(); m_histogramMarkers.back().m_markerColor = intToQColor(swgHistogramMarker->getMarkerColor()); m_histogramMarkers.back().m_show = swgHistogramMarker->getShow() != 0; + + if (i++ == 10) { // no more than 10 markers + break; + } } } @@ -367,6 +420,7 @@ void SpectrumSettings::updateFrom(const QStringList& keys, const SWGSDRangel::SW { QList *swgWaterfallMarkers = swgSpectrum->getWaterfallMarkers(); m_waterfallMarkers.clear(); + int i = 0; for (const auto &swgWaterfallMarker : *swgWaterfallMarkers) { @@ -375,6 +429,25 @@ void SpectrumSettings::updateFrom(const QStringList& keys, const SWGSDRangel::SW m_waterfallMarkers.back().m_time = swgWaterfallMarker->getTime(); m_waterfallMarkers.back().m_markerColor = intToQColor(swgWaterfallMarker->getMarkerColor()); m_waterfallMarkers.back().m_show = swgWaterfallMarker->getShow() != 0; + + if (i++ == 10) { // no more than 10 markers + break; + } + } + } + + if (keys.contains("spectrumConfig.annotationMarkers")) + { + QList *swgAnnotationMarkers = swgSpectrum->getAnnotationMarkers(); + m_waterfallMarkers.clear(); + + for (const auto &swgAnnotationMarker : *swgAnnotationMarkers) + { + m_annoationMarkers.push_back(SpectrumAnnotationMarker()); + m_annoationMarkers.back().m_startFrequency = swgAnnotationMarker->getStartFrequency(); + m_annoationMarkers.back().m_bandwidth = swgAnnotationMarker->getBandwidth() < 0 ? 0 : swgAnnotationMarker->getBandwidth(); + m_annoationMarkers.back().m_markerColor = intToQColor(swgAnnotationMarker->getMarkerColor()); + m_annoationMarkers.back().m_show = swgAnnotationMarker->getShow() != 0; } } } diff --git a/sdrbase/dsp/spectrumsettings.h b/sdrbase/dsp/spectrumsettings.h index 665dc54ae..d3999ac4b 100644 --- a/sdrbase/dsp/spectrumsettings.h +++ b/sdrbase/dsp/spectrumsettings.h @@ -41,7 +41,8 @@ public: enum MarkersDisplay { MarkersDisplayNone, - MarkersDisplaySpectrum + MarkersDisplaySpectrum, + MarkersDisplayAnnotations }; int m_fftSize; @@ -73,6 +74,7 @@ public: uint16_t m_wsSpectrumPort; //!< websocket spectrum server port QList m_histogramMarkers; QList m_waterfallMarkers; + QList m_annoationMarkers; static const int m_log2FFTSizeMin = 6; // 64 static const int m_log2FFTSizeMax = 15; // 32k diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index f38f4db06..690073b01 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -6162,6 +6162,12 @@ margin-bottom: 20px; "items" : { "$ref" : "#/definitions/SpectrumWaterfallMarker" } + }, + "annotationMarkers" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/SpectrumAnnotationMarker" + } } }, "description" : "GLSpectrumGUI settings" @@ -11782,6 +11788,26 @@ margin-bottom: 20px; } }, "description" : "SoapySDR" +}; + defs.SpectrumAnnotationMarker = { + "properties" : { + "startFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "bandwidth" : { + "type" : "integer" + }, + "markerColor" : { + "type" : "integer", + "description" : "Color in 8 bit BGR serie" + }, + "show" : { + "type" : "integer", + "description" : "Boolean - Marker display state\n * 0 - Hidden\n * 1 - Visible\n" + } + }, + "description" : "Spectrum annotation marker settings" }; defs.SpectrumHistogramMarker = { "properties" : { @@ -11800,7 +11826,7 @@ margin-bottom: 20px; }, "markerColor" : { "type" : "integer", - "description" : "Color in 8 bit RGB serie" + "description" : "Color in 8 bit BGR serie" }, "show" : { "type" : "integer", @@ -11854,7 +11880,7 @@ margin-bottom: 20px; }, "markerColor" : { "type" : "integer", - "description" : "Color in 8 bit RGB serie" + "description" : "Color in 8 bit BGR serie" }, "show" : { "type" : "integer", @@ -51943,7 +51969,7 @@ except ApiException as e:
- Generated 2022-01-15T03:12:23.419+01:00 + Generated 2022-01-15T23:01:29.100+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/GLSpectrum.yaml b/sdrbase/resources/webapi/doc/swagger/include/GLSpectrum.yaml index 09a0c1564..0da5a9c7d 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/GLSpectrum.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/GLSpectrum.yaml @@ -17,7 +17,7 @@ SpectrumHistogramMarker: * 2 - Max power markerColor: type: integer - description: Color in 8 bit RGB serie + description: Color in 8 bit BGR serie show: type: integer description: > @@ -37,7 +37,25 @@ SpectrumWaterfallMarker: description: Time shift in seconds markerColor: type: integer - description: Color in 8 bit RGB serie + description: Color in 8 bit BGR serie + show: + type: integer + description: > + Boolean - Marker display state + * 0 - Hidden + * 1 - Visible + +SpectrumAnnotationMarker: + description: Spectrum annotation marker settings + properties: + startFrequency: + type: integer + format: int64 + bandwidth: + type: integer + markerColor: + type: integer + description: Color in 8 bit BGR serie show: type: integer description: > @@ -129,3 +147,7 @@ GLSpectrum: type: array items: $ref: "/doc/swagger/include/GLSpectrum.yaml#/SpectrumWaterfallMarker" + annotationMarkers: + type: array + items: + $ref: "/doc/swagger/include/GLSpectrum.yaml#/SpectrumAnnotationMarker" diff --git a/sdrgui/gui/glspectrum.cpp b/sdrgui/gui/glspectrum.cpp index a25f431e0..ac5cdd4a0 100644 --- a/sdrgui/gui/glspectrum.cpp +++ b/sdrgui/gui/glspectrum.cpp @@ -16,9 +16,7 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#if 0 //def USE_SSE2 -#include -#endif +#include #include #include @@ -38,33 +36,34 @@ MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportFFTOverlap, Message) MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportPowerScale, Message) const float GLSpectrum::m_maxFrequencyZoom = 10.0f; +const float GLSpectrum::m_annotationMarkerHeight = 20.0f; GLSpectrum::GLSpectrum(QWidget* parent) : - QGLWidget(parent), - m_markersDisplay(SpectrumSettings::MarkersDisplaySpectrum), - m_cursorState(CSNormal), + QGLWidget(parent), + m_markersDisplay(SpectrumSettings::MarkersDisplaySpectrum), + m_cursorState(CSNormal), m_cursorChannel(0), - m_spectrumVis(nullptr), - m_fpsPeriodMs(50), - m_mouseInside(false), - m_changesPending(true), - m_centerFrequency(100000000), - m_referenceLevel(0), - m_powerRange(100), - m_linear(false), - m_decay(1), - m_sampleRate(500000), - m_timingRate(1), - m_fftOverlap(0), - m_fftSize(512), - m_nbBins(512), - m_displayGrid(true), - m_displayGridIntensity(5), - m_displayTraceIntensity(50), - m_invertedWaterfall(false), - m_displayMaxHold(false), - m_currentSpectrum(nullptr), - m_displayCurrent(false), + m_spectrumVis(nullptr), + m_fpsPeriodMs(50), + m_mouseInside(false), + m_changesPending(true), + m_centerFrequency(100000000), + m_referenceLevel(0), + m_powerRange(100), + m_linear(false), + m_decay(1), + m_sampleRate(500000), + m_timingRate(1), + m_fftOverlap(0), + m_fftSize(512), + m_nbBins(512), + m_displayGrid(true), + m_displayGridIntensity(5), + m_displayTraceIntensity(50), + m_invertedWaterfall(false), + m_displayMaxHold(false), + m_currentSpectrum(nullptr), + m_displayCurrent(false), m_leftMargin(0), m_rightMargin(0), m_topMargin(0), @@ -72,8 +71,8 @@ GLSpectrum::GLSpectrum(QWidget* parent) : m_histogramHeight(20), m_waterfallHeight(0), m_bottomMargin(0), - m_waterfallBuffer(nullptr), - m_waterfallBufferPos(0), + m_waterfallBuffer(nullptr), + m_waterfallBufferPos(0), m_waterfallTextureHeight(-1), m_waterfallTexturePos(0), m_displayWaterfall(true), @@ -89,41 +88,41 @@ GLSpectrum::GLSpectrum(QWidget* parent) : m_colorLoc(0), m_messageQueueToGUI(nullptr) { - setAutoFillBackground(false); - setAttribute(Qt::WA_OpaquePaintEvent, true); - setAttribute(Qt::WA_NoSystemBackground, true); - setMouseTracking(true); + setAutoFillBackground(false); + setAttribute(Qt::WA_OpaquePaintEvent, true); + setAttribute(Qt::WA_NoSystemBackground, true); + setMouseTracking(true); - setMinimumSize(200, 200); + setMinimumSize(200, 200); - m_waterfallShare = 0.66; + m_waterfallShare = 0.66; - for (int i = 0; i <= 239; i++) + 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(); - } + 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] = 0; + m_waterfallPalette[239] = 0xffffffff; + m_histogramPalette[0] = 0; - for (int i = 1; i < 240; i++) - { - QColor c; - int light = i < 60 ? 128 + (60-i) : 128; - int sat = i < 60 ? 140 + i : i < 180 ? 200 : 200 - (i-180); - c.setHsl(239 - i, sat, light); + for (int i = 1; i < 240; i++) + { + QColor c; + int light = i < 60 ? 128 + (60-i) : 128; + int sat = i < 60 ? 140 + i : i < 180 ? 200 : 200 - (i-180); + c.setHsl(239 - i, sat, light); ((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(); - } + } - // 4.2.3 palette + // 4.2.3 palette // for (int i = 1; i < 240; i++) // { // QColor c; @@ -154,103 +153,103 @@ GLSpectrum::GLSpectrum(QWidget* parent) : // ((quint8*)&m_histogramPalette[i])[3] = c.alpha(); // } - m_decayDivisor = 1; - m_decayDivisorCount = m_decayDivisor; - m_histogramStroke = 30; + m_decayDivisor = 1; + m_decayDivisorCount = m_decayDivisor; + m_histogramStroke = 30; - 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); + 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); m_textOverlayFont = font(); // QFontDatabase::systemFont(QFontDatabase::FixedFont); m_textOverlayFont.setBold(true); // m_textOverlayFont.setPointSize(font().pointSize() - 1); - resetFrequencyZoom(); + resetFrequencyZoom(); - m_timer.setTimerType(Qt::PreciseTimer); - connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); - m_timer.start(m_fpsPeriodMs); + m_timer.setTimerType(Qt::PreciseTimer); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); + m_timer.start(m_fpsPeriodMs); } GLSpectrum::~GLSpectrum() { - QMutexLocker mutexLocker(&m_mutex); + QMutexLocker mutexLocker(&m_mutex); - if (m_waterfallBuffer) + if (m_waterfallBuffer) { - delete m_waterfallBuffer; - m_waterfallBuffer = nullptr; - } + delete m_waterfallBuffer; + m_waterfallBuffer = nullptr; + } - if (m_histogramBuffer) + if (m_histogramBuffer) { - delete m_histogramBuffer; - m_histogramBuffer = nullptr; - } + delete m_histogramBuffer; + m_histogramBuffer = nullptr; + } - if (m_histogram) + if (m_histogram) { - delete[] m_histogram; - m_histogram = nullptr; - } + delete[] m_histogram; + m_histogram = nullptr; + } } void GLSpectrum::setCenterFrequency(qint64 frequency) { - m_mutex.lock(); - m_centerFrequency = frequency; - m_changesPending = true; - m_mutex.unlock(); - update(); + m_mutex.lock(); + m_centerFrequency = frequency; + m_changesPending = true; + m_mutex.unlock(); + update(); } void GLSpectrum::setReferenceLevel(Real referenceLevel) { - m_mutex.lock(); - m_referenceLevel = referenceLevel; - m_changesPending = true; - m_mutex.unlock(); - update(); + m_mutex.lock(); + m_referenceLevel = referenceLevel; + m_changesPending = true; + m_mutex.unlock(); + update(); } void GLSpectrum::setPowerRange(Real powerRange) { - m_mutex.lock(); - m_powerRange = powerRange; - m_changesPending = true; - m_mutex.unlock(); - update(); + m_mutex.lock(); + m_powerRange = powerRange; + m_changesPending = true; + m_mutex.unlock(); + update(); } void GLSpectrum::setDecay(int decay) { - m_decay = decay < 0 ? 0 : decay > 20 ? 20 : decay; + m_decay = decay < 0 ? 0 : decay > 20 ? 20 : decay; } void GLSpectrum::setDecayDivisor(int decayDivisor) { - m_decayDivisor = decayDivisor < 1 ? 1 : decayDivisor > 20 ? 20 : decayDivisor; + m_decayDivisor = decayDivisor < 1 ? 1 : decayDivisor > 20 ? 20 : decayDivisor; } void GLSpectrum::setHistoStroke(int stroke) { - m_histogramStroke = stroke < 1 ? 1 : stroke > 60 ? 60 : stroke; + m_histogramStroke = stroke < 1 ? 1 : stroke > 60 ? 60 : stroke; } void GLSpectrum::setSampleRate(qint32 sampleRate) { m_mutex.lock(); - m_sampleRate = sampleRate; - if (m_messageQueueToGUI) { - m_messageQueueToGUI->push(new MsgReportSampleRate(m_sampleRate)); - } - m_changesPending = true; - m_mutex.unlock(); - update(); + m_sampleRate = sampleRate; + if (m_messageQueueToGUI) { + m_messageQueueToGUI->push(new MsgReportSampleRate(m_sampleRate)); + } + m_changesPending = true; + m_mutex.unlock(); + update(); } void GLSpectrum::setTimingRate(qint32 timingRate) @@ -258,7 +257,7 @@ void GLSpectrum::setTimingRate(qint32 timingRate) m_mutex.lock(); m_timingRate = timingRate; m_changesPending = true; - m_mutex.unlock(); + m_mutex.unlock(); update(); } @@ -267,27 +266,27 @@ void GLSpectrum::setFFTOverlap(int overlap) m_mutex.lock(); m_fftOverlap = overlap; m_changesPending = true; - m_mutex.unlock(); + m_mutex.unlock(); update(); } void GLSpectrum::setDisplayWaterfall(bool display) { m_mutex.lock(); - m_displayWaterfall = display; + m_displayWaterfall = display; if (!display) { m_waterfallMarkers.clear(); } - m_changesPending = true; - stopDrag(); - m_mutex.unlock(); - update(); + m_changesPending = true; + stopDrag(); + m_mutex.unlock(); + update(); } void GLSpectrum::setSsbSpectrum(bool ssbSpectrum) { - m_ssbSpectrum = ssbSpectrum; - update(); + m_ssbSpectrum = ssbSpectrum; + update(); } void GLSpectrum::setLsbDisplay(bool lsbDisplay) @@ -299,231 +298,241 @@ void GLSpectrum::setLsbDisplay(bool lsbDisplay) void GLSpectrum::setInvertedWaterfall(bool inv) { m_mutex.lock(); - m_invertedWaterfall = inv; - m_changesPending = true; - stopDrag(); - m_mutex.unlock(); - update(); + m_invertedWaterfall = inv; + m_changesPending = true; + stopDrag(); + m_mutex.unlock(); + update(); } void GLSpectrum::setDisplayMaxHold(bool display) { m_mutex.lock(); - m_displayMaxHold = display; + m_displayMaxHold = display; if (!m_displayMaxHold && !m_displayCurrent && !m_displayHistogram) { m_histogramMarkers.clear(); } - m_changesPending = true; - stopDrag(); - m_mutex.unlock(); - update(); + m_changesPending = true; + stopDrag(); + m_mutex.unlock(); + update(); } void GLSpectrum::setDisplayCurrent(bool display) { m_mutex.lock(); - m_displayCurrent = display; + m_displayCurrent = display; if (!m_displayMaxHold && !m_displayCurrent && !m_displayHistogram) { m_histogramMarkers.clear(); } - m_changesPending = true; - stopDrag(); - m_mutex.unlock(); - update(); + m_changesPending = true; + stopDrag(); + m_mutex.unlock(); + update(); } void GLSpectrum::setDisplayHistogram(bool display) { m_mutex.lock(); - m_displayHistogram = display; + m_displayHistogram = display; if (!m_displayMaxHold && !m_displayCurrent && !m_displayHistogram) { m_histogramMarkers.clear(); } - m_changesPending = true; - stopDrag(); - m_mutex.unlock(); - update(); + m_changesPending = true; + stopDrag(); + m_mutex.unlock(); + update(); } void GLSpectrum::setDisplayGrid(bool display) { - m_displayGrid = display; - update(); + m_displayGrid = display; + update(); } void GLSpectrum::setDisplayGridIntensity(int intensity) { - m_displayGridIntensity = intensity; + m_displayGridIntensity = intensity; - if (m_displayGridIntensity > 100) { - m_displayGridIntensity = 100; - } else if (m_displayGridIntensity < 0) { - m_displayGridIntensity = 0; - } + if (m_displayGridIntensity > 100) { + m_displayGridIntensity = 100; + } else if (m_displayGridIntensity < 0) { + m_displayGridIntensity = 0; + } update(); } void GLSpectrum::setDisplayTraceIntensity(int intensity) { - m_displayTraceIntensity = intensity; + m_displayTraceIntensity = intensity; - if (m_displayTraceIntensity > 100) { - m_displayTraceIntensity = 100; - } else if (m_displayTraceIntensity < 0) { - m_displayTraceIntensity = 0; - } + if (m_displayTraceIntensity > 100) { + m_displayTraceIntensity = 100; + } else if (m_displayTraceIntensity < 0) { + m_displayTraceIntensity = 0; + } update(); } void GLSpectrum::setLinear(bool linear) { - m_mutex.lock(); + m_mutex.lock(); m_linear = linear; m_changesPending = true; - m_mutex.unlock(); + m_mutex.unlock(); update(); } void GLSpectrum::addChannelMarker(ChannelMarker* channelMarker) { - m_mutex.lock(); - connect(channelMarker, SIGNAL(changedByAPI()), this, SLOT(channelMarkerChanged())); - connect(channelMarker, SIGNAL(destroyed(QObject*)), this, SLOT(channelMarkerDestroyed(QObject*))); - m_channelMarkerStates.append(new ChannelMarkerState(channelMarker)); - m_changesPending = true; - stopDrag(); - m_mutex.unlock(); - update(); + m_mutex.lock(); + connect(channelMarker, SIGNAL(changedByAPI()), this, SLOT(channelMarkerChanged())); + connect(channelMarker, SIGNAL(destroyed(QObject*)), this, SLOT(channelMarkerDestroyed(QObject*))); + m_channelMarkerStates.append(new ChannelMarkerState(channelMarker)); + m_changesPending = true; + stopDrag(); + m_mutex.unlock(); + update(); } void GLSpectrum::removeChannelMarker(ChannelMarker* channelMarker) { - m_mutex.lock(); + m_mutex.lock(); - 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(); - m_mutex.unlock(); - update(); - return; - } - } + 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(); + m_mutex.unlock(); + update(); + return; + } + } - m_mutex.unlock(); + m_mutex.unlock(); } void GLSpectrum::setHistogramMarkers(const QList& histogramMarkers) { m_mutex.lock(); m_histogramMarkers = histogramMarkers; - updateHistogramMarkers(); + updateHistogramMarkers(); m_changesPending = true; m_mutex.unlock(); - update(); + update(); } void GLSpectrum::setWaterfallMarkers(const QList& waterfallMarkers) { m_mutex.lock(); m_waterfallMarkers = waterfallMarkers; - updateWaterfallMarkers(); + updateWaterfallMarkers(); m_changesPending = true; m_mutex.unlock(); - update(); + update(); +} + +void GLSpectrum::setAnnotationMarkers(const QList& annotationMarkers) +{ + m_mutex.lock(); + m_annotationMarkers = annotationMarkers; + updateAnnotationMarkers(); + m_changesPending = true; + m_mutex.unlock(); + update(); } float GLSpectrum::getPowerMax() const { - return m_linear ? m_powerScale.getRangeMax() : CalcDb::powerFromdB(m_powerScale.getRangeMax()); + return m_linear ? m_powerScale.getRangeMax() : CalcDb::powerFromdB(m_powerScale.getRangeMax()); } float GLSpectrum::getTimeMax() const { - return m_timeScale.getRangeMax(); + return m_timeScale.getRangeMax(); } void GLSpectrum::newSpectrum(const Real *spectrum, int nbBins, int fftSize) { - QMutexLocker mutexLocker(&m_mutex); + QMutexLocker mutexLocker(&m_mutex); - m_displayChanged = true; + m_displayChanged = true; - if (m_changesPending) + if (m_changesPending) { - m_fftSize = fftSize; - m_nbBins = nbBins; - return; - } + m_fftSize = fftSize; + m_nbBins = nbBins; + return; + } - if ((fftSize != m_fftSize) || (m_nbBins != nbBins)) + if ((fftSize != m_fftSize) || (m_nbBins != nbBins)) { - m_fftSize = fftSize; - m_nbBins = nbBins; - m_changesPending = true; - return; - } + m_fftSize = fftSize; + m_nbBins = nbBins; + m_changesPending = true; + return; + } - updateWaterfall(spectrum); - updateHistogram(spectrum); + updateWaterfall(spectrum); + updateHistogram(spectrum); } void GLSpectrum::updateWaterfall(const Real *spectrum) { - if (m_waterfallBufferPos < m_waterfallBuffer->height()) + if (m_waterfallBufferPos < m_waterfallBuffer->height()) { - quint32* pix = (quint32*)m_waterfallBuffer->scanLine(m_waterfallBufferPos); + quint32* pix = (quint32*)m_waterfallBuffer->scanLine(m_waterfallBufferPos); - for (int i = 0; i < m_nbBins; i++) + for (int i = 0; i < m_nbBins; i++) { - int v = (int)((spectrum[i] - m_referenceLevel) * 2.4 * 100.0 / m_powerRange + 240.0); + int v = (int)((spectrum[i] - m_referenceLevel) * 2.4 * 100.0 / m_powerRange + 240.0); if (v > 239) { - v = 239; + v = 239; } else if (v < 0) { - v = 0; + v = 0; } - *pix++ = m_waterfallPalette[(int)v]; - } + *pix++ = m_waterfallPalette[(int)v]; + } - m_waterfallBufferPos++; - } + m_waterfallBufferPos++; + } } void GLSpectrum::updateHistogram(const Real *spectrum) { - quint8* b = m_histogram; - int fftMulSize = 100 * m_nbBins; + quint8* b = m_histogram; + int fftMulSize = 100 * m_nbBins; - if ((m_displayHistogram || m_displayMaxHold) && (m_decay != 0)) - { - m_decayDivisorCount--; + if ((m_displayHistogram || m_displayMaxHold) && (m_decay != 0)) + { + m_decayDivisorCount--; - if ((m_decay > 1) || (m_decayDivisorCount <= 0)) - { - for (int i = 0; i < fftMulSize; i++) - { - if (*b > m_decay) { - *b = *b - m_decay; - } else { - *b = 0; - } + if ((m_decay > 1) || (m_decayDivisorCount <= 0)) + { + for (int i = 0; i < fftMulSize; i++) + { + if (*b > m_decay) { + *b = *b - m_decay; + } else { + *b = 0; + } - b++; - } + b++; + } - m_decayDivisorCount = m_decayDivisor; - } - } + m_decayDivisorCount = m_decayDivisor; + } + } - m_currentSpectrum = spectrum; // Store spectrum for current spectrum line display + m_currentSpectrum = spectrum; // Store spectrum for current spectrum line display #if 0 //def USE_SSE2 if(m_decay >= 0) { // normal @@ -612,622 +621,624 @@ void GLSpectrum::updateHistogram(const Real *spectrum) void GLSpectrum::initializeGL() { - QOpenGLContext *glCurrentContext = QOpenGLContext::currentContext(); + QOpenGLContext *glCurrentContext = QOpenGLContext::currentContext(); - if (glCurrentContext) + if (glCurrentContext) { - if (QOpenGLContext::currentContext()->isValid()) { - qDebug() << "GLSpectrum::initializeGL: context:" - << " major: " << (QOpenGLContext::currentContext()->format()).majorVersion() - << " minor: " << (QOpenGLContext::currentContext()->format()).minorVersion() - << " ES: " << (QOpenGLContext::currentContext()->isOpenGLES() ? "yes" : "no"); - } - else { - qDebug() << "GLSpectrum::initializeGL: current context is invalid"; - } - } + if (QOpenGLContext::currentContext()->isValid()) { + qDebug() << "GLSpectrum::initializeGL: context:" + << " major: " << (QOpenGLContext::currentContext()->format()).majorVersion() + << " minor: " << (QOpenGLContext::currentContext()->format()).minorVersion() + << " ES: " << (QOpenGLContext::currentContext()->isOpenGLES() ? "yes" : "no"); + } + else { + qDebug() << "GLSpectrum::initializeGL: current context is invalid"; + } + } else { - qCritical() << "GLSpectrum::initializeGL: no current context"; - return; - } + qCritical() << "GLSpectrum::initializeGL: no current context"; + return; + } - connect(glCurrentContext, &QOpenGLContext::aboutToBeDestroyed, this, &GLSpectrum::cleanup); // TODO: when migrating to QOpenGLWidget + connect(glCurrentContext, &QOpenGLContext::aboutToBeDestroyed, this, &GLSpectrum::cleanup); // TODO: when migrating to QOpenGLWidget - QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions(); - glFunctions->initializeOpenGLFunctions(); + QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions(); + glFunctions->initializeOpenGLFunctions(); - //glDisable(GL_DEPTH_TEST); - m_glShaderSimple.initializeGL(); - m_glShaderLeftScale.initializeGL(); - m_glShaderFrequencyScale.initializeGL(); - m_glShaderWaterfall.initializeGL(); - m_glShaderHistogram.initializeGL(); + //glDisable(GL_DEPTH_TEST); + m_glShaderSimple.initializeGL(); + m_glShaderLeftScale.initializeGL(); + m_glShaderFrequencyScale.initializeGL(); + m_glShaderWaterfall.initializeGL(); + m_glShaderHistogram.initializeGL(); m_glShaderTextOverlay.initializeGL(); - m_glShaderInfo.initializeGL(); + m_glShaderInfo.initializeGL(); } void GLSpectrum::resizeGL(int width, int height) { QMutexLocker mutexLocker(&m_mutex); - QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions(); - glFunctions->glViewport(0, 0, width, height); - m_changesPending = true; + QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions(); + glFunctions->glViewport(0, 0, width, height); + m_changesPending = true; } void GLSpectrum::clearSpectrumHistogram() { - if (!m_mutex.tryLock(2)) { - return; - } + if (!m_mutex.tryLock(2)) { + return; + } - memset(m_histogram, 0x00, 100 * m_nbBins); + memset(m_histogram, 0x00, 100 * m_nbBins); - m_mutex.unlock(); - update(); + m_mutex.unlock(); + update(); } void GLSpectrum::paintGL() { - if (!m_mutex.tryLock(2)) { - return; - } + if (!m_mutex.tryLock(2)) { + return; + } - if (m_changesPending) - { - applyChanges(); - m_changesPending = false; - } + if (m_changesPending) + { + applyChanges(); + m_changesPending = false; + } - if (m_nbBins <= 0) - { - m_mutex.unlock(); - return; - } + if (m_nbBins <= 0) + { + m_mutex.unlock(); + return; + } - QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions(); - glFunctions->glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glFunctions->glClear(GL_COLOR_BUFFER_BIT); + QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions(); + glFunctions->glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glFunctions->glClear(GL_COLOR_BUFFER_BIT); - // paint waterfall - if (m_displayWaterfall) - { - { - GLfloat vtx1[] = { - 0, m_invertedWaterfall ? 0.0f : 1.0f, - 1, m_invertedWaterfall ? 0.0f : 1.0f, - 1, m_invertedWaterfall ? 1.0f : 0.0f, - 0, m_invertedWaterfall ? 1.0f : 0.0f - }; + // paint waterfall + if (m_displayWaterfall) + { + { + GLfloat vtx1[] = { + 0, m_invertedWaterfall ? 0.0f : 1.0f, + 1, m_invertedWaterfall ? 0.0f : 1.0f, + 1, m_invertedWaterfall ? 1.0f : 0.0f, + 0, m_invertedWaterfall ? 1.0f : 0.0f + }; - if (m_waterfallTexturePos + m_waterfallBufferPos < m_waterfallTextureHeight) - { - m_glShaderWaterfall.subTexture(0, m_waterfallTexturePos, m_nbBins, m_waterfallBufferPos, m_waterfallBuffer->scanLine(0)); - m_waterfallTexturePos += m_waterfallBufferPos; - } - else - { - int breakLine = m_waterfallTextureHeight - m_waterfallTexturePos; - int linesLeft = m_waterfallTexturePos + m_waterfallBufferPos - m_waterfallTextureHeight; - m_glShaderWaterfall.subTexture(0, m_waterfallTexturePos, m_nbBins, breakLine, m_waterfallBuffer->scanLine(0)); - m_glShaderWaterfall.subTexture(0, 0, m_nbBins, linesLeft, m_waterfallBuffer->scanLine(breakLine)); - m_waterfallTexturePos = linesLeft; - } + if (m_waterfallTexturePos + m_waterfallBufferPos < m_waterfallTextureHeight) + { + m_glShaderWaterfall.subTexture(0, m_waterfallTexturePos, m_nbBins, m_waterfallBufferPos, m_waterfallBuffer->scanLine(0)); + m_waterfallTexturePos += m_waterfallBufferPos; + } + else + { + int breakLine = m_waterfallTextureHeight - m_waterfallTexturePos; + int linesLeft = m_waterfallTexturePos + m_waterfallBufferPos - m_waterfallTextureHeight; + m_glShaderWaterfall.subTexture(0, m_waterfallTexturePos, m_nbBins, breakLine, m_waterfallBuffer->scanLine(0)); + m_glShaderWaterfall.subTexture(0, 0, m_nbBins, linesLeft, m_waterfallBuffer->scanLine(breakLine)); + m_waterfallTexturePos = linesLeft; + } - m_waterfallBufferPos = 0; + m_waterfallBufferPos = 0; - float prop_y = m_waterfallTexturePos / (m_waterfallTextureHeight - 1.0); - float off = 1.0 / (m_waterfallTextureHeight - 1.0); + float prop_y = m_waterfallTexturePos / (m_waterfallTextureHeight - 1.0); + float off = 1.0 / (m_waterfallTextureHeight - 1.0); - GLfloat tex1[] = { - 0, prop_y + 1 - off, - 1, prop_y + 1 - off, - 1, prop_y, - 0, prop_y - }; + GLfloat tex1[] = { + 0, prop_y + 1 - off, + 1, prop_y + 1 - off, + 1, prop_y, + 0, prop_y + }; - m_glShaderWaterfall.drawSurface(m_glWaterfallBoxMatrix, tex1, vtx1, 4); - } + m_glShaderWaterfall.drawSurface(m_glWaterfallBoxMatrix, tex1, vtx1, 4); + } - // paint channels - if (m_mouseInside) - { - for (int i = 0; i < m_channelMarkerStates.size(); ++i) - { - ChannelMarkerState* dv = m_channelMarkerStates[i]; + // paint channels + if (m_mouseInside) + { + for (int i = 0; i < m_channelMarkerStates.size(); ++i) + { + ChannelMarkerState* dv = m_channelMarkerStates[i]; - if (dv->m_channelMarker->getVisible() + if (dv->m_channelMarker->getVisible() && (dv->m_channelMarker->getSourceOrSinkStream() == m_displaySourceOrSink) && dv->m_channelMarker->streamIndexApplies(m_displayStreamIndex)) - { - { - GLfloat q3[] { - 0, 0, - 1, 0, - 1, 1, - 0, 1, - 0.5, 0, - 0.5, 1, - }; + { + { + GLfloat q3[] { + 0, 0, + 1, 0, + 1, 1, + 0, 1, + 0.5, 0, + 0.5, 1, + }; - QVector4D color(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.3f); - m_glShaderSimple.drawSurface(dv->m_glMatrixWaterfall, color, q3, 4); + QVector4D color(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.3f); + m_glShaderSimple.drawSurface(dv->m_glMatrixWaterfall, color, q3, 4); - QVector4D colorLine(0.8f, 0.8f, 0.6f, 1.0f); - m_glShaderSimple.drawSegments(dv->m_glMatrixDsbWaterfall, colorLine, &q3[8], 2); + QVector4D colorLine(0.8f, 0.8f, 0.6f, 1.0f); + m_glShaderSimple.drawSegments(dv->m_glMatrixDsbWaterfall, colorLine, &q3[8], 2); - } - } - } - } + } + } + } + } - // draw rect around - { - GLfloat q3[] { - 1, 1, - 0, 1, - 0, 0, - 1, 0 - }; + // draw rect around + { + GLfloat q3[] { + 1, 1, + 0, 1, + 0, 0, + 1, 0 + }; - QVector4D color(1.0f, 1.0f, 1.0f, 0.5f); - m_glShaderSimple.drawContour(m_glWaterfallBoxMatrix, color, q3, 4); - } - } + QVector4D color(1.0f, 1.0f, 1.0f, 0.5f); + m_glShaderSimple.drawContour(m_glWaterfallBoxMatrix, color, q3, 4); + } + } - // paint histogram - if (m_displayHistogram || m_displayMaxHold || m_displayCurrent) - { - if (m_displayHistogram) - { - { - // import new lines into the texture - quint32* pix; - quint8* bs = m_histogram; + // paint histogram + if (m_displayHistogram || m_displayMaxHold || m_displayCurrent) + { + 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 y = 0; y < 100; y++) + { + quint8* b = bs; + pix = (quint32*)m_histogramBuffer->scanLine(99 - y); - for (int x = 0; x < m_nbBins; x++) - { - *pix = m_histogramPalette[*b]; - pix++; - b += 100; - } + for (int x = 0; x < m_nbBins; x++) + { + *pix = m_histogramPalette[*b]; + pix++; + b += 100; + } - bs++; - } + bs++; + } - GLfloat vtx1[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; - GLfloat tex1[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; + GLfloat vtx1[] = { + 0, 0, + 1, 0, + 1, 1, + 0, 1 + }; + GLfloat tex1[] = { + 0, 0, + 1, 0, + 1, 1, + 0, 1 + }; - m_glShaderHistogram.subTexture(0, 0, m_nbBins, 100, m_histogramBuffer->scanLine(0)); - m_glShaderHistogram.drawSurface(m_glHistogramBoxMatrix, tex1, vtx1, 4); - } - } + m_glShaderHistogram.subTexture(0, 0, m_nbBins, 100, m_histogramBuffer->scanLine(0)); + m_glShaderHistogram.drawSurface(m_glHistogramBoxMatrix, tex1, vtx1, 4); + } + } - // paint channels - if (m_mouseInside) - { - // Effective BW overlays - for (int i = 0; i < m_channelMarkerStates.size(); ++i) - { - ChannelMarkerState* dv = m_channelMarkerStates[i]; + // paint channels + if (m_mouseInside) + { + // Effective BW overlays + for (int i = 0; i < m_channelMarkerStates.size(); ++i) + { + ChannelMarkerState* dv = m_channelMarkerStates[i]; - if (dv->m_channelMarker->getVisible() + if (dv->m_channelMarker->getVisible() && (dv->m_channelMarker->getSourceOrSinkStream() == m_displaySourceOrSink) && dv->m_channelMarker->streamIndexApplies(m_displayStreamIndex)) - { - { - GLfloat q3[] { - 0, 0, - 1, 0, - 1, 1, - 0, 1, - 0.5, 0, - 0.5, 1 - }; + { + { + GLfloat q3[] { + 0, 0, + 1, 0, + 1, 1, + 0, 1, + 0.5, 0, + 0.5, 1 + }; - QVector4D color(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.3f); - m_glShaderSimple.drawSurface(dv->m_glMatrixHistogram, color, q3, 4); + QVector4D color(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.3f); + m_glShaderSimple.drawSurface(dv->m_glMatrixHistogram, color, q3, 4); - QVector4D colorLine(0.8f, 0.8f, 0.6f, 1.0f); + QVector4D colorLine(0.8f, 0.8f, 0.6f, 1.0f); - if (dv->m_channelMarker->getSidebands() != ChannelMarker::dsb) { - q3[6] = 0.5; - } + if (dv->m_channelMarker->getSidebands() != ChannelMarker::dsb) { + q3[6] = 0.5; + } m_glShaderSimple.drawSegments(dv->m_glMatrixDsbHistogram, colorLine, &q3[8], 2); m_glShaderSimple.drawSegments(dv->m_glMatrixFreqScale, colorLine, q3, 2); - } - } - } - } + } + } + } + } - // draw rect around - { - GLfloat q3[] { - 1, 1, - 0, 1, - 0, 0, - 1, 0 - }; + // draw rect around + { + GLfloat q3[] { + 1, 1, + 0, 1, + 0, 0, + 1, 0 + }; - QVector4D color(1.0f, 1.0f, 1.0f, 0.5f); - m_glShaderSimple.drawContour(m_glHistogramBoxMatrix, color, q3, 4); - } - } + QVector4D color(1.0f, 1.0f, 1.0f, 0.5f); + m_glShaderSimple.drawContour(m_glHistogramBoxMatrix, color, q3, 4); + } + } - // paint left scales (time and power) - if (m_displayWaterfall || m_displayMaxHold || m_displayCurrent || m_displayHistogram ) - { - { - GLfloat vtx1[] = { - 0, 1, - 1, 1, - 1, 0, - 0, 0 - }; - GLfloat tex1[] = { - 0, 1, - 1, 1, - 1, 0, - 0, 0 - }; + // paint left scales (time and power) + if (m_displayWaterfall || m_displayMaxHold || m_displayCurrent || m_displayHistogram ) + { + { + GLfloat vtx1[] = { + 0, 1, + 1, 1, + 1, 0, + 0, 0 + }; + GLfloat tex1[] = { + 0, 1, + 1, 1, + 1, 0, + 0, 0 + }; - m_glShaderLeftScale.drawSurface(m_glLeftScaleBoxMatrix, tex1, vtx1, 4); - } - } + m_glShaderLeftScale.drawSurface(m_glLeftScaleBoxMatrix, tex1, vtx1, 4); + } + } - // paint frequency scale - if (m_displayWaterfall || m_displayMaxHold || m_displayCurrent || m_displayHistogram ) - { - { - GLfloat vtx1[] = { - 0, 1, - 1, 1, - 1, 0, - 0, 0 - }; - GLfloat tex1[] = { - 0, 1, - 1, 1, - 1, 0, - 0, 0 - }; + // paint frequency scale + if (m_displayWaterfall || m_displayMaxHold || m_displayCurrent || m_displayHistogram ) + { + { + GLfloat vtx1[] = { + 0, 1, + 1, 1, + 1, 0, + 0, 0 + }; + GLfloat tex1[] = { + 0, 1, + 1, 1, + 1, 0, + 0, 0 + }; - m_glShaderFrequencyScale.drawSurface(m_glFrequencyScaleBoxMatrix, tex1, vtx1, 4); - } + m_glShaderFrequencyScale.drawSurface(m_glFrequencyScaleBoxMatrix, tex1, vtx1, 4); + } - // paint channels + // paint channels - // Effective bandwidth overlays - for (int i = 0; i < m_channelMarkerStates.size(); ++i) - { - ChannelMarkerState* dv = m_channelMarkerStates[i]; + // Effective bandwidth overlays + for (int i = 0; i < m_channelMarkerStates.size(); ++i) + { + ChannelMarkerState* dv = m_channelMarkerStates[i]; - // frequency scale channel overlay + // frequency scale channel overlay if (dv->m_channelMarker->getVisible() && (dv->m_channelMarker->getSourceOrSinkStream() == m_displaySourceOrSink) && dv->m_channelMarker->streamIndexApplies(m_displayStreamIndex)) - { - { - GLfloat q3[] { - 1, 0.2, - 0, 0.2, - 0, 0, - 1, 0, - 0.5, 0, - 0.5, 1 - }; + { + { + GLfloat q3[] { + 1, 0.2, + 0, 0.2, + 0, 0, + 1, 0, + 0.5, 0, + 0.5, 1 + }; - QVector4D color(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.5f); - m_glShaderSimple.drawSurface(dv->m_glMatrixFreqScale, color, q3, 4); + QVector4D color(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.5f); + m_glShaderSimple.drawSurface(dv->m_glMatrixFreqScale, color, q3, 4); - if (dv->m_channelMarker->getHighlighted()) - { - QVector4D colorLine(0.8f, 0.8f, 0.6f, 1.0f); + if (dv->m_channelMarker->getHighlighted()) + { + QVector4D colorLine(0.8f, 0.8f, 0.6f, 1.0f); m_glShaderSimple.drawSegments(dv->m_glMatrixDsbFreqScale, colorLine, &q3[8], 2); - m_glShaderSimple.drawSegments(dv->m_glMatrixFreqScale, colorLine, &q3[4], 2); - } - } - } - } - } + m_glShaderSimple.drawSegments(dv->m_glMatrixFreqScale, colorLine, &q3[4], 2); + } + } + } + } + } - // paint max hold lines on top of histogram - if (m_displayMaxHold) - { - if (m_maxHold.size() < (uint) m_nbBins) { - m_maxHold.resize(m_nbBins); - } + // paint max hold lines on top of histogram + if (m_displayMaxHold) + { + if (m_maxHold.size() < (uint) m_nbBins) { + m_maxHold.resize(m_nbBins); + } - for (int i = 0; i < m_nbBins; i++) - { - int j; - quint8* bs = m_histogram + i * 100; + for (int i = 0; i < m_nbBins; i++) + { + int j; + quint8* bs = m_histogram + i * 100; - for (j = 99; j >= 0; j--) - { - if (bs[j] > 0) { - break; - } - } + for (j = 99; j >= 0; j--) + { + if (bs[j] > 0) { + break; + } + } - // m_referenceLevel : top - // m_referenceLevel - m_powerRange : bottom - m_maxHold[i] = ((j - 99) * m_powerRange) / 99.0 + m_referenceLevel; - } - { - GLfloat *q3 = m_q3FFT.m_array; + // m_referenceLevel : top + // m_referenceLevel - m_powerRange : bottom + m_maxHold[i] = ((j - 99) * m_powerRange) / 99.0 + m_referenceLevel; + } + { + GLfloat *q3 = m_q3FFT.m_array; - for (int i = 0; i < m_nbBins; i++) - { - Real v = m_maxHold[i] - m_referenceLevel; + for (int i = 0; i < m_nbBins; i++) + { + Real v = m_maxHold[i] - m_referenceLevel; - if (v >= 0) { - v = 0; - } else if (v < -m_powerRange) { - v = -m_powerRange; - } + if (v >= 0) { + v = 0; + } else if (v < -m_powerRange) { + v = -m_powerRange; + } - q3[2*i] = (Real) i; - q3[2*i+1] = v; - } + q3[2*i] = (Real) i; + q3[2*i+1] = v; + } - QVector4D color(1.0f, 0.0f, 0.0f, (float) m_displayTraceIntensity / 100.0f); - m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_nbBins); - } - } + QVector4D color(1.0f, 0.0f, 0.0f, (float) m_displayTraceIntensity / 100.0f); + m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_nbBins); + } + } - // paint current spectrum line on top of histogram - if ((m_displayCurrent) && m_currentSpectrum) - { - { - Real bottom = -m_powerRange; - GLfloat *q3 = m_q3FFT.m_array; + // paint current spectrum line on top of histogram + if ((m_displayCurrent) && m_currentSpectrum) + { + { + Real bottom = -m_powerRange; + GLfloat *q3 = m_q3FFT.m_array; - for (int i = 0; i < m_nbBins; i++) - { - Real v = m_currentSpectrum[i] - m_referenceLevel; + for (int i = 0; i < m_nbBins; i++) + { + Real v = m_currentSpectrum[i] - m_referenceLevel; - if (v > 0) { - v = 0; - } else if (v < bottom) { - v = bottom; - } + if (v > 0) { + v = 0; + } else if (v < bottom) { + v = bottom; + } - q3[2*i] = (Real) i; - q3[2*i+1] = v; - } + q3[2*i] = (Real) i; + q3[2*i+1] = v; + } - QVector4D color(1.0f, 1.0f, 0.25f, (float) m_displayTraceIntensity / 100.0f); - m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_nbBins); - } - } + QVector4D color(1.0f, 1.0f, 0.25f, (float) m_displayTraceIntensity / 100.0f); + m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_nbBins); + } + } - if (m_markersDisplay == SpectrumSettings::MarkersDisplaySpectrum) { - drawSpectrumMarkers(); - } + if (m_markersDisplay == SpectrumSettings::MarkersDisplaySpectrum) { + drawSpectrumMarkers(); + } else if (m_markersDisplay == SpectrumSettings::MarkersDisplayAnnotations) { + drawAnnotationMarkers(); + } - // paint waterfall grid - if (m_displayWaterfall && m_displayGrid) - { - const ScaleEngine::TickList* tickList; - const ScaleEngine::Tick* tick; - tickList = &m_timeScale.getTickList(); + // paint waterfall grid + if (m_displayWaterfall && m_displayGrid) + { + const ScaleEngine::TickList* tickList; + const ScaleEngine::Tick* tick; + tickList = &m_timeScale.getTickList(); - { - GLfloat *q3 = m_q3TickTime.m_array; - int effectiveTicks = 0; + { + GLfloat *q3 = m_q3TickTime.m_array; + int effectiveTicks = 0; - for (int i= 0; i < tickList->count(); i++) - { - tick = &(*tickList)[i]; + 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(); - q3[4*effectiveTicks] = 0; - q3[4*effectiveTicks+1] = y; - q3[4*effectiveTicks+2] = 1; - q3[4*effectiveTicks+3] = y; - effectiveTicks++; - } - } - } + if (tick->major) + { + if (tick->textSize > 0) + { + float y = tick->pos / m_timeScale.getSize(); + q3[4*effectiveTicks] = 0; + q3[4*effectiveTicks+1] = y; + q3[4*effectiveTicks+2] = 1; + q3[4*effectiveTicks+3] = y; + effectiveTicks++; + } + } + } - QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f); - m_glShaderSimple.drawSegments(m_glWaterfallBoxMatrix, color, q3, 2*effectiveTicks); - } + QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f); + m_glShaderSimple.drawSegments(m_glWaterfallBoxMatrix, color, q3, 2*effectiveTicks); + } - tickList = &m_frequencyScale.getTickList(); + tickList = &m_frequencyScale.getTickList(); - { - GLfloat *q3 = m_q3TickFrequency.m_array; - int effectiveTicks = 0; + { + GLfloat *q3 = m_q3TickFrequency.m_array; + int effectiveTicks = 0; - for (int i= 0; i < tickList->count(); i++) - { - tick = &(*tickList)[i]; + 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(); - q3[4*effectiveTicks] = x; - q3[4*effectiveTicks+1] = 0; - q3[4*effectiveTicks+2] = x; - q3[4*effectiveTicks+3] = 1; - effectiveTicks++; - } - } - } + if (tick->major) + { + if (tick->textSize > 0) + { + float x = tick->pos / m_frequencyScale.getSize(); + q3[4*effectiveTicks] = x; + q3[4*effectiveTicks+1] = 0; + q3[4*effectiveTicks+2] = x; + q3[4*effectiveTicks+3] = 1; + effectiveTicks++; + } + } + } - QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f); - m_glShaderSimple.drawSegments(m_glWaterfallBoxMatrix, color, q3, 2*effectiveTicks); - } - } + QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f); + m_glShaderSimple.drawSegments(m_glWaterfallBoxMatrix, color, q3, 2*effectiveTicks); + } + } - // paint histogram grid - if ((m_displayHistogram || m_displayMaxHold || m_displayCurrent) && (m_displayGrid)) - { - const ScaleEngine::TickList* tickList; - const ScaleEngine::Tick* tick; - tickList = &m_powerScale.getTickList(); + // paint histogram grid + if ((m_displayHistogram || m_displayMaxHold || m_displayCurrent) && (m_displayGrid)) + { + const ScaleEngine::TickList* tickList; + const ScaleEngine::Tick* tick; + tickList = &m_powerScale.getTickList(); - { - GLfloat *q3 = m_q3TickPower.m_array; - int effectiveTicks = 0; + { + GLfloat *q3 = m_q3TickPower.m_array; + int effectiveTicks = 0; - for (int i= 0; i < tickList->count(); i++) - { - tick = &(*tickList)[i]; + 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(); - q3[4*effectiveTicks] = 0; - q3[4*effectiveTicks+1] = 1-y; - q3[4*effectiveTicks+2] = 1; - q3[4*effectiveTicks+3] = 1-y; - effectiveTicks++; - } - } - } + if (tick->major) + { + if (tick->textSize > 0) + { + float y = tick->pos / m_powerScale.getSize(); + q3[4*effectiveTicks] = 0; + q3[4*effectiveTicks+1] = 1-y; + q3[4*effectiveTicks+2] = 1; + q3[4*effectiveTicks+3] = 1-y; + effectiveTicks++; + } + } + } - QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f); - m_glShaderSimple.drawSegments(m_glHistogramBoxMatrix, color, q3, 2*effectiveTicks); - } + QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f); + m_glShaderSimple.drawSegments(m_glHistogramBoxMatrix, color, q3, 2*effectiveTicks); + } - tickList = &m_frequencyScale.getTickList(); + tickList = &m_frequencyScale.getTickList(); - { - GLfloat *q3 = m_q3TickFrequency.m_array; - int effectiveTicks = 0; + { + GLfloat *q3 = m_q3TickFrequency.m_array; + int effectiveTicks = 0; - for (int i= 0; i < tickList->count(); i++) - { - tick = &(*tickList)[i]; + 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(); - q3[4*effectiveTicks] = x; - q3[4*effectiveTicks+1] = 0; - q3[4*effectiveTicks+2] = x; - q3[4*effectiveTicks+3] = 1; - effectiveTicks++; - } - } - } + if (tick->major) + { + if (tick->textSize > 0) + { + float x = tick->pos / m_frequencyScale.getSize(); + q3[4*effectiveTicks] = x; + q3[4*effectiveTicks+1] = 0; + q3[4*effectiveTicks+2] = x; + q3[4*effectiveTicks+3] = 1; + effectiveTicks++; + } + } + } - QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f); - m_glShaderSimple.drawSegments(m_glHistogramBoxMatrix, color, q3, 2*effectiveTicks); - } - } + QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f); + m_glShaderSimple.drawSegments(m_glHistogramBoxMatrix, color, q3, 2*effectiveTicks); + } + } - // Paint info line - { - GLfloat vtx1[] = { - 0, 1, - 1, 1, - 1, 0, - 0, 0 - }; - GLfloat tex1[] = { - 0, 1, - 1, 1, - 1, 0, - 0, 0 - }; + // Paint info line + { + GLfloat vtx1[] = { + 0, 1, + 1, 1, + 1, 0, + 0, 0 + }; + GLfloat tex1[] = { + 0, 1, + 1, 1, + 1, 0, + 0, 0 + }; - m_glShaderInfo.drawSurface(m_glInfoBoxMatrix, tex1, vtx1, 4); - } + m_glShaderInfo.drawSurface(m_glInfoBoxMatrix, tex1, vtx1, 4); + } - m_mutex.unlock(); + m_mutex.unlock(); } void GLSpectrum::drawSpectrumMarkers() { - if (!m_currentSpectrum) { - return; - } + if (!m_currentSpectrum) { + return; + } - QVector4D lineColor(1.0f, 1.0f, 1.0f, 0.3f); + QVector4D lineColor(1.0f, 1.0f, 1.0f, 0.3f); // paint histogram markers if (m_histogramMarkers.size() > 0) { for (int i = 0; i < m_histogramMarkers.size(); i++) { - if (!m_histogramMarkers.at(i).m_show) { - continue; - } + if (!m_histogramMarkers.at(i).m_show) { + continue; + } - QPointF ypoint = m_histogramMarkers.at(i).m_point; - QString powerStr = m_histogramMarkers.at(i).m_powerStr; + QPointF ypoint = m_histogramMarkers.at(i).m_point; + QString powerStr = m_histogramMarkers.at(i).m_powerStr; - if (m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) - { - float power = m_currentSpectrum[m_histogramMarkers.at(i).m_fftBin]; - ypoint.ry() = - (m_powerScale.getRangeMax() - power) / m_powerScale.getRange(); - ypoint.ry() = ypoint.ry() < 0 ? - 0 : ypoint.ry() > 1 ? - 1 : ypoint.ry(); - powerStr = displayScaledF( - power, - m_linear ? 'e' : 'f', - m_linear ? 3 : 1, - false - ); - } - else if (m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax) - { - float power = m_currentSpectrum[m_histogramMarkers.at(i).m_fftBin]; + if (m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) + { + float power = m_currentSpectrum[m_histogramMarkers.at(i).m_fftBin]; + ypoint.ry() = + (m_powerScale.getRangeMax() - power) / m_powerScale.getRange(); + ypoint.ry() = ypoint.ry() < 0 ? + 0 : ypoint.ry() > 1 ? + 1 : ypoint.ry(); + powerStr = displayScaledF( + power, + m_linear ? 'e' : 'f', + m_linear ? 3 : 1, + false + ); + } + else if (m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax) + { + float power = m_currentSpectrum[m_histogramMarkers.at(i).m_fftBin]; - if ((m_histogramMarkers.at(i).m_holdReset) || (power > m_histogramMarkers[i].m_powerMax)) - { - m_histogramMarkers[i].m_powerMax = power; - m_histogramMarkers[i].m_holdReset = false; - } + if ((m_histogramMarkers.at(i).m_holdReset) || (power > m_histogramMarkers[i].m_powerMax)) + { + m_histogramMarkers[i].m_powerMax = power; + m_histogramMarkers[i].m_holdReset = false; + } - ypoint.ry() = - (m_powerScale.getRangeMax() - m_histogramMarkers[i].m_powerMax) / m_powerScale.getRange(); - ypoint.ry() = ypoint.ry() < 0 ? - 0 : ypoint.ry() > 1 ? - 1 : ypoint.ry(); - powerStr = displayScaledF( - m_histogramMarkers[i].m_powerMax, - m_linear ? 'e' : 'f', - m_linear ? 3 : 1, - false - ); - } + ypoint.ry() = + (m_powerScale.getRangeMax() - m_histogramMarkers[i].m_powerMax) / m_powerScale.getRange(); + ypoint.ry() = ypoint.ry() < 0 ? + 0 : ypoint.ry() > 1 ? + 1 : ypoint.ry(); + powerStr = displayScaledF( + m_histogramMarkers[i].m_powerMax, + m_linear ? 'e' : 'f', + m_linear ? 3 : 1, + false + ); + } - // crosshairs + // crosshairs GLfloat h[] { (float) m_histogramMarkers.at(i).m_point.x(), 0, (float) m_histogramMarkers.at(i).m_point.x(), 1 @@ -1238,8 +1249,8 @@ void GLSpectrum::drawSpectrumMarkers() 1, (float) ypoint.y() }; m_glShaderSimple.drawSegments(m_glHistogramBoxMatrix, lineColor, v, 2); - QColor textColor = m_histogramMarkers.at(i).m_markerColor; - // text + QColor textColor = m_histogramMarkers.at(i).m_markerColor; + // text if (i == 0) { drawTextOverlay( @@ -1263,32 +1274,32 @@ void GLSpectrum::drawSpectrumMarkers() } else { - textColor.setAlpha(192); - float power0, poweri; + textColor.setAlpha(192); + float power0, poweri; - if (m_histogramMarkers.at(0).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) { - power0 = m_currentSpectrum[m_histogramMarkers.at(0).m_fftBin]; - } else if (m_histogramMarkers.at(0).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax) { - power0 = m_histogramMarkers.at(0).m_powerMax; - } else { - power0 = m_linear ? m_histogramMarkers.at(0).m_power : CalcDb::dbPower(m_histogramMarkers.at(0).m_power); - } + if (m_histogramMarkers.at(0).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) { + power0 = m_currentSpectrum[m_histogramMarkers.at(0).m_fftBin]; + } else if (m_histogramMarkers.at(0).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax) { + power0 = m_histogramMarkers.at(0).m_powerMax; + } else { + power0 = m_linear ? m_histogramMarkers.at(0).m_power : CalcDb::dbPower(m_histogramMarkers.at(0).m_power); + } - if (m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) { - poweri = m_currentSpectrum[m_histogramMarkers.at(i).m_fftBin]; - } else if (m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax) { - poweri = m_histogramMarkers.at(i).m_powerMax; - } else { - poweri = m_linear ? m_histogramMarkers.at(i).m_power : CalcDb::dbPower(m_histogramMarkers.at(i).m_power); - } + if (m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) { + poweri = m_currentSpectrum[m_histogramMarkers.at(i).m_fftBin]; + } else if (m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax) { + poweri = m_histogramMarkers.at(i).m_powerMax; + } else { + poweri = m_linear ? m_histogramMarkers.at(i).m_power : CalcDb::dbPower(m_histogramMarkers.at(i).m_power); + } - QString deltaPowerStr; + QString deltaPowerStr; - if (m_linear) { - deltaPowerStr = displayScaledF(poweri - power0, 'e', 3, false); - } else { - deltaPowerStr = QString::number(poweri - power0, 'f', 1); - } + if (m_linear) { + deltaPowerStr = displayScaledF(poweri - power0, 'e', 3, false); + } else { + deltaPowerStr = QString::number(poweri - power0, 'f', 1); + } drawTextOverlay( m_histogramMarkers.at(i).m_deltaFrequencyStr, @@ -1318,9 +1329,9 @@ void GLSpectrum::drawSpectrumMarkers() // crosshairs for (int i = 0; i < m_waterfallMarkers.size(); i++) { - if (!m_waterfallMarkers.at(i).m_show) { - continue; - } + if (!m_waterfallMarkers.at(i).m_show) { + continue; + } GLfloat h[] { (float) m_waterfallMarkers.at(i).m_point.x(), 0, @@ -1336,8 +1347,8 @@ void GLSpectrum::drawSpectrumMarkers() // text // for (int i = 0; i < m_waterfallMarkers.size(); i++) // { - QColor textColor = m_waterfallMarkers.at(i).m_markerColor; - textColor.setAlpha(192); + QColor textColor = m_waterfallMarkers.at(i).m_markerColor; + textColor.setAlpha(192); if (i == 0) { @@ -1385,297 +1396,367 @@ void GLSpectrum::drawSpectrumMarkers() } } -void GLSpectrum::stopDrag() +void GLSpectrum::drawAnnotationMarkers() { - if (m_cursorState != CSNormal) + if ((!m_currentSpectrum) || (m_visibleAnnotationMarkers.size() == 0)) { + return; + } + + float h = m_annotationMarkerHeight / (float) m_histogramHeight; + + for (const auto &marker : m_visibleAnnotationMarkers) { - if ((m_cursorState == CSSplitterMoving) || (m_cursorState == CSChannelMoving)) { - releaseMouse(); + QVector4D color(marker->m_markerColor.redF(), marker->m_markerColor.greenF(), marker->m_markerColor.blueF(), 0.5f); + + if (marker->m_bandwidth == 0) + { + GLfloat d[] { + marker->m_startPos, 0, + marker->m_startPos, h + }; + m_glShaderSimple.drawSegments(m_glHistogramBoxMatrix, color, d, 2); + } + else + { + GLfloat q3[] { + marker->m_stopPos, h, + marker->m_startPos, h, + marker->m_startPos, 0, + marker->m_stopPos, 0 + }; + m_glShaderSimple.drawSurface(m_glHistogramBoxMatrix, color, q3, 4); } - setCursor(Qt::ArrowCursor); - m_cursorState = CSNormal; - } + if (marker->m_selected) + { + QVector4D color( + marker->m_markerColor.redF(), + marker->m_markerColor.greenF(), + marker->m_markerColor.blueF(), 0.5f + ); + GLfloat d1[] { + marker->m_startPos, 0, + marker->m_startPos, 1, + }; + m_glShaderSimple.drawSegments(m_glHistogramBoxMatrix, color, d1, 2); + + if (marker->m_bandwidth != 0) + { + GLfloat d2[] { + marker->m_stopPos, 0, + marker->m_stopPos, 1, + }; + m_glShaderSimple.drawSegments(m_glHistogramBoxMatrix, color, d2, 2); + } + + float txtpos = marker->m_startPos < 0.5f ? + marker->m_startPos : + marker->m_stopPos; + + drawTextOverlay( + marker->m_text, + QColor(255, 255, 255, 192), + m_textOverlayFont, + txtpos * m_histogramRect.width(), + 0, + marker->m_startPos < 0.5f, + true, + m_histogramRect); + } + } +} + +void GLSpectrum::stopDrag() +{ + if (m_cursorState != CSNormal) + { + if ((m_cursorState == CSSplitterMoving) || (m_cursorState == CSChannelMoving)) { + releaseMouse(); + } + + setCursor(Qt::ArrowCursor); + m_cursorState = CSNormal; + } } void GLSpectrum::applyChanges() { - if (m_nbBins <= 0) { - return; - } + if (m_nbBins <= 0) { + return; + } - QFontMetrics fm(font()); - int M = fm.horizontalAdvance("-"); + QFontMetrics fm(font()); + int M = fm.horizontalAdvance("-"); - m_topMargin = fm.ascent() * 2.0; - m_bottomMargin = fm.ascent() * 1.0; - m_infoHeight = fm.height() * 3; + m_topMargin = fm.ascent() * 2.0; + m_bottomMargin = fm.ascent() * 1.0; + m_infoHeight = fm.height() * 3; - int waterfallTop = 0; - m_frequencyScaleHeight = fm.height() * 3; // +1 line for marker frequency scale - int frequencyScaleTop = 0; - int histogramTop = 0; - //int m_leftMargin; - m_rightMargin = fm.horizontalAdvance("000"); + int waterfallTop = 0; + m_frequencyScaleHeight = fm.height() * 3; // +1 line for marker frequency scale + int frequencyScaleTop = 0; + int histogramTop = 0; + //int m_leftMargin; + m_rightMargin = fm.horizontalAdvance("000"); - // displays both histogram and waterfall - if (m_displayWaterfall && (m_displayHistogram | m_displayMaxHold | m_displayCurrent)) - { - m_waterfallHeight = height() * m_waterfallShare - 1; + // displays both histogram and waterfall + if (m_displayWaterfall && (m_displayHistogram | m_displayMaxHold | m_displayCurrent)) + { + m_waterfallHeight = height() * m_waterfallShare - 1; - if (m_waterfallHeight < 0) { - m_waterfallHeight = 0; - } + if (m_waterfallHeight < 0) { + m_waterfallHeight = 0; + } - if (m_invertedWaterfall) - { - histogramTop = m_topMargin; - m_histogramHeight = height() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight - m_bottomMargin; - waterfallTop = histogramTop + m_histogramHeight + m_frequencyScaleHeight + 1; - frequencyScaleTop = histogramTop + m_histogramHeight + 1; - } - else - { - waterfallTop = m_topMargin; - frequencyScaleTop = waterfallTop + m_waterfallHeight + 1; - histogramTop = waterfallTop + m_waterfallHeight + m_frequencyScaleHeight + 1; - m_histogramHeight = height() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight - m_bottomMargin; - } + if (m_invertedWaterfall) + { + histogramTop = m_topMargin; + m_histogramHeight = height() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight - m_bottomMargin; + waterfallTop = histogramTop + m_histogramHeight + m_frequencyScaleHeight + 1; + frequencyScaleTop = histogramTop + m_histogramHeight + 1; + } + else + { + waterfallTop = m_topMargin; + frequencyScaleTop = waterfallTop + m_waterfallHeight + 1; + histogramTop = waterfallTop + m_waterfallHeight + m_frequencyScaleHeight + 1; + m_histogramHeight = height() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight - m_bottomMargin; + } - m_timeScale.setSize(m_waterfallHeight); + m_timeScale.setSize(m_waterfallHeight); - if (m_sampleRate > 0) - { - float scaleDiv = ((float)m_sampleRate / (float)m_timingRate) * (m_ssbSpectrum ? 2 : 1); - float halfFFTSize = m_fftSize / 2; + if (m_sampleRate > 0) + { + float scaleDiv = ((float)m_sampleRate / (float)m_timingRate) * (m_ssbSpectrum ? 2 : 1); + float halfFFTSize = m_fftSize / 2; - if (halfFFTSize > m_fftOverlap) { - scaleDiv *= halfFFTSize / (halfFFTSize - m_fftOverlap); - } + if (halfFFTSize > m_fftOverlap) { + scaleDiv *= halfFFTSize / (halfFFTSize - m_fftOverlap); + } - if (!m_invertedWaterfall) { - m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, (m_waterfallHeight * m_fftSize) / scaleDiv, 0); - } else { - m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, 0, (m_waterfallHeight * m_fftSize) / scaleDiv); - } - } - else - { - m_timeScale.setRange(Unit::Time, 0, 1); - } + if (!m_invertedWaterfall) { + m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, (m_waterfallHeight * m_fftSize) / scaleDiv, 0); + } else { + m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, 0, (m_waterfallHeight * m_fftSize) / scaleDiv); + } + } + else + { + m_timeScale.setRange(Unit::Time, 0, 1); + } - m_powerScale.setSize(m_histogramHeight); + m_powerScale.setSize(m_histogramHeight); - if (m_linear) { + if (m_linear) { m_powerScale.setRange(Unit::Scientific, m_referenceLevel - m_powerRange, m_referenceLevel); - } else { - m_powerScale.setRange(Unit::Decibel, m_referenceLevel - m_powerRange, m_referenceLevel); - } + } else { + m_powerScale.setRange(Unit::Decibel, m_referenceLevel - m_powerRange, m_referenceLevel); + } - m_leftMargin = m_timeScale.getScaleWidth(); + m_leftMargin = m_timeScale.getScaleWidth(); - if (m_powerScale.getScaleWidth() > m_leftMargin) { - m_leftMargin = m_powerScale.getScaleWidth(); - } + if (m_powerScale.getScaleWidth() > m_leftMargin) { + m_leftMargin = m_powerScale.getScaleWidth(); + } - m_leftMargin += 2 * M; + m_leftMargin += 2 * M; - setFrequencyScale(); + setFrequencyScale(); - m_glWaterfallBoxMatrix.setToIdentity(); - m_glWaterfallBoxMatrix.translate( - -1.0f + ((float)(2*m_leftMargin) / (float) width()), - 1.0f - ((float)(2*waterfallTop) / (float) height()) - ); - m_glWaterfallBoxMatrix.scale( - ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), - (float) (-2*m_waterfallHeight) / (float) height() - ); + m_glWaterfallBoxMatrix.setToIdentity(); + m_glWaterfallBoxMatrix.translate( + -1.0f + ((float)(2*m_leftMargin) / (float) width()), + 1.0f - ((float)(2*waterfallTop) / (float) height()) + ); + m_glWaterfallBoxMatrix.scale( + ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), + (float) (-2*m_waterfallHeight) / (float) height() + ); - m_glHistogramBoxMatrix.setToIdentity(); - m_glHistogramBoxMatrix.translate( - -1.0f + ((float)(2*m_leftMargin) / (float) width()), - 1.0f - ((float)(2*histogramTop) / (float) height()) - ); - m_glHistogramBoxMatrix.scale( - ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), - (float) (-2*m_histogramHeight) / (float) height() - ); + m_glHistogramBoxMatrix.setToIdentity(); + m_glHistogramBoxMatrix.translate( + -1.0f + ((float)(2*m_leftMargin) / (float) width()), + 1.0f - ((float)(2*histogramTop) / (float) height()) + ); + m_glHistogramBoxMatrix.scale( + ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), + (float) (-2*m_histogramHeight) / (float) height() + ); - m_glHistogramSpectrumMatrix.setToIdentity(); - m_glHistogramSpectrumMatrix.translate( - -1.0f + ((float)(2*m_leftMargin) / (float) width()), - 1.0f - ((float)(2*histogramTop) / (float) height()) - ); - m_glHistogramSpectrumMatrix.scale( - ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins - 1)), - ((float) 2*m_histogramHeight / height()) / m_powerRange - ); + m_glHistogramSpectrumMatrix.setToIdentity(); + m_glHistogramSpectrumMatrix.translate( + -1.0f + ((float)(2*m_leftMargin) / (float) width()), + 1.0f - ((float)(2*histogramTop) / (float) height()) + ); + m_glHistogramSpectrumMatrix.scale( + ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins - 1)), + ((float) 2*m_histogramHeight / height()) / m_powerRange + ); - // m_frequencyScaleRect = QRect( - // 0, - // frequencyScaleTop, - // width(), - // m_frequencyScaleHeight - // ); + // m_frequencyScaleRect = QRect( + // 0, + // frequencyScaleTop, + // width(), + // m_frequencyScaleHeight + // ); - m_glFrequencyScaleBoxMatrix.setToIdentity(); - m_glFrequencyScaleBoxMatrix.translate ( - -1.0f, - 1.0f - ((float) 2*frequencyScaleTop / (float) height()) - ); - m_glFrequencyScaleBoxMatrix.scale ( - 2.0f, - (float) -2*m_frequencyScaleHeight / (float) height() - ); + m_glFrequencyScaleBoxMatrix.setToIdentity(); + m_glFrequencyScaleBoxMatrix.translate ( + -1.0f, + 1.0f - ((float) 2*frequencyScaleTop / (float) height()) + ); + m_glFrequencyScaleBoxMatrix.scale ( + 2.0f, + (float) -2*m_frequencyScaleHeight / (float) height() + ); - m_glLeftScaleBoxMatrix.setToIdentity(); - m_glLeftScaleBoxMatrix.translate(-1.0f, 1.0f); - m_glLeftScaleBoxMatrix.scale( - (float)(2*(m_leftMargin - 1)) / (float) width(), - -2.0f - ); - } - // displays waterfall only - else if (m_displayWaterfall) - { + m_glLeftScaleBoxMatrix.setToIdentity(); + m_glLeftScaleBoxMatrix.translate(-1.0f, 1.0f); + m_glLeftScaleBoxMatrix.scale( + (float)(2*(m_leftMargin - 1)) / (float) width(), + -2.0f + ); + } + // displays waterfall only + else if (m_displayWaterfall) + { m_histogramHeight = 0; - histogramTop = 0; - m_bottomMargin = m_frequencyScaleHeight; - m_waterfallHeight = height() - m_topMargin - m_frequencyScaleHeight; - waterfallTop = m_topMargin; - frequencyScaleTop = m_topMargin + m_waterfallHeight + 1; + histogramTop = 0; + m_bottomMargin = m_frequencyScaleHeight; + m_waterfallHeight = height() - m_topMargin - m_frequencyScaleHeight; + waterfallTop = m_topMargin; + frequencyScaleTop = m_topMargin + m_waterfallHeight + 1; - m_timeScale.setSize(m_waterfallHeight); + m_timeScale.setSize(m_waterfallHeight); - if (m_sampleRate > 0) - { - float scaleDiv = ((float)m_sampleRate / (float)m_timingRate) * (m_ssbSpectrum ? 2 : 1); - float halfFFTSize = m_fftSize / 2; + if (m_sampleRate > 0) + { + float scaleDiv = ((float)m_sampleRate / (float)m_timingRate) * (m_ssbSpectrum ? 2 : 1); + float halfFFTSize = m_fftSize / 2; - if (halfFFTSize > m_fftOverlap) { - scaleDiv *= halfFFTSize / (halfFFTSize - m_fftOverlap); - } + if (halfFFTSize > m_fftOverlap) { + scaleDiv *= halfFFTSize / (halfFFTSize - m_fftOverlap); + } - if (!m_invertedWaterfall) { - m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, (m_waterfallHeight * m_fftSize) / scaleDiv, 0); - } else { - m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, 0, (m_waterfallHeight * m_fftSize) / scaleDiv); - } - } - else - { - if (!m_invertedWaterfall) { - m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, 10, 0); - } else { - m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, 0, 10); - } - } + if (!m_invertedWaterfall) { + m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, (m_waterfallHeight * m_fftSize) / scaleDiv, 0); + } else { + m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, 0, (m_waterfallHeight * m_fftSize) / scaleDiv); + } + } + else + { + if (!m_invertedWaterfall) { + m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, 10, 0); + } else { + m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, 0, 10); + } + } - m_leftMargin = m_timeScale.getScaleWidth(); - m_leftMargin += 2 * M; + m_leftMargin = m_timeScale.getScaleWidth(); + m_leftMargin += 2 * M; - setFrequencyScale(); + setFrequencyScale(); - m_glWaterfallBoxMatrix.setToIdentity(); - m_glWaterfallBoxMatrix.translate( - -1.0f + ((float)(2*m_leftMargin) / (float) width()), - 1.0f - ((float)(2*m_topMargin) / (float) height()) - ); - m_glWaterfallBoxMatrix.scale( - ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), - (float) (-2*m_waterfallHeight) / (float) height() - ); + m_glWaterfallBoxMatrix.setToIdentity(); + m_glWaterfallBoxMatrix.translate( + -1.0f + ((float)(2*m_leftMargin) / (float) width()), + 1.0f - ((float)(2*m_topMargin) / (float) height()) + ); + m_glWaterfallBoxMatrix.scale( + ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), + (float) (-2*m_waterfallHeight) / (float) height() + ); - // m_frequencyScaleRect = QRect( - // 0, - // frequencyScaleTop, - // width(), - // m_frequencyScaleHeight - // ); + // m_frequencyScaleRect = QRect( + // 0, + // frequencyScaleTop, + // width(), + // m_frequencyScaleHeight + // ); - m_glFrequencyScaleBoxMatrix.setToIdentity(); - m_glFrequencyScaleBoxMatrix.translate ( - -1.0f, - 1.0f - ((float) 2*frequencyScaleTop / (float) height()) - ); - m_glFrequencyScaleBoxMatrix.scale ( - 2.0f, - (float) -2*m_frequencyScaleHeight / (float) height() - ); + m_glFrequencyScaleBoxMatrix.setToIdentity(); + m_glFrequencyScaleBoxMatrix.translate ( + -1.0f, + 1.0f - ((float) 2*frequencyScaleTop / (float) height()) + ); + m_glFrequencyScaleBoxMatrix.scale ( + 2.0f, + (float) -2*m_frequencyScaleHeight / (float) height() + ); - m_glLeftScaleBoxMatrix.setToIdentity(); - m_glLeftScaleBoxMatrix.translate(-1.0f, 1.0f); - m_glLeftScaleBoxMatrix.scale( - (float)(2*(m_leftMargin - 1)) / (float) width(), - -2.0f - ); - } - // displays histogram only - else if (m_displayHistogram || m_displayMaxHold || m_displayCurrent) - { - m_bottomMargin = m_frequencyScaleHeight; - frequencyScaleTop = height() - m_bottomMargin; - histogramTop = m_topMargin - 1; - m_waterfallHeight = 0; - m_histogramHeight = height() - m_topMargin - m_frequencyScaleHeight; + m_glLeftScaleBoxMatrix.setToIdentity(); + m_glLeftScaleBoxMatrix.translate(-1.0f, 1.0f); + m_glLeftScaleBoxMatrix.scale( + (float)(2*(m_leftMargin - 1)) / (float) width(), + -2.0f + ); + } + // displays histogram only + else if (m_displayHistogram || m_displayMaxHold || m_displayCurrent) + { + m_bottomMargin = m_frequencyScaleHeight; + frequencyScaleTop = height() - m_bottomMargin; + histogramTop = m_topMargin - 1; + m_waterfallHeight = 0; + m_histogramHeight = height() - m_topMargin - m_frequencyScaleHeight; - m_powerScale.setSize(m_histogramHeight); - m_powerScale.setRange(Unit::Decibel, m_referenceLevel - m_powerRange, m_referenceLevel); - m_leftMargin = m_powerScale.getScaleWidth(); - m_leftMargin += 2 * M; + m_powerScale.setSize(m_histogramHeight); + m_powerScale.setRange(Unit::Decibel, m_referenceLevel - m_powerRange, m_referenceLevel); + m_leftMargin = m_powerScale.getScaleWidth(); + m_leftMargin += 2 * M; - setFrequencyScale(); + setFrequencyScale(); - m_glHistogramSpectrumMatrix.setToIdentity(); - m_glHistogramSpectrumMatrix.translate( - -1.0f + ((float)(2*m_leftMargin) / (float) width()), - 1.0f - ((float)(2*histogramTop) / (float) height()) - ); - m_glHistogramSpectrumMatrix.scale( - ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins - 1)), - ((float) 2*(height() - m_topMargin - m_frequencyScaleHeight)) / (height()*m_powerRange) - ); + m_glHistogramSpectrumMatrix.setToIdentity(); + m_glHistogramSpectrumMatrix.translate( + -1.0f + ((float)(2*m_leftMargin) / (float) width()), + 1.0f - ((float)(2*histogramTop) / (float) height()) + ); + m_glHistogramSpectrumMatrix.scale( + ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins - 1)), + ((float) 2*(height() - m_topMargin - m_frequencyScaleHeight)) / (height()*m_powerRange) + ); - m_glHistogramBoxMatrix.setToIdentity(); - m_glHistogramBoxMatrix.translate( - -1.0f + ((float)(2*m_leftMargin) / (float) width()), - 1.0f - ((float)(2*histogramTop) / (float) height()) - ); - m_glHistogramBoxMatrix.scale( - ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), - (float) (-2*(height() - m_topMargin - m_frequencyScaleHeight)) / (float) height() - ); + m_glHistogramBoxMatrix.setToIdentity(); + m_glHistogramBoxMatrix.translate( + -1.0f + ((float)(2*m_leftMargin) / (float) width()), + 1.0f - ((float)(2*histogramTop) / (float) height()) + ); + m_glHistogramBoxMatrix.scale( + ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), + (float) (-2*(height() - m_topMargin - m_frequencyScaleHeight)) / (float) height() + ); - // m_frequencyScaleRect = QRect( - // 0, - // frequencyScaleTop, - // width(), - // m_frequencyScaleHeight - // ); + // m_frequencyScaleRect = QRect( + // 0, + // frequencyScaleTop, + // width(), + // m_frequencyScaleHeight + // ); - m_glFrequencyScaleBoxMatrix.setToIdentity(); - m_glFrequencyScaleBoxMatrix.translate ( - -1.0f, - 1.0f - ((float) 2*frequencyScaleTop / (float) height()) - ); - m_glFrequencyScaleBoxMatrix.scale ( - 2.0f, - (float) -2*m_frequencyScaleHeight / (float) height() - ); + m_glFrequencyScaleBoxMatrix.setToIdentity(); + m_glFrequencyScaleBoxMatrix.translate ( + -1.0f, + 1.0f - ((float) 2*frequencyScaleTop / (float) height()) + ); + m_glFrequencyScaleBoxMatrix.scale ( + 2.0f, + (float) -2*m_frequencyScaleHeight / (float) height() + ); - m_glLeftScaleBoxMatrix.setToIdentity(); - m_glLeftScaleBoxMatrix.translate(-1.0f, 1.0f); - m_glLeftScaleBoxMatrix.scale( - (float)(2*(m_leftMargin - 1)) / (float) width(), - -2.0f - ); - } - else - { - m_leftMargin = 2; - m_waterfallHeight = 0; - } + m_glLeftScaleBoxMatrix.setToIdentity(); + m_glLeftScaleBoxMatrix.translate(-1.0f, 1.0f); + m_glLeftScaleBoxMatrix.scale( + (float)(2*(m_leftMargin - 1)) / (float) width(), + -2.0f + ); + } + else + { + m_leftMargin = 2; + m_waterfallHeight = 0; + } // bounding boxes m_frequencyScaleRect = QRect( @@ -1723,237 +1804,237 @@ void GLSpectrum::applyChanges() ); } - // channel overlays - int64_t centerFrequency; - int frequencySpan; + // channel overlays + int64_t centerFrequency; + int frequencySpan; - if (m_frequencyZoomFactor == 1.0f) - { - centerFrequency = m_centerFrequency; - frequencySpan = m_sampleRate; - } - else - { - getFrequencyZoom(centerFrequency, frequencySpan); - } + if (m_frequencyZoomFactor == 1.0f) + { + centerFrequency = m_centerFrequency; + frequencySpan = m_sampleRate; + } + else + { + getFrequencyZoom(centerFrequency, frequencySpan); + } - for (int i = 0; i < m_channelMarkerStates.size(); ++i) - { - ChannelMarkerState* dv = m_channelMarkerStates[i]; + for (int i = 0; i < m_channelMarkerStates.size(); ++i) + { + ChannelMarkerState* dv = m_channelMarkerStates[i]; - qreal xc, pw, nw, dsbw; - ChannelMarker::sidebands_t sidebands = dv->m_channelMarker->getSidebands(); - xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency - dsbw = dv->m_channelMarker->getBandwidth(); + qreal xc, pw, nw, dsbw; + ChannelMarker::sidebands_t sidebands = dv->m_channelMarker->getSidebands(); + xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency + dsbw = dv->m_channelMarker->getBandwidth(); - if (sidebands == ChannelMarker::usb) { - nw = dv->m_channelMarker->getLowCutoff(); // negative bandwidth - int bw = dv->m_channelMarker->getBandwidth() / 2; - pw = (qreal) bw; // positive bandwidth - } else if (sidebands == ChannelMarker::lsb) { - pw = dv->m_channelMarker->getLowCutoff(); - int bw = dv->m_channelMarker->getBandwidth() / 2; - nw = (qreal) bw; - } else if (sidebands == ChannelMarker::vusb) { + if (sidebands == ChannelMarker::usb) { + nw = dv->m_channelMarker->getLowCutoff(); // negative bandwidth + int bw = dv->m_channelMarker->getBandwidth() / 2; + pw = (qreal) bw; // positive bandwidth + } else if (sidebands == ChannelMarker::lsb) { + pw = dv->m_channelMarker->getLowCutoff(); + int bw = dv->m_channelMarker->getBandwidth() / 2; + nw = (qreal) bw; + } else if (sidebands == ChannelMarker::vusb) { nw = -dv->m_channelMarker->getOppositeBandwidth(); // negative bandwidth pw = dv->m_channelMarker->getBandwidth(); // positive bandwidth } else if (sidebands == ChannelMarker::vlsb) { pw = dv->m_channelMarker->getOppositeBandwidth(); // positive bandwidth nw = -dv->m_channelMarker->getBandwidth(); // negative bandwidth - } else { - pw = dsbw / 2; - nw = -pw; - } + } else { + pw = dsbw / 2; + nw = -pw; + } - // draw the DSB rectangle + // draw the DSB rectangle - QMatrix4x4 glMatrixDsb; - glMatrixDsb.setToIdentity(); - glMatrixDsb.translate( - -1.0f + 2.0f * ((m_leftMargin + m_frequencyScale.getPosFromValue(xc - (dsbw/2))) / (float) width()), - 1.0f - ); - glMatrixDsb.scale( - 2.0f * (dsbw / (float) frequencySpan), - -2.0f - ); + QMatrix4x4 glMatrixDsb; + glMatrixDsb.setToIdentity(); + glMatrixDsb.translate( + -1.0f + 2.0f * ((m_leftMargin + m_frequencyScale.getPosFromValue(xc - (dsbw/2))) / (float) width()), + 1.0f + ); + glMatrixDsb.scale( + 2.0f * (dsbw / (float) frequencySpan), + -2.0f + ); - dv->m_glMatrixDsbWaterfall = glMatrixDsb; - dv->m_glMatrixDsbWaterfall.translate( - 0.0f, - (float) waterfallTop / (float) height() - ); - dv->m_glMatrixDsbWaterfall.scale( - (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), - (float) m_waterfallHeight / (float) height() - ); + dv->m_glMatrixDsbWaterfall = glMatrixDsb; + dv->m_glMatrixDsbWaterfall.translate( + 0.0f, + (float) waterfallTop / (float) height() + ); + dv->m_glMatrixDsbWaterfall.scale( + (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), + (float) m_waterfallHeight / (float) height() + ); - dv->m_glMatrixDsbHistogram = glMatrixDsb; - dv->m_glMatrixDsbHistogram.translate( - 0.0f, - (float) histogramTop / (float) height() - ); - dv->m_glMatrixDsbHistogram.scale( - (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), - (float) m_histogramHeight / (float) height() - ); + dv->m_glMatrixDsbHistogram = glMatrixDsb; + dv->m_glMatrixDsbHistogram.translate( + 0.0f, + (float) histogramTop / (float) height() + ); + dv->m_glMatrixDsbHistogram.scale( + (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), + (float) m_histogramHeight / (float) height() + ); - dv->m_glMatrixDsbFreqScale = glMatrixDsb; - dv->m_glMatrixDsbFreqScale.translate( - 0.0f, - (float) frequencyScaleTop / (float) height() - ); - dv->m_glMatrixDsbFreqScale.scale( - (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), - (float) m_frequencyScaleHeight / (float) height() - ); + dv->m_glMatrixDsbFreqScale = glMatrixDsb; + dv->m_glMatrixDsbFreqScale.translate( + 0.0f, + (float) frequencyScaleTop / (float) height() + ); + dv->m_glMatrixDsbFreqScale.scale( + (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), + (float) m_frequencyScaleHeight / (float) height() + ); - // draw the effective BW rectangle + // draw the effective BW rectangle - QMatrix4x4 glMatrix; - glMatrix.setToIdentity(); - glMatrix.translate( - -1.0f + 2.0f * ((m_leftMargin + m_frequencyScale.getPosFromValue(xc + nw)) / (float) width()), - 1.0f - ); - glMatrix.scale( - 2.0f * ((pw-nw) / (float) frequencySpan), - -2.0f - ); + QMatrix4x4 glMatrix; + glMatrix.setToIdentity(); + glMatrix.translate( + -1.0f + 2.0f * ((m_leftMargin + m_frequencyScale.getPosFromValue(xc + nw)) / (float) width()), + 1.0f + ); + glMatrix.scale( + 2.0f * ((pw-nw) / (float) frequencySpan), + -2.0f + ); - dv->m_glMatrixWaterfall = glMatrix; - dv->m_glMatrixWaterfall.translate( - 0.0f, - (float) waterfallTop / (float) height() - ); - dv->m_glMatrixWaterfall.scale( - (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), - (float) m_waterfallHeight / (float) height() - ); + dv->m_glMatrixWaterfall = glMatrix; + dv->m_glMatrixWaterfall.translate( + 0.0f, + (float) waterfallTop / (float) height() + ); + dv->m_glMatrixWaterfall.scale( + (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), + (float) m_waterfallHeight / (float) height() + ); - dv->m_glMatrixHistogram = glMatrix; - dv->m_glMatrixHistogram.translate( - 0.0f, - (float) histogramTop / (float) height() - ); - dv->m_glMatrixHistogram.scale( - (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), - (float) m_histogramHeight / (float) height() - ); + dv->m_glMatrixHistogram = glMatrix; + dv->m_glMatrixHistogram.translate( + 0.0f, + (float) histogramTop / (float) height() + ); + dv->m_glMatrixHistogram.scale( + (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), + (float) m_histogramHeight / (float) height() + ); - dv->m_glMatrixFreqScale = glMatrix; - dv->m_glMatrixFreqScale.translate( - 0.0f, - (float) frequencyScaleTop / (float) height() - ); - dv->m_glMatrixFreqScale.scale( - (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), - (float) m_frequencyScaleHeight / (float) height() - ); + dv->m_glMatrixFreqScale = glMatrix; + dv->m_glMatrixFreqScale.translate( + 0.0f, + (float) frequencyScaleTop / (float) height() + ); + dv->m_glMatrixFreqScale.scale( + (float) (width() - m_leftMargin - m_rightMargin) / (float) width(), + (float) m_frequencyScaleHeight / (float) height() + ); - /* - dv->m_glRect.setRect( - m_frequencyScale.getPosFromValue(m_centerFrequency + dv->m_channelMarker->getCenterFrequency() - dv->m_channelMarker->getBandwidth() / 2) / (float)(width() - m_leftMargin - m_rightMargin), - 0, - (dv->m_channelMarker->getBandwidth() / (float)m_sampleRate), - 1); - */ + /* + dv->m_glRect.setRect( + m_frequencyScale.getPosFromValue(m_centerFrequency + dv->m_channelMarker->getCenterFrequency() - dv->m_channelMarker->getBandwidth() / 2) / (float)(width() - m_leftMargin - m_rightMargin), + 0, + (dv->m_channelMarker->getBandwidth() / (float)m_sampleRate), + 1); + */ - if (m_displayHistogram || m_displayMaxHold || m_displayCurrent || m_displayWaterfall) - { - dv->m_rect.setRect(m_frequencyScale.getPosFromValue(xc) + m_leftMargin - 1, - m_topMargin, - 5, - height() - m_topMargin - m_bottomMargin); - } + if (m_displayHistogram || m_displayMaxHold || m_displayCurrent || m_displayWaterfall) + { + dv->m_rect.setRect(m_frequencyScale.getPosFromValue(xc) + m_leftMargin - 1, + m_topMargin, + 5, + height() - m_topMargin - m_bottomMargin); + } - /* - if(m_displayHistogram || m_displayMaxHold || m_displayWaterfall) { - dv->m_rect.setRect(m_frequencyScale.getPosFromValue(m_centerFrequency + dv->m_channelMarker->getCenterFrequency()) + m_leftMargin - 1, - m_topMargin, - 5, - height() - m_topMargin - m_bottomMargin); - } - */ - } + /* + if(m_displayHistogram || m_displayMaxHold || m_displayWaterfall) { + dv->m_rect.setRect(m_frequencyScale.getPosFromValue(m_centerFrequency + dv->m_channelMarker->getCenterFrequency()) + m_leftMargin - 1, + m_topMargin, + 5, + height() - m_topMargin - m_bottomMargin); + } + */ + } - // prepare left scales (time and power) - { - m_leftMarginPixmap = QPixmap(m_leftMargin - 1, height()); - m_leftMarginPixmap.fill(Qt::black); - { - QPainter painter(&m_leftMarginPixmap); - painter.setPen(QColor(0xf0, 0xf0, 0xff)); - painter.setFont(font()); - 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(m_leftMargin - M - tick->textSize, waterfallTop + fm.ascent() + tick->textPos), tick->text); - } - } - } - if (m_displayHistogram || m_displayMaxHold || m_displayCurrent) { - 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(m_leftMargin - M - tick->textSize, histogramTop + m_histogramHeight - tick->textPos - 1), tick->text); - } - } - } - } + // prepare left scales (time and power) + { + m_leftMarginPixmap = QPixmap(m_leftMargin - 1, height()); + m_leftMarginPixmap.fill(Qt::black); + { + QPainter painter(&m_leftMarginPixmap); + painter.setPen(QColor(0xf0, 0xf0, 0xff)); + painter.setFont(font()); + 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(m_leftMargin - M - tick->textSize, waterfallTop + fm.ascent() + tick->textPos), tick->text); + } + } + } + if (m_displayHistogram || m_displayMaxHold || m_displayCurrent) { + 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(m_leftMargin - M - tick->textSize, histogramTop + m_histogramHeight - tick->textPos - 1), tick->text); + } + } + } + } - m_glShaderLeftScale.initTexture(m_leftMarginPixmap.toImage()); - } - // prepare frequency scale - if (m_displayWaterfall || m_displayHistogram || m_displayMaxHold || m_displayCurrent){ - m_frequencyPixmap = QPixmap(width(), m_frequencyScaleHeight); - m_frequencyPixmap.fill(Qt::transparent); - { - QPainter painter(&m_frequencyPixmap); - painter.setPen(Qt::NoPen); - painter.setBrush(Qt::black); - painter.setBrush(Qt::transparent); - painter.drawRect(m_leftMargin, 0, width() - m_leftMargin, m_frequencyScaleHeight); - painter.setPen(QColor(0xf0, 0xf0, 0xff)); - painter.setFont(font()); - const ScaleEngine::TickList* tickList = &m_frequencyScale.getTickList(); - const ScaleEngine::Tick* tick; + m_glShaderLeftScale.initTexture(m_leftMarginPixmap.toImage()); + } + // prepare frequency scale + if (m_displayWaterfall || m_displayHistogram || m_displayMaxHold || m_displayCurrent){ + m_frequencyPixmap = QPixmap(width(), m_frequencyScaleHeight); + m_frequencyPixmap.fill(Qt::transparent); + { + QPainter painter(&m_frequencyPixmap); + painter.setPen(Qt::NoPen); + painter.setBrush(Qt::black); + painter.setBrush(Qt::transparent); + painter.drawRect(m_leftMargin, 0, width() - m_leftMargin, m_frequencyScaleHeight); + painter.setPen(QColor(0xf0, 0xf0, 0xff)); + painter.setFont(font()); + 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(m_leftMargin + tick->textPos, fm.height() + fm.ascent() / 2 - 1), tick->text); - } - } + for (int i = 0; i < tickList->count(); i++) { + tick = &(*tickList)[i]; + if (tick->major) { + if (tick->textSize > 0) + painter.drawText(QPointF(m_leftMargin + tick->textPos, fm.height() + fm.ascent() / 2 - 1), tick->text); + } + } - // Frequency overlay on highlighted marker - for (int i = 0; i < m_channelMarkerStates.size(); ++i) + // Frequency overlay on highlighted marker + for (int i = 0; i < m_channelMarkerStates.size(); ++i) { - ChannelMarkerState* dv = m_channelMarkerStates[i]; + ChannelMarkerState* dv = m_channelMarkerStates[i]; - if (dv->m_channelMarker->getHighlighted() + if (dv->m_channelMarker->getHighlighted() && (dv->m_channelMarker->getSourceOrSinkStream() == m_displaySourceOrSink) && dv->m_channelMarker->streamIndexApplies(m_displayStreamIndex)) - { - qreal xc; - int shift; - //ChannelMarker::sidebands_t sidebands = dv->m_channelMarker->getSidebands(); - xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency - QString ftext; - switch (dv->m_channelMarker->getFrequencyScaleDisplayType()) - { - case ChannelMarker::FScaleDisplay_freq: - ftext = QString::number((m_centerFrequency + dv->m_channelMarker->getCenterFrequency())/1e6, 'f', 6); - break; + { + qreal xc; + int shift; + //ChannelMarker::sidebands_t sidebands = dv->m_channelMarker->getSidebands(); + xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency + QString ftext; + switch (dv->m_channelMarker->getFrequencyScaleDisplayType()) + { + case ChannelMarker::FScaleDisplay_freq: + ftext = QString::number((m_centerFrequency + dv->m_channelMarker->getCenterFrequency())/1e6, 'f', 6); + break; case ChannelMarker::FScaleDisplay_title: ftext = dv->m_channelMarker->getTitle(); break; @@ -1963,236 +2044,285 @@ void GLSpectrum::applyChanges() case ChannelMarker::FScaleDisplay_addressReceive: ftext = dv->m_channelMarker->getDisplayAddressReceive(); break; - default: + default: ftext = QString::number((m_centerFrequency + dv->m_channelMarker->getCenterFrequency())/1e6, 'f', 6); break; - } - if (dv->m_channelMarker->getCenterFrequency() < 0) { // left half of scale - ftext = " " + ftext; - shift = 0; - } else { // right half of scale - ftext = ftext + " "; - shift = - fm.horizontalAdvance(ftext); - } - painter.drawText(QPointF(m_leftMargin + m_frequencyScale.getPosFromValue(xc) + shift, 2*fm.height() + fm.ascent() / 2 - 1), ftext); - } - } + } + if (dv->m_channelMarker->getCenterFrequency() < 0) { // left half of scale + ftext = " " + ftext; + shift = 0; + } else { // right half of scale + ftext = ftext + " "; + shift = - fm.horizontalAdvance(ftext); + } + painter.drawText(QPointF(m_leftMargin + m_frequencyScale.getPosFromValue(xc) + shift, 2*fm.height() + fm.ascent() / 2 - 1), ftext); + } + } - } + } - m_glShaderFrequencyScale.initTexture(m_frequencyPixmap.toImage()); - } + m_glShaderFrequencyScale.initTexture(m_frequencyPixmap.toImage()); + } - // Top info line - m_glInfoBoxMatrix.setToIdentity(); - m_glInfoBoxMatrix.translate ( - -1.0f, - 1.0f - ); - m_glInfoBoxMatrix.scale ( - 2.0f, - (float) -2*m_infoHeight / (float) height() - ); + // Top info line + m_glInfoBoxMatrix.setToIdentity(); + m_glInfoBoxMatrix.translate ( + -1.0f, + 1.0f + ); + m_glInfoBoxMatrix.scale ( + 2.0f, + (float) -2*m_infoHeight / (float) height() + ); m_infoRect = QRect( 0, 0, width(), m_infoHeight ); - QString infoText; - formatTextInfo(infoText); - m_infoPixmap = QPixmap(width(), m_infoHeight); - m_infoPixmap.fill(Qt::transparent); - { - QPainter painter(&m_infoPixmap); - painter.setPen(Qt::NoPen); - painter.setBrush(Qt::black); - painter.setBrush(Qt::transparent); - painter.drawRect(m_leftMargin, 0, width() - m_leftMargin, m_infoHeight); - painter.setPen(QColor(0xf0, 0xf0, 0xff)); - painter.setFont(font()); - painter.drawText(QPointF(m_leftMargin, fm.height() + fm.ascent() / 2 - 2), infoText); - } + QString infoText; + formatTextInfo(infoText); + m_infoPixmap = QPixmap(width(), m_infoHeight); + m_infoPixmap.fill(Qt::transparent); + { + QPainter painter(&m_infoPixmap); + painter.setPen(Qt::NoPen); + painter.setBrush(Qt::black); + painter.setBrush(Qt::transparent); + painter.drawRect(m_leftMargin, 0, width() - m_leftMargin, m_infoHeight); + painter.setPen(QColor(0xf0, 0xf0, 0xff)); + painter.setFont(font()); + painter.drawText(QPointF(m_leftMargin, fm.height() + fm.ascent() / 2 - 2), infoText); + } - m_glShaderInfo.initTexture(m_infoPixmap.toImage()); + m_glShaderInfo.initTexture(m_infoPixmap.toImage()); - bool fftSizeChanged = true; + bool fftSizeChanged = true; - if (m_waterfallBuffer) { - fftSizeChanged = m_waterfallBuffer->width() != m_nbBins; - } + if (m_waterfallBuffer) { + fftSizeChanged = m_waterfallBuffer->width() != m_nbBins; + } - bool windowSizeChanged = m_waterfallTextureHeight != m_waterfallHeight; + bool windowSizeChanged = m_waterfallTextureHeight != m_waterfallHeight; - if (fftSizeChanged || windowSizeChanged) - { - if (m_waterfallBuffer) { - delete m_waterfallBuffer; - } + if (fftSizeChanged || windowSizeChanged) + { + if (m_waterfallBuffer) { + delete m_waterfallBuffer; + } - m_waterfallBuffer = new QImage(m_nbBins, m_waterfallHeight, QImage::Format_ARGB32); + m_waterfallBuffer = new QImage(m_nbBins, m_waterfallHeight, QImage::Format_ARGB32); m_waterfallBuffer->fill(qRgb(0x00, 0x00, 0x00)); m_glShaderWaterfall.initTexture(*m_waterfallBuffer); m_waterfallBufferPos = 0; - } + } - if (fftSizeChanged) - { - if (m_histogramBuffer) + if (fftSizeChanged) + { + if (m_histogramBuffer) { - delete m_histogramBuffer; - m_histogramBuffer = nullptr; - } + delete m_histogramBuffer; + m_histogramBuffer = nullptr; + } - if (m_histogram) { - delete[] m_histogram; - m_histogram = nullptr; - } + if (m_histogram) { + delete[] m_histogram; + m_histogram = nullptr; + } - m_histogramBuffer = new QImage(m_nbBins, 100, QImage::Format_RGB32); + m_histogramBuffer = new QImage(m_nbBins, 100, QImage::Format_RGB32); m_histogramBuffer->fill(qRgb(0x00, 0x00, 0x00)); m_glShaderHistogram.initTexture(*m_histogramBuffer, QOpenGLTexture::ClampToEdge); - m_histogram = new quint8[100 * m_nbBins]; - memset(m_histogram, 0x00, 100 * m_nbBins); + m_histogram = new quint8[100 * m_nbBins]; + memset(m_histogram, 0x00, 100 * m_nbBins); - m_q3FFT.allocate(2*m_nbBins); - } + m_q3FFT.allocate(2*m_nbBins); + } - if (fftSizeChanged || windowSizeChanged) - { - m_waterfallTextureHeight = m_waterfallHeight; - m_waterfallTexturePos = 0; - } + if (fftSizeChanged || windowSizeChanged) + { + m_waterfallTextureHeight = m_waterfallHeight; + m_waterfallTexturePos = 0; + } - m_q3TickTime.allocate(4*m_timeScale.getTickList().count()); + m_q3TickTime.allocate(4*m_timeScale.getTickList().count()); m_q3TickFrequency.allocate(4*m_frequencyScale.getTickList().count()); m_q3TickPower.allocate(4*m_powerScale.getTickList().count()); - updateHistogramMarkers(); - updateWaterfallMarkers(); + updateHistogramMarkers(); + updateWaterfallMarkers(); + updateSortedAnnotationMarkers(); } // applyChanges void GLSpectrum::updateHistogramMarkers() { - for (int i = 0; i < m_histogramMarkers.size(); i++) - { - float powerI = m_linear ? m_histogramMarkers[i].m_power : CalcDb::dbPower(m_histogramMarkers[i].m_power); - m_histogramMarkers[i].m_point.rx() = - (m_histogramMarkers[i].m_frequency - m_frequencyScale.getRangeMin()) / m_frequencyScale.getRange(); - m_histogramMarkers[i].m_point.ry() = - (m_powerScale.getRangeMax() - powerI) / m_powerScale.getRange(); - m_histogramMarkers[i].m_fftBin = - (((m_histogramMarkers[i].m_frequency - m_centerFrequency) / (float) m_sampleRate) * m_fftSize) + (m_fftSize / 2); - m_histogramMarkers[i].m_point.rx() = m_histogramMarkers[i].m_point.rx() < 0 ? - 0 : m_histogramMarkers[i].m_point.rx() > 1 ? - 1 : m_histogramMarkers[i].m_point.rx(); - m_histogramMarkers[i].m_point.ry() = m_histogramMarkers[i].m_point.ry() < 0 ? - 0 : m_histogramMarkers[i].m_point.ry() > 1 ? - 1 : m_histogramMarkers[i].m_point.ry(); - m_histogramMarkers[i].m_fftBin = m_histogramMarkers[i].m_fftBin < 0 ? - 0 : m_histogramMarkers[i].m_fftBin > m_fftSize - 1 ? - m_fftSize - 1 : m_histogramMarkers[i].m_fftBin; - m_histogramMarkers[i].m_frequencyStr = displayScaled( - m_histogramMarkers[i].m_frequency, - 'f', - getPrecision((m_centerFrequency*1000)/m_sampleRate), - false); - m_histogramMarkers[i].m_powerStr = displayScaledF( - powerI, - m_linear ? 'e' : 'f', - m_linear ? 3 : 1, - false); + for (int i = 0; i < m_histogramMarkers.size(); i++) + { + float powerI = m_linear ? m_histogramMarkers[i].m_power : CalcDb::dbPower(m_histogramMarkers[i].m_power); + m_histogramMarkers[i].m_point.rx() = + (m_histogramMarkers[i].m_frequency - m_frequencyScale.getRangeMin()) / m_frequencyScale.getRange(); + m_histogramMarkers[i].m_point.ry() = + (m_powerScale.getRangeMax() - powerI) / m_powerScale.getRange(); + m_histogramMarkers[i].m_fftBin = + (((m_histogramMarkers[i].m_frequency - m_centerFrequency) / (float) m_sampleRate) * m_fftSize) + (m_fftSize / 2); + m_histogramMarkers[i].m_point.rx() = m_histogramMarkers[i].m_point.rx() < 0 ? + 0 : m_histogramMarkers[i].m_point.rx() > 1 ? + 1 : m_histogramMarkers[i].m_point.rx(); + m_histogramMarkers[i].m_point.ry() = m_histogramMarkers[i].m_point.ry() < 0 ? + 0 : m_histogramMarkers[i].m_point.ry() > 1 ? + 1 : m_histogramMarkers[i].m_point.ry(); + m_histogramMarkers[i].m_fftBin = m_histogramMarkers[i].m_fftBin < 0 ? + 0 : m_histogramMarkers[i].m_fftBin > m_fftSize - 1 ? + m_fftSize - 1 : m_histogramMarkers[i].m_fftBin; + m_histogramMarkers[i].m_frequencyStr = displayScaled( + m_histogramMarkers[i].m_frequency, + 'f', + getPrecision((m_centerFrequency*1000)/m_sampleRate), + false); + m_histogramMarkers[i].m_powerStr = displayScaledF( + powerI, + m_linear ? 'e' : 'f', + m_linear ? 3 : 1, + false); - if (i > 0) - { - int64_t deltaFrequency = m_histogramMarkers.at(i).m_frequency - m_histogramMarkers.at(0).m_frequency; - m_histogramMarkers.back().m_deltaFrequencyStr = displayScaled( - deltaFrequency, - 'f', - getPrecision(deltaFrequency/m_sampleRate), - true); - float power0 = m_linear ? - m_histogramMarkers.at(0).m_power : - CalcDb::dbPower(m_histogramMarkers.at(0).m_power); - float powerI = m_linear ? - m_histogramMarkers.at(i).m_power : - CalcDb::dbPower(m_histogramMarkers.at(i).m_power); - m_histogramMarkers.back().m_deltaPowerStr = displayScaledF( - powerI - power0, - m_linear ? 'e' : 'f', - m_linear ? 3 : 1, - false); - } - } + if (i > 0) + { + int64_t deltaFrequency = m_histogramMarkers.at(i).m_frequency - m_histogramMarkers.at(0).m_frequency; + m_histogramMarkers.back().m_deltaFrequencyStr = displayScaled( + deltaFrequency, + 'f', + getPrecision(deltaFrequency/m_sampleRate), + true); + float power0 = m_linear ? + m_histogramMarkers.at(0).m_power : + CalcDb::dbPower(m_histogramMarkers.at(0).m_power); + float powerI = m_linear ? + m_histogramMarkers.at(i).m_power : + CalcDb::dbPower(m_histogramMarkers.at(i).m_power); + m_histogramMarkers.back().m_deltaPowerStr = displayScaledF( + powerI - power0, + m_linear ? 'e' : 'f', + m_linear ? 3 : 1, + false); + } + } } void GLSpectrum::updateWaterfallMarkers() { - for (int i = 0; i < m_waterfallMarkers.size(); i++) - { - m_waterfallMarkers[i].m_point.rx() = - (m_waterfallMarkers[i].m_frequency - m_frequencyScale.getRangeMin()) / m_frequencyScale.getRange(); - m_waterfallMarkers[i].m_point.ry() = - (m_waterfallMarkers[i].m_time - m_timeScale.getRangeMin()) / m_timeScale.getRange(); - m_waterfallMarkers[i].m_point.rx() = m_waterfallMarkers[i].m_point.rx() < 0 ? - 0 : m_waterfallMarkers[i].m_point.rx() > 1 ? - 1 : m_waterfallMarkers[i].m_point.rx(); - m_waterfallMarkers[i].m_point.ry() = m_waterfallMarkers[i].m_point.ry() < 0 ? - 0 : m_waterfallMarkers[i].m_point.ry() > 1 ? - 1 : m_waterfallMarkers[i].m_point.ry(); - m_waterfallMarkers[i].m_frequencyStr = displayScaled( - m_waterfallMarkers[i].m_frequency, - 'f', - getPrecision((m_centerFrequency*1000)/m_sampleRate), - false); - m_waterfallMarkers[i].m_timeStr = displayScaledF( - m_waterfallMarkers[i].m_time, - 'f', - 3, - true); + for (int i = 0; i < m_waterfallMarkers.size(); i++) + { + m_waterfallMarkers[i].m_point.rx() = + (m_waterfallMarkers[i].m_frequency - m_frequencyScale.getRangeMin()) / m_frequencyScale.getRange(); + m_waterfallMarkers[i].m_point.ry() = + (m_waterfallMarkers[i].m_time - m_timeScale.getRangeMin()) / m_timeScale.getRange(); + m_waterfallMarkers[i].m_point.rx() = m_waterfallMarkers[i].m_point.rx() < 0 ? + 0 : m_waterfallMarkers[i].m_point.rx() > 1 ? + 1 : m_waterfallMarkers[i].m_point.rx(); + m_waterfallMarkers[i].m_point.ry() = m_waterfallMarkers[i].m_point.ry() < 0 ? + 0 : m_waterfallMarkers[i].m_point.ry() > 1 ? + 1 : m_waterfallMarkers[i].m_point.ry(); + m_waterfallMarkers[i].m_frequencyStr = displayScaled( + m_waterfallMarkers[i].m_frequency, + 'f', + getPrecision((m_centerFrequency*1000)/m_sampleRate), + false); + m_waterfallMarkers[i].m_timeStr = displayScaledF( + m_waterfallMarkers[i].m_time, + 'f', + 3, + true); - if (i > 0) + if (i > 0) + { + int64_t deltaFrequency = m_waterfallMarkers.at(i).m_frequency - m_waterfallMarkers.at(0).m_frequency; + m_waterfallMarkers.back().m_deltaFrequencyStr = displayScaled( + deltaFrequency, + 'f', + getPrecision(deltaFrequency/m_sampleRate), + true); + m_waterfallMarkers.back().m_deltaTimeStr = displayScaledF( + m_waterfallMarkers.at(i).m_time - m_waterfallMarkers.at(0).m_time, + 'f', + 3, + true); + } + } +} + +void GLSpectrum::updateAnnotationMarkers() +{ + if (m_markersDisplay != SpectrumSettings::MarkersDisplayAnnotations) { + return; + } + + m_sortedAnnotationMarkers.clear(); + + for (auto &marker : m_annotationMarkers) { + m_sortedAnnotationMarkers.push_back(&marker); + } + + std::sort(m_sortedAnnotationMarkers.begin(), m_sortedAnnotationMarkers.end(), annotationDisplayLessThan); + updateSortedAnnotationMarkers(); +} + +void GLSpectrum::updateSortedAnnotationMarkers() +{ + if (m_markersDisplay != SpectrumSettings::MarkersDisplayAnnotations) { + return; + } + + m_visibleAnnotationMarkers.clear(); + + for (auto &marker : m_sortedAnnotationMarkers) + { + float startPos = (marker->m_startFrequency - m_frequencyScale.getRangeMin()) / m_frequencyScale.getRange(); + float stopPos = ((marker->m_startFrequency + marker->m_bandwidth) - m_frequencyScale.getRangeMin()) / m_frequencyScale.getRange(); + + if ((startPos > 1.0f) || (stopPos < 0.0f)) // out of range { - int64_t deltaFrequency = m_waterfallMarkers.at(i).m_frequency - m_waterfallMarkers.at(0).m_frequency; - m_waterfallMarkers.back().m_deltaFrequencyStr = displayScaled( - deltaFrequency, - 'f', - getPrecision(deltaFrequency/m_sampleRate), - true); - m_waterfallMarkers.back().m_deltaTimeStr = displayScaledF( - m_waterfallMarkers.at(i).m_time - m_waterfallMarkers.at(0).m_time, - 'f', - 3, - true); - } - } + marker->m_selected = false; + continue; + } + + m_visibleAnnotationMarkers.push_back(marker); + m_visibleAnnotationMarkers.back()->m_startPos = startPos < 0.0f ? 0.0f : startPos; + m_visibleAnnotationMarkers.back()->m_stopPos = stopPos > 1.0f ? 1.0f : stopPos; + } +} + +void GLSpectrum::updateMarkersDisplay() +{ + if (m_markersDisplay == SpectrumSettings::MarkersDisplayAnnotations) { + updateAnnotationMarkers(); + } } void GLSpectrum::mouseMoveEvent(QMouseEvent* event) { - if (m_displayWaterfall || m_displayHistogram || m_displayMaxHold || m_displayCurrent) - { - 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_displayWaterfall || m_displayHistogram || m_displayMaxHold || m_displayCurrent) + { + 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) { @@ -2214,9 +2344,9 @@ void GLSpectrum::mouseMoveEvent(QMouseEvent* event) m_waterfallShare = newShare; m_changesPending = true; - if (m_messageQueueToGUI) { - m_messageQueueToGUI->push(new MsgReportWaterfallShare(m_waterfallShare)); - } + if (m_messageQueueToGUI) { + m_messageQueueToGUI->push(new MsgReportWaterfallShare(m_waterfallShare)); + } update(); return; @@ -2269,13 +2399,13 @@ void GLSpectrum::mouseMoveEvent(QMouseEvent* event) } } - if (m_cursorState == CSChannel) - { - setCursor(Qt::ArrowCursor); - m_cursorState = CSNormal; + if (m_cursorState == CSChannel) + { + setCursor(Qt::ArrowCursor); + m_cursorState = CSNormal; - return; - } + return; + } } void GLSpectrum::mousePressEvent(QMouseEvent* event) @@ -2331,7 +2461,7 @@ void GLSpectrum::mousePressEvent(QMouseEvent* event) update(); } } - else if (event->button() == Qt::LeftButton) + else if (event->button() == Qt::LeftButton) { if (event->modifiers() & Qt::ShiftModifier) { @@ -2341,8 +2471,8 @@ void GLSpectrum::mousePressEvent(QMouseEvent* event) pHis.ry() = (ep.y()/height() - m_histogramRect.top()) / m_histogramRect.height(); float frequency = m_frequencyScale.getRangeMin() + pHis.x()*m_frequencyScale.getRange(); float powerVal = m_powerScale.getRangeMax() - pHis.y()*m_powerScale.getRange(); - float power = m_linear ? powerVal : CalcDb::powerFromdB(powerVal); - int fftBin = (((frequency - m_centerFrequency) / (float) m_sampleRate) * m_fftSize) + (m_fftSize / 2); + float power = m_linear ? powerVal : CalcDb::powerFromdB(powerVal); + int fftBin = (((frequency - m_centerFrequency) / (float) m_sampleRate) * m_fftSize) + (m_fftSize / 2); if ((pHis.x() >= 0) && (pHis.x() <= 1) && (pHis.y() >= 0) && (pHis.y() <= 1)) { @@ -2351,7 +2481,7 @@ void GLSpectrum::mousePressEvent(QMouseEvent* event) m_histogramMarkers.push_back(SpectrumHistogramMarker()); m_histogramMarkers.back().m_point = pHis; m_histogramMarkers.back().m_frequency = frequency; - m_histogramMarkers.back().m_fftBin = fftBin; + m_histogramMarkers.back().m_fftBin = fftBin; m_histogramMarkers.back().m_frequencyStr = displayScaled( frequency, 'f', @@ -2372,9 +2502,9 @@ void GLSpectrum::mousePressEvent(QMouseEvent* event) 'f', getPrecision(deltaFrequency/m_sampleRate), true); - float power0 = m_linear ? - m_histogramMarkers.at(0).m_power : - CalcDb::dbPower(m_histogramMarkers.at(0).m_power); + float power0 = m_linear ? + m_histogramMarkers.at(0).m_power : + CalcDb::dbPower(m_histogramMarkers.at(0).m_power); m_histogramMarkers.back().m_deltaPowerStr = displayScaledF( power - power0, m_linear ? 'e' : 'f', @@ -2434,10 +2564,35 @@ void GLSpectrum::mousePressEvent(QMouseEvent* event) update(); } } - else if (event->modifiers() & Qt::AltModifier) - { - frequencyPan(event); - } + else if (event->modifiers() & Qt::AltModifier) + { + frequencyPan(event); + } + + if ((m_markersDisplay == SpectrumSettings::MarkersDisplayAnnotations) && + (ep.y() <= m_histogramRect.top()*height() + m_annotationMarkerHeight + 2.0f)) + { + QPointF pHis; + pHis.rx() = (ep.x()/width() - m_histogramRect.left()) / m_histogramRect.width(); + qint64 selectedFrequency = m_frequencyScale.getRangeMin() + pHis.x() * m_frequencyScale.getRange(); + bool selected = false; + + for (auto iMarker = m_visibleAnnotationMarkers.rbegin(); iMarker != m_visibleAnnotationMarkers.rend(); ++iMarker) + { + qint64 stopFrequency = (*iMarker)->m_startFrequency + + ((*iMarker)->m_bandwidth == 0 ? m_frequencyScale.getRange()*0.01f : (*iMarker)->m_bandwidth); + + if (((*iMarker)->m_startFrequency < selectedFrequency) && (selectedFrequency <= stopFrequency) && !selected) + { + (*iMarker)->m_selected = true; + selected = true; + } + else + { + (*iMarker)->m_selected = false; + } + } + } if (m_cursorState == CSSplitter) { @@ -2452,9 +2607,11 @@ void GLSpectrum::mousePressEvent(QMouseEvent* event) return; } else if ((m_cursorState == CSNormal) && - (m_channelMarkerStates.size() == 1) && - !(event->modifiers() & Qt::ShiftModifier) && - !(event->modifiers() & Qt::AltModifier)) + (m_channelMarkerStates.size() == 1) && + !(event->modifiers() & Qt::ShiftModifier) && + !(event->modifiers() & Qt::AltModifier) && + !(event->modifiers() & Qt::ControlModifier) && + (ep.y() > m_histogramRect.top()*height() + m_annotationMarkerHeight + 2.0f)) // out of annotation selection zone { grabMouse(); setCursor(Qt::SizeHorCursor); @@ -2477,24 +2634,24 @@ void GLSpectrum::mousePressEvent(QMouseEvent* event) void GLSpectrum::mouseReleaseEvent(QMouseEvent*) { - if (m_cursorState == CSSplitterMoving) + if (m_cursorState == CSSplitterMoving) { - releaseMouse(); - m_cursorState = CSSplitter; - } + releaseMouse(); + m_cursorState = CSSplitter; + } else if (m_cursorState == CSChannelMoving) { - releaseMouse(); - m_cursorState = CSChannel; - } + releaseMouse(); + m_cursorState = CSChannel; + } } void GLSpectrum::wheelEvent(QWheelEvent *event) { if (event->modifiers() & Qt::ShiftModifier) { - channelMarkerMove(event, 100); + channelMarkerMove(event, 100); } else if (event->modifiers() & Qt::ControlModifier) { - channelMarkerMove(event, 10); + channelMarkerMove(event, 10); } else { channelMarkerMove(event, 1); } @@ -2503,169 +2660,169 @@ void GLSpectrum::wheelEvent(QWheelEvent *event) void GLSpectrum::zoom(QWheelEvent *event) { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - const QPointF& p = event->position(); + const QPointF& p = event->position(); #else - const QPointF& p = event->pos(); + const QPointF& p = event->pos(); #endif - float pwx = (p.x() - m_leftMargin) / (width() - m_leftMargin - m_rightMargin); // x position in window + float pwx = (p.x() - m_leftMargin) / (width() - m_leftMargin - m_rightMargin); // x position in window - if ((pwx >= 0.0f) && (pwx <= 1.0f)) - { - if (event->angleDelta().y() > 0) // zoom in - { - if (m_frequencyZoomFactor < m_maxFrequencyZoom) { - m_frequencyZoomFactor += 0.5f; - } else { - return; - } - } - else - { - if (m_frequencyZoomFactor > 1.0f) { - m_frequencyZoomFactor -= 0.5f; - } else { - return; - } - } + if ((pwx >= 0.0f) && (pwx <= 1.0f)) + { + if (event->angleDelta().y() > 0) // zoom in + { + if (m_frequencyZoomFactor < m_maxFrequencyZoom) { + m_frequencyZoomFactor += 0.5f; + } else { + return; + } + } + else + { + if (m_frequencyZoomFactor > 1.0f) { + m_frequencyZoomFactor -= 0.5f; + } else { + return; + } + } - frequencyZoom(pwx); - } - else - { - float pwyh, pwyw; + frequencyZoom(pwx); + } + else + { + float pwyh, pwyw; - if (m_invertedWaterfall) // histo on top - { - pwyh = (p.y() - m_topMargin) / m_histogramHeight; - pwyw = (p.y() - m_topMargin - m_histogramHeight - m_frequencyScaleHeight) / m_waterfallHeight; - } - else // waterfall on top - { - pwyw = (p.y() - m_topMargin) / m_waterfallHeight; - pwyh = (p.y() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight) / m_histogramHeight; - } + if (m_invertedWaterfall) // histo on top + { + pwyh = (p.y() - m_topMargin) / m_histogramHeight; + pwyw = (p.y() - m_topMargin - m_histogramHeight - m_frequencyScaleHeight) / m_waterfallHeight; + } + else // waterfall on top + { + pwyw = (p.y() - m_topMargin) / m_waterfallHeight; + pwyh = (p.y() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight) / m_histogramHeight; + } - //qDebug("GLSpectrum::zoom: pwyh: %f pwyw: %f", pwyh, pwyw); + //qDebug("GLSpectrum::zoom: pwyh: %f pwyw: %f", pwyh, pwyw); - if ((pwyw >= 0.0f) && (pwyw <= 1.0f)) { - timeZoom(event->angleDelta().y() > 0); - } + if ((pwyw >= 0.0f) && (pwyw <= 1.0f)) { + timeZoom(event->angleDelta().y() > 0); + } - if ((pwyh >= 0.0f) && (pwyh <= 1.0f) && !m_linear) { - powerZoom(pwyh, event->angleDelta().y() > 0); - } - } + if ((pwyh >= 0.0f) && (pwyh <= 1.0f) && !m_linear) { + powerZoom(pwyh, event->angleDelta().y() > 0); + } + } } void GLSpectrum::frequencyZoom(float pw) { - m_frequencyZoomPos += (pw - 0.5f) * (1.0f / m_frequencyZoomFactor); - float lim = 0.5f / m_frequencyZoomFactor; - m_frequencyZoomPos = m_frequencyZoomPos < lim ? lim : m_frequencyZoomPos > 1 - lim ? 1 - lim : m_frequencyZoomPos; + m_frequencyZoomPos += (pw - 0.5f) * (1.0f / m_frequencyZoomFactor); + float lim = 0.5f / m_frequencyZoomFactor; + m_frequencyZoomPos = m_frequencyZoomPos < lim ? lim : m_frequencyZoomPos > 1 - lim ? 1 - lim : m_frequencyZoomPos; - qDebug("GLSpectrum::frequencyZoom: pw: %f p: %f z: %f", pw, m_frequencyZoomPos, m_frequencyZoomFactor); - updateFFTLimits(); + qDebug("GLSpectrum::frequencyZoom: pw: %f p: %f z: %f", pw, m_frequencyZoomPos, m_frequencyZoomFactor); + updateFFTLimits(); } void GLSpectrum::frequencyPan(QMouseEvent *event) { - if (m_frequencyZoomFactor == 1.0f) { - return; - } + if (m_frequencyZoomFactor == 1.0f) { + return; + } - const QPointF& p = event->pos(); - float pw = (p.x() - m_leftMargin) / (width() - m_leftMargin - m_rightMargin); // position in window - pw = pw < 0.0f ? 0.0f : pw > 1.0f ? 1.0 : pw; - float dw = pw - 0.5f; - m_frequencyZoomPos += dw * (1.0f / m_frequencyZoomFactor); - float lim = 0.5f / m_frequencyZoomFactor; - m_frequencyZoomPos = m_frequencyZoomPos < lim ? lim : m_frequencyZoomPos > 1 - lim ? 1 - lim : m_frequencyZoomPos; + const QPointF& p = event->pos(); + float pw = (p.x() - m_leftMargin) / (width() - m_leftMargin - m_rightMargin); // position in window + pw = pw < 0.0f ? 0.0f : pw > 1.0f ? 1.0 : pw; + float dw = pw - 0.5f; + m_frequencyZoomPos += dw * (1.0f / m_frequencyZoomFactor); + float lim = 0.5f / m_frequencyZoomFactor; + m_frequencyZoomPos = m_frequencyZoomPos < lim ? lim : m_frequencyZoomPos > 1 - lim ? 1 - lim : m_frequencyZoomPos; - qDebug("GLSpectrum::frequencyPan: pw: %f p: %f", pw, m_frequencyZoomPos); - updateFFTLimits(); + qDebug("GLSpectrum::frequencyPan: pw: %f p: %f", pw, m_frequencyZoomPos); + updateFFTLimits(); } void GLSpectrum::timeZoom(bool zoomInElseOut) { - if ((m_fftOverlap == 0) && !zoomInElseOut) { - return; - } + if ((m_fftOverlap == 0) && !zoomInElseOut) { + return; + } - if (zoomInElseOut && (m_fftOverlap == m_fftSize/2 - 1)) { - return; - } + if (zoomInElseOut && (m_fftOverlap == m_fftSize/2 - 1)) { + return; + } - m_fftOverlap = m_fftOverlap + (zoomInElseOut ? 1 : -1); - m_changesPending = true; + m_fftOverlap = m_fftOverlap + (zoomInElseOut ? 1 : -1); + m_changesPending = true; - if (m_messageQueueToGUI) - { - MsgReportFFTOverlap *msg = new MsgReportFFTOverlap(m_fftOverlap); - m_messageQueueToGUI->push(msg); - } + if (m_messageQueueToGUI) + { + MsgReportFFTOverlap *msg = new MsgReportFFTOverlap(m_fftOverlap); + m_messageQueueToGUI->push(msg); + } } void GLSpectrum::powerZoom(float pw, bool zoomInElseOut) { - m_powerRange = m_powerRange + (zoomInElseOut ? -2 : 2); + m_powerRange = m_powerRange + (zoomInElseOut ? -2 : 2); - if (pw > 2.0/3.0) { // bottom - m_referenceLevel = m_referenceLevel + (zoomInElseOut ? -2 : 2); - } else if (pw > 1.0/3.0) { // middle - m_referenceLevel = m_referenceLevel + (zoomInElseOut ? -1 : 1); - } // top + if (pw > 2.0/3.0) { // bottom + m_referenceLevel = m_referenceLevel + (zoomInElseOut ? -2 : 2); + } else if (pw > 1.0/3.0) { // middle + m_referenceLevel = m_referenceLevel + (zoomInElseOut ? -1 : 1); + } // top - m_powerRange = m_powerRange < 1 ? 1 : m_powerRange > 100 ? 100 : m_powerRange; - m_referenceLevel = m_referenceLevel < -110 ? -110 : m_referenceLevel > 0 ? 0 : m_referenceLevel; - m_changesPending = true; + m_powerRange = m_powerRange < 1 ? 1 : m_powerRange > 100 ? 100 : m_powerRange; + m_referenceLevel = m_referenceLevel < -110 ? -110 : m_referenceLevel > 0 ? 0 : m_referenceLevel; + m_changesPending = true; - if (m_messageQueueToGUI) - { - MsgReportPowerScale *msg = new MsgReportPowerScale(m_referenceLevel, m_powerRange); - m_messageQueueToGUI->push(msg); - } + if (m_messageQueueToGUI) + { + MsgReportPowerScale *msg = new MsgReportPowerScale(m_referenceLevel, m_powerRange); + m_messageQueueToGUI->push(msg); + } } void GLSpectrum::resetFrequencyZoom() { - m_frequencyZoomFactor = 1.0f; - m_frequencyZoomPos = 0.5f; + m_frequencyZoomFactor = 1.0f; + m_frequencyZoomPos = 0.5f; - updateFFTLimits(); + updateFFTLimits(); } void GLSpectrum::updateFFTLimits() { - if (!m_spectrumVis) { - return; - } + if (!m_spectrumVis) { + return; + } - SpectrumVis::MsgFrequencyZooming *msg = SpectrumVis::MsgFrequencyZooming::create( - m_frequencyZoomFactor, m_frequencyZoomPos - ); + SpectrumVis::MsgFrequencyZooming *msg = SpectrumVis::MsgFrequencyZooming::create( + m_frequencyZoomFactor, m_frequencyZoomPos + ); - m_spectrumVis->getInputMessageQueue()->push(msg); - m_changesPending = true; + m_spectrumVis->getInputMessageQueue()->push(msg); + m_changesPending = true; } void GLSpectrum::setFrequencyScale() { - int frequencySpan; - int64_t centerFrequency; + int frequencySpan; + int64_t centerFrequency; - getFrequencyZoom(centerFrequency, frequencySpan); - m_frequencyScale.setSize(width() - m_leftMargin - m_rightMargin); - m_frequencyScale.setRange(Unit::Frequency, centerFrequency - frequencySpan / 2.0, centerFrequency + frequencySpan / 2.0); - m_frequencyScale.setMakeOpposite(m_lsbDisplay); + getFrequencyZoom(centerFrequency, frequencySpan); + m_frequencyScale.setSize(width() - m_leftMargin - m_rightMargin); + m_frequencyScale.setRange(Unit::Frequency, centerFrequency - frequencySpan / 2.0, centerFrequency + frequencySpan / 2.0); + m_frequencyScale.setMakeOpposite(m_lsbDisplay); } void GLSpectrum::getFrequencyZoom(int64_t& centerFrequency, int& frequencySpan) { - frequencySpan = (m_frequencyZoomFactor == 1) ? - m_sampleRate : m_sampleRate * (1.0 / m_frequencyZoomFactor); - centerFrequency = (m_frequencyZoomFactor == 1) ? - m_centerFrequency : (m_frequencyZoomPos - 0.5) * m_sampleRate + m_centerFrequency; + frequencySpan = (m_frequencyZoomFactor == 1) ? + m_sampleRate : m_sampleRate * (1.0 / m_frequencyZoomFactor); + centerFrequency = (m_frequencyZoomFactor == 1) ? + m_centerFrequency : (m_frequencyZoomPos - 0.5) * m_sampleRate + m_centerFrequency; } // void GLSpectrum::updateFFTLimits() @@ -2713,46 +2870,46 @@ void GLSpectrum::channelMarkerMove(QWheelEvent *event, int mul) setCursor(c); } - return; + return; } } - zoom(event); + zoom(event); } void GLSpectrum::enterEvent(QEvent* event) { - m_mouseInside = true; - update(); - QGLWidget::enterEvent(event); + m_mouseInside = true; + update(); + QGLWidget::enterEvent(event); } void GLSpectrum::leaveEvent(QEvent* event) { - m_mouseInside = false; - update(); - QGLWidget::enterEvent(event); + m_mouseInside = false; + update(); + QGLWidget::enterEvent(event); } void GLSpectrum::tick() { - if (m_displayChanged) + if (m_displayChanged) { - m_displayChanged = false; - update(); - } + m_displayChanged = false; + update(); + } } void GLSpectrum::channelMarkerChanged() { QMutexLocker mutexLocker(&m_mutex); - m_changesPending = true; - update(); + m_changesPending = true; + update(); } void GLSpectrum::channelMarkerDestroyed(QObject* object) { - removeChannelMarker((ChannelMarker*)object); + removeChannelMarker((ChannelMarker*)object); } void GLSpectrum::setWaterfallShare(Real waterfallShare) @@ -2760,42 +2917,42 @@ void GLSpectrum::setWaterfallShare(Real waterfallShare) QMutexLocker mutexLocker(&m_mutex); if (waterfallShare < 0.1f) { - m_waterfallShare = 0.1f; - } else if (waterfallShare > 0.8f) { - m_waterfallShare = 0.8f; - } else { - m_waterfallShare = waterfallShare; - } + m_waterfallShare = 0.1f; + } else if (waterfallShare > 0.8f) { + m_waterfallShare = 0.8f; + } else { + m_waterfallShare = waterfallShare; + } m_changesPending = true; } void GLSpectrum::setFPSPeriodMs(int fpsPeriodMs) { - if (fpsPeriodMs == 0) - { - disconnect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); - m_timer.stop(); - } - else - { - connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); - m_timer.start(fpsPeriodMs); - } + if (fpsPeriodMs == 0) + { + disconnect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); + m_timer.stop(); + } + else + { + connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); + m_timer.start(fpsPeriodMs); + } - m_fpsPeriodMs = fpsPeriodMs; + m_fpsPeriodMs = fpsPeriodMs; } void GLSpectrum::cleanup() { - //makeCurrent(); - m_glShaderSimple.cleanup(); - m_glShaderFrequencyScale.cleanup(); - m_glShaderHistogram.cleanup(); - m_glShaderLeftScale.cleanup(); - m_glShaderWaterfall.cleanup(); + //makeCurrent(); + m_glShaderSimple.cleanup(); + m_glShaderFrequencyScale.cleanup(); + m_glShaderHistogram.cleanup(); + m_glShaderLeftScale.cleanup(); + m_glShaderWaterfall.cleanup(); m_glShaderTextOverlay.cleanup(); - m_glShaderInfo.cleanup(); + m_glShaderInfo.cleanup(); //doneCurrent(); } @@ -2929,20 +3086,20 @@ void GLSpectrum::drawTextOverlay( void GLSpectrum::formatTextInfo(QString& info) { - if (m_frequencyZoomFactor != 1.0f) { - info.append(tr("%1x ").arg(QString::number(m_frequencyZoomFactor, 'f', 1))); - } + if (m_frequencyZoomFactor != 1.0f) { + info.append(tr("%1x ").arg(QString::number(m_frequencyZoomFactor, 'f', 1))); + } - if (m_sampleRate == 0) - { - info.append(tr("CF:%1 SP:%2").arg(m_centerFrequency).arg(m_sampleRate)); - } - else - { - int64_t centerFrequency; - int frequencySpan; - getFrequencyZoom(centerFrequency, frequencySpan); - info.append(tr("CF:%1 ").arg(displayScaled(centerFrequency, 'f', getPrecision(centerFrequency/frequencySpan), true))); - info.append(tr("SP:%1 ").arg(displayScaled(frequencySpan, 'f', 3, true))); - } + if (m_sampleRate == 0) + { + info.append(tr("CF:%1 SP:%2").arg(m_centerFrequency).arg(m_sampleRate)); + } + else + { + int64_t centerFrequency; + int frequencySpan; + getFrequencyZoom(centerFrequency, frequencySpan); + info.append(tr("CF:%1 ").arg(displayScaled(centerFrequency, 'f', getPrecision(centerFrequency/frequencySpan), true))); + info.append(tr("SP:%1 ").arg(displayScaled(frequencySpan, 'f', 3, true))); + } } diff --git a/sdrgui/gui/glspectrum.h b/sdrgui/gui/glspectrum.h index cde2cd2d6..0c86ed143 100644 --- a/sdrgui/gui/glspectrum.h +++ b/sdrgui/gui/glspectrum.h @@ -44,7 +44,7 @@ class MessageQueue; class SpectrumVis; class SDRGUI_API GLSpectrum : public QGLWidget, public GLSpectrumInterface { - Q_OBJECT + Q_OBJECT public: class MsgReportSampleRate : public Message { @@ -110,43 +110,43 @@ public: Real m_range; }; - GLSpectrum(QWidget* parent = nullptr); - virtual ~GLSpectrum(); + GLSpectrum(QWidget* parent = nullptr); + virtual ~GLSpectrum(); - void setCenterFrequency(qint64 frequency); + void setCenterFrequency(qint64 frequency); qint64 getCenterFrequency() const { return m_centerFrequency; } float getPowerMax() const; float getTimeMax() const; - void setSampleRate(qint32 sampleRate); - void setTimingRate(qint32 timingRate); + void setSampleRate(qint32 sampleRate); + void setTimingRate(qint32 timingRate); void setFFTOverlap(int overlap); - void setReferenceLevel(Real referenceLevel); - void setPowerRange(Real powerRange); - void setDecay(int decay); - void setDecayDivisor(int decayDivisor); - void setHistoStroke(int stroke); - void setDisplayWaterfall(bool display); - void setSsbSpectrum(bool ssbSpectrum); - void setLsbDisplay(bool lsbDisplay); - void setInvertedWaterfall(bool inv); - void setDisplayMaxHold(bool display); - void setDisplayCurrent(bool display); - void setDisplayHistogram(bool display); - void setDisplayGrid(bool display); - void setDisplayGridIntensity(int intensity); - void setDisplayTraceIntensity(int intensity); - void setLinear(bool linear); - qint32 getSampleRate() const { return m_sampleRate; } + void setReferenceLevel(Real referenceLevel); + void setPowerRange(Real powerRange); + void setDecay(int decay); + void setDecayDivisor(int decayDivisor); + void setHistoStroke(int stroke); + void setDisplayWaterfall(bool display); + void setSsbSpectrum(bool ssbSpectrum); + void setLsbDisplay(bool lsbDisplay); + void setInvertedWaterfall(bool inv); + void setDisplayMaxHold(bool display); + void setDisplayCurrent(bool display); + void setDisplayHistogram(bool display); + void setDisplayGrid(bool display); + void setDisplayGridIntensity(int intensity); + void setDisplayTraceIntensity(int intensity); + void setLinear(bool linear); + qint32 getSampleRate() const { return m_sampleRate; } - void addChannelMarker(ChannelMarker* channelMarker); - void removeChannelMarker(ChannelMarker* channelMarker); - void setMessageQueueToGUI(MessageQueue* messageQueue) { m_messageQueueToGUI = messageQueue; } + void addChannelMarker(ChannelMarker* channelMarker); + void removeChannelMarker(ChannelMarker* channelMarker); + void setMessageQueueToGUI(MessageQueue* messageQueue) { m_messageQueueToGUI = messageQueue; } - virtual void newSpectrum(const Real* spectrum, int nbBins, int fftSize); - void clearSpectrumHistogram(); + virtual void newSpectrum(const Real* spectrum, int nbBins, int fftSize); + void clearSpectrumHistogram(); - Real getWaterfallShare() const { return m_waterfallShare; } - void setWaterfallShare(Real waterfallShare); + Real getWaterfallShare() const { return m_waterfallShare; } + void setWaterfallShare(Real waterfallShare); void setFPSPeriodMs(int fpsPeriodMs); void setDisplayedStream(bool sourceOrSink, int streamIndex) @@ -161,72 +161,80 @@ public: const QList& getWaterfallMarkers() const { return m_waterfallMarkers; } QList& getWaterfallMarkers() { return m_waterfallMarkers; } void setWaterfallMarkers(const QList& waterfallMarkers); + const QList& getAnnotationMarkers() const { return m_annotationMarkers; } + QList& getAnnotationMarkers() { return m_annotationMarkers; } + void setAnnotationMarkers(const QList& annotationMarkers); void updateHistogramMarkers(); void updateWaterfallMarkers(); + void updateAnnotationMarkers(); + void updateMarkersDisplay(); SpectrumSettings::MarkersDisplay& getMarkersDisplay() { return m_markersDisplay; } private: - struct ChannelMarkerState { - ChannelMarker* m_channelMarker; - QMatrix4x4 m_glMatrixWaterfall; - QMatrix4x4 m_glMatrixDsbWaterfall; - QMatrix4x4 m_glMatrixFreqScale; - QMatrix4x4 m_glMatrixDsbFreqScale; - QMatrix4x4 m_glMatrixHistogram; - QMatrix4x4 m_glMatrixDsbHistogram; - QRect m_rect; + struct ChannelMarkerState { + ChannelMarker* m_channelMarker; + QMatrix4x4 m_glMatrixWaterfall; + QMatrix4x4 m_glMatrixDsbWaterfall; + QMatrix4x4 m_glMatrixFreqScale; + QMatrix4x4 m_glMatrixDsbFreqScale; + QMatrix4x4 m_glMatrixHistogram; + QMatrix4x4 m_glMatrixDsbHistogram; + QRect m_rect; - ChannelMarkerState(ChannelMarker* channelMarker) : - m_channelMarker(channelMarker) - { } - }; - QList m_channelMarkerStates; + ChannelMarkerState(ChannelMarker* channelMarker) : + m_channelMarker(channelMarker) + { } + }; + QList m_channelMarkerStates; - enum CursorState { - CSNormal, - CSSplitter, - CSSplitterMoving, - CSChannel, - CSChannelMoving - }; + enum CursorState { + CSNormal, + CSSplitter, + CSSplitterMoving, + CSChannel, + CSChannelMoving + }; QList m_histogramMarkers; QList m_waterfallMarkers; + QList m_annotationMarkers; + QList m_sortedAnnotationMarkers; + QList m_visibleAnnotationMarkers; SpectrumSettings::MarkersDisplay m_markersDisplay; - CursorState m_cursorState; - int m_cursorChannel; + CursorState m_cursorState; + int m_cursorChannel; SpectrumVis* m_spectrumVis; - QTimer m_timer; + QTimer m_timer; int m_fpsPeriodMs; - QMutex m_mutex; - bool m_mouseInside; - bool m_changesPending; + QMutex m_mutex; + bool m_mouseInside; + bool m_changesPending; - qint64 m_centerFrequency; - Real m_referenceLevel; - Real m_powerRange; - bool m_linear; - int m_decay; - quint32 m_sampleRate; - quint32 m_timingRate; + qint64 m_centerFrequency; + Real m_referenceLevel; + Real m_powerRange; + bool m_linear; + int m_decay; + quint32 m_sampleRate; + quint32 m_timingRate; int m_fftOverlap; - int m_fftSize; //!< FFT size in number of bins + int m_fftSize; //!< FFT size in number of bins int m_nbBins; //!< Number of visible FFT bins (zoom support) - bool m_displayGrid; - int m_displayGridIntensity; - int m_displayTraceIntensity; - bool m_invertedWaterfall; + bool m_displayGrid; + int m_displayGridIntensity; + int m_displayTraceIntensity; + bool m_invertedWaterfall; - std::vector m_maxHold; - bool m_displayMaxHold; - const Real *m_currentSpectrum; - bool m_displayCurrent; + std::vector m_maxHold; + bool m_displayMaxHold; + const Real *m_currentSpectrum; + bool m_displayCurrent; - Real m_waterfallShare; + Real m_waterfallShare; int m_leftMargin; int m_rightMargin; @@ -237,76 +245,78 @@ private: int m_waterfallHeight; int m_bottomMargin; QFont m_textOverlayFont; - QPixmap m_leftMarginPixmap; - QPixmap m_frequencyPixmap; + QPixmap m_leftMarginPixmap; + QPixmap m_frequencyPixmap; QPixmap m_infoPixmap; - ScaleEngine m_timeScale; - ScaleEngine m_powerScale; - ScaleEngine m_frequencyScale; + ScaleEngine m_timeScale; + ScaleEngine m_powerScale; + ScaleEngine m_frequencyScale; QRectF m_histogramRect; - QRect m_frequencyScaleRect; + QRect m_frequencyScaleRect; QRectF m_waterfallRect; QRect m_infoRect; - QMatrix4x4 m_glFrequencyScaleBoxMatrix; - QMatrix4x4 m_glLeftScaleBoxMatrix; + QMatrix4x4 m_glFrequencyScaleBoxMatrix; + QMatrix4x4 m_glLeftScaleBoxMatrix; QMatrix4x4 m_glInfoBoxMatrix; - QRgb m_waterfallPalette[240]; - QImage* m_waterfallBuffer; - int m_waterfallBufferPos; - int m_waterfallTextureHeight; - int m_waterfallTexturePos; - QMatrix4x4 m_glWaterfallBoxMatrix; - bool m_displayWaterfall; - bool m_ssbSpectrum; - bool m_lsbDisplay; + QRgb m_waterfallPalette[240]; + QImage* m_waterfallBuffer; + int m_waterfallBufferPos; + int m_waterfallTextureHeight; + int m_waterfallTexturePos; + QMatrix4x4 m_glWaterfallBoxMatrix; + bool m_displayWaterfall; + bool m_ssbSpectrum; + bool m_lsbDisplay; - QRgb m_histogramPalette[240]; - QImage* m_histogramBuffer; - quint8* m_histogram; //!< Spectrum phosphor matrix of FFT width and PSD height scaled to 100. values [0..239] - int m_decayDivisor; - int m_decayDivisorCount; - int m_histogramStroke; - QMatrix4x4 m_glHistogramSpectrumMatrix; - QMatrix4x4 m_glHistogramBoxMatrix; - bool m_displayHistogram; - bool m_displayChanged; + QRgb m_histogramPalette[240]; + QImage* m_histogramBuffer; + quint8* m_histogram; //!< Spectrum phosphor matrix of FFT width and PSD height scaled to 100. values [0..239] + int m_decayDivisor; + int m_decayDivisorCount; + int m_histogramStroke; + QMatrix4x4 m_glHistogramSpectrumMatrix; + QMatrix4x4 m_glHistogramBoxMatrix; + bool m_displayHistogram; + bool m_displayChanged; bool m_displaySourceOrSink; int m_displayStreamIndex; float m_frequencyZoomFactor; float m_frequencyZoomPos; static const float m_maxFrequencyZoom; + static const float m_annotationMarkerHeight; - GLShaderSimple m_glShaderSimple; - GLShaderTextured m_glShaderLeftScale; - GLShaderTextured m_glShaderFrequencyScale; - GLShaderTextured m_glShaderWaterfall; - GLShaderTextured m_glShaderHistogram; + GLShaderSimple m_glShaderSimple; + GLShaderTextured m_glShaderLeftScale; + GLShaderTextured m_glShaderFrequencyScale; + GLShaderTextured m_glShaderWaterfall; + GLShaderTextured m_glShaderHistogram; GLShaderTextured m_glShaderTextOverlay; GLShaderTextured m_glShaderInfo; - int m_matrixLoc; - int m_colorLoc; - IncrementalArray m_q3TickTime; - IncrementalArray m_q3TickFrequency; - IncrementalArray m_q3TickPower; - IncrementalArray m_q3FFT; + int m_matrixLoc; + int m_colorLoc; + IncrementalArray m_q3TickTime; + IncrementalArray m_q3TickFrequency; + IncrementalArray m_q3TickPower; + IncrementalArray m_q3FFT; - MessageQueue *m_messageQueueToGUI; + MessageQueue *m_messageQueueToGUI; - void updateWaterfall(const Real *spectrum); - void updateHistogram(const Real *spectrum); + void updateWaterfall(const Real *spectrum); + void updateHistogram(const Real *spectrum); - void initializeGL(); - void resizeGL(int width, int height); - void paintGL(); + void initializeGL(); + void resizeGL(int width, int height); + void paintGL(); void drawSpectrumMarkers(); + void drawAnnotationMarkers(); - void stopDrag(); - void applyChanges(); + void stopDrag(); + void applyChanges(); - void mouseMoveEvent(QMouseEvent* event); - void mousePressEvent(QMouseEvent* event); - void mouseReleaseEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); void wheelEvent(QWheelEvent*); void channelMarkerMove(QWheelEvent*, int mul); void zoom(QWheelEvent*); @@ -319,8 +329,8 @@ private: void setFrequencyScale(); void getFrequencyZoom(int64_t& centerFrequency, int& frequencySpan); - void enterEvent(QEvent* event); - void leaveEvent(QEvent* event); + void enterEvent(QEvent* event); + void leaveEvent(QEvent* event); QString displayScaled(int64_t value, char type, int precision, bool showMult); QString displayScaledF(float value, char type, int precision, bool showMult); @@ -335,12 +345,22 @@ private: bool topHalf, const QRectF& glRect); void formatTextInfo(QString& info); + void updateSortedAnnotationMarkers(); + + static bool annotationDisplayLessThan(const SpectrumAnnotationMarker *m1, const SpectrumAnnotationMarker *m2) + { + if (m1->m_bandwidth == m2->m_bandwidth) { + return m1->m_startFrequency < m2->m_startFrequency; + } else { + return m1->m_bandwidth > m2->m_bandwidth; // larger bandwidths should come first for display (lower layer) + } + } private slots: - void cleanup(); - void tick(); - void channelMarkerChanged(); - void channelMarkerDestroyed(QObject* object); + void cleanup(); + void tick(); + void channelMarkerChanged(); + void channelMarkerDestroyed(QObject* object); }; #endif // INCLUDE_GLSPECTRUM_H diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp index 022f19f6a..3ec720391 100644 --- a/sdrgui/gui/glspectrumgui.cpp +++ b/sdrgui/gui/glspectrumgui.cpp @@ -36,14 +36,14 @@ const int GLSpectrumGUI::m_fpsMs[] = {500, 200, 100, 50, 20, 10, 5}; GLSpectrumGUI::GLSpectrumGUI(QWidget* parent) : - QWidget(parent), - ui(new Ui::GLSpectrumGUI), - m_spectrumVis(nullptr), - m_glSpectrum(nullptr), + QWidget(parent), + ui(new Ui::GLSpectrumGUI), + m_spectrumVis(nullptr), + m_glSpectrum(nullptr), m_doApplySettings(true) { - ui->setupUi(this); - on_linscale_toggled(false); + ui->setupUi(this); + on_linscale_toggled(false); QString levelStyle = QString( "QSpinBox {background-color: rgb(79, 79, 79);}" @@ -59,27 +59,27 @@ GLSpectrumGUI::GLSpectrumGUI(QWidget* parent) : // ui->levelRange->findChild()->setStyleSheet("color: white; background-color: rgb(79, 79, 79); border: 1px solid gray; border-radius: 4px;"); // ui->levelRange->setStyleSheet("background-color: rgb(79, 79, 79);"); - connect(&m_messageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + connect(&m_messageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); CRightClickEnabler *wsSpectrumRightClickEnabler = new CRightClickEnabler(ui->wsSpectrum); connect(wsSpectrumRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openWebsocketSpectrumSettingsDialog(const QPoint &))); displaySettings(); - setAveragingCombo(); + setAveragingCombo(); applySettings(); } GLSpectrumGUI::~GLSpectrumGUI() { - delete ui; + delete ui; } void GLSpectrumGUI::setBuddies(SpectrumVis* spectrumVis, GLSpectrum* glSpectrum) { - m_spectrumVis = spectrumVis; - m_glSpectrum = glSpectrum; + m_spectrumVis = spectrumVis; + m_glSpectrum = glSpectrum; m_glSpectrum->setSpectrumVis(spectrumVis); - m_glSpectrum->setMessageQueueToGUI(&m_messageQueue); + m_glSpectrum->setMessageQueueToGUI(&m_messageQueue); m_spectrumVis->setMessageQueueToGUI(&m_messageQueue); } @@ -87,7 +87,7 @@ void GLSpectrumGUI::resetToDefaults() { m_settings.resetToDefaults(); displaySettings(); - applySettings(); + applySettings(); } QByteArray GLSpectrumGUI::serialize() const @@ -134,40 +134,40 @@ void GLSpectrumGUI::updateSettings() void GLSpectrumGUI::displaySettings() { blockApplySettings(true); - ui->refLevel->setValue(m_settings.m_refLevel); - ui->levelRange->setValue(m_settings.m_powerRange); - ui->decay->setSliderPosition(m_settings.m_decay); - ui->decayDivisor->setSliderPosition(m_settings.m_decayDivisor); - ui->stroke->setSliderPosition(m_settings.m_histogramStroke); - ui->waterfall->setChecked(m_settings.m_displayWaterfall); - ui->maxHold->setChecked(m_settings.m_displayMaxHold); - ui->current->setChecked(m_settings.m_displayCurrent); - ui->histogram->setChecked(m_settings.m_displayHistogram); - ui->invertWaterfall->setChecked(m_settings.m_invertedWaterfall); - ui->grid->setChecked(m_settings.m_displayGrid); - ui->gridIntensity->setSliderPosition(m_settings.m_displayGridIntensity); + ui->refLevel->setValue(m_settings.m_refLevel); + ui->levelRange->setValue(m_settings.m_powerRange); + ui->decay->setSliderPosition(m_settings.m_decay); + ui->decayDivisor->setSliderPosition(m_settings.m_decayDivisor); + ui->stroke->setSliderPosition(m_settings.m_histogramStroke); + ui->waterfall->setChecked(m_settings.m_displayWaterfall); + ui->maxHold->setChecked(m_settings.m_displayMaxHold); + ui->current->setChecked(m_settings.m_displayCurrent); + ui->histogram->setChecked(m_settings.m_displayHistogram); + ui->invertWaterfall->setChecked(m_settings.m_invertedWaterfall); + ui->grid->setChecked(m_settings.m_displayGrid); + ui->gridIntensity->setSliderPosition(m_settings.m_displayGridIntensity); - ui->decay->setToolTip(QString("Decay: %1").arg(m_settings.m_decay)); - ui->decayDivisor->setToolTip(QString("Decay divisor: %1").arg(m_settings.m_decayDivisor)); - ui->stroke->setToolTip(QString("Stroke: %1").arg(m_settings.m_histogramStroke)); - ui->gridIntensity->setToolTip(QString("Grid intensity: %1").arg(m_settings.m_displayGridIntensity)); - ui->traceIntensity->setToolTip(QString("Trace intensity: %1").arg(m_settings.m_displayTraceIntensity)); + ui->decay->setToolTip(QString("Decay: %1").arg(m_settings.m_decay)); + ui->decayDivisor->setToolTip(QString("Decay divisor: %1").arg(m_settings.m_decayDivisor)); + ui->stroke->setToolTip(QString("Stroke: %1").arg(m_settings.m_histogramStroke)); + ui->gridIntensity->setToolTip(QString("Grid intensity: %1").arg(m_settings.m_displayGridIntensity)); + ui->traceIntensity->setToolTip(QString("Trace intensity: %1").arg(m_settings.m_displayTraceIntensity)); - ui->fftWindow->blockSignals(true); - ui->averaging->blockSignals(true); - ui->averagingMode->blockSignals(true); - ui->linscale->blockSignals(true); + ui->fftWindow->blockSignals(true); + ui->averaging->blockSignals(true); + ui->averagingMode->blockSignals(true); + ui->linscale->blockSignals(true); - ui->fftWindow->setCurrentIndex(m_settings.m_fftWindow); + ui->fftWindow->setCurrentIndex(m_settings.m_fftWindow); - for (int i = SpectrumSettings::m_log2FFTSizeMin; i <= SpectrumSettings::m_log2FFTSizeMax; i++) - { - if (m_settings.m_fftSize == (1 << i)) - { - ui->fftSize->setCurrentIndex(i - SpectrumSettings::m_log2FFTSizeMin); - break; - } - } + for (int i = SpectrumSettings::m_log2FFTSizeMin; i <= SpectrumSettings::m_log2FFTSizeMax; i++) + { + if (m_settings.m_fftSize == (1 << i)) + { + ui->fftSize->setCurrentIndex(i - SpectrumSettings::m_log2FFTSizeMin); + break; + } + } setFFTSizeToolitp(); unsigned int i = 0; @@ -183,15 +183,15 @@ void GLSpectrumGUI::displaySettings() ui->fftOverlap->setValue(m_settings.m_fftOverlap); setMaximumOverlap(); - ui->averaging->setCurrentIndex(m_settings.m_averagingIndex); - ui->averagingMode->setCurrentIndex((int) m_settings.m_averagingMode); - ui->linscale->setChecked(m_settings.m_linear); - setAveragingToolitp(); + ui->averaging->setCurrentIndex(m_settings.m_averagingIndex); + ui->averagingMode->setCurrentIndex((int) m_settings.m_averagingMode); + ui->linscale->setChecked(m_settings.m_linear); + setAveragingToolitp(); - ui->fftWindow->blockSignals(false); - ui->averaging->blockSignals(false); - ui->averagingMode->blockSignals(false); - ui->linscale->blockSignals(false); + ui->fftWindow->blockSignals(false); + ui->averaging->blockSignals(false); + ui->averagingMode->blockSignals(false); + ui->linscale->blockSignals(false); blockApplySettings(false); } @@ -250,23 +250,24 @@ void GLSpectrumGUI::applySpectrumSettings() m_glSpectrum->setHistogramMarkers(m_settings.m_histogramMarkers); m_glSpectrum->setWaterfallMarkers(m_settings.m_waterfallMarkers); + m_glSpectrum->setAnnotationMarkers(m_settings.m_annoationMarkers); } void GLSpectrumGUI::on_fftWindow_currentIndexChanged(int index) { - qDebug("GLSpectrumGUI::on_fftWindow_currentIndexChanged: %d", index); - m_settings.m_fftWindow = (FFTWindow::Function) index; - applySettings(); + qDebug("GLSpectrumGUI::on_fftWindow_currentIndexChanged: %d", index); + m_settings.m_fftWindow = (FFTWindow::Function) index; + applySettings(); } void GLSpectrumGUI::on_fftSize_currentIndexChanged(int index) { - qDebug("GLSpectrumGUI::on_fftSize_currentIndexChanged: %d", index); - m_settings.m_fftSize = 1 << (SpectrumSettings::m_log2FFTSizeMin + index); + qDebug("GLSpectrumGUI::on_fftSize_currentIndexChanged: %d", index); + m_settings.m_fftSize = 1 << (SpectrumSettings::m_log2FFTSizeMin + index); setAveragingCombo(); setMaximumOverlap(); - applySettings(); - setAveragingToolitp(); + applySettings(); + setAveragingToolitp(); setFFTSizeToolitp(); } @@ -309,8 +310,8 @@ void GLSpectrumGUI::on_autoscale_clicked(bool checked) m_settings.m_refLevel = maxLvl; m_settings.m_powerRange = maxLvl - minLvl; - ui->refLevel->setValue(m_settings.m_refLevel); - ui->levelRange->setValue(m_settings.m_powerRange); + ui->refLevel->setValue(m_settings.m_refLevel); + ui->levelRange->setValue(m_settings.m_powerRange); // qDebug("GLSpectrumGUI::on_autoscale_clicked: max: %d min %d max: %e min: %e", // maxLvl, minLvl, maxAvg, minAvg); @@ -319,7 +320,7 @@ void GLSpectrumGUI::on_autoscale_clicked(bool checked) void GLSpectrumGUI::on_averagingMode_currentIndexChanged(int index) { - qDebug("GLSpectrumGUI::on_averagingMode_currentIndexChanged: %d", index); + qDebug("GLSpectrumGUI::on_averagingMode_currentIndexChanged: %d", index); m_settings.m_averagingMode = index < 0 ? SpectrumSettings::AvgModeNone : index > 3 ? @@ -327,23 +328,23 @@ void GLSpectrumGUI::on_averagingMode_currentIndexChanged(int index) (SpectrumSettings::AveragingMode) index; setAveragingCombo(); - applySettings(); + applySettings(); setAveragingToolitp(); } void GLSpectrumGUI::on_averaging_currentIndexChanged(int index) { - qDebug("GLSpectrumGUI::on_averaging_currentIndexChanged: %d", index); + qDebug("GLSpectrumGUI::on_averaging_currentIndexChanged: %d", index); m_settings.m_averagingIndex = index; - applySettings(); + applySettings(); setAveragingToolitp(); } void GLSpectrumGUI::on_linscale_toggled(bool checked) { - qDebug("GLSpectrumGUI::on_averaging_currentIndexChanged: %s", checked ? "lin" : "log"); + qDebug("GLSpectrumGUI::on_averaging_currentIndexChanged: %s", checked ? "lin" : "log"); m_settings.m_linear = checked; - applySettings(); + applySettings(); } void GLSpectrumGUI::on_wsSpectrum_toggled(bool checked) @@ -366,6 +367,7 @@ void GLSpectrumGUI::on_markers_clicked(bool checked) SpectrumMarkersDialog markersDialog( m_glSpectrum->getHistogramMarkers(), m_glSpectrum->getWaterfallMarkers(), + m_glSpectrum->getAnnotationMarkers(), m_glSpectrum->getMarkersDisplay(), this ); @@ -376,24 +378,27 @@ void GLSpectrumGUI::on_markers_clicked(bool checked) connect(&markersDialog, SIGNAL(updateHistogram()), this, SLOT(updateHistogramMarkers())); connect(&markersDialog, SIGNAL(updateWaterfall()), this, SLOT(updateWaterfallMarkers())); + connect(&markersDialog, SIGNAL(updateAnnotations()), this, SLOT(updateAnnotationMarkers())); + connect(&markersDialog, SIGNAL(updateMarkersDisplay()), this, SLOT(updateMarkersDisplay())); markersDialog.exec(); m_settings.m_histogramMarkers = m_glSpectrum->getHistogramMarkers(); m_settings.m_waterfallMarkers = m_glSpectrum->getWaterfallMarkers(); + m_settings.m_annoationMarkers = m_glSpectrum->getAnnotationMarkers(); applySettings(); } void GLSpectrumGUI::on_refLevel_valueChanged(int value) { - m_settings.m_refLevel = value; + m_settings.m_refLevel = value; applySettings(); } void GLSpectrumGUI::on_levelRange_valueChanged(int value) { - m_settings.m_powerRange = value; + m_settings.m_powerRange = value; applySettings(); } @@ -406,72 +411,72 @@ void GLSpectrumGUI::on_fps_currentIndexChanged(int index) void GLSpectrumGUI::on_decay_valueChanged(int index) { - m_settings.m_decay = index; - ui->decay->setToolTip(QString("Decay: %1").arg(m_settings.m_decay)); + m_settings.m_decay = index; + ui->decay->setToolTip(QString("Decay: %1").arg(m_settings.m_decay)); applySettings(); } void GLSpectrumGUI::on_decayDivisor_valueChanged(int index) { - m_settings.m_decayDivisor = index; - ui->decayDivisor->setToolTip(QString("Decay divisor: %1").arg(m_settings.m_decayDivisor)); + m_settings.m_decayDivisor = index; + ui->decayDivisor->setToolTip(QString("Decay divisor: %1").arg(m_settings.m_decayDivisor)); applySettings(); } void GLSpectrumGUI::on_stroke_valueChanged(int index) { - m_settings.m_histogramStroke = index; - ui->stroke->setToolTip(QString("Stroke: %1").arg(m_settings.m_histogramStroke)); + m_settings.m_histogramStroke = index; + ui->stroke->setToolTip(QString("Stroke: %1").arg(m_settings.m_histogramStroke)); applySettings(); } void GLSpectrumGUI::on_waterfall_toggled(bool checked) { - m_settings.m_displayWaterfall = checked; + m_settings.m_displayWaterfall = checked; applySettings(); } void GLSpectrumGUI::on_histogram_toggled(bool checked) { - m_settings.m_displayHistogram = checked; + m_settings.m_displayHistogram = checked; applySettings(); } void GLSpectrumGUI::on_maxHold_toggled(bool checked) { - m_settings.m_displayMaxHold = checked; + m_settings.m_displayMaxHold = checked; applySettings(); } void GLSpectrumGUI::on_current_toggled(bool checked) { - m_settings.m_displayCurrent = checked; + m_settings.m_displayCurrent = checked; applySettings(); } void GLSpectrumGUI::on_invertWaterfall_toggled(bool checked) { - m_settings.m_invertedWaterfall = checked; + m_settings.m_invertedWaterfall = checked; applySettings(); } void GLSpectrumGUI::on_grid_toggled(bool checked) { - m_settings.m_displayGrid = checked; + m_settings.m_displayGrid = checked; applySettings(); } void GLSpectrumGUI::on_gridIntensity_valueChanged(int index) { - m_settings.m_displayGridIntensity = index; - ui->gridIntensity->setToolTip(QString("Grid intensity: %1").arg(m_settings.m_displayGridIntensity)); + m_settings.m_displayGridIntensity = index; + ui->gridIntensity->setToolTip(QString("Grid intensity: %1").arg(m_settings.m_displayGridIntensity)); applySettings(); } void GLSpectrumGUI::on_traceIntensity_valueChanged(int index) { - m_settings.m_displayTraceIntensity = index; - ui->traceIntensity->setToolTip(QString("Trace intensity: %1").arg(m_settings.m_displayTraceIntensity)); + m_settings.m_displayTraceIntensity = index; + ui->traceIntensity->setToolTip(QString("Trace intensity: %1").arg(m_settings.m_displayTraceIntensity)); applySettings(); } @@ -479,9 +484,9 @@ void GLSpectrumGUI::on_clearSpectrum_clicked(bool checked) { (void) checked; - if (m_glSpectrum) { - m_glSpectrum->clearSpectrumHistogram(); - } + if (m_glSpectrum) { + m_glSpectrum->clearSpectrumHistogram(); + } } void GLSpectrumGUI::on_freeze_toggled(bool checked) @@ -493,7 +498,7 @@ void GLSpectrumGUI::on_freeze_toggled(bool checked) void GLSpectrumGUI::setAveragingCombo() { int index = ui->averaging->currentIndex(); - ui->averaging->blockSignals(true); + ui->averaging->blockSignals(true); ui->averaging->clear(); ui->averaging->addItem(QString("1")); uint64_t maxAveraging = SpectrumSettings::getMaxAveragingValue(m_settings.m_fftSize, m_settings.m_averagingMode); @@ -523,7 +528,7 @@ void GLSpectrumGUI::setAveragingCombo() } ui->averaging->setCurrentIndex(index >= ui->averaging->count() ? ui->averaging->count() - 1 : index); - ui->averaging->blockSignals(false); + ui->averaging->blockSignals(false); } void GLSpectrumGUI::setNumberStr(int n, QString& s) @@ -732,3 +737,17 @@ void GLSpectrumGUI::updateWaterfallMarkers() m_glSpectrum->updateWaterfallMarkers(); } } + +void GLSpectrumGUI::updateAnnotationMarkers() +{ + if (m_glSpectrum) { + m_glSpectrum->updateAnnotationMarkers(); + } +} + +void GLSpectrumGUI::updateMarkersDisplay() +{ + if (m_glSpectrum) { + m_glSpectrum->updateMarkersDisplay(); + } +} diff --git a/sdrgui/gui/glspectrumgui.h b/sdrgui/gui/glspectrumgui.h index e5ba84b85..4f83b6d9c 100644 --- a/sdrgui/gui/glspectrumgui.h +++ b/sdrgui/gui/glspectrumgui.h @@ -117,6 +117,8 @@ private slots: void updateHistogramMarkers(); void updateWaterfallMarkers(); + void updateAnnotationMarkers(); + void updateMarkersDisplay(); }; #endif // INCLUDE_GLSPECTRUMGUI_H diff --git a/sdrgui/gui/spectrummarkersdialog.cpp b/sdrgui/gui/spectrummarkersdialog.cpp index 6de214be7..c5bdd8baa 100644 --- a/sdrgui/gui/spectrummarkersdialog.cpp +++ b/sdrgui/gui/spectrummarkersdialog.cpp @@ -17,8 +17,10 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#include #include "util/db.h" +#include "util/csv.h" #include "spectrummarkersdialog.h" #include "ui_spectrummarkersdialog.h" @@ -27,17 +29,21 @@ SpectrumMarkersDialog::SpectrumMarkersDialog( QList& histogramMarkers, QList& waterfallMarkers, + QList& annotationMarkers, SpectrumSettings::MarkersDisplay& markersDisplay, QWidget* parent) : QDialog(parent), ui(new Ui::SpectrumMarkersDialog), m_histogramMarkers(histogramMarkers), m_waterfallMarkers(waterfallMarkers), + m_annotationMarkers(annotationMarkers), m_markersDisplay(markersDisplay), m_histogramMarkerIndex(0), m_waterfallMarkerIndex(0), + m_annotationMarkerIndex(0), m_centerFrequency(0), - m_power(0.5f) + m_power(0.5f), + m_annoFreqStartElseCenter(true) { ui->setupUi(this); ui->markerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); @@ -46,9 +52,15 @@ SpectrumMarkersDialog::SpectrumMarkersDialog( ui->wMarkerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); ui->wMarkerFrequency->setValueRange(false, 10, -9999999999L, 9999999999L); ui->wMarker->setMaximum(m_waterfallMarkers.size() - 1); + ui->aMarkerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + ui->aMarkerFrequency->setValueRange(false, 10, -9999999999L, 9999999999L); + ui->aMarker->setMaximum(m_annotationMarkers.size() - 1); + ui->aMarkerBandwidth->setColorMapper(ColorMapper::GrayYellow); + ui->aMarkerBandwidth->setValueRange(true, 9, 0, 999999999L); ui->showSelect->setCurrentIndex((int) m_markersDisplay); displayHistogramMarker(); displayWaterfallMarker(); + displayAnnotationMarker(); } SpectrumMarkersDialog::~SpectrumMarkersDialog() @@ -56,6 +68,14 @@ SpectrumMarkersDialog::~SpectrumMarkersDialog() void SpectrumMarkersDialog::displayHistogramMarker() { + ui->markerFrequency->blockSignals(true); + ui->centerFrequency->blockSignals(true); + ui->markerColor->blockSignals(true); + ui->showMarker->blockSignals(true); + ui->marker->blockSignals(true); + ui->powerMode->blockSignals(true); + ui->fixedPower->blockSignals(true); + if (m_histogramMarkers.size() == 0) { ui->marker->setEnabled(false); @@ -63,6 +83,7 @@ void SpectrumMarkersDialog::displayHistogramMarker() ui->powerMode->setEnabled(false); ui->fixedPower->setEnabled(false); ui->showMarker->setEnabled(false); + ui->marker->setValue(0); ui->markerText->setText("-"); ui->fixedPower->setValue(0); ui->fixedPowerText->setText(tr("0.0")); @@ -74,6 +95,7 @@ void SpectrumMarkersDialog::displayHistogramMarker() ui->powerMode->setEnabled(true); ui->fixedPower->setEnabled(true); ui->showMarker->setEnabled(true); + ui->marker->setValue(m_histogramMarkerIndex); ui->markerText->setText(tr("%1").arg(m_histogramMarkerIndex)); ui->markerFrequency->setValue(m_histogramMarkers[m_histogramMarkerIndex].m_frequency); ui->powerMode->setCurrentIndex((int) m_histogramMarkers[m_histogramMarkerIndex].m_markerType); @@ -85,10 +107,27 @@ void SpectrumMarkersDialog::displayHistogramMarker() ui->markerColor->setStyleSheet(tr("QLabel { background-color : rgb(%1,%2,%3); }").arg(r).arg(g).arg(b)); ui->showMarker->setChecked(m_histogramMarkers[m_histogramMarkerIndex].m_show); } + + ui->markerFrequency->blockSignals(false); + ui->centerFrequency->blockSignals(false); + ui->markerColor->blockSignals(false); + ui->showMarker->blockSignals(false); + ui->marker->blockSignals(false); + ui->powerMode->blockSignals(false); + ui->fixedPower->blockSignals(false); } void SpectrumMarkersDialog::displayWaterfallMarker() { + ui->wMarkerFrequency->blockSignals(true); + ui->wCenterFrequency->blockSignals(true); + ui->wMarkerColor->blockSignals(true); + ui->wShowMarker->blockSignals(true); + ui->wMarker->blockSignals(true); + ui->timeFine->blockSignals(true); + ui->timeCoarse->blockSignals(true); + ui->timeExp->blockSignals(true); + if (m_waterfallMarkers.size() == 0) { ui->wMarker->setEnabled(false); @@ -97,6 +136,7 @@ void SpectrumMarkersDialog::displayWaterfallMarker() ui->timeFine->setEnabled(false); ui->timeExp->setEnabled(false); ui->wShowMarker->setEnabled(false); + ui->wMarker->setValue(0); ui->wMarkerText->setText("-"); ui->timeCoarse->setValue(0); ui->timeFine->setValue(0); @@ -112,6 +152,7 @@ void SpectrumMarkersDialog::displayWaterfallMarker() ui->timeFine->setEnabled(true); ui->timeExp->setEnabled(true); ui->wShowMarker->setEnabled(true); + ui->wMarker->setValue(m_waterfallMarkerIndex); ui->wMarkerText->setText(tr("%1").arg(m_waterfallMarkerIndex)); ui->wMarkerFrequency->setValue(m_waterfallMarkers[m_waterfallMarkerIndex].m_frequency); int r,g,b,a; @@ -119,6 +160,75 @@ void SpectrumMarkersDialog::displayWaterfallMarker() ui->wMarkerColor->setStyleSheet(tr("QLabel { background-color : rgb(%1,%2,%3); }").arg(r).arg(g).arg(b)); displayTime(m_waterfallMarkers[m_waterfallMarkerIndex].m_time); } + + ui->wMarkerFrequency->blockSignals(false); + ui->wCenterFrequency->blockSignals(false); + ui->wMarkerColor->blockSignals(false); + ui->wShowMarker->blockSignals(false); + ui->wMarker->blockSignals(false); + ui->timeFine->blockSignals(false); + ui->timeCoarse->blockSignals(false); + ui->timeExp->blockSignals(false); +} + +void SpectrumMarkersDialog::displayAnnotationMarker() +{ + ui->aMarkerFrequency->blockSignals(true); + ui->aCenterFrequency->blockSignals(true); + ui->aMarkerColor->blockSignals(true); + ui->aShowMarker->blockSignals(true); + ui->aMarkerText->blockSignals(true); + ui->aMarker->blockSignals(true); + ui->aMarkerAdd->blockSignals(true); + ui->aMarkerDel->blockSignals(true); + ui->aMarkerBandwidth->blockSignals(true); + ui->aMarkerToggleFrequency->blockSignals(true); + + if (m_annotationMarkers.size() == 0) + { + ui->aMarker->setEnabled(false); + ui->aMarkerFrequency->setEnabled(false); + ui->aMarkerBandwidth->setEnabled(false); + ui->aShowMarker->setEnabled(false); + ui->aMarkerIndexText->setText("-"); + ui->aMarkerText->setText(""); + } + else + { + ui->aMarker->setEnabled(true); + ui->aMarkerFrequency->setEnabled(true); + ui->aMarkerBandwidth->setEnabled(true); + ui->aShowMarker->setEnabled(true); + ui->aMarker->setValue(m_annotationMarkerIndex); + ui->aMarkerIndexText->setText(tr("%1").arg(m_annotationMarkerIndex)); + qint64 frequency = m_annotationMarkers[m_annotationMarkerIndex].m_startFrequency + + (m_annoFreqStartElseCenter ? 0 : m_annotationMarkers[m_annotationMarkerIndex].m_bandwidth / 2); + ui->aMarkerFrequency->setValue(frequency); + ui->aMarkerBandwidth->setValue(m_annotationMarkers[m_annotationMarkerIndex].m_bandwidth); + ui->aMarkerFreqLabel->setText(m_annoFreqStartElseCenter ? "Cent" : "Start"); + frequency = m_annotationMarkers[m_annotationMarkerIndex].m_startFrequency + + (m_annoFreqStartElseCenter ? m_annotationMarkers[m_annotationMarkerIndex].m_bandwidth / 2 : 0); + ui->aMarkerFreqText->setText(tr("%L1").arg(frequency)); + ui->aMarkerStopText->setText(tr("%L1").arg( + m_annotationMarkers[m_annotationMarkerIndex].m_startFrequency + m_annotationMarkers[m_annotationMarkerIndex].m_bandwidth)); + int r,g,b,a; + m_annotationMarkers[m_annotationMarkerIndex].m_markerColor.getRgb(&r, &g, &b, &a); + ui->aMarkerColor->setStyleSheet(tr("QLabel { background-color : rgb(%1,%2,%3); }").arg(r).arg(g).arg(b)); + ui->aMarkerText->setText(tr("%1").arg(m_annotationMarkers[m_annotationMarkerIndex].m_text)); + } + + ui->aMarkerToggleFrequency->setChecked(m_annoFreqStartElseCenter); + + ui->aMarkerFrequency->blockSignals(false); + ui->aCenterFrequency->blockSignals(false); + ui->aMarkerColor->blockSignals(false); + ui->aShowMarker->blockSignals(false); + ui->aMarkerText->blockSignals(false); + ui->aMarker->blockSignals(false); + ui->aMarkerAdd->blockSignals(false); + ui->aMarkerDel->blockSignals(false); + ui->aMarkerBandwidth->blockSignals(false); + ui->aMarkerToggleFrequency->blockSignals(false); } void SpectrumMarkersDialog::displayTime(float time) @@ -426,7 +536,252 @@ void SpectrumMarkersDialog::on_wMarkerDel_clicked() displayWaterfallMarker(); } +void SpectrumMarkersDialog::on_aMarkerToggleFrequency_toggled(bool checked) +{ + m_annoFreqStartElseCenter = checked; + ui->aMarkerToggleFrequency->setText(checked ? "Start" : "Cent"); + displayAnnotationMarker(); +} + +void SpectrumMarkersDialog::on_aMarkerFrequency_changed(qint64 value) +{ + if (m_annotationMarkers.size() == 0) { + return; + } + + if (m_annoFreqStartElseCenter) { + m_annotationMarkers[m_annotationMarkerIndex].m_startFrequency = value; + } else { + m_annotationMarkers[m_annotationMarkerIndex].m_startFrequency = value - + (m_annotationMarkers[m_annotationMarkerIndex].m_bandwidth / 2); + } + + displayAnnotationMarker(); + emit updateAnnotations(); +} + +void SpectrumMarkersDialog::on_aCenterFrequency_clicked() +{ + if (m_annotationMarkers.size() == 0) { + return; + } + + qDebug("SpectrumMarkersDialog::on_aCenterFrequency_clicked: %lld", m_centerFrequency); + m_annotationMarkers[m_annotationMarkerIndex].m_startFrequency = m_centerFrequency - + (m_annoFreqStartElseCenter ? 0 : m_annotationMarkers[m_annotationMarkerIndex].m_bandwidth/2); + displayAnnotationMarker(); + emit updateAnnotations(); +} + +void SpectrumMarkersDialog::on_aMakerDuplicate_clicked() +{ + if (m_annotationMarkers.size() == 0) { + return; + } + + m_annotationMarkers.push_back(m_annotationMarkers[m_annotationMarkerIndex]); + ui->aMarker->setMaximum(m_annotationMarkers.size() - 1); + m_annotationMarkerIndex = m_annotationMarkers.size() - 1; + displayAnnotationMarker(); + emit updateAnnotations(); +} + +void SpectrumMarkersDialog::on_aMakersSort_clicked() +{ + std::sort(m_annotationMarkers.begin(), m_annotationMarkers.end(), annotationMarkerLessThan); + displayAnnotationMarker(); + emit updateAnnotations(); +} + +void SpectrumMarkersDialog::on_aMarkerColor_clicked() +{ + if (m_annotationMarkers.size() == 0) { + return; + } + + QColor newColor = QColorDialog::getColor( + m_annotationMarkers[m_annotationMarkerIndex].m_markerColor, + this, + tr("Select Color for marker"), + QColorDialog::DontUseNativeDialog + ); + + if (newColor.isValid()) // user clicked OK and selected a color + { + m_annotationMarkers[m_annotationMarkerIndex].m_markerColor = newColor; + displayAnnotationMarker(); + } +} + +void SpectrumMarkersDialog::on_aShowMarker_clicked(bool clicked) +{ + if (m_annotationMarkers.size() == 0) { + return; + } + + m_annotationMarkers[m_annotationMarkerIndex].m_show = clicked; +} + +void SpectrumMarkersDialog::on_aMarkerText_editingFinished() +{ + if (m_annotationMarkers.size() == 0) { + return; + } + + m_annotationMarkers[m_annotationMarkerIndex].m_text = ui->aMarkerText->text(); + emit updateAnnotations(); +} + +void SpectrumMarkersDialog::on_aMarker_valueChanged(int value) +{ + if (m_annotationMarkers.size() == 0) { + return; + } + + m_annotationMarkerIndex = value; + displayAnnotationMarker(); +} + +void SpectrumMarkersDialog::on_aMarkerAdd_clicked() +{ + m_annotationMarkers.append(SpectrumAnnotationMarker()); + m_annotationMarkers.back().m_startFrequency = m_centerFrequency; + m_annotationMarkerIndex = m_annotationMarkers.size() - 1; + ui->aMarker->setMaximum(m_annotationMarkers.size() - 1); + displayAnnotationMarker(); + emit updateAnnotations(); +} + +void SpectrumMarkersDialog::on_aMarkerDel_clicked() +{ + if (m_annotationMarkers.size() == 0) { + return; + } + + m_annotationMarkers.removeAt(m_annotationMarkerIndex); + m_annotationMarkerIndex = m_annotationMarkerIndex < m_annotationMarkers.size() ? + m_annotationMarkerIndex : m_annotationMarkerIndex - 1; + ui->aMarker->setMaximum(m_annotationMarkers.size() - 1); + displayAnnotationMarker(); + emit updateAnnotations(); +} + +void SpectrumMarkersDialog::on_aMarkerBandwidth_changed(qint64 value) +{ + if (m_annotationMarkers.size() == 0) { + return; + } + + m_annotationMarkers[m_annotationMarkerIndex].m_bandwidth = value < 0 ? 0 : value; + + if (!m_annoFreqStartElseCenter) + { + m_annotationMarkers[m_annotationMarkerIndex].m_startFrequency = ui->aMarkerFrequency->getValue() - + (m_annotationMarkers[m_annotationMarkerIndex].m_bandwidth / 2); + } + + displayAnnotationMarker(); + emit updateAnnotations(); +} + +void SpectrumMarkersDialog::on_aMarkersImport_clicked() +{ + QFileDialog fileDialog(nullptr, "Select .csv annotation markers file to read", "", "*.csv"); + + if (fileDialog.exec()) + { + QStringList fileNames = fileDialog.selectedFiles(); + + if (fileNames.size() > 0) + { + QFile file(fileNames[0]); + + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + + QTextStream in(&file); + QString error; + QHash colIndexes = CSV::readHeader( + in, + {"Start", "Width", "Text", "Show", "Red", "Green", "Blue"}, + error + ); + + if (error.isEmpty()) + { + QStringList cols; + int startCol = colIndexes.value("Start"); + int widthCol = colIndexes.value("Width"); + int textCol = colIndexes.value("Text"); + int showCol = colIndexes.value("Show"); + int redCol = colIndexes.value("Red"); + int greenCol = colIndexes.value("Green"); + int blueCol = colIndexes.value("Blue"); + + m_annotationMarkers.clear(); + + while (CSV::readRow(in, &cols)) + { + m_annotationMarkers.push_back(SpectrumAnnotationMarker()); + m_annotationMarkers.back().m_startFrequency = cols[startCol].toLongLong(); + m_annotationMarkers.back().m_bandwidth = cols[widthCol].toUInt(); + m_annotationMarkers.back().m_text = cols[textCol]; + m_annotationMarkers.back().m_show = cols[showCol].toInt() != 0; + int r = cols[redCol].toInt(); + int g = cols[greenCol].toInt(); + int b = cols[blueCol].toInt(); + m_annotationMarkers.back().m_markerColor = QColor(r, g, b); + } + + m_annotationMarkerIndex = 0; + ui->aMarker->setMaximum(m_annotationMarkers.size() - 1); + displayAnnotationMarker(); + emit updateAnnotations(); + } + } + } + } +} + +void SpectrumMarkersDialog::on_aMarkersExport_clicked() +{ + QFileDialog fileDialog(nullptr, "Select file to write annotation markers to", "", "*.csv"); + fileDialog.setAcceptMode(QFileDialog::AcceptSave); + + if (fileDialog.exec()) + { + QStringList fileNames = fileDialog.selectedFiles(); + + if (fileNames.size() > 0) + { + QFile file(fileNames[0]); + + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) + { + QTextStream stream; + stream.setDevice(&file); + stream << "Start,Width,Text,Show,Red,Green,Blue\n"; + + for (const auto &marker : m_annotationMarkers) + { + stream << marker.m_startFrequency << "," + << marker.m_bandwidth << "," + << marker.m_text << "," + << (marker.m_show ? "1" : "0") << "," + << marker.m_markerColor.red() << "," + << marker.m_markerColor.green() << "," + << marker.m_markerColor.blue() << "\n"; + } + + stream.flush(); + file.close(); + } + } + } +} + void SpectrumMarkersDialog::on_showSelect_currentIndexChanged(int index) { m_markersDisplay = (SpectrumSettings::MarkersDisplay) index; + emit updateMarkersDisplay(); } diff --git a/sdrgui/gui/spectrummarkersdialog.h b/sdrgui/gui/spectrummarkersdialog.h index 407ec51ed..567e41c3e 100644 --- a/sdrgui/gui/spectrummarkersdialog.h +++ b/sdrgui/gui/spectrummarkersdialog.h @@ -37,6 +37,7 @@ public: explicit SpectrumMarkersDialog( QList& histogramMarkers, QList& waterfallMarkers, + QList& annotationMarkers, SpectrumSettings::MarkersDisplay& markersDisplay, QWidget* parent = nullptr ); @@ -49,15 +50,19 @@ private: Ui::SpectrumMarkersDialog* ui; QList& m_histogramMarkers; QList& m_waterfallMarkers; + QList& m_annotationMarkers; SpectrumSettings::MarkersDisplay& m_markersDisplay; int m_histogramMarkerIndex; int m_waterfallMarkerIndex; + int m_annotationMarkerIndex; qint64 m_centerFrequency; float m_power; float m_time; + bool m_annoFreqStartElseCenter; void displayHistogramMarker(); void displayWaterfallMarker(); + void displayAnnotationMarker(); void displayTime(float time); float getTime() const; @@ -73,6 +78,7 @@ private slots: void on_markerDel_clicked(); void on_powerMode_currentIndexChanged(int index); void on_powerHoldReset_clicked(); + void on_wMarkerFrequency_changed(qint64 value); void on_timeCoarse_valueChanged(int value); void on_timeFine_valueChanged(int value); @@ -84,11 +90,33 @@ private slots: void on_wSetReference_clicked(); void on_wMarkerAdd_clicked(); void on_wMarkerDel_clicked(); + + void on_aMarkerToggleFrequency_toggled(bool checked); + void on_aMarkerFrequency_changed(qint64 value); + void on_aCenterFrequency_clicked(); + void on_aMakerDuplicate_clicked(); + void on_aMakersSort_clicked(); + void on_aMarkerColor_clicked(); + void on_aShowMarker_clicked(bool clicked); + void on_aMarkerText_editingFinished(); + void on_aMarker_valueChanged(int value); + void on_aMarkerAdd_clicked(); + void on_aMarkerDel_clicked(); + void on_aMarkerBandwidth_changed(qint64 value); + void on_aMarkersExport_clicked(); + void on_aMarkersImport_clicked(); + + static bool annotationMarkerLessThan(const SpectrumAnnotationMarker& m1, const SpectrumAnnotationMarker& m2) { + return m1.m_startFrequency < m2.m_startFrequency; + } + void on_showSelect_currentIndexChanged(int index); signals: void updateHistogram(); void updateWaterfall(); + void updateAnnotations(); + void updateMarkersDisplay(); }; #endif // SDRBASE_GUI_SPECTRUMMARKERSDIALOG_H_ diff --git a/sdrgui/gui/spectrummarkersdialog.ui b/sdrgui/gui/spectrummarkersdialog.ui index 3d7adad0c..12c1ebaa9 100644 --- a/sdrgui/gui/spectrummarkersdialog.ui +++ b/sdrgui/gui/spectrummarkersdialog.ui @@ -6,10 +6,16 @@ 0 0 - 418 - 237 + 480 + 300 + + + 480 + 300 + + Liberation Sans @@ -23,13 +29,13 @@ - 0 + 2 Hist - + 0 @@ -39,6 +45,9 @@ + + 2 + @@ -488,6 +497,9 @@ + + 2 + @@ -987,6 +999,665 @@ + + + Anno + + + + + 0 + 0 + 451 + 151 + + + + + 2 + + + + + + + + 24 + 0 + + + + Mk + + + + + + + + 15 + 0 + + + + Marker index + + + 0 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 24 + 24 + + + + Marker index selection + + + 0 + + + 1 + + + + + + + 0 + + + + + + 18 + 18 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 190 + 190 + 190 + + + + + + + + + Liberation Sans + 10 + + + + Add a new marker + + + + + + + + + + + + 18 + 18 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 190 + 190 + 190 + + + + + + + + + Liberation Sans + 10 + + + + Remove current marker + + + - + + + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + Current marker color (click to change) + + + + + + + + + + Show this marker + + + + + + true + + + + + + + Marker text + + + 30 + + + + + + + Export annotation marks to .csv file + + + + + + + :/export.png:/export.png + + + + + + + Import annotation marks from .csv file + + + + + + + :/import.png:/import.png + + + + + + + + + + + Start + + + true + + + false + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + DejaVu Sans Mono + 12 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Marker start frequency (Hz) + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Marker frequency (Hz) + + + Hz + + + + + + + + 24 + 24 + + + + Set marker frequency to center frequency + + + C + + + + + + + + 24 + 24 + + + + Duplicate current marker + + + + + + + :/duplicate.png:/duplicate.png + + + + + + + + 24 + 24 + + + + Sort markers by increasing start frequency + + + + + + + :/sort.png:/sort.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 30 + 0 + + + + Cent + + + + + + + + 140 + 0 + + + + + DejaVu Sans Mono + 12 + + + + Marker stop frequency (Hz) + + + 0,000,000,000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Marker frequency (Hz) + + + Hz + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 30 + 0 + + + + Stop + + + + + + + + 140 + 0 + + + + + DejaVu Sans Mono + 12 + + + + Marker stop frequency (Hz) + + + 0,000,000,000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Marker frequency (Hz) + + + Hz + + + + + + + + + + + + 15 + 0 + + + + BW + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + DejaVu Sans Mono + 12 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Marker width (Hz) + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Marker frequency (Hz) + + + Hz + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + @@ -1016,6 +1687,11 @@ Spec + + + Anno + + diff --git a/sdrgui/mainwindow.cpp b/sdrgui/mainwindow.cpp index f39810e73..c68559bb0 100644 --- a/sdrgui/mainwindow.cpp +++ b/sdrgui/mainwindow.cpp @@ -1181,7 +1181,6 @@ bool MainWindow::handleMessage(const Message& cmd) { int nbMIMOChannels = deviceUI->getNumberOfAvailableMIMOChannels(); int nbRxChannels = deviceUI->getNumberOfAvailableRxChannels(); - int nbTxChannels = deviceUI->getNumberOfAvailableTxChannels(); int direction = notif.getDirection(); if (direction == 2) { diff --git a/sdrgui/resources/res.qrc b/sdrgui/resources/res.qrc index 3bc51a654..2347c901e 100644 --- a/sdrgui/resources/res.qrc +++ b/sdrgui/resources/res.qrc @@ -1,5 +1,6 @@ + sort.png audio_mic.png info.png darklight.png diff --git a/sdrgui/resources/sort.png b/sdrgui/resources/sort.png new file mode 100644 index 0000000000000000000000000000000000000000..796c20565da30c024ae0616dd657e395e19483eb GIT binary patch literal 975 zcmV;=12FuFP)EX>4Tx04R}tkv&MmP!xqvQ$>-ALyL$gWT;LSL`5963Pq?8YK2xEOkVm2O&XFE z7e~Rh;NZ_<)xpJCR|i)?5c~mgbaGO3krMAq3N2#1@OU5R-E(;FK0v6KnPzp21DbA| zsYG1NWLL$mR|F77KY|#RnPtpLQWC!Pbx++?cQKyj-}h(rsyT}R0g-r?8KzCVK|H-_ z8=UuvBdjQ^#OK6gCS8#Dk?V@bZ=4G*3p_Jorc?985n{2>#!4HrqNx#25l2-`r+gvf zvC4UivsSLM<~{ifLpgnAnd`KMkia6AAVGwJDoQBBMvQiy6bmUjkNfxsUB5&wg5p5ycZNYkv6H^9Lm zFj}DOb)R>4x6ke0p62|104OJNiTCE@3;+NC24YJ`L;zp_hXBuy&>j{5000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2j&427789~PKnh300GNML_t(Y$HkU0YZO5g$A2@o zx58>=VdH^<0Y89XqoTs0RXRy0f=CJ>cKHB`Hb$#RP_eO*Ys3^*5(vRU(61n3NN~b7_L7l+N4g(vd);ago%+CEUpwT9iiFeMe1E(t8iF0lw>BP){ zBuQ3*x}_TcuO%g&0g@Jh+YOR4z{^emNf&_C(EJTNsDwwrcJQxBy4MA;1jNC=1H7+< ze@Pkwlh9sn4RFqV3hpEC{fmDx#{18}Jdgof08vZ8N|t4>`u+a*2F<3K4e~ty*%|=Q zG%AYF*_DP2df4mr#*&s>1AvP_-#Pb2 z(p=5tH_EgF&b9_fS}ChQC}2k`8+IO8D{GvjCtdG=k*3??Ut_LTV$Y_P>zlyGhHqGN z&OPt6$>D(PNm>BLHM*@V%a%H)X=S~)17xq#{iP_1`8bYkW^0B(imE-;LuXlK8> xr{eFnBAeNLNtdS_yhzeJN#D%u^ntuk{s1&V1}>3Hr;-2w002ovPDHLkV1m3cx1<07 literal 0 HcmV?d00001 diff --git a/swagger/sdrangel/api/swagger/include/GLSpectrum.yaml b/swagger/sdrangel/api/swagger/include/GLSpectrum.yaml index a644f40c8..b25174ab1 100644 --- a/swagger/sdrangel/api/swagger/include/GLSpectrum.yaml +++ b/swagger/sdrangel/api/swagger/include/GLSpectrum.yaml @@ -17,7 +17,7 @@ SpectrumHistogramMarker: * 2 - Max power markerColor: type: integer - description: Color in 8 bit RGB serie + description: Color in 8 bit BGR serie show: type: integer description: > @@ -37,7 +37,25 @@ SpectrumWaterfallMarker: description: Time shift in seconds markerColor: type: integer - description: Color in 8 bit RGB serie + description: Color in 8 bit BGR serie + show: + type: integer + description: > + Boolean - Marker display state + * 0 - Hidden + * 1 - Visible + +SpectrumAnnotationMarker: + description: Spectrum annotation marker settings + properties: + startFrequency: + type: integer + format: int64 + bandwidth: + type: integer + markerColor: + type: integer + description: Color in 8 bit BGR serie show: type: integer description: > @@ -129,3 +147,7 @@ GLSpectrum: type: array items: $ref: "http://swgserver:8081/api/swagger/include/GLSpectrum.yaml#/SpectrumWaterfallMarker" + annotationMarkers: + type: array + items: + $ref: "http://swgserver:8081/api/swagger/include/GLSpectrum.yaml#/SpectrumAnnotationMarker" diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index f38f4db06..690073b01 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -6162,6 +6162,12 @@ margin-bottom: 20px; "items" : { "$ref" : "#/definitions/SpectrumWaterfallMarker" } + }, + "annotationMarkers" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/SpectrumAnnotationMarker" + } } }, "description" : "GLSpectrumGUI settings" @@ -11782,6 +11788,26 @@ margin-bottom: 20px; } }, "description" : "SoapySDR" +}; + defs.SpectrumAnnotationMarker = { + "properties" : { + "startFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "bandwidth" : { + "type" : "integer" + }, + "markerColor" : { + "type" : "integer", + "description" : "Color in 8 bit BGR serie" + }, + "show" : { + "type" : "integer", + "description" : "Boolean - Marker display state\n * 0 - Hidden\n * 1 - Visible\n" + } + }, + "description" : "Spectrum annotation marker settings" }; defs.SpectrumHistogramMarker = { "properties" : { @@ -11800,7 +11826,7 @@ margin-bottom: 20px; }, "markerColor" : { "type" : "integer", - "description" : "Color in 8 bit RGB serie" + "description" : "Color in 8 bit BGR serie" }, "show" : { "type" : "integer", @@ -11854,7 +11880,7 @@ margin-bottom: 20px; }, "markerColor" : { "type" : "integer", - "description" : "Color in 8 bit RGB serie" + "description" : "Color in 8 bit BGR serie" }, "show" : { "type" : "integer", @@ -51943,7 +51969,7 @@ except ApiException as e:
- Generated 2022-01-15T03:12:23.419+01:00 + Generated 2022-01-15T23:01:29.100+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGGLSpectrum.cpp b/swagger/sdrangel/code/qt5/client/SWGGLSpectrum.cpp index caf795dac..e59b7fc9e 100644 --- a/swagger/sdrangel/code/qt5/client/SWGGLSpectrum.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGGLSpectrum.cpp @@ -84,6 +84,8 @@ SWGGLSpectrum::SWGGLSpectrum() { m_histogram_markers_isSet = false; waterfall_markers = nullptr; m_waterfall_markers_isSet = false; + annotation_markers = nullptr; + m_annotation_markers_isSet = false; } SWGGLSpectrum::~SWGGLSpectrum() { @@ -148,6 +150,8 @@ SWGGLSpectrum::init() { m_histogram_markers_isSet = false; waterfall_markers = new QList(); m_waterfall_markers_isSet = false; + annotation_markers = new QList(); + m_annotation_markers_isSet = false; } void @@ -194,6 +198,13 @@ SWGGLSpectrum::cleanup() { } delete waterfall_markers; } + if(annotation_markers != nullptr) { + auto arr = annotation_markers; + for(auto o: *arr) { + delete o; + } + delete annotation_markers; + } } SWGGLSpectrum* @@ -263,6 +274,8 @@ SWGGLSpectrum::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&histogram_markers, pJson["histogramMarkers"], "QList", "SWGSpectrumHistogramMarker"); ::SWGSDRangel::setValue(&waterfall_markers, pJson["waterfallMarkers"], "QList", "SWGSpectrumWaterfallMarker"); + + ::SWGSDRangel::setValue(&annotation_markers, pJson["annotationMarkers"], "QList", "SWGSpectrumAnnotationMarker"); } QString @@ -363,6 +376,9 @@ SWGGLSpectrum::asJsonObject() { if(waterfall_markers && waterfall_markers->size() > 0){ toJsonArray((QList*)waterfall_markers, obj, "waterfallMarkers", "SWGSpectrumWaterfallMarker"); } + if(annotation_markers && annotation_markers->size() > 0){ + toJsonArray((QList*)annotation_markers, obj, "annotationMarkers", "SWGSpectrumAnnotationMarker"); + } return obj; } @@ -647,6 +663,16 @@ SWGGLSpectrum::setWaterfallMarkers(QList* waterfall this->m_waterfall_markers_isSet = true; } +QList* +SWGGLSpectrum::getAnnotationMarkers() { + return annotation_markers; +} +void +SWGGLSpectrum::setAnnotationMarkers(QList* annotation_markers) { + this->annotation_markers = annotation_markers; + this->m_annotation_markers_isSet = true; +} + bool SWGGLSpectrum::isSet(){ @@ -736,6 +762,9 @@ SWGGLSpectrum::isSet(){ if(waterfall_markers && (waterfall_markers->size() > 0)){ isObjectUpdated = true; break; } + if(annotation_markers && (annotation_markers->size() > 0)){ + isObjectUpdated = true; break; + } }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGGLSpectrum.h b/swagger/sdrangel/code/qt5/client/SWGGLSpectrum.h index 9f4276a35..2d06b3e72 100644 --- a/swagger/sdrangel/code/qt5/client/SWGGLSpectrum.h +++ b/swagger/sdrangel/code/qt5/client/SWGGLSpectrum.h @@ -22,6 +22,7 @@ #include +#include "SWGSpectrumAnnotationMarker.h" #include "SWGSpectrumHistogramMarker.h" #include "SWGSpectrumWaterfallMarker.h" #include @@ -129,6 +130,9 @@ public: QList* getWaterfallMarkers(); void setWaterfallMarkers(QList* waterfall_markers); + QList* getAnnotationMarkers(); + void setAnnotationMarkers(QList* annotation_markers); + virtual bool isSet() override; @@ -217,6 +221,9 @@ private: QList* waterfall_markers; bool m_waterfall_markers_isSet; + QList* annotation_markers; + bool m_annotation_markers_isSet; + }; } diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index 1aa8c468d..c1ce2e593 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -264,6 +264,7 @@ #include "SWGSoapySDRInputSettings.h" #include "SWGSoapySDROutputSettings.h" #include "SWGSoapySDRReport.h" +#include "SWGSpectrumAnnotationMarker.h" #include "SWGSpectrumHistogramMarker.h" #include "SWGSpectrumServer.h" #include "SWGSpectrumServer_clients.h" @@ -1564,6 +1565,11 @@ namespace SWGSDRangel { obj->init(); return obj; } + if(QString("SWGSpectrumAnnotationMarker").compare(type) == 0) { + SWGSpectrumAnnotationMarker *obj = new SWGSpectrumAnnotationMarker(); + obj->init(); + return obj; + } if(QString("SWGSpectrumHistogramMarker").compare(type) == 0) { SWGSpectrumHistogramMarker *obj = new SWGSpectrumHistogramMarker(); obj->init(); diff --git a/swagger/sdrangel/code/qt5/client/SWGSpectrumAnnotationMarker.cpp b/swagger/sdrangel/code/qt5/client/SWGSpectrumAnnotationMarker.cpp new file mode 100644 index 000000000..0f882911d --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSpectrumAnnotationMarker.cpp @@ -0,0 +1,177 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGSpectrumAnnotationMarker.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGSpectrumAnnotationMarker::SWGSpectrumAnnotationMarker(QString* json) { + init(); + this->fromJson(*json); +} + +SWGSpectrumAnnotationMarker::SWGSpectrumAnnotationMarker() { + start_frequency = 0L; + m_start_frequency_isSet = false; + bandwidth = 0; + m_bandwidth_isSet = false; + marker_color = 0; + m_marker_color_isSet = false; + show = 0; + m_show_isSet = false; +} + +SWGSpectrumAnnotationMarker::~SWGSpectrumAnnotationMarker() { + this->cleanup(); +} + +void +SWGSpectrumAnnotationMarker::init() { + start_frequency = 0L; + m_start_frequency_isSet = false; + bandwidth = 0; + m_bandwidth_isSet = false; + marker_color = 0; + m_marker_color_isSet = false; + show = 0; + m_show_isSet = false; +} + +void +SWGSpectrumAnnotationMarker::cleanup() { + + + + +} + +SWGSpectrumAnnotationMarker* +SWGSpectrumAnnotationMarker::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGSpectrumAnnotationMarker::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&start_frequency, pJson["startFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&bandwidth, pJson["bandwidth"], "qint32", ""); + + ::SWGSDRangel::setValue(&marker_color, pJson["markerColor"], "qint32", ""); + + ::SWGSDRangel::setValue(&show, pJson["show"], "qint32", ""); + +} + +QString +SWGSpectrumAnnotationMarker::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGSpectrumAnnotationMarker::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_start_frequency_isSet){ + obj->insert("startFrequency", QJsonValue(start_frequency)); + } + if(m_bandwidth_isSet){ + obj->insert("bandwidth", QJsonValue(bandwidth)); + } + if(m_marker_color_isSet){ + obj->insert("markerColor", QJsonValue(marker_color)); + } + if(m_show_isSet){ + obj->insert("show", QJsonValue(show)); + } + + return obj; +} + +qint64 +SWGSpectrumAnnotationMarker::getStartFrequency() { + return start_frequency; +} +void +SWGSpectrumAnnotationMarker::setStartFrequency(qint64 start_frequency) { + this->start_frequency = start_frequency; + this->m_start_frequency_isSet = true; +} + +qint32 +SWGSpectrumAnnotationMarker::getBandwidth() { + return bandwidth; +} +void +SWGSpectrumAnnotationMarker::setBandwidth(qint32 bandwidth) { + this->bandwidth = bandwidth; + this->m_bandwidth_isSet = true; +} + +qint32 +SWGSpectrumAnnotationMarker::getMarkerColor() { + return marker_color; +} +void +SWGSpectrumAnnotationMarker::setMarkerColor(qint32 marker_color) { + this->marker_color = marker_color; + this->m_marker_color_isSet = true; +} + +qint32 +SWGSpectrumAnnotationMarker::getShow() { + return show; +} +void +SWGSpectrumAnnotationMarker::setShow(qint32 show) { + this->show = show; + this->m_show_isSet = true; +} + + +bool +SWGSpectrumAnnotationMarker::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_start_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_bandwidth_isSet){ + isObjectUpdated = true; break; + } + if(m_marker_color_isSet){ + isObjectUpdated = true; break; + } + if(m_show_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGSpectrumAnnotationMarker.h b/swagger/sdrangel/code/qt5/client/SWGSpectrumAnnotationMarker.h new file mode 100644 index 000000000..7e5be8371 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSpectrumAnnotationMarker.h @@ -0,0 +1,76 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGSpectrumAnnotationMarker.h + * + * Spectrum annotation marker settings + */ + +#ifndef SWGSpectrumAnnotationMarker_H_ +#define SWGSpectrumAnnotationMarker_H_ + +#include + + + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGSpectrumAnnotationMarker: public SWGObject { +public: + SWGSpectrumAnnotationMarker(); + SWGSpectrumAnnotationMarker(QString* json); + virtual ~SWGSpectrumAnnotationMarker(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGSpectrumAnnotationMarker* fromJson(QString &jsonString) override; + + qint64 getStartFrequency(); + void setStartFrequency(qint64 start_frequency); + + qint32 getBandwidth(); + void setBandwidth(qint32 bandwidth); + + qint32 getMarkerColor(); + void setMarkerColor(qint32 marker_color); + + qint32 getShow(); + void setShow(qint32 show); + + + virtual bool isSet() override; + +private: + qint64 start_frequency; + bool m_start_frequency_isSet; + + qint32 bandwidth; + bool m_bandwidth_isSet; + + qint32 marker_color; + bool m_marker_color_isSet; + + qint32 show; + bool m_show_isSet; + +}; + +} + +#endif /* SWGSpectrumAnnotationMarker_H_ */