Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package soapy-uhd for openSUSE:Factory 
checked in at 2026-10-05 16:18:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/soapy-uhd (Old)
 and      /work/SRC/openSUSE:Factory/.soapy-uhd.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "soapy-uhd"

Mon Oct  5 16:18:55 2026 rev:13 rq:1382552 version:0.4.1git20261004

Changes:
--------
--- /work/SRC/openSUSE:Factory/soapy-uhd/soapy-uhd.changes      2026-09-01 
15:48:04.430164423 +0200
+++ /work/SRC/openSUSE:Factory/.soapy-uhd.new.3698736/soapy-uhd.changes 
2026-10-05 16:19:15.125841220 +0200
@@ -1,0 +2,35 @@
+Mon Oct  5 08:03:53 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 0.4.1git20261004 (a6134ed1), 14 new commits:
+  * Require UHD >= 4.0; upstream dropped the UHD 3.x code paths but
+    never landed its find_package(UHD 4.0) gate, so the spec's
+    pkgconfig(uhd) >= 4.0 floor is the only guard (SoapyUHD#72)
+  * Advertise the UHD 4.10 'mtu' stream argument (SoapyUHD#67),
+    handle UHD 4.10's EVENT_CODE_OK (SoapyUHD#70) and define
+    get_stream_info for UHD >= 4.11 (SoapyUHD#78)
+  * Map ERROR_CODE_LATE_COMMAND to SOAPY_SDR_TIME_ERROR instead of
+    SOAPY_SDR_STREAM_ERROR, so callers can tell timing failures
+    from generic stream errors (SoapyUHD#69)
+  * Fix hasIQBalanceMode() falling back to hasDCOffsetMode()
+    (SoapyUHD#69)
+  * Cache the stream channel count instead of making a virtual call
+    per packet in the read/write path (SoapyUHD#68)
+  * CMake: minimum 3.10, SoapySDR >= 0.7, target-scoped instead of
+    global compile flags (SoapyUHD#71)
+- Drop boost.patch, boost-lexical-cast.patch and cxx17.patch: all
+  three adopted upstream (SoapyUHD#64, #69 and #70 respectively)
+- Require pkgconfig(uhd) >= 4.0 and pkgconfig(SoapySDR) >= 0.7
+- BuildRequires: libboost_headers-devel replaces
+  libboost_chrono-devel, libboost_date_time-devel and
+  libboost_thread-devel; find_package(Boost) no longer requests
+  components
+- Drop the CMAKE_POLICY_VERSION_MINIMUM=3.5 workaround: upstream
+  raised cmake_minimum_required to 3.10
+- Add a _service pinning the upstream git commit, and replace
+  soapy-uhd-0.4.1git20250213.tar.gz with
+  soapy-uhd-0.4.1git20261004.tar.gz: the GitHub archive Source URL
+  404s for a date-based version
+- Enable %check: run upstream's unit tests (15 hardware-free
+  cases), the package's only rpmlint warning
+
+-------------------------------------------------------------------

Old:
----
  boost-lexical-cast.patch
  boost.patch
  cxx17.patch
  soapy-uhd-0.4.1git20250213.tar.gz

New:
----
  _service
  soapy-uhd-0.4.1git20261004.tar.gz

----------(Old B)----------
  Old:    global compile flags (SoapyUHD#71)
- Drop boost.patch, boost-lexical-cast.patch and cxx17.patch: all
  three adopted upstream (SoapyUHD#64, #69 and #70 respectively)
  Old:    global compile flags (SoapyUHD#71)
- Drop boost.patch, boost-lexical-cast.patch and cxx17.patch: all
  three adopted upstream (SoapyUHD#64, #69 and #70 respectively)
  Old:    global compile flags (SoapyUHD#71)
- Drop boost.patch, boost-lexical-cast.patch and cxx17.patch: all
  three adopted upstream (SoapyUHD#64, #69 and #70 respectively)
----------(Old E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ soapy-uhd.spec ++++++
--- /var/tmp/diff_new_pack.aQkgib/_old  2026-10-05 16:19:16.339891876 +0200
+++ /var/tmp/diff_new_pack.aQkgib/_new  2026-10-05 16:19:16.343892043 +0200
@@ -20,28 +20,27 @@
 %define soapy_modver 0.8-3
 %define soapy_modname soapysdr%{soapy_modver}-module-uhd
 Name:           soapy-uhd
-Version:        0.4.1git20250213
+Version:        0.4.1git20261004
 Release:        0
 Summary:        Soapy SDR plugins for UHD supported SDR devices
 # The three built sources carry the deprecated SPDX id GPL-3.0, which maps
-# to GPL-3.0-only; the only or-later grant is in CMakeLists.txt, not shipped.
+# to GPL-3.0-only. Upstream set that id deliberately in commit ac3ce7f ("The
+# intended license is GPL-3 to match libuhd license"); the files were
+# BSL-1.0 before it. The only or-later wording in the tree is GNU Radio's,
+# inherited into CMakeLists.txt, which is neither built nor shipped.
 License:        GPL-3.0-only
 URL:            https://github.com/pothosware/SoapyUHD/wiki
 #Git-Clone:     https://github.com/pothosware/SoapyUHD.git
-Source:         
https://github.com/pothosware/SoapyUHD/archive/%{name}-%{version}.tar.gz
-Patch0:         boost.patch
-# PATCH-FIX-UPSTREAM cxx17.patch pothosware/SoapyUHD#75 - build with C++17 
(UHD 4.x headers use std::optional / std::is_convertible_v)
-Patch1:         cxx17.patch
-# PATCH-FIX-UPSTREAM boost-lexical-cast.patch pothosware/SoapyUHD#76 - include 
boost/lexical_cast.hpp explicitly (newer boost dropped the transitive include)
-Patch2:         boost-lexical-cast.patch
+Source:         %{name}-%{version}.tar.gz
 BuildRequires:  cmake
 BuildRequires:  gcc-c++
-BuildRequires:  libboost_chrono-devel
-BuildRequires:  libboost_date_time-devel
-BuildRequires:  libboost_thread-devel
+# upstream dropped BOOST_REQUIRED_COMPONENTS; only the headers are used now
+BuildRequires:  libboost_headers-devel
 BuildRequires:  pkgconfig
-BuildRequires:  pkgconfig(SoapySDR)
-BuildRequires:  pkgconfig(uhd)
+# CMakeLists.txt: find_package(SoapySDR "0.7" NO_MODULE REQUIRED)
+BuildRequires:  pkgconfig(SoapySDR) >= 0.7
+# SoapyUHD#72 dropped all UHD < 4.0 code paths
+BuildRequires:  pkgconfig(uhd) >= 4.0
 
 %description
 Soapy UHD - Soapy SDR devices for UHD.
@@ -63,15 +62,15 @@
 A UHD module that supports Soapy devices within the UHD API.
 
 %prep
-%autosetup -p1 -n SoapyUHD
+%autosetup -p1 -n %{name}-%{version}
 
 %build
-# Remove cmake4 error due to not setting
-# min cmake version - sflees.de
-export CMAKE_POLICY_VERSION_MINIMUM=3.5
 %cmake
 %cmake_build
 
+%check
+%ctest
+
 %install
 %cmake_install
 

++++++ _service ++++++
<services>
  <!-- upstream's newest tag is soapy-uhd-0.4.1 (2020-09-20); everything
       since then is unreleased, so pin a commit -->
  <service name="tar_scm" mode="manual">
    <param name="url">https://github.com/pothosware/SoapyUHD.git</param>
    <param name="scm">git</param>
    <param name="revision">a6134ed1360df65e1bb4a52ac523efad9e39ab2f</param>
    <param name="versionformat">0.4.1git%cd</param>
    <param name="filename">soapy-uhd</param>
    <param name="changesgenerate">disable</param>
  </service>
  <service name="recompress" mode="manual">
    <param name="file">*.tar</param>
    <param name="compression">gz</param>
  </service>
</services>
(No newline at EOF)

++++++ soapy-uhd-0.4.1git20250213.tar.gz -> soapy-uhd-0.4.1git20261004.tar.gz 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/.github/workflows/build.yml 
new/soapy-uhd-0.4.1git20261004/.github/workflows/build.yml
--- old/SoapyUHD/.github/workflows/build.yml    1970-01-01 01:00:00.000000000 
+0100
+++ new/soapy-uhd-0.4.1git20261004/.github/workflows/build.yml  2026-10-04 
19:53:23.000000000 +0200
@@ -0,0 +1,65 @@
+name: Build check
+on:
+  push:
+  pull_request:
+  workflow_dispatch:
+
+jobs:
+  macos_macports_build_job:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [macos-15, macos-26]
+    runs-on: ${{ matrix.os }}
+    name: Build on ${{ matrix.os }} (macports)
+    steps:
+      - uses: actions/checkout@v7
+      - uses: melusina-org/setup-macports@v1
+      - name: Install ports
+        run: port install SoapySDR py310-setuptools uhd-devel
+        # Note: MacPorts uhd-devel depends on non-default boost181
+      - name: Configure
+        run:  BOOST_ROOT=/opt/local/libexec/boost/1.81 cmake -B build
+      - name: Build
+        run: cmake --build build
+      - name: Test
+        run: ctest --test-dir build --output-on-failure
+
+  macos_homebrew_build_job:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [macos-15, macos-26]
+    runs-on: ${{ matrix.os }}
+    name: Build on ${{ matrix.os }} (homebrew)
+    steps:
+      - uses: actions/checkout@v7
+      - name: Setup tools
+        run: brew install soapysdr uhd
+      - name: Configure
+        run: cmake -B build
+      - name: Build
+        run: cmake --build build
+      - name: Test
+        run: ctest --test-dir build --output-on-failure
+
+  linux_build_job:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-22.04, ubuntu-24.04]
+    runs-on: ${{ matrix.os }}
+    name: Build on ${{ matrix.os }}
+    steps:
+      - uses: actions/checkout@v7
+      - name: Setup tools
+        run: |
+          sudo apt-get update -q -y
+          sudo apt-get install -y --no-install-recommends cmake ninja-build
+          sudo apt-get install -q -y libsoapysdr-dev libuhd-dev
+      - name: Configure
+        run: cmake -GNinja -B build
+      - name: Build
+        run: cmake --build build
+      - name: Test
+        run: ctest --test-dir build --output-on-failure
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/.gitignore 
new/soapy-uhd-0.4.1git20261004/.gitignore
--- old/SoapyUHD/.gitignore     1970-01-01 01:00:00.000000000 +0100
+++ new/soapy-uhd-0.4.1git20261004/.gitignore   2026-10-04 19:53:23.000000000 
+0200
@@ -0,0 +1 @@
+/build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/.travis.yml 
new/soapy-uhd-0.4.1git20261004/.travis.yml
--- old/SoapyUHD/.travis.yml    2021-05-01 11:16:23.067447504 +0200
+++ new/soapy-uhd-0.4.1git20261004/.travis.yml  1970-01-01 01:00:00.000000000 
+0100
@@ -1,60 +0,0 @@
-########################################################################
-## Travis CI config for SoapyUHD
-##
-## * installs UHD from PPA
-## * installs SoapySDR from source
-## * matrix tests multiple UHD versions
-## * confirms build and install
-## * checks that drivers load
-########################################################################
-
-sudo: required
-dist: focal
-
-language: cpp
-compiler: gcc
-
-env:
-  global:
-    - INSTALL_PREFIX=/usr/local
-    - SOAPY_SDR_BRANCH=master
-  matrix:
-    - BUILD_TYPE=Debug
-    - BUILD_TYPE=Release
-
-before_install:
-  # regular ubuntu packages
-  - sudo add-apt-repository main
-  - sudo add-apt-repository universe
-
-  # driver development files from ppa
-  - sudo add-apt-repository -y ppa:ettusresearch/uhd
-
-  # update after package changes
-  - sudo apt-get update
-
-install:
-  #boost development files
-  - sudo apt-get install -qq libboost-all-dev
-
-  #sdr development files
-  - sudo apt-get install --no-install-recommends -q -y libuhd-dev
-
-  # install SoapySDR from source
-  - git clone https://github.com/pothosware/SoapySDR.git
-  - pushd SoapySDR
-  - git checkout ${SOAPY_SDR_BRANCH}
-  - mkdir build && cd build
-  - cmake ../ -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} 
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_PYTHON=OFF -DENABLE_PYTHON3=OFF
-  - make && sudo make install
-  - popd
-
-script:
-  - mkdir build && cd build
-  - cmake ../ -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} 
-DCMAKE_BUILD_TYPE=${BUILD_TYPE}
-  - make && sudo make install
-  # print info about the install
-  - export LD_LIBRARY_PATH=${INSTALL_PREFIX}/lib:${LD_LIBRARY_PATH}
-  - export PATH=${INSTALL_PREFIX}/bin:${PATH}
-  - SoapySDRUtil --info
-  - SoapySDRUtil --check=uhd
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/CMakeLists.txt 
new/soapy-uhd-0.4.1git20261004/CMakeLists.txt
--- old/SoapyUHD/CMakeLists.txt 2021-11-16 23:31:11.009881523 +0100
+++ new/soapy-uhd-0.4.1git20261004/CMakeLists.txt       2026-10-04 
19:53:23.000000000 +0200
@@ -21,23 +21,40 @@
 ########################################################################
 # Project setup
 ########################################################################
-cmake_minimum_required(VERSION 2.8.7)
+cmake_minimum_required(VERSION 3.10...3.30)
 project(SoapyUHD CXX C)
 enable_testing()
 
-set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD 17)
+
+option(BUILD_UHD_SUPPORT   "Build the SoapySDR-side module exposing UHD 
devices to SoapySDR"   ON)
+option(BUILD_SOAPY_SUPPORT "Build the UHD-side module exposing Soapy devices 
to UHD"          ON)
+
+if(NOT BUILD_UHD_SUPPORT AND NOT BUILD_SOAPY_SUPPORT)
+    message(FATAL_ERROR "Both BUILD_UHD_SUPPORT and BUILD_SOAPY_SUPPORT are 
OFF -- nothing to build.")
+endif()
 
 #select the release build type by default to get optimization flags
 if(NOT CMAKE_BUILD_TYPE)
-   set(CMAKE_BUILD_TYPE "Release")
-   message(STATUS "Build type not specified: defaulting to release.")
+    set(CMAKE_BUILD_TYPE "Release")
+    message(STATUS "Build type not specified: defaulting to release.")
 endif(NOT CMAKE_BUILD_TYPE)
 set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "")
 
 ########################################################################
+# Setup SoapySDR and set default modules location
+########################################################################
+find_package(SoapySDR "0.7" NO_MODULE REQUIRED)
+
+get_filename_component(_SoapySDR_ROOT "${SoapySDR_INCLUDE_DIRS}/.." ABSOLUTE)
+message(STATUS "SoapySDR root directory: ${_SoapySDR_ROOT}")
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND NOT "${_SoapySDR_ROOT}" 
STREQUAL "/usr")
+    set_property(CACHE CMAKE_INSTALL_PREFIX PROPERTY VALUE ${_SoapySDR_ROOT})
+endif()
+
+########################################################################
 # Dependencies
 ########################################################################
-find_package(SoapySDR "0.6" NO_MODULE REQUIRED)
 find_package(UHD NO_MODULE)
 
 #try old-style find script
@@ -47,8 +64,7 @@
 endif()
 
 if (NOT UHD_FOUND)
-    message(WARNING "UHD not found -- required for Soapy UHD support")
-    return()
+    message(FATAL_ERROR "UHD not found -- required for Soapy UHD support")
 endif()
 
 if (NOT UHD_ROOT)
@@ -57,10 +73,9 @@
 message(STATUS "UHD root directory: ${UHD_ROOT}")
 message(STATUS "UHD include directories: ${UHD_INCLUDE_DIRS}")
 message(STATUS "UHD libraries: ${UHD_LIBRARIES}")
+message(STATUS "UHD version: ${UHD_VERSION}")
 
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-include_directories(${SoapySDR_INCLUDE_DIRS})
-include_directories(${UHD_INCLUDE_DIRS})
+set(UHD_FEATURE_DEFS "")
 
 message(STATUS "Checking uhd::device::register_device() API...")
 message(STATUS "  Reading ${UHD_INCLUDE_DIRS}/uhd/device.hpp...")
@@ -69,7 +84,7 @@
 if ("${has_device_filter}" STREQUAL "-1")
     message(STATUS "  has original API")
 else()
-    add_definitions(-DUHD_HAS_DEVICE_FILTER)
+    list(APPEND UHD_FEATURE_DEFS UHD_HAS_DEVICE_FILTER)
     message(STATUS "  has filter API")
 endif()
 
@@ -80,7 +95,7 @@
 if ("${has_set_rx_agc}" STREQUAL "-1")
     message(STATUS "  missing set_rx_agc() API")
 else()
-    add_definitions(-DUHD_HAS_SET_RX_AGC)
+    list(APPEND UHD_FEATURE_DEFS UHD_HAS_SET_RX_AGC)
     message(STATUS "  has set_rx_agc() API")
 endif()
 
@@ -91,80 +106,75 @@
 if ("${has_set_publisher}" STREQUAL "-1")
     message(STATUS "  missing set_publisher() API")
 else()
-    add_definitions(-DUHD_HAS_SET_PUBLISHER)
+    list(APPEND UHD_FEATURE_DEFS UHD_HAS_SET_PUBLISHER)
     message(STATUS "  has set_publisher() API")
 endif()
 
 if (EXISTS "${UHD_INCLUDE_DIRS}/uhd/utils/msg.hpp")
-    add_definitions(-DUHD_HAS_MSG_HPP)
+    list(APPEND UHD_FEATURE_DEFS UHD_HAS_MSG_HPP)
     message(STATUS "  use msg.hpp for logging")
 else()
     message(STATUS "  use log.hpp for logging")
 endif()
 
 ########################################################################
-# Setup boost
+# Setup Boost
 ########################################################################
 MESSAGE(STATUS "Configuring Boost C++ Libraries...")
 
-# Although not required on my system, some users have linking issues without
-SET(BOOST_REQUIRED_COMPONENTS
-    thread
-    system
-)
-
 if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
     list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix
 endif(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
 
-set(Boost_ADDITIONAL_VERSIONS
-    "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" 
"1.39"
-    "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" 
"1.44"
-    "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" 
"1.49"
-    "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" 
"1.54"
-    "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" 
"1.59"
-    "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" 
"1.64"
-    "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" 
"1.69"
-)
-
-find_package(Boost COMPONENTS ${BOOST_REQUIRED_COMPONENTS})
+find_package(Boost)
 
 if(NOT Boost_FOUND)
-    message(WARNING "Boost required to build -- ignoring uhd support")
-    return()
+    message(FATAL_ERROR "Boost not found -- required for Soapy UHD support")
 endif()
 
-ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK)
-
-include_directories(${Boost_INCLUDE_DIRS})
-link_directories(${Boost_LIBRARY_DIRS})
+list(APPEND UHD_FEATURE_DEFS BOOST_ALL_DYN_LINK)
 
 message(STATUS "Boost include directories: ${Boost_INCLUDE_DIRS}")
 message(STATUS "Boost library directories: ${Boost_LIBRARY_DIRS}")
 message(STATUS "Boost libraries: ${Boost_LIBRARIES}")
 
+set(SOAPY_UHD_INCLUDE_DIRS
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${SoapySDR_INCLUDE_DIRS}
+    ${UHD_INCLUDE_DIRS}
+    ${Boost_INCLUDE_DIRS}
+)
+
 ########################################################################
 # Build a Soapy module to support UHD devices
 ########################################################################
-SOAPY_SDR_MODULE_UTIL(
-    TARGET uhdSupport
-    SOURCES SoapyUHDDevice.cpp
-    LIBRARIES
-        ${UHD_LIBRARIES}
-        ${Boost_LIBRARIES}
-)
+if(BUILD_UHD_SUPPORT)
+    SOAPY_SDR_MODULE_UTIL(
+        TARGET uhdSupport
+        SOURCES SoapyUHDDevice.cpp
+        LIBRARIES
+            ${UHD_LIBRARIES}
+            ${Boost_LIBRARIES}
+    )
+    target_include_directories(uhdSupport PRIVATE ${SOAPY_UHD_INCLUDE_DIRS})
+    target_compile_definitions(uhdSupport PRIVATE ${UHD_FEATURE_DEFS})
+endif()
 
 ########################################################################
 # Build a UHD module to support Soapy devices
 ########################################################################
-add_library(soapySupport MODULE UHDSoapyDevice.cpp)
-target_link_libraries(soapySupport
-    ${UHD_LIBRARIES}
-    ${SoapySDR_LIBRARIES}
-    ${Boost_LIBRARIES})
-install(TARGETS soapySupport
-    DESTINATION ${UHD_ROOT}/lib${LIB_SUFFIX}/uhd/modules
-)
+if(BUILD_SOAPY_SUPPORT)
+    add_library(soapySupport MODULE UHDSoapyDevice.cpp)
+    target_include_directories(soapySupport PRIVATE ${SOAPY_UHD_INCLUDE_DIRS})
+    target_compile_definitions(soapySupport PRIVATE ${UHD_FEATURE_DEFS})
+    target_link_libraries(soapySupport
+        ${UHD_LIBRARIES}
+        ${SoapySDR_LIBRARIES}
+        ${Boost_LIBRARIES})
+    install(TARGETS soapySupport
+        DESTINATION ${UHD_ROOT}/lib${LIB_SUFFIX}/uhd/modules
+    )
+endif()
 
 ########################################################################
 # rpath setup - http://www.cmake.org/Wiki/CMake_RPATH_handling
@@ -194,6 +204,11 @@
 endif()
 
 ########################################################################
+# Tests
+########################################################################
+add_subdirectory(tests)
+
+########################################################################
 # Print Summary
 ########################################################################
 MESSAGE(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/README.md 
new/soapy-uhd-0.4.1git20261004/README.md
--- old/SoapyUHD/README.md      2019-12-14 15:05:27.038913815 +0100
+++ new/soapy-uhd-0.4.1git20261004/README.md    2026-10-04 19:53:23.000000000 
+0200
@@ -1,9 +1,5 @@
 # Soapy SDR plugins for UHD devices
 
-## Build Status
-
-- Travis: [![Travis Build 
Status](https://travis-ci.org/pothosware/SoapyUHD.svg?branch=master)](https://travis-ci.org/pothosware/SoapyUHD)
-
 ## Dependencies
 
 * UHD - https://github.com/EttusResearch/uhd/wiki
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/SoapyUHDDevice.cpp 
new/soapy-uhd-0.4.1git20261004/SoapyUHDDevice.cpp
--- old/SoapyUHD/SoapyUHDDevice.cpp     2021-11-11 19:48:36.308031092 +0100
+++ new/soapy-uhd-0.4.1git20261004/SoapyUHDDevice.cpp   2026-10-04 
19:53:23.000000000 +0200
@@ -12,14 +12,11 @@
 #include <SoapySDR/Logger.hpp>
 #include <uhd/version.hpp>
 #include <uhd/device.hpp>
-#ifdef UHD_HAS_MSG_HPP
-#include <uhd/utils/msg.hpp>
-#else
 #include <uhd/utils/log_add.hpp>
-#endif
 #include <uhd/usrp/multi_usrp.hpp>
 #include <uhd/property_tree.hpp>
 #include <uhd/version.hpp>
+#include <boost/lexical_cast.hpp>
 #include <cctype>
 #include <iostream>
 
@@ -30,6 +27,7 @@
 {
     uhd::rx_streamer::sptr rx;
     uhd::tx_streamer::sptr tx;
+    size_t num_channels = 0;
 };
 
 /***********************************************************************
@@ -219,6 +217,17 @@
             streamArgs.push_back(underflowPolicyArg);
         }
 
+#if UHD_VERSION >= 4100000
+        SoapySDR::ArgInfo mtuArg;
+        mtuArg.key = "mtu";
+        mtuArg.value = "0";
+        mtuArg.name = "Override link MTU";
+        mtuArg.description = "Override the auto-detected link MTU (UHD >= 
4.10). 0 = use detected value.";
+        mtuArg.units = "bytes";
+        mtuArg.type = SoapySDR::ArgInfo::INT;
+        streamArgs.push_back(mtuArg);
+#endif
+
         return streamArgs;
     }
 
@@ -242,8 +251,16 @@
 
         //create streamers
         SoapyUHDStream *stream = new SoapyUHDStream();
-        if (dir == SOAPY_SDR_TX) stream->tx = _dev->get_tx_stream(stream_args);
-        if (dir == SOAPY_SDR_RX) stream->rx = _dev->get_rx_stream(stream_args);
+        if (dir == SOAPY_SDR_TX)
+        {
+            stream->tx = _dev->get_tx_stream(stream_args);
+            stream->num_channels = stream->tx->get_num_channels();
+        }
+        if (dir == SOAPY_SDR_RX)
+        {
+            stream->rx = _dev->get_rx_stream(stream_args);
+            stream->num_channels = stream->rx->get_num_channels();
+        }
         return reinterpret_cast<SoapySDR::Stream *>(stream);
     }
 
@@ -300,11 +317,12 @@
 
     int readStream(SoapySDR::Stream *handle, void * const *buffs, const size_t 
numElems, int &flags, long long &timeNs, const long timeoutUs)
     {
-        uhd::rx_streamer::sptr &stream = reinterpret_cast<SoapyUHDStream 
*>(handle)->rx;
+        SoapyUHDStream *streamObj = reinterpret_cast<SoapyUHDStream *>(handle);
+        uhd::rx_streamer::sptr &stream = streamObj->rx;
 
         //receive into buffers and metadata
         uhd::rx_metadata_t md;
-        uhd::rx_streamer::buffs_type stream_buffs(buffs, 
stream->get_num_channels());
+        uhd::rx_streamer::buffs_type stream_buffs(buffs, 
streamObj->num_channels);
         int ret = stream->recv(stream_buffs, numElems, md, timeoutUs/1e6, 
(flags & SOAPY_SDR_ONE_PACKET) != 0);
 
         //parse the metadata
@@ -320,7 +338,7 @@
         case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: return SOAPY_SDR_TIMEOUT;
         case uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET: return 
SOAPY_SDR_CORRUPTION;
         case uhd::rx_metadata_t::ERROR_CODE_ALIGNMENT: return 
SOAPY_SDR_CORRUPTION;
-        case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND: return 
SOAPY_SDR_STREAM_ERROR;
+        case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND: return 
SOAPY_SDR_TIME_ERROR;
         case uhd::rx_metadata_t::ERROR_CODE_BROKEN_CHAIN: return 
SOAPY_SDR_STREAM_ERROR;
         }
         return ret;
@@ -328,7 +346,8 @@
 
     int writeStream(SoapySDR::Stream *handle, const void * const *buffs, const 
size_t numElems, int &flags, const long long timeNs, const long timeoutUs)
     {
-        uhd::tx_streamer::sptr &stream = reinterpret_cast<SoapyUHDStream 
*>(handle)->tx;
+        SoapyUHDStream *streamObj = reinterpret_cast<SoapyUHDStream *>(handle);
+        uhd::tx_streamer::sptr &stream = streamObj->tx;
 
         //load metadata
         uhd::tx_metadata_t md;
@@ -337,7 +356,7 @@
         md.time_spec = uhd::time_spec_t::from_ticks(timeNs, 1e9);
 
         //send buffers and metadata
-        uhd::tx_streamer::buffs_type stream_buffs(buffs, 
stream->get_num_channels());
+        uhd::tx_streamer::buffs_type stream_buffs(buffs, 
streamObj->num_channels);
         int ret = stream->send(stream_buffs, numElems, md, timeoutUs/1e6);
 
         flags = 0;
@@ -361,6 +380,9 @@
 
         switch (md.event_code)
         {
+#if UHD_VERSION >= 4100000
+        case uhd::async_metadata_t::EVENT_CODE_OK: break;
+#endif
         case uhd::async_metadata_t::EVENT_CODE_BURST_ACK: flags |= 
SOAPY_SDR_END_BURST; break;
         case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW: return 
SOAPY_SDR_UNDERFLOW;
         case uhd::async_metadata_t::EVENT_CODE_SEQ_ERROR: return 
SOAPY_SDR_CORRUPTION;
@@ -507,7 +529,7 @@
             return __doesMBoardFEPropTreeEntryExist(dir, channel, 
"iq_balance/enable");
         }
 
-        return SoapySDR::Device::hasDCOffsetMode(dir, channel);
+        return SoapySDR::Device::hasIQBalanceMode(dir, channel);
     }
 
     void setIQBalanceMode(const int dir, const size_t channel, const bool 
automatic)
@@ -545,21 +567,17 @@
 
     bool hasGainMode(const int dir, const size_t channel) const
     {
-        #ifdef UHD_HAS_SET_RX_AGC
         if (dir == SOAPY_SDR_TX) return false;
         if (dir == SOAPY_SDR_RX)
         {
             return __doesDBoardFEPropTreeEntryExist(dir, channel, 
"gain/agc/enable");
         }
-        #endif
         return SoapySDR::Device::hasGainMode(dir, channel);
     }
 
     void setGainMode(const int dir, const size_t channel, const bool automatic)
     {
-        #ifdef UHD_HAS_SET_RX_AGC
         if (dir == SOAPY_SDR_RX) return _dev->set_rx_agc(automatic, channel);
-        #endif
         return SoapySDR::Device::setGainMode(dir, channel, automatic);
     }
 
@@ -1043,11 +1061,7 @@
 
     uhd::property_tree::sptr _get_tree(void) const
     {
-        #if UHD_VERSION >= 4000000
         return _dev->get_tree();
-        #else
-        return _dev->get_device()->get_tree();
-        #endif
     }
 
     uhd::usrp::multi_usrp::sptr _dev;
@@ -1058,20 +1072,6 @@
 /***********************************************************************
  * Register into logger
  **********************************************************************/
-#ifdef UHD_HAS_MSG_HPP
-static void SoapyUHDLogger(uhd::msg::type_t t, const std::string &s)
-{
-    if (s.empty()) return;
-    if (s[s.size()-1] == '\n') return SoapyUHDLogger(t, s.substr(0, 
s.size()-1));
-    switch (t)
-    {
-    case uhd::msg::status: SoapySDR::log(SOAPY_SDR_INFO, s); break;
-    case uhd::msg::warning: SoapySDR::log(SOAPY_SDR_WARNING, s); break;
-    case uhd::msg::error: SoapySDR::log(SOAPY_SDR_ERROR, s); break;
-    case uhd::msg::fastpath: SoapySDR::log(SOAPY_SDR_SSI, s); break;
-    }
-}
-#else
 static void SoapyUHDLogger(const uhd::log::logging_info &info)
 {
     //build a log message formatted from the information
@@ -1101,7 +1101,6 @@
     default: break;
     }
 }
-#endif
 
 /***********************************************************************
  * Registration
@@ -1114,11 +1113,7 @@
     args[SOAPY_UHD_NO_DEEPER] = "";
 
     //perform the discovery
-    #ifdef UHD_HAS_DEVICE_FILTER
     const uhd::device_addrs_t addrs = uhd::device::find(kwargsToDict(args), 
uhd::device::USRP);
-    #else
-    const uhd::device_addrs_t addrs = uhd::device::find(kwargsToDict(args));
-    #endif
 
     //convert addrs to results
     std::vector<SoapySDR::Kwargs> results;
@@ -1151,11 +1146,7 @@
         "Suggestion: install an ABI compatible version of UHD,\n"
         "or rebuild SoapySDR UHD support against this ABI version.\n"
     ) % UHD_VERSION_ABI_STRING % uhd::get_abi_string()));
-    #ifdef UHD_HAS_MSG_HPP
-    uhd::msg::register_handler(&SoapyUHDLogger);
-    #else
     uhd::log::add_logger("SoapyUHDDevice", &SoapyUHDLogger);
-    #endif
     return new SoapyUHDDevice(uhd::usrp::multi_usrp::make(kwargsToDict(args)), 
args);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/TypeHelpers.hpp 
new/soapy-uhd-0.4.1git20261004/TypeHelpers.hpp
--- old/SoapyUHD/TypeHelpers.hpp        2019-12-14 15:05:27.038913815 +0100
+++ new/soapy-uhd-0.4.1git20261004/TypeHelpers.hpp      2026-10-04 
19:53:23.000000000 +0200
@@ -40,11 +40,7 @@
     SoapySDR::RangeList out;
     for (size_t i = 0; i < metaRange.size(); i++)
     {
-        #ifdef SOAPY_SDR_API_HAS_RANGE_TYPE_STEP
         out.push_back(SoapySDR::Range(metaRange[i].start(), 
metaRange[i].stop(), metaRange[i].step()));
-        #else
-        out.push_back(SoapySDR::Range(metaRange[i].start(), 
metaRange[i].stop()));
-        #endif
     }
     return out;
 }
@@ -54,11 +50,7 @@
     uhd::meta_range_t out;
     for (size_t i = 0; i < ranges.size(); i++)
     {
-        #ifdef SOAPY_SDR_API_HAS_RANGE_TYPE_STEP
         out.push_back(uhd::range_t(ranges[i].minimum(), ranges[i].maximum(), 
ranges[i].step()));
-        #else
-        out.push_back(uhd::range_t(ranges[i].minimum(), ranges[i].maximum()));
-        #endif
     }
     if (out.empty()) out.push_back(uhd::range_t(0.0));
     return out;
@@ -66,11 +58,7 @@
 
 static inline SoapySDR::Range metaRangeToRange(const uhd::meta_range_t 
&metaRange)
 {
-    #ifdef SOAPY_SDR_API_HAS_RANGE_TYPE_STEP
     return SoapySDR::Range(metaRange.start(), metaRange.stop(), 
metaRange.step());
-    #else
-    return SoapySDR::Range(metaRange.start(), metaRange.stop());
-    #endif
 }
 
 static inline uhd::meta_range_t numberListToMetaRange(const 
std::vector<double> &nums)
@@ -106,10 +94,8 @@
 
 static inline uhd::meta_range_t rangeToMetaRange(const SoapySDR::Range &range, 
double step = 0.0)
 {
-    //when range step is supported, use it only if initialized to non-zero
-    #ifdef SOAPY_SDR_API_HAS_RANGE_TYPE_STEP
+    //use range.step() if initialized to non-zero
     if (range.step() != 0.0) step = range.step();
-    #endif
 
     return uhd::meta_range_t(range.minimum(), range.maximum(), step);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/UHDSoapyDevice.cpp 
new/soapy-uhd-0.4.1git20261004/UHDSoapyDevice.cpp
--- old/SoapyUHD/UHDSoapyDevice.cpp     2025-02-15 15:13:25.185218036 +0100
+++ new/soapy-uhd-0.4.1git20261004/UHDSoapyDevice.cpp   2026-10-04 
19:53:23.000000000 +0200
@@ -2,11 +2,6 @@
 // Copyright (c) 2018 Deepwave Digital, Inc.
 // SPDX-License-Identifier: GPL-3.0
 
-#ifdef UHD_HAS_SET_PUBLISHER
-#define publish set_publisher
-#define subscribe add_desired_subscriber
-#endif
-
 /***********************************************************************
  * A UHD module that supports Soapy devices within the UHD API.
  **********************************************************************/
@@ -17,11 +12,7 @@
 #include <uhd/version.hpp>
 #include <uhd/device.hpp>
 #include <uhd/convert.hpp>
-#ifdef UHD_HAS_MSG_HPP
-#include <uhd/utils/msg.hpp>
-#else
 #include <uhd/utils/log.hpp>
-#endif
 #include <uhd/types/sensors.hpp>
 #include <uhd/types/ranges.hpp>
 #include <uhd/usrp/mboard_eeprom.hpp>
@@ -35,6 +26,7 @@
 #include <boost/format.hpp>
 #include <boost/thread/mutex.hpp>
 #include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
 #include <boost/weak_ptr.hpp>
 #include <boost/algorithm/string.hpp>
 
@@ -111,20 +103,12 @@
 
     uhd::meta_range_t get_bw_range(const int dir, const size_t chan)
     {
-        #ifdef SOAPY_SDR_API_HAS_GET_BANDWIDTH_RANGE
         return rangeListToMetaRange(_device->getBandwidthRange(dir, chan));
-        #else
-        return numberListToMetaRange(_device->listBandwidths(dir, chan));
-        #endif
     }
 
     uhd::meta_range_t get_rate_range(const int dir, const size_t chan)
     {
-        #ifdef SOAPY_SDR_API_HAS_GET_SAMPLE_RATE_RANGE
         return rangeListToMetaRange(_device->getSampleRateRange(dir, chan));
-        #else
-        return numberListToMetaRange(_device->listSampleRates(dir, chan));
-        #endif
     }
 
     void set_sample_rate(const int dir, const size_t chan, const double rate)
@@ -181,13 +165,8 @@
     std::map<int, std::map<size_t, double>> _sampleRates;
 
     //stash streamers to implement old-style issue stream cmd and async message
-    #if UHD_VERSION >= 4000000
     std::map<size_t, std::weak_ptr<uhd::rx_streamer> > _rx_streamers;
     std::map<size_t, std::weak_ptr<uhd::tx_streamer> > _tx_streamers;
-    #else
-    std::map<size_t, boost::weak_ptr<uhd::rx_streamer> > _rx_streamers;
-    std::map<size_t, boost::weak_ptr<uhd::tx_streamer> > _tx_streamers;
-    #endif
 };
 
 /***********************************************************************
@@ -224,45 +203,45 @@
 
     //the frontend mapping
     _tree->create<uhd::usrp::subdev_spec_t>(mb_path / "rx_subdev_spec")
-        .publish(boost::bind(&UHDSoapyDevice::get_frontend_mapping, this, 
SOAPY_SDR_RX))
-        .subscribe(boost::bind(&UHDSoapyDevice::set_frontend_mapping, this, 
SOAPY_SDR_RX, _1));
+        .set_publisher(boost::bind(&UHDSoapyDevice::get_frontend_mapping, 
this, SOAPY_SDR_RX))
+        
.add_desired_subscriber(boost::bind(&UHDSoapyDevice::set_frontend_mapping, 
this, SOAPY_SDR_RX, _1));
     _tree->create<uhd::usrp::subdev_spec_t>(mb_path / "tx_subdev_spec")
-        .publish(boost::bind(&UHDSoapyDevice::get_frontend_mapping, this, 
SOAPY_SDR_TX))
-        .subscribe(boost::bind(&UHDSoapyDevice::set_frontend_mapping, this, 
SOAPY_SDR_TX, _1));
+        .set_publisher(boost::bind(&UHDSoapyDevice::get_frontend_mapping, 
this, SOAPY_SDR_TX))
+        
.add_desired_subscriber(boost::bind(&UHDSoapyDevice::set_frontend_mapping, 
this, SOAPY_SDR_TX, _1));
 
     //timed command support
     _tree->create<uhd::time_spec_t>(mb_path / "time" / "cmd")
-        .subscribe(boost::bind(&UHDSoapyDevice::set_hardware_time, this, 
"CMD", _1));
+        
.add_desired_subscriber(boost::bind(&UHDSoapyDevice::set_hardware_time, this, 
"CMD", _1));
     _tree->create<double>(mb_path / "tick_rate")
-        .publish(boost::bind(&SoapySDR::Device::getMasterClockRate, _device))
-        .subscribe(boost::bind(&SoapySDR::Device::setMasterClockRate, _device, 
_1));
+        .set_publisher(boost::bind(&SoapySDR::Device::getMasterClockRate, 
_device))
+        
.add_desired_subscriber(boost::bind(&SoapySDR::Device::setMasterClockRate, 
_device, _1));
 
     //hardware time support
     _tree->create<uhd::time_spec_t>(mb_path / "time" / "now")
-        .publish(boost::bind(&UHDSoapyDevice::get_hardware_time, this, ""))
-        .subscribe(boost::bind(&UHDSoapyDevice::set_hardware_time, this, "", 
_1));
+        .set_publisher(boost::bind(&UHDSoapyDevice::get_hardware_time, this, 
""))
+        
.add_desired_subscriber(boost::bind(&UHDSoapyDevice::set_hardware_time, this, 
"", _1));
     _tree->create<uhd::time_spec_t>(mb_path / "time" / "pps")
-        .publish(boost::bind(&UHDSoapyDevice::get_hardware_time, this, "PPS"))
-        .subscribe(boost::bind(&UHDSoapyDevice::set_hardware_time, this, 
"PPS", _1));
+        .set_publisher(boost::bind(&UHDSoapyDevice::get_hardware_time, this, 
"PPS"))
+        
.add_desired_subscriber(boost::bind(&UHDSoapyDevice::set_hardware_time, this, 
"PPS", _1));
 
     //clock and time sources
     _tree->create<std::vector<std::string> >(mb_path / "clock_source"/ 
"options")
-        .publish(boost::bind(&SoapySDR::Device::listClockSources, _device));
+        .set_publisher(boost::bind(&SoapySDR::Device::listClockSources, 
_device));
     _tree->create<std::string>(mb_path / "clock_source" / "value")
-        .publish(boost::bind(&SoapySDR::Device::getClockSource, _device))
-        .subscribe(boost::bind(&SoapySDR::Device::setClockSource, _device, 
_1));
+        .set_publisher(boost::bind(&SoapySDR::Device::getClockSource, _device))
+        .add_desired_subscriber(boost::bind(&SoapySDR::Device::setClockSource, 
_device, _1));
     _tree->create<std::vector<std::string> >(mb_path / "time_source"/ 
"options")
-        .publish(boost::bind(&SoapySDR::Device::listTimeSources, _device));
+        .set_publisher(boost::bind(&SoapySDR::Device::listTimeSources, 
_device));
     _tree->create<std::string>(mb_path / "time_source" / "value")
-        .publish(boost::bind(&SoapySDR::Device::getTimeSource, _device))
-        .subscribe(boost::bind(&SoapySDR::Device::setTimeSource, _device, _1));
+        .set_publisher(boost::bind(&SoapySDR::Device::getTimeSource, _device))
+        .add_desired_subscriber(boost::bind(&SoapySDR::Device::setTimeSource, 
_device, _1));
 
     //mboard sensors
     _tree->create<int>(mb_path / "sensors"); //ensure this path exists
     for(const std::string &name : _device->listSensors())
     {
         _tree->create<uhd::sensor_value_t>(mb_path / "sensors" / name)
-            .publish(boost::bind(&UHDSoapyDevice::get_mboard_sensor, this, 
name));
+            .set_publisher(boost::bind(&UHDSoapyDevice::get_mboard_sensor, 
this, name));
     }
 
     //gpio banks
@@ -280,8 +259,8 @@
         for(const std::string &attr : attrs)
         {
             _tree->create<boost::uint32_t>(mb_path / "gpio" / bank / attr)
-                .subscribe(boost::bind(&UHDSoapyDevice::set_gpio_attr, this, 
bank, attr, _1))
-                .publish(boost::bind(&UHDSoapyDevice::get_gpio_attr, this, 
bank, attr));
+                
.add_desired_subscriber(boost::bind(&UHDSoapyDevice::set_gpio_attr, this, bank, 
attr, _1))
+                .set_publisher(boost::bind(&UHDSoapyDevice::get_gpio_attr, 
this, bank, attr));
         }
     }
 
@@ -342,10 +321,10 @@
 
     //samp rate
     _tree->create<uhd::meta_range_t>(dsp_path / "rate" / "range")
-        .publish(boost::bind(&UHDSoapyDevice::get_rate_range, this, dir, 
chan));
+        .set_publisher(boost::bind(&UHDSoapyDevice::get_rate_range, this, dir, 
chan));
     _tree->create<double>(dsp_path / "rate" / "value")
-        .publish(boost::bind(&SoapySDR::Device::getSampleRate, _device, dir, 
chan))
-        .subscribe(boost::bind(&UHDSoapyDevice::set_sample_rate, this, dir, 
chan, _1));
+        .set_publisher(boost::bind(&SoapySDR::Device::getSampleRate, _device, 
dir, chan))
+        .add_desired_subscriber(boost::bind(&UHDSoapyDevice::set_sample_rate, 
this, dir, chan, _1));
 
     //dsp freq (when there is no tunable cordic)
     if (bbCompName.empty())
@@ -357,17 +336,17 @@
     else
     {
         _tree->create<double>(dsp_path / "freq" / "value")
-            .publish(boost::bind(&SoapySDR::Device::getFrequency, _device, 
dir, chan, bbCompName))
-            .subscribe(boost::bind(&UHDSoapyDevice::set_frequency, this, dir, 
chan, bbCompName, _1));
+            .set_publisher(boost::bind(&SoapySDR::Device::getFrequency, 
_device, dir, chan, bbCompName))
+            
.add_desired_subscriber(boost::bind(&UHDSoapyDevice::set_frequency, this, dir, 
chan, bbCompName, _1));
         _tree->create<uhd::meta_range_t>(dsp_path / "freq" / "range")
-            .publish(boost::bind(&UHDSoapyDevice::get_freq_range, this, dir, 
chan, bbCompName));
+            .set_publisher(boost::bind(&UHDSoapyDevice::get_freq_range, this, 
dir, chan, bbCompName));
     }
 
     //old style stream cmd
     if (dir == SOAPY_SDR_RX)
     {
         _tree->create<uhd::stream_cmd_t>(dsp_path / "stream_cmd")
-            .subscribe(boost::bind(&UHDSoapyDevice::old_issue_stream_cmd, 
this, chan, _1));
+            
.add_desired_subscriber(boost::bind(&UHDSoapyDevice::old_issue_stream_cmd, 
this, chan, _1));
     }
 
     //frontend sensors
@@ -376,7 +355,7 @@
     {
         //install the sensor
         _tree->create<uhd::sensor_value_t>(rf_fe_path / "sensors" / name)
-            .publish(boost::bind(&UHDSoapyDevice::get_channel_sensor, this, 
dir, chan, name));
+            .set_publisher(boost::bind(&UHDSoapyDevice::get_channel_sensor, 
this, dir, chan, name));
     }
 
     //dummy eeprom values
@@ -397,71 +376,69 @@
     for(const std::string &name : _device->listGains(dir, chan))
     {
         _tree->create<uhd::meta_range_t>(rf_fe_path / "gains" / name / "range")
-            .publish(boost::bind(&UHDSoapyDevice::get_gain_range, this, dir, 
chan, name));
+            .set_publisher(boost::bind(&UHDSoapyDevice::get_gain_range, this, 
dir, chan, name));
         _tree->create<double>(rf_fe_path / "gains" / name / "value")
-            .publish(boost::bind(&SoapySDR::Device::getGain, _device, dir, 
chan, name))
-            .subscribe(boost::bind(&SoapySDR::Device::setGain, _device, dir, 
chan, name, _1));
+            .set_publisher(boost::bind(&SoapySDR::Device::getGain, _device, 
dir, chan, name))
+            .add_desired_subscriber(boost::bind(&SoapySDR::Device::setGain, 
_device, dir, chan, name, _1));
     }
 
     //agc
     _tree->create<bool>(rf_fe_path / "gain" / "agc" / "enable")
-        .publish(boost::bind(&SoapySDR::Device::getGainMode, _device, dir, 
chan))
-        .subscribe(boost::bind(&SoapySDR::Device::setGainMode, _device, dir, 
chan, _1));
+        .set_publisher(boost::bind(&SoapySDR::Device::getGainMode, _device, 
dir, chan))
+        .add_desired_subscriber(boost::bind(&SoapySDR::Device::setGainMode, 
_device, dir, chan, _1));
 
     //freq
     _tree->create<double>(rf_fe_path / "freq" / "value")
-        .publish(boost::bind(&SoapySDR::Device::getFrequency, _device, dir, 
chan, rfCompName))
-        .subscribe(boost::bind(&UHDSoapyDevice::set_frequency, this, dir, 
chan, rfCompName, _1));
+        .set_publisher(boost::bind(&SoapySDR::Device::getFrequency, _device, 
dir, chan, rfCompName))
+        .add_desired_subscriber(boost::bind(&UHDSoapyDevice::set_frequency, 
this, dir, chan, rfCompName, _1));
     _tree->create<uhd::meta_range_t>(rf_fe_path / "freq" / "range")
-        .publish(boost::bind(&UHDSoapyDevice::get_freq_range, this, dir, chan, 
rfCompName));
+        .set_publisher(boost::bind(&UHDSoapyDevice::get_freq_range, this, dir, 
chan, rfCompName));
     _tree->create<bool>(rf_fe_path / "use_lo_offset").set(false);
     _tree->create<uhd::device_addr_t>(rf_fe_path / "tune_args")
-        .subscribe(boost::bind(&UHDSoapyDevice::stash_tune_args, this, dir, 
chan, _1));
+        .add_desired_subscriber(boost::bind(&UHDSoapyDevice::stash_tune_args, 
this, dir, chan, _1));
 
     //ant
     _tree->create<std::vector<std::string> >(rf_fe_path / "antenna" / 
"options")
-        .publish(boost::bind(&SoapySDR::Device::listAntennas, _device, dir, 
chan));
+        .set_publisher(boost::bind(&SoapySDR::Device::listAntennas, _device, 
dir, chan));
     _tree->create<std::string>(rf_fe_path / "antenna" / "value")
-        .publish(boost::bind(&SoapySDR::Device::getAntenna, _device, dir, 
chan))
-        .subscribe(boost::bind(&SoapySDR::Device::setAntenna, _device, dir, 
chan, _1));
+        .set_publisher(boost::bind(&SoapySDR::Device::getAntenna, _device, 
dir, chan))
+        .add_desired_subscriber(boost::bind(&SoapySDR::Device::setAntenna, 
_device, dir, chan, _1));
 
     //bw
     _tree->create<double>(rf_fe_path / "bandwidth" / "value")
-        .publish(boost::bind(&SoapySDR::Device::getBandwidth, _device, dir, 
chan))
-        .subscribe(boost::bind(&SoapySDR::Device::setBandwidth, _device, dir, 
chan, _1));
+        .set_publisher(boost::bind(&SoapySDR::Device::getBandwidth, _device, 
dir, chan))
+        .add_desired_subscriber(boost::bind(&SoapySDR::Device::setBandwidth, 
_device, dir, chan, _1));
     _tree->create<uhd::meta_range_t>(rf_fe_path / "bandwidth" / "range")
-        .publish(boost::bind(&UHDSoapyDevice::get_bw_range, this, dir, chan));
+        .set_publisher(boost::bind(&UHDSoapyDevice::get_bw_range, this, dir, 
chan));
 
     //corrections
     if (_device->hasDCOffsetMode(dir, chan))
     {
         _tree->create<bool>(rf_fe_path / "dc_offset" / "enable")
-            .publish(boost::bind(&SoapySDR::Device::getDCOffsetMode, _device, 
dir, chan))
-            .subscribe(boost::bind(&SoapySDR::Device::setDCOffsetMode, 
_device, dir, chan, _1));
+            .set_publisher(boost::bind(&SoapySDR::Device::getDCOffsetMode, 
_device, dir, chan))
+            
.add_desired_subscriber(boost::bind(&SoapySDR::Device::setDCOffsetMode, 
_device, dir, chan, _1));
     }
 
     if (_device->hasDCOffset(dir, chan))
     {
         _tree->create<std::complex<double>>(rf_fe_path / "dc_offset" / "value")
-            .publish(boost::bind(&SoapySDR::Device::getDCOffset, _device, dir, 
chan))
-            .subscribe(boost::bind(&SoapySDR::Device::setDCOffset, _device, 
dir, chan, _1));
+            .set_publisher(boost::bind(&SoapySDR::Device::getDCOffset, 
_device, dir, chan))
+            
.add_desired_subscriber(boost::bind(&SoapySDR::Device::setDCOffset, _device, 
dir, chan, _1));
     }
 
     if (_device->hasIQBalance(dir, chan))
     {
         _tree->create<std::complex<double>>(rf_fe_path / "iq_balance" / 
"value")
-            .publish(boost::bind(&SoapySDR::Device::getIQBalance, _device, 
dir, chan))
-            .subscribe(boost::bind(&SoapySDR::Device::setIQBalance, _device, 
dir, chan, _1));
+            .set_publisher(boost::bind(&SoapySDR::Device::getIQBalance, 
_device, dir, chan))
+            
.add_desired_subscriber(boost::bind(&SoapySDR::Device::setIQBalance, _device, 
dir, chan, _1));
     }
 
-    #ifdef SOAPY_SDR_API_HAS_IQ_BALANCE_MODE
     if (_device->hasIQBalanceMode(dir, chan))
     {
         _tree->create<bool>(rf_fe_path / "iq_balance" / "enable")
-            .publish(boost::bind(&SoapySDR::Device::getIQBalanceMode, _device, 
dir, chan))
-            .subscribe(boost::bind(&SoapySDR::Device::setIQBalanceMode, 
_device, dir, chan, _1));
+            .set_publisher(boost::bind(&SoapySDR::Device::getIQBalanceMode, 
_device, dir, chan))
+            
.add_desired_subscriber(boost::bind(&SoapySDR::Device::setIQBalanceMode, 
_device, dir, chan, _1));
     }
-    #endif
 }
 
 void UHDSoapyDevice::setupFakeChannelHooks(const int dir, const size_t 
/*chan*/, const std::string &dirName, const std::string &chName)
@@ -568,12 +545,12 @@
         _device->closeStream(_stream);
     }
 
-    size_t get_num_channels(void) const
+    size_t get_num_channels(void) const override
     {
         return _nchan;
     }
 
-    size_t get_max_num_samps(void) const
+    size_t get_max_num_samps(void) const override
     {
         return _device->getStreamMTU(_stream);
     }
@@ -584,7 +561,7 @@
         uhd::rx_metadata_t &md,
         const double timeout = 0.1,
         const bool one_packet = false
-    )
+    ) override
     {
         size_t total = 0;
         md.reset();
@@ -674,7 +651,7 @@
         return total;
     }
 
-    void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd)
+    void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd) override
     {
         int flags = 0;
         if (not stream_cmd.stream_now) flags |= SOAPY_SDR_HAS_TIME;
@@ -715,13 +692,19 @@
     }
     #endif
 
+    #if UHD_VERSION >= 4110000
+    uhd::device_addr_t get_stream_info(const size_t /*chan*/) const override
+    {
+        throw uhd::not_implemented_error("get_stream_info is not implemented 
here!");
+    }
+    #endif
+
 private:
     SoapySDR::Device *_device;
     SoapySDR::Stream *_stream;
     const size_t _nchan;
     const size_t _elemSize;
     std::vector<void *> _offsetBuffs;
-    bool _doErrorOnNextRecv;
     bool _nextTimeValid;
     uhd::time_spec_t _nextTime;
     const double &_sampRate;
@@ -758,12 +741,12 @@
         _device->closeStream(_stream);
     }
 
-    size_t get_num_channels(void) const
+    size_t get_num_channels(void) const override
     {
         return _nchan;
     }
 
-    size_t get_max_num_samps(void) const
+    size_t get_max_num_samps(void) const override
     {
         return _device->getStreamMTU(_stream);
     }
@@ -773,7 +756,7 @@
         size_t nsamps_per_buff,
         const uhd::tx_metadata_t &md,
         const double timeout = 0.1
-    )
+    ) override
     {
         //perform activation at the latest/on the first call to send
         if (not _active)
@@ -808,7 +791,7 @@
         return total;
     }
 
-    bool recv_async_msg(uhd::async_metadata_t &md, double timeout = 0.1)
+    bool recv_async_msg(uhd::async_metadata_t &md, double timeout = 0.1) 
override
     {
         size_t chanMask = 0;
         int flags = 0;
@@ -867,6 +850,13 @@
     }
     #endif
 
+    #if UHD_VERSION >= 4110000
+    uhd::device_addr_t get_stream_info(const size_t /*chan*/) const override
+    {
+        throw uhd::not_implemented_error("get_stream_info is not implemented 
here!");
+    }
+    #endif
+
 private:
     bool _active;
     SoapySDR::Device *_device;
@@ -899,17 +889,6 @@
     #define component "UHDSoapyDevice"
     switch(logLevel)
     {
-    #ifdef UHD_HAS_MSG_HPP
-    case SOAPY_SDR_FATAL:
-    case SOAPY_SDR_CRITICAL:
-    case SOAPY_SDR_ERROR: UHD_MSG(error) << message << std::endl; break;
-    case SOAPY_SDR_WARNING: UHD_MSG(warning) << message << std::endl; break;
-    case SOAPY_SDR_NOTICE:
-    case SOAPY_SDR_INFO:
-    case SOAPY_SDR_DEBUG:
-    case SOAPY_SDR_TRACE: UHD_MSG(status) << message << std::endl; break;
-    case SOAPY_SDR_SSI: UHD_MSG(fastpath) << message << std::flush; break;
-    #else
     case SOAPY_SDR_FATAL:
     case SOAPY_SDR_CRITICAL:  UHD_LOG_FATAL(component, message); break;
     case SOAPY_SDR_ERROR:     UHD_LOG_FATAL(component, message); break;
@@ -919,7 +898,6 @@
     case SOAPY_SDR_DEBUG:
     case SOAPY_SDR_TRACE:     UHD_LOG_TRACE(component, message); break;
     case SOAPY_SDR_SSI:       UHD_LOG_FASTPATH(message); break;
-    #endif
     }
 }
 
@@ -961,9 +939,5 @@
 
 UHD_STATIC_BLOCK(registerUHDSoapyDevice)
 {
-    #ifdef UHD_HAS_DEVICE_FILTER
     uhd::device::register_device(&findUHDSoapyDevice, &makeUHDSoapyDevice, 
uhd::device::USRP);
-    #else
-    uhd::device::register_device(&findUHDSoapyDevice, &makeUHDSoapyDevice);
-    #endif
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/tests/CMakeLists.txt 
new/soapy-uhd-0.4.1git20261004/tests/CMakeLists.txt
--- old/SoapyUHD/tests/CMakeLists.txt   1970-01-01 01:00:00.000000000 +0100
+++ new/soapy-uhd-0.4.1git20261004/tests/CMakeLists.txt 2026-10-04 
19:53:23.000000000 +0200
@@ -0,0 +1,19 @@
+########################################################################
+# Unit tests for TypeHelpers.hpp free functions
+########################################################################
+add_executable(test_type_helpers test_type_helpers.cpp)
+
+target_include_directories(test_type_helpers PRIVATE
+    ${CMAKE_SOURCE_DIR}
+    ${SoapySDR_INCLUDE_DIRS}
+    ${UHD_INCLUDE_DIRS}
+    ${Boost_INCLUDE_DIRS}
+)
+
+target_link_libraries(test_type_helpers PRIVATE
+    ${SoapySDR_LIBRARIES}
+    ${UHD_LIBRARIES}
+    ${Boost_LIBRARIES}
+)
+
+add_test(NAME type_helpers COMMAND test_type_helpers)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SoapyUHD/tests/test_type_helpers.cpp 
new/soapy-uhd-0.4.1git20261004/tests/test_type_helpers.cpp
--- old/SoapyUHD/tests/test_type_helpers.cpp    1970-01-01 01:00:00.000000000 
+0100
+++ new/soapy-uhd-0.4.1git20261004/tests/test_type_helpers.cpp  2026-10-04 
19:53:23.000000000 +0200
@@ -0,0 +1,213 @@
+// Copyright (c) 2026 SoapyUHD contributors
+// SPDX-License-Identifier: GPL-3.0
+//
+// Unit tests for TypeHelpers.hpp free functions.
+// Bare-stdlib harness; no external test framework.
+
+#include "TypeHelpers.hpp"
+
+#include <cmath>
+#include <iostream>
+#include <string>
+#include <vector>
+
+static int g_failures = 0;
+
+#define CHECK(cond) do { \
+    if (!(cond)) { \
+        std::cerr << "FAIL: " #cond " at " << __FILE__ << ":" << __LINE__ << 
"\n"; \
+        ++g_failures; \
+    } \
+} while (0)
+
+#define CHECK_NEAR(a, b, eps) do { \
+    if (std::fabs((a) - (b)) > (eps)) { \
+        std::cerr << "FAIL: |" #a " - " #b "| > " #eps \
+                  << " (got " << (a) << " vs " << (b) << ")" \
+                  << " at " << __FILE__ << ":" << __LINE__ << "\n"; \
+        ++g_failures; \
+    } \
+} while (0)
+
+static void test_dict_kwargs_round_trip()
+{
+    SoapySDR::Kwargs kw;
+    kw["driver"] = "uhd";
+    kw["type"]   = "b200";
+    kw["serial"] = "BADC10E";
+
+    uhd::device_addr_t addr = kwargsToDict(kw);
+    CHECK(addr.has_key("driver"));
+    CHECK(addr.has_key("type"));
+    CHECK(addr.has_key("serial"));
+    CHECK(addr["driver"] == "uhd");
+
+    SoapySDR::Kwargs kw2 = dictToKwargs(addr);
+    CHECK(kw2.size() == 3);
+    CHECK(kw2.at("driver") == "uhd");
+    CHECK(kw2.at("type")   == "b200");
+    CHECK(kw2.at("serial") == "BADC10E");
+}
+
+static void test_dict_kwargs_empty()
+{
+    SoapySDR::Kwargs kw;
+    uhd::device_addr_t addr = kwargsToDict(kw);
+    CHECK(addr.size() == 0);
+
+    SoapySDR::Kwargs kw2 = dictToKwargs(addr);
+    CHECK(kw2.empty());
+}
+
+static void test_meta_range_to_range_list_single()
+{
+    uhd::meta_range_t mr(0.0, 100.0, 1.0);
+    SoapySDR::RangeList rl = metaRangeToRangeList(mr);
+    CHECK(rl.size() == 1);
+    CHECK_NEAR(rl[0].minimum(),   0.0, 1e-9);
+    CHECK_NEAR(rl[0].maximum(), 100.0, 1e-9);
+}
+
+static void test_meta_range_to_range_list_multi()
+{
+    uhd::meta_range_t mr;
+    mr.push_back(uhd::range_t(0.0, 10.0));
+    mr.push_back(uhd::range_t(20.0, 30.0));
+    SoapySDR::RangeList rl = metaRangeToRangeList(mr);
+    CHECK(rl.size() == 2);
+    CHECK_NEAR(rl[0].maximum(), 10.0, 1e-9);
+    CHECK_NEAR(rl[1].minimum(), 20.0, 1e-9);
+}
+
+static void test_range_list_to_meta_range_round_trip()
+{
+    SoapySDR::RangeList rl;
+    rl.push_back(SoapySDR::Range(1.0, 2.0));
+    rl.push_back(SoapySDR::Range(5.0, 10.0));
+    uhd::meta_range_t mr = rangeListToMetaRange(rl);
+    CHECK(mr.size() == 2);
+    CHECK_NEAR(mr[0].start(),  1.0, 1e-9);
+    CHECK_NEAR(mr[1].stop(),  10.0, 1e-9);
+}
+
+static void test_range_list_to_meta_range_empty_yields_zero()
+{
+    SoapySDR::RangeList rl;
+    uhd::meta_range_t mr = rangeListToMetaRange(rl);
+    CHECK(mr.size() == 1);
+    CHECK_NEAR(mr[0].start(), 0.0, 1e-9);
+    CHECK_NEAR(mr[0].stop(),  0.0, 1e-9);
+}
+
+static void test_meta_range_to_range_top_level()
+{
+    uhd::meta_range_t mr(-50.0, 50.0, 0.5);
+    SoapySDR::Range r = metaRangeToRange(mr);
+    CHECK_NEAR(r.minimum(), -50.0, 1e-9);
+    CHECK_NEAR(r.maximum(),  50.0, 1e-9);
+}
+
+static void test_number_list_to_meta_range_empty_yields_zero()
+{
+    std::vector<double> v;
+    uhd::meta_range_t mr = numberListToMetaRange(v);
+    CHECK(mr.size() == 1);
+    CHECK_NEAR(mr[0].start(), 0.0, 1e-9);
+}
+
+static void test_meta_range_to_numeric_list_single_returns_bounds()
+{
+    uhd::meta_range_t mr(10.0, 20.0);
+    std::vector<double> v = metaRangeToNumericList(mr);
+    CHECK(v.size() == 2);
+    CHECK_NEAR(v[0], 10.0, 1e-9);
+    CHECK_NEAR(v[1], 20.0, 1e-9);
+}
+
+static void test_meta_range_to_numeric_list_multi_returns_starts()
+{
+    uhd::meta_range_t mr;
+    mr.push_back(uhd::range_t(1.0));
+    mr.push_back(uhd::range_t(2.0));
+    mr.push_back(uhd::range_t(3.0));
+    std::vector<double> v = metaRangeToNumericList(mr);
+    CHECK(v.size() == 3);
+    CHECK_NEAR(v[0], 1.0, 1e-9);
+    CHECK_NEAR(v[2], 3.0, 1e-9);
+}
+
+static void test_range_to_meta_range_default_step()
+{
+    SoapySDR::Range r(0.0, 100.0);
+    uhd::meta_range_t mr = rangeToMetaRange(r);
+    CHECK_NEAR(mr.start(),   0.0, 1e-9);
+    CHECK_NEAR(mr.stop(),  100.0, 1e-9);
+}
+
+static void test_sensor_arginfo_round_trip_bool()
+{
+    uhd::sensor_value_t s("locked", true, "true", "false");
+    SoapySDR::ArgInfo ai = sensorToArgInfo(s, "locked");
+    CHECK(ai.key  == "locked");
+    CHECK(ai.type == SoapySDR::ArgInfo::BOOL);
+
+    uhd::sensor_value_t s2 = argInfoToSensor(ai, "true");
+    CHECK(s2.to_bool() == true);
+}
+
+static void test_sensor_arginfo_round_trip_int()
+{
+    uhd::sensor_value_t s("count", 42, "items");
+    SoapySDR::ArgInfo ai = sensorToArgInfo(s, "count");
+    CHECK(ai.type == SoapySDR::ArgInfo::INT);
+
+    uhd::sensor_value_t s2 = argInfoToSensor(ai, "42");
+    CHECK(s2.to_int() == 42);
+}
+
+static void test_sensor_arginfo_round_trip_real()
+{
+    uhd::sensor_value_t s("temp", 25.5, "C");
+    SoapySDR::ArgInfo ai = sensorToArgInfo(s, "temp");
+    CHECK(ai.type == SoapySDR::ArgInfo::FLOAT);
+
+    uhd::sensor_value_t s2 = argInfoToSensor(ai, "25.5");
+    CHECK_NEAR(s2.to_real(), 25.5, 1e-9);
+}
+
+static void test_sensor_arginfo_round_trip_string()
+{
+    uhd::sensor_value_t s("status", std::string("active"), "");
+    SoapySDR::ArgInfo ai = sensorToArgInfo(s, "status");
+    CHECK(ai.type == SoapySDR::ArgInfo::STRING);
+
+    uhd::sensor_value_t s2 = argInfoToSensor(ai, "active");
+    CHECK(s2.value == "active");
+}
+
+int main()
+{
+    test_dict_kwargs_round_trip();
+    test_dict_kwargs_empty();
+    test_meta_range_to_range_list_single();
+    test_meta_range_to_range_list_multi();
+    test_range_list_to_meta_range_round_trip();
+    test_range_list_to_meta_range_empty_yields_zero();
+    test_meta_range_to_range_top_level();
+    test_number_list_to_meta_range_empty_yields_zero();
+    test_meta_range_to_numeric_list_single_returns_bounds();
+    test_meta_range_to_numeric_list_multi_returns_starts();
+    test_range_to_meta_range_default_step();
+    test_sensor_arginfo_round_trip_bool();
+    test_sensor_arginfo_round_trip_int();
+    test_sensor_arginfo_round_trip_real();
+    test_sensor_arginfo_round_trip_string();
+
+    if (g_failures == 0)
+    {
+        std::cout << "All tests passed.\n";
+        return 0;
+    }
+    std::cerr << g_failures << " test(s) FAILED.\n";
+    return 1;
+}

Reply via email to