From ce5916acefe70a3dd1a8a8165cec718dcb91434d Mon Sep 17 00:00:00 2001
From: Wolfgang Fritz <wolfgang.fritz@gmx.net>
Date: Thu, 31 Mar 2016 18:25:02 +0200
Subject: [PATCH] Probe SDR devices only at program start

The probing of SDR devices is only done once before the first
configuration isn done. Later the cached list of devices is used. Reason
for this is that some devices (SDRPlay RSP) get reinitialized during
device probe and lose their configuration.
---
 src/applications/gqrx/mainwindow.cpp |   9 ++-
 src/applications/gqrx/mainwindow.h   |   2 +
 src/qtgui/ioconfig.cpp               | 134 +++++++++++++++++++----------------
 src/qtgui/ioconfig.h                 |   3 +-
 4 files changed, 84 insertions(+), 64 deletions(-)

diff --git a/src/applications/gqrx/mainwindow.cpp b/src/applications/gqrx/mainwindow.cpp
index 671f978..c20766a 100644
--- a/src/applications/gqrx/mainwindow.cpp
+++ b/src/applications/gqrx/mainwindow.cpp
@@ -280,6 +280,10 @@ MainWindow::MainWindow(const QString cfgfile, bool edit_conf, QWidget *parent) :
     ui->plotter->setTooltipsEnabled(true);
 #endif
 
