From 6213e79898ec96f6e496df63db65cefa046e0108 Mon Sep 17 00:00:00 2001
From: Ruslan Migirov <trapi78@gmail.com>
Date: Tue, 1 Oct 2024 03:52:07 +0300
Subject: [PATCH] Implement device enumeration using SoapySDR

---
 src/applications/gqrx/receiver.cpp | 27 ++++++++++++++++++++++-----
 src/qtgui/ioconfig.cpp             | 23 ++++++++++++++++-------
 2 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/src/applications/gqrx/receiver.cpp b/src/applications/gqrx/receiver.cpp
index 5320c05957..1289ad8962 100644
--- a/src/applications/gqrx/receiver.cpp
+++ b/src/applications/gqrx/receiver.cpp
@@ -31,6 +31,7 @@
 #include <osmosdr/source.h>
 #include <gnuradio/soapy/source.h>
 #include <osmosdr/ranges.h>
+#include <SoapySDR/Device.hpp>
 
 #include "applications/gqrx/receiver.h"
 #include "dsp/correct_iq_cc.h"
@@ -80,14 +81,30 @@ receiver::receiver(const std::string input_device,
 
     if (input_device.empty())
     {
-        //src = osmosdr::source::make("file="+escape_filename(get_zero_file())+",freq=428e6,rate=96000,repeat=true,throttle=true");
-        soapy_src = gr::soapy::source::make("driver=rtlsdr","fc32",1,"","",{""},{""});
+        std::vector<SoapySDR::Kwargs> devices = SoapySDR::Device::enumerate();
+
+        if (devices.empty())
+        {
+            std::cerr << "No SoapySDR devices found." << std::endl;
+            throw std::runtime_error("No SoapySDR devices found.");
+        }
+        else
+        {
+            SoapySDR::Kwargs device = devices[0];
+            std::cout << "Selected Device Properties" << std::endl;
+            for (SoapySDR::Kwargs::const_iterator it = device.begin(); it != device.end(); it++)
+            {
+                std::cout << "  " << it->first << " = " << it->second << std::endl;
+            }
+
+            std::string input_device = std::string("driver=") + device["driver"];
+            soapy_src = gr::soapy::source::make(input_device,"fc32",1);
+        }
     }
     else
     {
         input_devstr = input_device;
-        //src = osmosdr::source::make(input_device);
-        soapy_src = gr::soapy::source::make(input_device,"",0,"","",{""},{""});
+        soapy_src = gr::soapy::source::make(input_device,"fc32",1);
     }
 
     // input decimator
@@ -229,7 +246,7 @@ void receiver::set_input_device(const std::string device)
     try
     {
         //src = osmosdr::source::make(device);
-        soapy_src = gr::soapy::source::make("driver=rtlsdr","fc32",1,"","",{""},{""});
+        soapy_src = gr::soapy::source::make(input_devstr,"fc32",1);
     }
     catch (std::exception &x)
     {
diff --git a/src/qtgui/ioconfig.cpp b/src/qtgui/ioconfig.cpp
index c0f0b033e1..939b05c4e6 100644
--- a/src/qtgui/ioconfig.cpp
+++ b/src/qtgui/ioconfig.cpp
@@ -33,6 +33,8 @@
 #include <osmosdr/source.h>
 #include <osmosdr/ranges.h>
 
+#include <SoapySDR/Device.hpp>
+
 #ifdef WITH_PULSEAUDIO
 #include "pulseaudio/pa_device_list.h"
 #elif WITH_PORTAUDIO
@@ -138,24 +140,31 @@ void CIoConfig::getDeviceList(std::map<QString, QVariant> &devList)
     }
 #endif
 
-    // Get list of input devices discovered by gr-osmosdr and store them in
+    // Get list of input devices discovered by gr-soapy and store them in
     // the device list together with the device descriptor strings
-    osmosdr::devices_t devs = osmosdr::device::find();
+    std::vector<SoapySDR::Kwargs> devices = SoapySDR::Device::enumerate();
 
     qDebug() << __FUNCTION__ << ": Available input devices:";
-    for (auto &dev : devs)
+    for (const auto &dev : devices)
     {
+        // Get the device label
         if (dev.count("label"))
         {
-            devlabel = QString(dev["label"].c_str());
-            dev.erase("label");
+            devlabel = QString::fromStdString(dev.at("label"));
         }
         else
         {
-            devlabel = "Unknown";
+            // Construct a label from driver and serial if label is not available
+            QString driver = dev.count("driver") ? QString::fromStdString(dev.at("driver")) : "Unknown";
+            QString serial = dev.count("serial") ? QString::fromStdString(dev.at("serial")) : "";
+            devlabel = QString("%1 (%2)").arg(driver, serial);
         }
 
-        devstr = QString(escapeDevstr(dev.to_string()).c_str());
+        // Serialize the device arguments
+        std::string device_args = SoapySDR::KwargsToString(dev);
+        devstr = QString::fromStdString(device_args);
+
+        // Insert into the device list
         devList.insert(std::pair<QString, QVariant>(devlabel, devstr));
         qDebug() << "  " << devlabel;
     }