<pre style='margin:0'>
ra1nb0w (ra1nb0w) pushed a commit to branch master
in repository macports-ports.

</pre>
<p><a href="https://github.com/macports/macports-ports/commit/08eba079a37a5e07c925bc625710bbb168f69967">https://github.com/macports/macports-ports/commit/08eba079a37a5e07c925bc625710bbb168f69967</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new 08eba07  gqrx-devel: update commit to e0d84133
</span>08eba07 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit 08eba079a37a5e07c925bc625710bbb168f69967
</span>Author: Davide Gerhard <ra1nb0w@macports.org>
AuthorDate: Tue Apr 21 12:32:39 2020 +0200

<span style='display:block; white-space:pre;color:#404040;'>    gqrx-devel: update commit to e0d84133
</span>---
 science/gqrx/Portfile                 |   10 +-
 science/gqrx/files/experimental.patch | 2060 +++------------------------------
 2 files changed, 150 insertions(+), 1920 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/science/gqrx/Portfile b/science/gqrx/Portfile
</span><span style='display:block; white-space:pre;color:#808080;'>index 06fde93..c06ccad 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/science/gqrx/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/science/gqrx/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -36,11 +36,11 @@ if {${subport} eq ${name}} {
</span> subport gqrx-devel {
 
     name         gqrx-devel
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    github.setup csete gqrx ca0a6154620ac1a8c232241d52a2ffaa0ef9a9a5
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    version      20200416-[string range ${github.version} 0 7]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    checksums    rmd160  14939c0c127511bb9b1c340f56ff0985a8b84475 \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                 sha256  6940abe572e3d9de8f6118783a7918c08c9305ce020771f165888882e0c84206 \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                 size    1338132
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    github.setup csete gqrx e0d8413351c3ba95e9a34bc7660d7a7ba7cb4aff
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    version      20200419-[string range ${github.version} 0 7]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    checksums    rmd160  055dd08412d6603db68bf9f066575296a191ac64 \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 sha256  35ad943a6cbfc12972f18b8499457a3b9bdbdaaca78ae1359bb4267330e97ab7 \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 size    1339596
</span>     revision     0
 
     long_description    ${long_description} \
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/science/gqrx/files/experimental.patch b/science/gqrx/files/experimental.patch
</span><span style='display:block; white-space:pre;color:#808080;'>index 3574534..591c6df 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/science/gqrx/files/experimental.patch
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/science/gqrx/files/experimental.patch
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,8 +1,8 @@
</span> diff --git gqrx.pro gqrx.pro
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index d68723f..00ad537 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index cae9bb6..49addf7 100644
</span> --- gqrx.pro
 +++ gqrx.pro
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -121,6 +121,7 @@ SOURCES += \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -123,6 +123,7 @@ SOURCES += \
</span>      src/qtgui/afsk1200win.cpp \
      src/qtgui/agc_options.cpp \
      src/qtgui/audio_options.cpp \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -10,7 +10,7 @@ index d68723f..00ad537 100644
</span>      src/qtgui/bookmarks.cpp \
      src/qtgui/bookmarkstablemodel.cpp \
      src/qtgui/bookmarkstaglist.cpp \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -141,7 +142,9 @@ SOURCES += \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -143,7 +144,9 @@ SOURCES += \
</span>      src/qtgui/qtcolorpicker.cpp \
      src/receivers/nbrx.cpp \
      src/receivers/receiver_base.cpp \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -21,7 +21,7 @@ index d68723f..00ad537 100644
</span>  
  HEADERS += \
      src/applications/gqrx/gqrx.h \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -179,6 +182,7 @@ HEADERS += \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -183,6 +186,7 @@ HEADERS += \
</span>      src/qtgui/afsk1200win.h \
      src/qtgui/agc_options.h \
      src/qtgui/audio_options.h \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -29,7 +29,7 @@ index d68723f..00ad537 100644
</span>      src/qtgui/bookmarks.h \
      src/qtgui/bookmarkstablemodel.h \
      src/qtgui/bookmarkstaglist.h \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -200,7 +204,9 @@ HEADERS += \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -204,7 +208,9 @@ HEADERS += \
</span>      src/qtgui/qtcolorpicker.h \
      src/receivers/nbrx.h \
      src/receivers/receiver_base.h \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -40,7 +40,7 @@ index d68723f..00ad537 100644
</span>  
  FORMS += \
      src/applications/gqrx/mainwindow.ui \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -217,7 +223,8 @@ FORMS += \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -221,7 +227,8 @@ FORMS += \
</span>      src/qtgui/iq_tool.ui \
      src/qtgui/dockrxopt.ui \
      src/qtgui/ioconfig.ui \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -51,7 +51,7 @@ index d68723f..00ad537 100644
</span>  # Use pulseaudio (ps: could use equals? undocumented)
  equals(AUDIO_BACKEND, "pulseaudio"): {
 diff --git src/applications/gqrx/mainwindow.cpp src/applications/gqrx/mainwindow.cpp
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index b6e9407..d90034c 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index b6e9407..a669580 100644
</span> --- src/applications/gqrx/mainwindow.cpp
 +++ src/applications/gqrx/mainwindow.cpp
 @@ -48,6 +48,7 @@
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -101,7 +101,18 @@ index b6e9407..d90034c 100644
</span>      uiDockBookmarks = new DockBookmarks(this);
  
      // setup some toggle view shortcuts
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -236,6 +247,7 @@ MainWindow::MainWindow(const QString cfgfile, bool edit_conf, QWidget *parent) :
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -139,6 +150,10 @@ MainWindow::MainWindow(const QString cfgfile, bool edit_conf, QWidget *parent) :
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     uiDockBookmarks->toggleViewAction()->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     ui->mainToolBar->toggleViewAction()->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_T));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    /* frequency setting shortcut */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    QShortcut *freq_shortcut = new QShortcut(QKeySequence(Qt::Key_F), this);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    QObject::connect(freq_shortcut, &QShortcut::activated, this, &MainWindow::frequencyFocusShortcut);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -236,6 +251,7 @@ MainWindow::MainWindow(const QString cfgfile, bool edit_conf, QWidget *parent) :
</span>      connect(uiDockFft, SIGNAL(resetFftZoom()), ui->plotter, SLOT(resetHorizontalZoom()));
      connect(uiDockFft, SIGNAL(gotoFftCenter()), ui->plotter, SLOT(moveToCenterFreq()));
      connect(uiDockFft, SIGNAL(gotoDemodFreq()), ui->plotter, SLOT(moveToDemodFreq()));
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -109,7 +120,7 @@ index b6e9407..d90034c 100644
</span>      connect(uiDockFft, SIGNAL(wfColormapChanged(const QString)), ui->plotter, SLOT(setWfColormap(const QString)));
      connect(uiDockFft, SIGNAL(wfColormapChanged(const QString)), uiDockAudio, SLOT(setWfColormap(const QString)));
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -259,6 +271,9 @@ MainWindow::MainWindow(const QString cfgfile, bool edit_conf, QWidget *parent) :
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -259,6 +275,9 @@ MainWindow::MainWindow(const QString cfgfile, bool edit_conf, QWidget *parent) :
</span>      connect(uiDockBookmarks, SIGNAL(newBookmarkActivated(qint64, QString, int)), this, SLOT(onBookmarkActivated(qint64, QString, int)));
      connect(uiDockBookmarks->actionAddBookmark, SIGNAL(triggered()), this, SLOT(on_actionAddBookmark_triggered()));
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -119,7 +130,7 @@ index b6e9407..d90034c 100644
</span>  
      // I/Q playback
      connect(iq_tool, SIGNAL(startRecording(QString)), this, SLOT(startIqRecording(QString)));
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -348,6 +363,9 @@ MainWindow::~MainWindow()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -348,6 +367,9 @@ MainWindow::~MainWindow()
</span>      audio_fft_timer->stop();
      delete audio_fft_timer;
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -129,7 +140,7 @@ index b6e9407..d90034c 100644
</span>      if (m_settings)
      {
          m_settings->setValue("configversion", 2);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -370,6 +388,7 @@ MainWindow::~MainWindow()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -370,6 +392,7 @@ MainWindow::~MainWindow()
</span>      }
  
      delete iq_tool;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -137,7 +148,7 @@ index b6e9407..d90034c 100644
</span>      delete ui;
      delete uiDockRxOpt;
      delete uiDockAudio;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -591,6 +610,7 @@ bool MainWindow::loadConfig(const QString cfgfile, bool check_crash,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -591,6 +614,7 @@ bool MainWindow::loadConfig(const QString cfgfile, bool check_crash,
</span>      uiDockRxOpt->readSettings(m_settings);
      uiDockFft->readSettings(m_settings);
      uiDockAudio->readSettings(m_settings);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -145,7 +156,7 @@ index b6e9407..d90034c 100644
</span>  
      {
          int64_val = m_settings->value("input/frequency", 14236000).toLongLong(&conv_ok);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -710,6 +730,7 @@ void MainWindow::storeSession()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -710,6 +734,7 @@ void MainWindow::storeSession()
</span>  
          remote->saveSettings(m_settings);
          iq_tool->saveSettings(m_settings);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -153,7 +164,7 @@ index b6e9407..d90034c 100644
</span>  
          {
              int     flo, fhi;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -2056,6 +2077,11 @@ void MainWindow::afsk1200win_closed()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -2056,6 +2081,11 @@ void MainWindow::afsk1200win_closed()
</span>      dec_afsk1200 = 0;
  }
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -165,1910 +176,137 @@ index b6e9407..d90034c 100644
</span>  
  /**
   * Cyclic processing for acquiring samples from receiver and processing them
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -2335,3 +2361,24 @@ void MainWindow::on_actionAddBookmark_triggered()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -2335,3 +2365,19 @@ void MainWindow::on_actionAddBookmark_triggered()
</span>          ui->plotter->updateOverlay();
      }
  }
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+void MainWindow::keyPressEvent(QKeyEvent *event)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    switch (event->key())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case Qt::Key_F:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        ui->freqCtrl->setFrequencyFocus();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void MainWindow::addClusterSpot()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    ui->plotter->updateOverlay();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void MainWindow::checkDXCSpotTimeout()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    DXCSpots::Get().checkSpotTimeout();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    ui->plotter->updateOverlay();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git src/applications/gqrx/mainwindow.h src/applications/gqrx/mainwindow.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index de45c6b..c7b99d1 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- src/applications/gqrx/mainwindow.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ src/applications/gqrx/mainwindow.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -32,6 +32,7 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include <QMessageBox>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include <QFileDialog>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include <QSvgWidget>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <QKeyEvent>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "qtgui/dockrxopt.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "qtgui/dockaudio.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -41,6 +42,8 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "qtgui/dockrds.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "qtgui/afsk1200win.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "qtgui/iq_tool.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "qtgui/dxc_options.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "qtgui/dxc_spots.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "applications/gqrx/remote_control.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -99,6 +102,7 @@ private:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     DockRDS        *uiDockRDS;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     CIqTool        *iq_tool;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    DXC_Options    *dxc_options;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     /* data decoders */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -110,6 +114,7 @@ private:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     QTimer   *iq_fft_timer;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     QTimer   *audio_fft_timer;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     QTimer   *rds_timer;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    QTimer   *dxc_timer;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     receiver *rx;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -120,6 +125,9 @@ private:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     // dummy widget to enforce linking to QtSvg
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     QSvgWidget      *qsvg_dummy;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+protected:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void    keyPressEvent(QKeyEvent *);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- private:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void updateHWFrequencyRange(bool ignore_limits);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void updateFrequencyRange();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -201,6 +209,9 @@ private slots:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     /* Bookmarks */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void onBookmarkActivated(qint64 freq, QString demod, int bandwidth);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /* DXC Spots */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void addClusterSpot();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     /* menu and toolbar actions */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void on_actionDSP_triggered(bool checked);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     int  on_actionIoConfig_triggered();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -218,6 +229,7 @@ private slots:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void on_actionAbout_triggered();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void on_actionAboutQt_triggered();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void on_actionAddBookmark_triggered();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void on_actionDX_Cluster_triggered();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     /* window close signals */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -230,6 +242,7 @@ private slots:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void iqFftTimeout();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void audioFftTimeout();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void rdsTimeout();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void checkDXCSpotTimeout();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- };
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #endif // MAINWINDOW_H
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git src/applications/gqrx/mainwindow.ui src/applications/gqrx/mainwindow.ui
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index 0fb1f36..dc39a81 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- src/applications/gqrx/mainwindow.ui
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ src/applications/gqrx/mainwindow.ui
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -195,7 +195,7 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-      <x>0</x>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-      <y>0</y>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-      <width>521</width>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--     <height>19</height>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+     <height>22</height>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     </rect>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    </property>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    <widget class="QMenu" name="menu_File">
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -242,6 +242,7 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     <addaction name="separator"/>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     <addaction name="actionAFSK1200"/>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     <addaction name="separator"/>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    <addaction name="actionDX_Cluster"/>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    </widget>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    <addaction name="menu_File"/>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    <addaction name="menu_Tools"/>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -541,6 +542,17 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     <string>Ctrl+W</string>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    </property>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   </action>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+  <action name="actionDX_Cluster">
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+   <property name="text">
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    <string>DX Cluster</string>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+   </property>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+   <property name="toolTip">
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    <string>Open DX Cluster Dialog</string>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+   </property>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+   <property name="shortcut">
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    <string>Ctrl+C</string>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+   </property>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+  </action>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  </widget>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  <layoutdefault spacing="6" margin="11"/>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  <customwidgets>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git src/applications/gqrx/receiver.cpp src/applications/gqrx/receiver.cpp
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index 4114b08..9406cba 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- src/applications/gqrx/receiver.cpp
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ src/applications/gqrx/receiver.cpp
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -50,6 +50,7 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #define DEFAULT_AUDIO_GAIN -6.0
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#define TARGET_QUAD_RATE 1e6
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  * @brief Public contructor.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -103,19 +104,21 @@ receiver::receiver(const std::string input_device,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             d_decim = 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        d_quad_rate = d_input_rate / (double)d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_decim_rate = d_input_rate / (double)d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        d_quad_rate = d_input_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_decim_rate = d_input_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_ddc_decim = std::max(1, (int)(d_decim_rate / TARGET_QUAD_RATE));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_quad_rate = d_decim_rate / d_ddc_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    ddc = make_downconverter_cc(d_ddc_decim, 0.0, d_decim_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     rx  = make_nbrx(d_quad_rate, d_audio_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    rot = gr::blocks::rotator_cc::make(0.0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     iq_swap = make_iq_swap_cc(false);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    dc_corr = make_dc_corr_cc(d_quad_rate, 1.0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    iq_fft = make_rx_fft_c(8192u, d_quad_rate, gr::filter::firdes::WIN_HANN);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    dc_corr = make_dc_corr_cc(d_decim_rate, 1.0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_fft = make_rx_fft_c(8192u, d_decim_rate, gr::filter::firdes::WIN_HANN);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     audio_fft = make_rx_fft_f(8192u, gr::filter::firdes::WIN_HANN);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     audio_gain0 = gr::blocks::multiply_const_ff::make(0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -351,11 +354,13 @@ double receiver::set_input_rate(double rate)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         d_input_rate = rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    d_quad_rate = d_input_rate / (double)d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    dc_corr->set_sample_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_decim_rate = d_input_rate / (double)d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_ddc_decim = std::max(1, (int)(d_decim_rate / TARGET_QUAD_RATE));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_quad_rate = d_decim_rate / d_ddc_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    dc_corr->set_sample_rate(d_decim_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    ddc->set_decim_and_samp_rate(d_ddc_decim, d_decim_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     rx->set_quad_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     iq_fft->set_quad_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    update_ddc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return d_input_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -399,18 +404,20 @@ unsigned int receiver::set_input_decim(unsigned int decim)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             d_decim = 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        d_quad_rate = d_input_rate / (double)d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_decim_rate = d_input_rate / (double)d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        d_quad_rate = d_input_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_decim_rate = d_input_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     // update quadrature rate
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    dc_corr->set_sample_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_ddc_decim = std::max(1, (int)(d_decim_rate / TARGET_QUAD_RATE));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_quad_rate = d_decim_rate / d_ddc_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    dc_corr->set_sample_rate(d_decim_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    ddc->set_decim_and_samp_rate(d_ddc_decim, d_decim_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     rx->set_quad_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     iq_fft->set_quad_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    update_ddc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -424,7 +431,7 @@ unsigned int receiver::set_input_decim(unsigned int decim)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #ifdef CUSTOM_AIRSPY_KERNELS
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (input_devstr.find("airspy") != std::string::npos)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        src->set_bandwidth(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        src->set_bandwidth(d_decim_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -648,7 +655,7 @@ receiver::status receiver::set_auto_gain(bool automatic)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- receiver::status receiver::set_filter_offset(double offset_hz)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     d_filter_offset = offset_hz;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    update_ddc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    ddc->set_center_freq(d_filter_offset - d_cw_offset);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -667,7 +674,7 @@ double receiver::get_filter_offset(void) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- receiver::status receiver::set_cw_offset(double offset_hz)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     d_cw_offset = offset_hz;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    update_ddc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    ddc->set_center_freq(d_filter_offset - d_cw_offset);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     rx->set_cw_offset(d_cw_offset);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1329,8 +1336,8 @@ void receiver::connect_all(rx_chain type)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     // Audio path (if there is a receiver)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (type != RX_CHAIN_NONE)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        tb->connect(b, 0, rot, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        tb->connect(rot, 0, rx, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(b, 0, ddc, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(ddc, 0, rx, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         tb->connect(rx, 0, audio_fft, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         tb->connect(rx, 0, audio_udp_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         tb->connect(rx, 1, audio_udp_sink, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1354,12 +1361,6 @@ void receiver::connect_all(rx_chain type)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--/** Convenience function to update all DDC related components. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--void receiver::update_ddc()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    rot->set_phase_inc(2.0 * M_PI * (-d_filter_offset + d_cw_offset) / d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- void receiver::get_rds_data(std::string &outbuff, int &num)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     rx->get_rds_data(outbuff, num);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git src/applications/gqrx/receiver.cpp.orig src/applications/gqrx/receiver.cpp.orig
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-new file mode 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index 0000000..4114b08
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- /dev/null
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ src/applications/gqrx/receiver.cpp.orig
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -0,0 +1,1390 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/* -*- c++ -*- */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/*
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Gqrx SDR: Software defined radio receiver powered by GNU Radio and Qt
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *           http://gqrx.dk/
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Copyright 2011-2014 Alexandru Csete OZ9AEC.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Gqrx is free software; you can redistribute it and/or modify
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * it under the terms of the GNU General Public License as published by
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * the Free Software Foundation; either version 3, or (at your option)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * any later version.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Gqrx is distributed in the hope that it will be useful,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * GNU General Public License for more details.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * You should have received a copy of the GNU General Public License
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * along with Gqrx; see the file COPYING.  If not, write to
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * the Free Software Foundation, Inc., 51 Franklin Street,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Boston, MA 02110-1301, USA.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <cmath>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <iostream>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#ifndef _MSC_VER
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <unistd.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <iostream>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <gnuradio/prefs.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <gnuradio/top_block.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <osmosdr/source.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <osmosdr/ranges.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "applications/gqrx/receiver.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "dsp/correct_iq_cc.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+//#include "dsp/hbf_decim.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "dsp/filter/fir_decim.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "dsp/rx_fft.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "receivers/nbrx.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "receivers/wfmrx.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#ifdef WITH_PULSEAUDIO
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "pulseaudio/pa_sink.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#elif WITH_PORTAUDIO
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "portaudio/portaudio_sink.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <gnuradio/audio/sink.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#define DEFAULT_AUDIO_GAIN -6.0
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Public contructor.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param input_device Input device specifier.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param audio_device Audio output device specifier,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *                     e.g. hw:0 when using ALSA or Portaudio.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::receiver(const std::string input_device,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                   const std::string audio_device,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                   unsigned int decimation)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    : d_running(false),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_input_rate(96000.0),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_audio_rate(48000),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_decim(decimation),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_rf_freq(144800000.0),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_filter_offset(0.0),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_cw_offset(0.0),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_recording_iq(false),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_recording_wav(false),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_sniffer_active(false),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_iq_rev(false),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_dc_cancel(false),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_iq_balance(false),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_demod(RX_DEMOD_OFF)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb = gr::make_top_block("gqrx");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (input_device.empty())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        src = osmosdr::source::make("file="+get_random_file()+",freq=428e6,rate=96000,repeat=true,throttle=true");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        input_devstr = input_device;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        src = osmosdr::source::make(input_device);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // input decimator
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        try
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            input_decim = make_fir_decim_cc(d_decim);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        catch (std::range_error &e)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            std::cout << "Error creating input decimator " << d_decim
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                      << ": " << e.what() << std::endl
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                      << "Using decimation 1." << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            d_decim = 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_quad_rate = d_input_rate / (double)d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_quad_rate = d_input_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx  = make_nbrx(d_quad_rate, d_audio_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rot = gr::blocks::rotator_cc::make(0.0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_swap = make_iq_swap_cc(false);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    dc_corr = make_dc_corr_cc(d_quad_rate, 1.0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_fft = make_rx_fft_c(8192u, d_quad_rate, gr::filter::firdes::WIN_HANN);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_fft = make_rx_fft_f(8192u, gr::filter::firdes::WIN_HANN);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_gain0 = gr::blocks::multiply_const_ff::make(0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_gain1 = gr::blocks::multiply_const_ff::make(0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    set_af_gain(DEFAULT_AUDIO_GAIN);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_udp_sink = make_udp_sink_f();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#ifdef WITH_PULSEAUDIO
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_snk = make_pa_sink(audio_device, d_audio_rate, "GQRX", "Audio output");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#elif WITH_PORTAUDIO
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_snk = make_portaudio_sink(audio_device, d_audio_rate, "GQRX", "Audio output");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_snk = gr::audio::sink::make(d_audio_rate, audio_device, true);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    output_devstr = audio_device;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /* wav sink and source is created when rec/play is started */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_null_sink0 = gr::blocks::null_sink::make(sizeof(float));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_null_sink1 = gr::blocks::null_sink::make(sizeof(float));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    sniffer = make_sniffer_f();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /* sniffer_rr is created at each activation. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    set_demod(RX_DEMOD_NFM);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#ifndef QT_NO_DEBUG_OUTPUT
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    gr::prefs pref;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    std::cout << "Using audio backend: "
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+              << pref.get_string("audio", "audio_module", "N/A")
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+              << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::~receiver()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Start the receiver. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::start()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->start();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_running = true;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Stop the receiver. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::stop()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->wait(); // If the graph is needed to run again, wait() must be called after stop
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_running = false;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Select new input device.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @bug When using ALSA, program will crash if the new device
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *      is the same as the previously used device:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *      audio_alsa_source[hw:1]: Device or resource busy
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::set_input_device(const std::string device)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    std::string error = "";
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (device.empty())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (input_devstr.compare(device) == 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#ifndef QT_NO_DEBUG_OUTPUT
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "No change in input device:" << std::endl
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                  << "  old: " << input_devstr << std::endl
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                  << "  new: " << device << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    input_devstr = device;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // tb->lock() can hang occasionally
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->wait();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(src, 0, input_decim, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(input_decim, 0, iq_swap, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(src, 0, iq_swap, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    src.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    try
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        src = osmosdr::source::make(device);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    catch (std::runtime_error &x)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        error = x.what();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        src = osmosdr::source::make("file="+get_random_file()+",freq=428e6,rate=96000,repeat=true,throttle=true");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if(src->get_sample_rate() != 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        set_input_rate(src->get_sample_rate());
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(src, 0, input_decim, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(input_decim, 0, iq_swap, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(src, 0, iq_swap, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->start();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (error != "")
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        throw std::runtime_error(error);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Select new audio output device. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::set_output_device(const std::string device)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (output_devstr.compare(device) == 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#ifndef QT_NO_DEBUG_OUTPUT
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "No change in output device:" << std::endl
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                  << "  old: " << output_devstr << std::endl
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                  << "  new: " << device << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#ifndef QT_NO_DEBUG_OUTPUT
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    std::cout << "New audio output device:" << std::endl
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+              << "   old: " << output_devstr << std::endl
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+              << "   new: " << device << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    output_devstr = device;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_demod != RX_DEMOD_OFF)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(audio_gain0, 0, audio_snk, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(audio_gain1, 0, audio_snk, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_snk.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#ifdef WITH_PULSEAUDIO
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_snk = make_pa_sink(device, d_audio_rate, "GQRX", "Audio output");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#elif WITH_PORTAUDIO
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_snk = make_portaudio_sink(device, d_audio_rate, "GQRX", "Audio output");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_snk = gr::audio::sink::make(d_audio_rate, device, true);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_demod != RX_DEMOD_OFF)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(audio_gain0, 0, audio_snk, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(audio_gain1, 0, audio_snk, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Get a list of available antenna connectors. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+std::vector<std::string> receiver::get_antennas(void) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return src->get_antennas();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Select antenna conenctor. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::set_antenna(const std::string &antenna)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!antenna.empty())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        src->set_antenna(antenna);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Set new input sample rate.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param rate The desired input rate
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return The actual sample rate set or 0 if there was an error with the
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *         device.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+double receiver::set_input_rate(double rate)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    double  current_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    bool    rate_has_changed;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    current_rate = src->get_sample_rate();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rate_has_changed = !(rate == current_rate ||
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            std::abs(rate - current_rate) < std::abs(std::min(rate, current_rate))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            * std::numeric_limits<double>::epsilon());
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_input_rate = src->set_sample_rate(rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_input_rate == 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        // This can be the case when no device is attached and gr-osmosdr
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        // puts in a null_source with rate 100 ksps or if the rate has not
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        // changed
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        if (rate_has_changed)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            std::cerr << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            std::cerr << "Failed to set RX input rate to " << rate << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            std::cerr << "Your device may not be working properly." << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            std::cerr << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_input_rate = rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_quad_rate = d_input_rate / (double)d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    dc_corr->set_sample_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx->set_quad_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_fft->set_quad_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    update_ddc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return d_input_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Set input decimation */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+unsigned int receiver::set_input_decim(unsigned int decim)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (decim == d_decim)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->wait();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(src, 0, input_decim, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(input_decim, 0, iq_swap, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(src, 0, iq_swap, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    input_decim.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_decim = decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        try
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            input_decim = make_fir_decim_cc(d_decim);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        catch (std::range_error &e)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            std::cout << "Error opening creating input decimator " << d_decim
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                      << ": " << e.what() << std::endl
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                      << "Using decimation 1." << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            d_decim = 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_quad_rate = d_input_rate / (double)d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_quad_rate = d_input_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // update quadrature rate
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    dc_corr->set_sample_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx->set_quad_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_fft->set_quad_rate(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    update_ddc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(src, 0, input_decim, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(input_decim, 0, iq_swap, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(src, 0, iq_swap, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#ifdef CUSTOM_AIRSPY_KERNELS
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (input_devstr.find("airspy") != std::string::npos)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        src->set_bandwidth(d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->start();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Set new analog bandwidth.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param bw The new bandwidth.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return The actual bandwidth.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+double receiver::set_analog_bandwidth(double bw)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return src->set_bandwidth(bw);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Get current analog bandwidth. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+double receiver::get_analog_bandwidth(void) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return src->get_bandwidth();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Set I/Q reversed. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::set_iq_swap(bool reversed)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (reversed == d_iq_rev)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_iq_rev = reversed;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_swap->set_enabled(d_iq_rev);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Get current I/Q reversed setting.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @retval true I/Q swappign is enabled.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @retval false I/Q swapping is disabled.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+bool receiver::get_iq_swap(void) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return d_iq_rev;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Enable/disable automatic DC removal in the I/Q stream.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param enable Whether DC removal should enabled or not.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::set_dc_cancel(bool enable)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (enable == d_dc_cancel)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_dc_cancel = enable;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // until we have a way to switch on/off
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // inside the dc_corr_cc we do a reconf
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx_demod demod = d_demod;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_demod = RX_DEMOD_OFF;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    set_demod(demod);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Get auto DC cancel status.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @retval true  Automatic DC removal is enabled.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @retval false Automatic DC removal is disabled.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+bool receiver::get_dc_cancel(void) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return d_dc_cancel;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Enable/disable automatic I/Q balance.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param enable Whether automatic I/Q balance should be enabled.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::set_iq_balance(bool enable)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (enable == d_iq_balance)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_iq_balance = enable;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    src->set_iq_balance_mode(enable ? 2 : 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Get auto I/Q balance status.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @retval true  Automatic I/Q balance is enabled.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @retval false Automatic I/Q balance is disabled.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+bool receiver::get_iq_balance(void) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return d_iq_balance;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Set RF frequency.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param freq_hz The desired frequency in Hz.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return RX_STATUS_ERROR if an error occurs, e.g. the frequency is out of range.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @sa get_rf_freq()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_rf_freq(double freq_hz)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_rf_freq = freq_hz;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    src->set_center_freq(d_rf_freq);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // FIXME: read back frequency?
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Get RF frequency.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return The current RF frequency.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @sa set_rf_freq()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+double receiver::get_rf_freq(void)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_rf_freq = src->get_center_freq();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return d_rf_freq;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Get the RF frequency range of the current input device.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param start The lower limit of the range in Hz.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param stop  The upper limit of the range in Hz.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param step  The frequency step in Hz.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @returns STATUS_OK if the range could be retrieved, STATUS_ERROR if an error has occurred.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::get_rf_range(double *start, double *stop, double *step)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    osmosdr::freq_range_t range;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    range = src->get_freq_range();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // currently range is empty for all but E4000
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!range.empty())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        if (range.start() < range.stop())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            *start = range.start();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            *stop  = range.stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            *step  = range.step();  /** FIXME: got 0 for rtl-sdr? **/
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Get the names of available gain stages. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+std::vector<std::string> receiver::get_gain_names()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return src->get_gain_names();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Get gain range for a specific stage.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param[in]  name The name of the gain stage.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param[out] start Lower limit for this gain setting.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param[out] stop  Upper limit for this gain setting.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param[out] step  The resolution for this gain setting.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * This function retunrs the range for the requested gain stage.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::get_gain_range(std::string &name, double *start,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                                          double *stop, double *step) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    osmosdr::gain_range_t range;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    range = src->get_gain_range(name);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    *start = range.start();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    *stop  = range.stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    *step  = range.step();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_gain(std::string name, double value)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    src->set_gain(value, name);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+double receiver::get_gain(std::string name) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return src->get_gain(name);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Set RF gain.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param gain_rel The desired relative gain between 0.0 and 1.0 (use -1 for
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *                 AGC where supported).
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return RX_STATUS_ERROR if an error occurs, e.g. the gain is out of valid range.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_auto_gain(bool automatic)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    src->set_gain_mode(automatic);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Set filter offset.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param offset_hz The desired filter offset in Hz.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return RX_STATUS_ERROR if the tuning offset is out of range.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * This method sets a new tuning offset for the receiver. The tuning offset is used
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * to tune within the passband, i.e. select a specific channel within the received
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * spectrum.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * The valid range for the tuning is +/- 0.5 * the bandwidth although this is just a
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * logical limit.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @sa get_filter_offset()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_filter_offset(double offset_hz)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_filter_offset = offset_hz;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    update_ddc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Get filter offset.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return The current filter offset.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @sa set_filter_offset()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+double receiver::get_filter_offset(void) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return d_filter_offset;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/* CW offset can serve as a "BFO" if the GUI needs it */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_cw_offset(double offset_hz)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_cw_offset = offset_hz;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    update_ddc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx->set_cw_offset(d_cw_offset);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+double receiver::get_cw_offset(void) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return d_cw_offset;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_filter(double low, double high, filter_shape shape)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    double trans_width;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if ((low >= high) || (std::abs(high-low) < RX_FILTER_MIN_WIDTH))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    switch (shape) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case FILTER_SHAPE_SOFT:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        trans_width = std::abs(high - low) * 0.5;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case FILTER_SHAPE_SHARP:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        trans_width = std::abs(high - low) * 0.1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case FILTER_SHAPE_NORMAL:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    default:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        trans_width = std::abs(high - low) * 0.2;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx->set_filter(low, high, trans_width);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_freq_corr(double ppm)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    src->set_freq_corr(ppm);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Get current signal power.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param dbfs Whether to use dbfs or absolute power.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return The current signal power.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * This method returns the current signal power detected by the receiver. The detector
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * is located after the band pass filter. The full scale is 1.0
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+float receiver::get_signal_pwr(bool dbfs) const
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return rx->get_signal_level(dbfs);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Set new FFT size. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::set_iq_fft_size(int newsize)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_fft->set_fft_size(newsize);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::set_iq_fft_window(int window_type)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_fft->set_window_type(window_type);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Get latest baseband FFT data. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::get_iq_fft_data(std::complex<float>* fftPoints, unsigned int &fftsize)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_fft->get_fft_data(fftPoints, fftsize);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Get latest audio FFT data. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::get_audio_fft_data(std::complex<float>* fftPoints, unsigned int &fftsize)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_fft->get_fft_data(fftPoints, fftsize);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_nb_on(int nbid, bool on)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_nb())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_nb_on(nbid, on);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_nb_threshold(int nbid, float threshold)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_nb())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_nb_threshold(nbid, threshold);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Set squelch level.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param level_db The new level in dBFS.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_sql_level(double level_db)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_sql())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_sql_level(level_db);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Set squelch alpha */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_sql_alpha(double alpha)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_sql())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_sql_alpha(alpha);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Enable/disable receiver AGC.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * When AGC is disabled a fixed manual gain is used, see set_agc_manual_gain().
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_agc_on(bool agc_on)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_agc())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_agc_on(agc_on);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Enable/disable AGC hang. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_agc_hang(bool use_hang)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_agc())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_agc_hang(use_hang);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Set AGC threshold. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_agc_threshold(int threshold)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_agc())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_agc_threshold(threshold);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Set AGC slope. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_agc_slope(int slope)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_agc())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_agc_slope(slope);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Set AGC decay time. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_agc_decay(int decay_ms)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_agc())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_agc_decay(decay_ms);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Set fixed gain used when AGC is OFF. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_agc_manual_gain(int gain)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_agc())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_agc_manual_gain(gain);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK; // FIXME
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_demod(rx_demod demod)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    status ret = STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // Allow reconf using same demod to provide a workaround
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // for the "jerky streaming" we may experience with rtl
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // dongles (the jerkyness disappears when we run this function)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    //if (demod == d_demod)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    //    return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // tb->lock() seems to hang occasioanlly
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->wait();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect_all();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    switch (demod)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_DEMOD_OFF:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect_all(RX_CHAIN_NONE);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_DEMOD_NONE:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect_all(RX_CHAIN_NBRX);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_demod(nbrx::NBRX_DEMOD_NONE);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_DEMOD_AM:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect_all(RX_CHAIN_NBRX);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_demod(nbrx::NBRX_DEMOD_AM);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_DEMOD_NFM:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect_all(RX_CHAIN_NBRX);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_demod(nbrx::NBRX_DEMOD_FM);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_DEMOD_WFM_M:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect_all(RX_CHAIN_WFMRX);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_demod(wfmrx::WFMRX_DEMOD_MONO);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_DEMOD_WFM_S:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect_all(RX_CHAIN_WFMRX);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_demod(wfmrx::WFMRX_DEMOD_STEREO);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_DEMOD_WFM_S_OIRT:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect_all(RX_CHAIN_WFMRX);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_demod(wfmrx::WFMRX_DEMOD_STEREO_UKW);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_DEMOD_SSB:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect_all(RX_CHAIN_NBRX);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_demod(nbrx::NBRX_DEMOD_SSB);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    default:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        ret = STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_demod = demod;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->start();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Set maximum deviation of the FM demodulator.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param maxdev_hz The new maximum deviation in Hz.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_fm_maxdev(float maxdev_hz)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_fm())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_fm_maxdev(maxdev_hz);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_fm_deemph(double tau)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_fm())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_fm_deemph(tau);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_am_dcr(bool enabled)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (rx->has_am())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rx->set_am_dcr(enabled);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::set_af_gain(float gain_db)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    float k;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /* convert dB to factor */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    k = pow(10.0, gain_db / 20.0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    //std::cout << "G:" << gain_db << "dB / K:" << k << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_gain0->set_k(k);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_gain1->set_k(k);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Start WAV file recorder.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param filename The filename where to record.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * A new recorder object is created every time we start recording and deleted every time
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * we stop recording. The idea of creating one object and starting/stopping using different
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * file names does not work with WAV files (the initial /tmp/gqrx.wav will not be stopped
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * because the wav file can not be empty). See https://github.com/csete/gqrx/issues/36
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::start_audio_recording(const std::string filename)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_recording_wav)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        /* error - we are already recording */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "ERROR: Can not start audio recorder (already recording)" << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        /* receiver is not running */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "Can not start audio recorder (receiver not running)" << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // if this fails, we don't want to go and crash now, do we
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    try {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        wav_sink = gr::blocks::wavfile_sink::make(filename.c_str(), 2,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                                                  (unsigned int) d_audio_rate,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                                                  16);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    catch (std::runtime_error &e) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "Error opening " << filename << ": " << e.what() << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 0, wav_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 1, wav_sink, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_recording_wav = true;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    std::cout << "Recording audio to " << filename << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Stop WAV file recorder. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::stop_audio_recording()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!d_recording_wav) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        /* error: we are not recording */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "ERROR: Can not stop audio recorder (not recording)" << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        /* receiver is not running */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "Can not stop audio recorder (receiver not running)" << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // not strictly necessary to lock but I think it is safer
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    wav_sink->close();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 0, wav_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 1, wav_sink, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    wav_sink.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_recording_wav = false;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    std::cout << "Audio recorder stopped" << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Start audio playback. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::start_audio_playback(const std::string filename)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!d_running)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        /* receiver is not running */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "Can not start audio playback (receiver not running)" << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    try {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        // output ports set automatically from file
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        wav_src = gr::blocks::wavfile_source::make(filename.c_str(), false);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    catch (std::runtime_error &e) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "Error loading " << filename << ": " << e.what() << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /** FIXME: We can only handle native rate (should maybe use the audio_rr)? */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    unsigned int audio_rate = (unsigned int) d_audio_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (wav_src->sample_rate() != audio_rate)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "BUG: Can not handle sample rate " << wav_src->sample_rate() << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        wav_src.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /** FIXME: We can only handle stereo files */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (wav_src->channels() != 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << "BUG: Can not handle other than 2 channels. File has " << wav_src->channels() << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        wav_src.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /* route demodulator output to null sink */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 0, audio_gain0, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 1, audio_gain1, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 0, audio_fft, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 0, audio_udp_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 1, audio_udp_sink, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 0, audio_null_sink0, 0); /** FIXME: other channel? */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 1, audio_null_sink1, 0); /** FIXME: other channel? */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(wav_src, 0, audio_gain0, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(wav_src, 1, audio_gain1, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(wav_src, 0, audio_fft, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(wav_src, 0, audio_udp_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(wav_src, 1, audio_udp_sink, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    start();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    std::cout << "Playing audio from " << filename << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Stop audio playback. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::stop_audio_playback()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /* disconnect wav source and reconnect receiver */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(wav_src, 0, audio_gain0, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(wav_src, 1, audio_gain1, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(wav_src, 0, audio_fft, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(wav_src, 0, audio_udp_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(wav_src, 1, audio_udp_sink, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 0, audio_null_sink0, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 1, audio_null_sink1, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 0, audio_gain0, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 1, audio_gain1, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 0, audio_fft, 0);  /** FIXME: other channel? */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 0, audio_udp_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 1, audio_udp_sink, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    start();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /* delete wav_src since we can not change file name */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    wav_src.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Start UDP streaming of audio. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::start_udp_streaming(const std::string host, int port, bool stereo)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_udp_sink->start_streaming(host, port, stereo);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Stop UDP streaming of audio. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::stop_udp_streaming()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    audio_udp_sink->stop_streaming();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Start I/Q data recorder.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param filename The filename where to record.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::start_iq_recording(const std::string filename)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    receiver::status status = STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_recording_iq) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << __func__ << ": already recording" << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    try
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        iq_sink = gr::blocks::file_sink::make(sizeof(gr_complex), filename.c_str(), true);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    catch (std::runtime_error &e)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        std::cout << __func__ << ": couldn't open I/Q file" << std::endl;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(input_decim, 0, iq_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(src, 0, iq_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_recording_iq = true;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return status;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Stop I/Q data recorder. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::stop_iq_recording()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!d_recording_iq) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        /* error: we are not recording */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_sink->close();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(input_decim, 0, iq_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->disconnect(src, 0, iq_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    iq_sink.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_recording_iq = false;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Seek to position in IQ file source.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param pos Byte offset from the beginning of the file.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::seek_iq_file(long pos)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    receiver::status status = STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (src->seek(pos, SEEK_SET))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        status = STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        status = STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return status;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Start data sniffer.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @param buffsize The buffer that should be used in the sniffer.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return STATUS_OK if the sniffer was started, STATUS_ERROR if the sniffer is already in use.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::start_sniffer(unsigned int samprate, int buffsize)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_sniffer_active) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        /* sniffer already in use */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    sniffer->set_buffer_size(buffsize);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    sniffer_rr = make_resampler_ff((float)samprate/(float)d_audio_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(rx, 0, sniffer_rr, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(sniffer_rr, 0, sniffer, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_sniffer_active = true;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/**
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @brief Stop data sniffer.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * @return STATUS_ERROR i the sniffer is not currently active.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+receiver::status receiver::stop_sniffer()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!d_sniffer_active) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(rx, 0, sniffer_rr, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->disconnect(sniffer_rr, 0, sniffer, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_sniffer_active = false;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    /* delete resampler */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    sniffer_rr.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return STATUS_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Get sniffer data. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::get_sniffer_data(float * outbuff, unsigned int &num)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    sniffer->get_samples(outbuff, num);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Convenience function to connect all blocks. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::connect_all(rx_chain type)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    gr::basic_block_sptr b;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // Setup source
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    b = src;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // Pre-processing
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim >= 2)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(b, 0, input_decim, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        b = input_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_recording_iq)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        // We record IQ with minimal pre-processing
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(b, 0, iq_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(b, 0, iq_swap, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    b = iq_swap;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_dc_cancel)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(b, 0, dc_corr, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        b = dc_corr;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // Visualization
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tb->connect(b, 0, iq_fft, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // RX demod chain
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    switch (type)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_CHAIN_NBRX:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        if (rx->name() != "NBRX")
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            rx.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            rx = make_nbrx(d_quad_rate, d_audio_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    case RX_CHAIN_WFMRX:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        if (rx->name() != "WFMRX")
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            rx.reset();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            rx = make_wfmrx(d_quad_rate, d_audio_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    default:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        break;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // Audio path (if there is a receiver)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (type != RX_CHAIN_NONE)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(b, 0, rot, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(rot, 0, rx, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(rx, 0, audio_fft, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(rx, 0, audio_udp_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(rx, 1, audio_udp_sink, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(rx, 0, audio_gain0, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(rx, 1, audio_gain1, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(audio_gain0, 0, audio_snk, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(audio_gain1, 0, audio_snk, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    // Recorders and sniffers
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_recording_wav)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(rx, 0, wav_sink, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(rx, 1, wav_sink, 1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_sniffer_active)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(rx, 0, sniffer_rr, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        tb->connect(sniffer_rr, 0, sniffer, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/** Convenience function to update all DDC related components. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::update_ddc()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rot->set_phase_inc(2.0 * M_PI * (-d_filter_offset + d_cw_offset) / d_quad_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::get_rds_data(std::string &outbuff, int &num)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx->get_rds_data(outbuff, num);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::start_rds_decoder(void)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx->start_rds_decoder();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    start();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::stop_rds_decoder(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++void MainWindow::addClusterSpot()
</span> +{
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    stop();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx->stop_rds_decoder();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    start();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    ui->plotter->updateOverlay();
</span> +}
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+bool receiver::is_rds_decoder_active(void) const
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++void MainWindow::checkDXCSpotTimeout()
</span> +{
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return rx->is_rds_decoder_active();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    DXCSpots::Get().checkSpotTimeout();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    ui->plotter->updateOverlay();
</span> +}
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+void receiver::reset_rds_parser(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++void MainWindow::frequencyFocusShortcut()
</span> +{
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    rx->reset_rds_parser();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    ui->freqCtrl->setFrequencyFocus();
</span> +}
<span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git src/applications/gqrx/receiver.h src/applications/gqrx/receiver.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index 109a80d..b577ae9 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- src/applications/gqrx/receiver.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ src/applications/gqrx/receiver.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -31,7 +31,6 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git src/applications/gqrx/mainwindow.h src/applications/gqrx/mainwindow.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index de45c6b..38f15c4 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- src/applications/gqrx/mainwindow.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ src/applications/gqrx/mainwindow.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -32,6 +32,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <QMessageBox>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <QFileDialog>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <QSvgWidget>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <QShortcut>
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include <gnuradio/blocks/file_sink.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include <gnuradio/blocks/null_sink.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--#include <gnuradio/blocks/rotator_cc.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include <gnuradio/blocks/wavfile_sink.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include <gnuradio/blocks/wavfile_source.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include <gnuradio/top_block.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -39,6 +38,7 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include <string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "qtgui/dockrxopt.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "qtgui/dockaudio.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -41,6 +42,8 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "qtgui/dockrds.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "qtgui/afsk1200win.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "qtgui/iq_tool.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include "qtgui/dxc_options.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include "qtgui/dxc_spots.h"
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "dsp/correct_iq_cc.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "dsp/downconverter.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "dsp/filter/fir_decim.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "dsp/rx_noise_blanker_cc.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "dsp/rx_filter.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -226,14 +226,15 @@ public:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "applications/gqrx/remote_control.h"
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>- private:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void        connect_all(rx_chain type);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    void        update_ddc();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -99,6 +102,7 @@ private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     DockRDS        *uiDockRDS;
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>- private:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     bool        d_running;          /*!< Whether receiver is running or not. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     double      d_input_rate;       /*!< Input sample rate. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    double      d_quad_rate;        /*!< Quadrature rate (input_rate / decim) */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    double      d_decim_rate;       /*!< Rate after decimation (input_rate / decim) */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    double      d_quad_rate;        /*!< Quadrature rate (after down-conversion) */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     double      d_audio_rate;       /*!< Audio output rate. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     unsigned int    d_decim;        /*!< input decimation. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    unsigned int    d_ddc_decim;    /*!< Down-conversion decimation. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     double      d_rf_freq;          /*!< Current RF frequency. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     double      d_filter_offset;    /*!< Current filter offset */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     double      d_cw_offset;        /*!< CW offset */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -261,7 +262,7 @@ private:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     rx_fft_c_sptr             iq_fft;     /*!< Baseband FFT block. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     rx_fft_f_sptr             audio_fft;  /*!< Audio FFT block. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     CIqTool        *iq_tool;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    DXC_Options    *dxc_options;
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>--    gr::blocks::rotator_cc::sptr rot;     /*!< Rotator used when only shifting frequency */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    downconverter_cc_sptr     ddc;        /*!< Digital down-converter for demod chain. */
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     gr::blocks::multiply_const_ff::sptr audio_gain0; /*!< Audio gain block. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     gr::blocks::multiply_const_ff::sptr audio_gain1; /*!< Audio gain block. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git src/dsp/CMakeLists.txt src/dsp/CMakeLists.txt
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index daae9fc..3e984e1 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- src/dsp/CMakeLists.txt
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ src/dsp/CMakeLists.txt
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -22,6 +22,8 @@ add_source_files(SRCS_LIST
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   agc_impl.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   correct_iq_cc.cpp
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   correct_iq_cc.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+  downconverter.cpp
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+  downconverter.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   lpf.cpp
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   lpf.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   resampler_xx.cpp
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git src/dsp/downconverter.cpp src/dsp/downconverter.cpp
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-new file mode 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index 0000000..dde591e
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- /dev/null
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ src/dsp/downconverter.cpp
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -0,0 +1,106 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/* -*- c++ -*- */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/*
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Gqrx SDR: Software defined radio receiver powered by GNU Radio and Qt
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *           http://gqrx.dk/
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Copyright 2020 Clayton Smith VE3IRR.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Gqrx is free software; you can redistribute it and/or modify
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * it under the terms of the GNU General Public License as published by
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * the Free Software Foundation; either version 3, or (at your option)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * any later version.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Gqrx is distributed in the hope that it will be useful,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * GNU General Public License for more details.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * You should have received a copy of the GNU General Public License
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * along with Gqrx; see the file COPYING.  If not, write to
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * the Free Software Foundation, Inc., 51 Franklin Street,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Boston, MA 02110-1301, USA.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <math.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <gnuradio/filter/firdes.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <gnuradio/io_signature.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "downconverter.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#define LPF_CUTOFF 120e3
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+downconverter_cc_sptr make_downconverter_cc(unsigned int decim, double center_freq, double samp_rate)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    return gnuradio::get_initial_sptr(new downconverter_cc(decim, center_freq, samp_rate));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+downconverter_cc::downconverter_cc(unsigned int decim, double center_freq, double samp_rate)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    : gr::hier_block2("downconverter_cc",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+          gr::io_signature::make(1, 1, sizeof(gr_complex)),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+          gr::io_signature::make(1, 1, sizeof(gr_complex))),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_decim(decim),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_center_freq(center_freq),
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+      d_samp_rate(samp_rate)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    connect_all();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    update_proto_taps();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    update_phase_inc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+downconverter_cc::~downconverter_cc()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void downconverter_cc::set_decim_and_samp_rate(unsigned int decim, double samp_rate)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_samp_rate = samp_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (decim != d_decim)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        d_decim = decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        lock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        disconnect_all();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect_all();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        unlock();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    update_proto_taps();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    update_phase_inc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void downconverter_cc::set_center_freq(double center_freq)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    d_center_freq = center_freq;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    update_phase_inc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void downconverter_cc::connect_all()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim > 1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        filt = gr::filter::freq_xlating_fir_filter_ccf::make(d_decim, {1}, 0.0, d_samp_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect(self(), 0, filt, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect(filt, 0, self(), 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rot = gr::blocks::rotator_cc::make(0.0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect(self(), 0, rot, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        connect(rot, 0, self(), 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void downconverter_cc::update_proto_taps()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim > 1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        double out_rate = d_samp_rate / d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        filt->set_taps(gr::filter::firdes::low_pass(1.0, d_samp_rate, LPF_CUTOFF, out_rate - 2*LPF_CUTOFF));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+void downconverter_cc::update_phase_inc()
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (d_decim > 1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        filt->set_center_freq(d_center_freq);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        rot->set_phase_inc(-2.0 * M_PI * d_center_freq / d_samp_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git src/dsp/downconverter.h src/dsp/downconverter.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-new file mode 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index 0000000..9c3b55a
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- /dev/null
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ src/dsp/downconverter.h
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -0,0 +1,61 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/* -*- c++ -*- */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+/*
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Gqrx SDR: Software defined radio receiver powered by GNU Radio and Qt
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *           http://gqrx.dk/
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Copyright 2020 Clayton Smith VE3IRR.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Gqrx is free software; you can redistribute it and/or modify
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * it under the terms of the GNU General Public License as published by
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * the Free Software Foundation; either version 3, or (at your option)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * any later version.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Gqrx is distributed in the hope that it will be useful,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * GNU General Public License for more details.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ *
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * You should have received a copy of the GNU General Public License
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * along with Gqrx; see the file COPYING.  If not, write to
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * the Free Software Foundation, Inc., 51 Franklin Street,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ * Boston, MA 02110-1301, USA.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+ */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#pragma once
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#if GNURADIO_VERSION < 0x030800
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <gnuradio/filter/freq_xlating_fir_filter_ccf.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <gnuradio/filter/freq_xlating_fir_filter.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <gnuradio/blocks/rotator_cc.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include <gnuradio/hier_block2.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+class downconverter_cc;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+typedef boost::shared_ptr<downconverter_cc> downconverter_cc_sptr;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+downconverter_cc_sptr make_downconverter_cc(unsigned int decim, double center_freq, double samp_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+class downconverter_cc : public gr::hier_block2
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    friend downconverter_cc_sptr make_downconverter_cc(unsigned int decim, double center_freq, double samp_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+public:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    downconverter_cc(unsigned int decim, double center_freq, double samp_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    ~downconverter_cc();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void set_decim_and_samp_rate(unsigned int decim, double samp_rate);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void set_center_freq(double center_freq);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+private:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    unsigned int d_decim;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    double d_center_freq;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    double d_samp_rate;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    std::vector<float> d_proto_taps;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void connect_all();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void update_proto_taps();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void update_phase_inc();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     /* data decoders */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -110,6 +114,7 @@ private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     QTimer   *iq_fft_timer;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     QTimer   *audio_fft_timer;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     QTimer   *rds_timer;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    QTimer   *dxc_timer;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     receiver *rx;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -126,6 +131,8 @@ private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void updateGainStages(bool read_from_device);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void showSimpleTextFile(const QString &resource_path,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                             const QString &window_title);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    /* key shortcut */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    void frequencyFocusShortcut();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ private slots:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     /* rf */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -201,6 +208,9 @@ private slots:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     /* Bookmarks */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void onBookmarkActivated(qint64 freq, QString demod, int bandwidth);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    /* DXC Spots */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    void addClusterSpot();
</span> +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    gr::filter::freq_xlating_fir_filter_ccf::sptr filt;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    gr::blocks::rotator_cc::sptr rot;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     /* menu and toolbar actions */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void on_actionDSP_triggered(bool checked);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     int  on_actionIoConfig_triggered();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -218,6 +228,7 @@ private slots:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void on_actionAbout_triggered();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void on_actionAboutQt_triggered();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void on_actionAddBookmark_triggered();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    void on_actionDX_Cluster_triggered();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     /* window close signals */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -230,6 +241,7 @@ private slots:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void iqFftTimeout();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void audioFftTimeout();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void rdsTimeout();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    void checkDXCSpotTimeout();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #endif // MAINWINDOW_H
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git src/applications/gqrx/mainwindow.ui src/applications/gqrx/mainwindow.ui
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 0fb1f36..dc39a81 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- src/applications/gqrx/mainwindow.ui
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ src/applications/gqrx/mainwindow.ui
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -195,7 +195,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      <x>0</x>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      <y>0</y>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      <width>521</width>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-     <height>19</height>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++     <height>22</height>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     </rect>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    </property>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <widget class="QMenu" name="menu_File">
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -242,6 +242,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     <addaction name="separator"/>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     <addaction name="actionAFSK1200"/>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     <addaction name="separator"/>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    <addaction name="actionDX_Cluster"/>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    </widget>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <addaction name="menu_File"/>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <addaction name="menu_Tools"/>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -541,6 +542,17 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     <string>Ctrl+W</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    </property>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   </action>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  <action name="actionDX_Cluster">
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   <property name="text">
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    <string>DX Cluster</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   </property>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   <property name="toolTip">
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    <string>Open DX Cluster Dialog</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   </property>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   <property name="shortcut">
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    <string>Ctrl+C</string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   </property>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  </action>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  </widget>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  <layoutdefault spacing="6" margin="11"/>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  <customwidgets>
</span> diff --git src/dsp/rx_noise_blanker_cc.cpp src/dsp/rx_noise_blanker_cc.cpp
 index c8e2447..ae9fd2b 100644
 --- src/dsp/rx_noise_blanker_cc.cpp
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3991,7 +2229,7 @@ index 0000000..c7b0d00
</span> +
 +#endif // DXC_SPOTS_H
 diff --git src/qtgui/freqctrl.cpp src/qtgui/freqctrl.cpp
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index ed419ed..976cc5e 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index ed419ed..d9dd132 100644
</span> --- src/qtgui/freqctrl.cpp
 +++ src/qtgui/freqctrl.cpp
 @@ -484,6 +484,7 @@ void CFreqCtrl::keyPressEvent(QKeyEvent *event)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4007,20 +2245,20 @@ index ed419ed..976cc5e 100644
</span>      }
  }
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+void CFreqCtrl::cursorTo(uint8_t position)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    cursor().setPos(mapToGlobal(m_DigitInfo[position].dQRect.center()));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span> +void CFreqCtrl::setFrequencyFocus()
 +{
 +    uint8_t position = floor(log10(m_freq));
 +    position = (uint8_t)fmax(position, 4);      // restrict min to 100s of kHz
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    cursorTo(position);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    QMouseEvent *mouseEvent = new QMouseEvent(QEvent::MouseMove,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                                              m_DigitInfo[position].dQRect.center(),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                                              Qt::NoButton,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                                              Qt::NoButton,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                                              Qt::NoModifier);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    mouseMoveEvent(mouseEvent);
</span> +}
 diff --git src/qtgui/freqctrl.h src/qtgui/freqctrl.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 08143ab..38dc92c 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 08143ab..adeea2a 100644
</span> --- src/qtgui/freqctrl.h
 +++ src/qtgui/freqctrl.h
 @@ -56,6 +56,7 @@ signals:
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4031,14 +2269,6 @@ index 08143ab..38dc92c 100644
</span>  
  protected:
      void    paintEvent(QPaintEvent *);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -77,6 +78,7 @@ private:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void    clearFreq();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void    cursorHome();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void    cursorEnd();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    void    cursorTo(uint8_t position);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void    moveCursorLeft();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     void    moveCursorRight();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     bool    inRect(QRect &rect, QPoint &point);
</span> diff --git src/qtgui/plotter.cpp src/qtgui/plotter.cpp
 index a9d9cff..aaf5950 100644
 --- src/qtgui/plotter.cpp
</pre><pre style='margin:0'>

</pre>