+    // Create list of input devices. This must be done before the configuration is
+    // restored because device probing might change the device configuration
+    CIoConfig::getDeviceList(devList);
+
     // restore last session
     if (!loadConfig(cfgfile, true))
     {
@@ -1716,7 +1720,7 @@ int MainWindow::on_actionIoConfig_triggered()
 {
     qDebug() << "Configure I/O devices.";
 
-    CIoConfig *ioconf = new CIoConfig(m_settings);
+    CIoConfig *ioconf = new CIoConfig(m_settings, devList);
     int confres = ioconf->exec();
 
     if (confres == QDialog::Accepted)
@@ -1744,7 +1748,7 @@ int MainWindow::firstTimeConfig()
 {
     qDebug() << __func__;
 
-    CIoConfig *ioconf = new CIoConfig(m_settings);
+    CIoConfig *ioconf = new CIoConfig(m_settings, devList);
     int confres = ioconf->exec();
 
     if (confres == QDialog::Accepted)
@@ -2093,6 +2097,7 @@ void MainWindow::showSimpleTextFile(const QString &resource_path,
     // browser and layout deleted automatically
 }
 
+
 /**
  * @brief Action: About Qthid
  *
diff --git a/src/applications/gqrx/mainwindow.h b/src/applications/gqrx/mainwindow.h
index f3c702b..2160777 100644
--- a/src/applications/gqrx/mainwindow.h
+++ b/src/applications/gqrx/mainwindow.h
@@ -116,6 +116,8 @@ private:
 
     RemoteControl *remote;
 
+    std::map<QString, QVariant> devList;
+
 private:
     void updateHWFrequencyRange(bool ignore_limits);
     void updateFrequencyRange();
diff --git a/src/qtgui/ioconfig.cpp b/src/qtgui/ioconfig.cpp
index 83603ed..7e1b881 100644
--- a/src/qtgui/ioconfig.cpp
+++ b/src/qtgui/ioconfig.cpp
@@ -44,69 +44,26 @@
 #include "ui_ioconfig.h"
 
 
-CIoConfig::CIoConfig(QSettings *settings, QWidget *parent) :
+CIoConfig::CIoConfig(QSettings *settings, std::map<QString, QVariant> &devList, QWidget *parent) :
     QDialog(parent),
     ui(new Ui::CIoConfig),
     m_settings(settings)
 {
     unsigned int i=0;
     QString devstr;
-    QString devlabel;
     bool cfgmatch=false; //flag to indicate that device from config was found
 
     ui->setupUi(this);
 
     QString indev = settings->value("input/device", "").toString();
 
-    // automatic discovery of FCD does not work on Mac
-    // so we do it ourselves
-#if defined(GQRX_OS_MACX)
-    osxaudio_device_list devices;
-    inDevList = devices.get_input_devices();
-
-    string this_dev;
-    for (i = 0; i < inDevList.size(); i++)
+    // insert the device list in device combo box
+    std::map<QString, QVariant>::iterator I = devList.begin();
+    i = 0;
+    while (I != devList.end())
     {
-        this_dev = inDevList[i].get_name();
-        if (this_dev.find("FUNcube Dongle V1.0") != string::npos)
-        {
-            devstr = "fcd,type=1,device='FUNcube Dongle V1.0'";
-            ui->inDevCombo->addItem("FUNcube Dongle V1.0", QVariant(devstr));
-        }
-        else if (this_dev.find("FUNcube Dongle V2.0") != string::npos)
-        {
-            devstr = "fcd,type=2,device='FUNcube Dongle V2.0'";
-            ui->inDevCombo->addItem("FUNcube Dongle V2.0", QVariant(devstr));
-        }
-
-        if (indev == QString(inDevList[i].get_name().c_str()))
-        {
-            ui->inDevCombo->setCurrentIndex(i);
-            ui->inDevEdit->setText(devstr);
-            cfgmatch = true;
-        }
-    }
-#endif
-
-    // Get list of input devices discovered by gr-osmosdr and store them in
-    // the input device selector together with the device descriptor strings
-    osmosdr::devices_t devs = osmosdr::device::find();
-
-    qDebug() << __FUNCTION__ << ": Available input devices:";
-    BOOST_FOREACH(osmosdr::device_t &dev, devs)
-    {
-        if (dev.count("label"))
-        {
-            devlabel = QString(dev["label"].c_str());
-            dev.erase("label");
-        }
-        else
-        {
-            devlabel = "Unknown";
-        }
-
-        devstr = QString(dev.to_string().c_str());
-        ui->inDevCombo->addItem(devlabel, QVariant(devstr));
+        devstr = (*I).second.toString();
+        ui->inDevCombo->addItem((*I).first, devstr);
 
         // is this the device stored in config?
         if (indev == devstr)
@@ -115,20 +72,11 @@ CIoConfig::CIoConfig(QSettings *settings, QWidget *parent) :
             ui->inDevEdit->setText(devstr);
             cfgmatch = true;
         }
-
-        qDebug() << "   " << i << ":"  << devlabel;
+        ++I;
         ++i;
-
-        // Following code could be used for multiple matches
-        /* QStringList list;
-        int pos = 0;
-        while ((pos = rx.indexIn(devstr, pos)) != -1) {
-            list << rx.cap(1);
-            pos += rx.matchedLength();
-        } */
-
     }
 
+
     ui->inDevCombo->addItem(tr("Other..."), QVariant(""));
 
     // If device string from config is not one of the detected devices
@@ -221,6 +169,70 @@ CIoConfig::~CIoConfig()
     delete ui;
 }
 
+/**
+ * @brief get the list of devices
+ */
+void CIoConfig::getDeviceList(std::map<QString, QVariant> &devList)
+{
+    unsigned int i=0;
+    QString devstr;
+    QString devlabel;
+
+#if defined(GQRX_OS_MACX)
+    // automatic discovery of FCD does not work on Mac
+    // so we do it ourselves
+    osxaudio_device_list devices;
+    inDevList = devices.get_input_devices();
+
+    string this_dev;
+    for (i = 0; i < inDevList.size(); i++)
+    {
+        this_dev = inDevList[i].get_name();
+        if (this_dev.find("FUNcube Dongle V1.0") != string::npos)
+        {
+            devstr = "fcd,type=1,device='FUNcube Dongle V1.0'";
+            devList.insert(std::pair<QString, QVariant>(QString("FUNcube Dongle V1.0"), QVariant(devstr)));
+        }
+        else if (this_dev.find("FUNcube Dongle V2.0") != string::npos)
+        {
+            devstr = "fcd,type=2,device='FUNcube Dongle V2.0'";
+            devList.insert(std::pair<QString, QVariant>(QString("FUNcube Dongle V2.0"), QVariant(devstr)));
+        }
+    }
+#endif
+
+    // Get list of input devices discovered by gr-osmosdr and store them in
+    // the device list together with the device descriptor strings
+    osmosdr::devices_t devs = osmosdr::device::find();
+
+    qDebug() << __FUNCTION__ << ": Available input devices:";
+    BOOST_FOREACH(osmosdr::device_t &dev, devs)
+    {
+        if (dev.count("label"))
+        {
+            devlabel = QString(dev["label"].c_str());
+            dev.erase("label");
+        }
+        else
+        {
+            devlabel = "Unknown";
+        }
+
+        devstr = QString(dev.to_string().c_str());
+        devList.insert(std::pair<QString, QVariant>(devlabel, devstr));
+
+        qDebug() << "   " << i << ":"  << devlabel;
+        ++i;
+
+        // Following code could be used for multiple matches
+        /* QStringList list;
+        int pos = 0;
+        while ((pos = rx.indexIn(devstr, pos)) != -1) {
+            list << rx.cap(1);
+            pos += rx.matchedLength();
+        } */
+    }
+}
 
 /** @brief Save configuration. */
 void CIoConfig::saveConfig()
diff --git a/src/qtgui/ioconfig.h b/src/qtgui/ioconfig.h
index 016a15c..cfb75e7 100644
--- a/src/qtgui/ioconfig.h
+++ b/src/qtgui/ioconfig.h
@@ -44,8 +44,9 @@ class CIoConfig : public QDialog
     Q_OBJECT
 
 public:
-    explicit CIoConfig(QSettings *settings, QWidget *parent = 0);
+    explicit CIoConfig(QSettings *settings, std::map<QString, QVariant> &devList, QWidget *parent = 0);
     virtual ~CIoConfig();
+    static void getDeviceList(std::map<QString, QVariant> &devList);
 
 private slots:
     void saveConfig();
-- 
1.9.1

