#!/usr/bin/env bash if [ -z "$BASH_VERSION" ]; then echo "Error: This script must be run with Bash." >&2 exit 1 fi set -Eeuo pipefail ####################################### # CONFIG ####################################### # Build hashes and the licence text are resolved at runtime from the upstream # installer (https://www.sdrplay.com/software/install.sh). The values below # are used as fallbacks if upstream is unreachable or unparseable, and the # build hashes are also honoured as user overrides when set in the # environment before invocation. _SDRCONNECT_GITBUILD_USER_SET="${SDRCONNECT_GITBUILD+set}" _RIGCONTROL_GITBUILD_USER_SET="${RIGCONTROL_GITBUILD+set}" : "${SDRCONNECT_GITBUILD:=a4b8da76b}" : "${RIGCONTROL_GITBUILD:=4a50e06}" UPSTREAM_INSTALLER_URL="https://www.sdrplay.com/software/install.sh" SDRCONNECT_DIR="/opt/sdrconnect" RIGCONTROL_DIR="/opt/rigcontrol" # Artifact filenames and URLs depend on the resolved build hashes and are # populated by resolve_artifacts() after fetch_gitbuilds() runs. SDRCONNECT_TAR_X86_64="" SDRCONNECT_TAR_ARM64="" RIGCONTROL_TAR_X86_64="" RIGCONTROL_TAR_ARM64="" SDRCONNECT_URL_X86_64="" SDRCONNECT_URL_ARM64="" RIGCONTROL_URL_X86_64="" RIGCONTROL_URL_ARM64="" PROFILE_SCRIPT="/etc/profile.d/sdrconnect.sh" UDEV_RULES="/etc/udev/rules.d/66-sdrplay.rules" OLD_UDEV_RULES="/etc/udev/rules.d/66-mirics.rules" ICON_PATH="/usr/share/icons/hicolor/64x64/apps" DOC1="/usr/share/doc/sdrconnect" DOC2="/usr/share/doc/rigcontrol" UNINSTALLER="${SDRCONNECT_DIR}/sdrconnect-uninstall.sh" MANIFEST="${SDRCONNECT_DIR}/install-manifest.txt" ####################################### # DESKTOP ENTRIES ####################################### DESKTOP_ENTRIES=( "sdrconnect|SDRconnect|/opt/sdrconnect/SDRconnect|sdrconnect|Utility;" "rigcontrol|RigControl|/opt/rigcontrol/RigControl|rigcontrol|Utility;" "nrspadministrator|NRSPAdministrator|/opt/sdrconnect/NRSPAdministrator|nrspadministrator|Utility;" "nrspupdater|NRSPUpdater|/opt/sdrconnect/NRSPUpdater|nrspupdater|Utility;" ) ####################################### # SYSTEMD SERVICES ####################################### SYSTEMD_SERVICES=( "sdrconnectserver|/opt/sdrconnect/SDRconnect --server|SDRconnect Server Service" ) ####################################### # LICENSE ####################################### LICENSE_TEXT=$(cat <<'EOF' SDRconnect Installation ======================= To continue with the installation, please review and accept this license agreement, use the SPACE BAR to page down, B to page up, UP and DOWN arrows to move one line at a time and Q will close the license agreement at any time or when you see END. Accept the license agreement by typing yes followed by pressing the RETURN or ENTER key when prompted. SDRPLAY LIMITED END USER LICENCE AGREEMENT IMPORTANT: READ CAREFULLY The SDRplay software ('Software') you are about to install, run and/or use is licensed by SDRplay Limited, a company registered in England (No. 09035244), whose registered office is 21 Lenten Street, ALTON, GU34 1HG ('SDRplay'), and is subject to the following licence terms ('Licence'). "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. By proceeding to install, run and/or use the Software, you confirm that you accept and agree to be bound by the terms of this Licence. If you do not agree to any of the terms of this Licence, SDRplay is unwilling to provide access to the Software to you and you should not proceed further and may not use the Software. 1. Licence To Use The Software. 1.1 Grant of Licence. Subject to the terms and conditions of this License, SDRplay hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license to publicly display, publicly perform the Software in Object form. 1.2 Restrictions. 1.2.1 Except as described in 1.2.2 below, you may use the Software only with SDRplay hardware radio products which are produced and distributed by SDRplay Limited. 1.2.2 If you use the EXTIO interface of SDRuno, which is available in versions 1.05 and earlier, you may use the Software with radio hardware from any supplier that supports the EXTIO interface. 1.2.3 You may not: modify, disassemble, decompile or reverse engineer the Software, except to the extent specifically authorised under applicable law notwithstanding contractual prohibition. 1.3 Open Source Software. The Software may contain code, commonly referred to as open source software, which is distributed under any of the many known variations of open source licence terms, including terms which allow the free distribution and modification of the relevant software's source code and/or which require all distributors to make such source code freely available upon request, including any contributions or modifications made by such distributor (collectively, 'Open Source Software'). To the extent that the Software contains any Open Source Software, that element only is licensed to you pursuant to the relevant licence terms of the applicable third party licensor ('Open Source Licence Terms') and not pursuant to this Licence, and you accept and agree to be bound by such terms. A copy of the Open Source Licence Terms will be made available upon request. 2. Confidentiality Obligations. You acknowledge that the Software contains confidential, proprietary and trade secret information belonging to SDRplay and you agree to hold such information, and any other confidential or proprietary information of SDRplay (collectively, "Confidential Information") in strict confidence and agree not to disclose any Confidential Information to any third party. You will have no obligation to maintain the confidentiality of any information which: (a) is or becomes publicly available without breach of this Licence; (b) is rightfully received by you from a third party without an obligation of confidentiality and without breach of this Licence; (c) is required to be disclosed by law or regulation or by court order; or (d) has been approved for release by written permission of SDRplay. 3. Ownership. You acknowledge and agree that SDRplay or its third party licensors (including in particular Mirics Limited) own all rights, title and interest in and to the Software and all modifications, enhancements and derivative works SDRplay may develop to or from the Software and any and all intellectual property rights in all of the foregoing. You agree not to use any of SDRplay's or Mirics' trademarks or other business names included in the Software for any purpose. You acknowledge that, except as expressly set out in this Licence, nothing in this Licence will give you rights in respect of any intellectual property rights owned by SDRplay or its licensors. All intellectual property rights and other rights of SDRplay and its licensors which are not expressly granted to you by this Licence are reserved. 4. Limited Warranty. SDRplay warrants that the Software will, under normal operating conditions, operate substantially in accordance with SDRplay's published specification for the Software. SDRplay does not represent or warrant that: (a) the use of the Software will be secure, timely, uninterrupted or error-free or compatible in combination with any other hardware, software, system or data; (b) the Software will meet your expectations; (c) errors or defects in the Software will be corrected; or that (d) the Software is free of viruses or other harmful components. SDRplay makes no representation and gives no warranty in respect of any Open Source Software component of the Software. Except as expressly set out in this Licence, no implied conditions, warranties or other terms, including any implied terms relating to satisfactory quality or fitness for any purpose, will apply to the Software and, to the maximum extent permitted by applicable law, are excluded by SDRplay. 5. SDRplay's Liability. Nothing in this Licence will limit or exclude SDRplay's liability to you: (a) for death or personal injury caused by SDRplay's negligence; (b) for fraud; (c) for breach of any obligations implied by section 12 of the Sale of Goods Act 1979 or section 2 of the Supply of Goods and Services Act 1982; or (d) for any other liability that may not, under applicable law, be limited or excluded. Subject to this, in no event will SDRplay be liable to you for any indirect or consequential losses, or for any loss of profit, revenue, contracts, data, goodwill or other similar losses, and any liability SDRplay does have for losses you suffer arising under or in connection with this Licence and/or the Software is strictly limited to losses that were reasonably foreseeable. 6. Data. The Software may, without further notification, transmit details of any radio device using the Software, other than through the EXTIO or other interface, to an SDRplay server, and may update data held on any such device, and alert users to any available firmware updates. 7. General. You may not transfer or assign any or all of your rights and/or obligations under this Licence. All notices given by you to SDRplay must be given in writing to SDRplay's registered office address. If SDRplay fails to enforce any of our rights, that does not result in a waiver of that right. If any provision of these terms and conditions is found to be unenforceable, all other provisions shall remain unaffected. The terms of this Licence may not be varied except with SDRplay's express written consent. The terms of this Licence represent the entire agreement between you and SDRplay in relation to the subject matter of this Licence. The terms of this Licence shall be governed by English law and you agree that any claim you may have against SDRplay arising under or in connection with this Licence and/or the Software may only be dealt with by the English courts, provided that, if you are a consumer: (a) and you live in a part of the United Kingdom other than England, the applicable law of that part of the United Kingdom will govern and any claim may be brought by you before the courts there; or (b) you live in another member state of the European Union, any claim may be brought by you before the courts there. Effective 12 Jan 2021 Type 'yes' to accept. EOF ) ####################################### # GLOBALS ####################################### DRY_RUN=0 ARCH="" SUDO="" TMP_DIR="$(mktemp -d)" ROLLBACK=() ####################################### # OUTPUT ####################################### if [[ -t 1 ]]; then RED=$'\033[0;31m'; GREEN=$'\033[0;32m'; YELLOW=$'\033[1;33m'; NC=$'\033[0m' else RED=""; GREEN=""; YELLOW=""; NC="" fi info(){ echo -e "${GREEN}[INFO]${NC} $*"; } warn(){ echo -e "${YELLOW}[WARN]${NC} $*"; } error(){ echo -e "${RED}[ERROR]${NC} $*" >&2; } warn_license_fallback(){ local reason="$1" echo echo -e "${YELLOW}========================================================================${NC}" echo -e "${YELLOW} WARNING: ${reason}${NC}" echo -e "${YELLOW} Falling back to the licence text embedded in this installer.${NC}" echo -e "${YELLOW} This may differ from the current upstream licence at:${NC}" echo -e "${YELLOW} ${UPSTREAM_INSTALLER_URL}${NC}" echo -e "${YELLOW}========================================================================${NC}" echo } ####################################### # ARGS ####################################### for arg in "$@"; do [[ "$arg" == "--dry-run" ]] && DRY_RUN=1 done ####################################### # CLEANUP + ROLLBACK ####################################### cleanup(){ rm -rf "$TMP_DIR"; } rollback(){ error "Failure - rolling back" for ((i=${#ROLLBACK[@]}-1;i>=0;i--)); do eval "${ROLLBACK[$i]}" || true; done } trap cleanup EXIT trap rollback ERR ####################################### # PLATFORM ####################################### check_platform(){ [[ "$(uname -s)" == "Linux" ]] || { error "Linux only"; exit 1; } case "$(uname -m)" in x86_64|amd64) ARCH="x86_64";; aarch64|arm64) ARCH="arm64";; *) error "Unsupported arch"; exit 1;; esac } ####################################### # SUDO ####################################### setup_sudo(){ [[ "$EUID" -ne 0 ]] && SUDO="sudo"; } ensure_sudo(){ [[ -z "$SUDO" || "$DRY_RUN" -eq 1 ]] && return info "Requesting sudo..." sudo -v } run(){ [[ "$DRY_RUN" -eq 1 ]] && echo "[DRY-RUN] $*" || "$@"; } run_root(){ [[ "$DRY_RUN" -eq 1 ]] && echo "[DRY-RUN] $SUDO $*" || ${SUDO:-} "$@"; } ####################################### # DEPENDENCIES ####################################### ####################################### # DISTRO FAMILY PROFILES # # To add a new distro family: # 1. Add a _packages function returning the package list # 2. Add a _check function to test if a package is installed # 3. Add an _install function to install missing packages # 4. Add detection logic in detect_distro_family() ####################################### _DEB_ASOUND="" debian_resolve_asound(){ [[ -n "$_DEB_ASOUND" ]] && return # The libasound2 → libasound2t64 rename (Y2038 transition) hit Debian 13 # and Ubuntu 24.04, but not all derivatives followed. On noble libasound2 # is purely virtual; on Devuan libasound2t64 doesn't exist. Probe apt-cache # to pick whichever name is a real package on this host. if apt-cache show libasound2t64 2>/dev/null | grep -q "^Package: libasound2t64"; then _DEB_ASOUND="libasound2t64" else _DEB_ASOUND="libasound2" fi } debian_packages(){ debian_resolve_asound echo "curl tar ca-certificates gzip libusb-1.0-0 $_DEB_ASOUND libuuid1 libudev1 libmp3lame-dev libhamlib-dev" } debian_check(){ dpkg -s "$1" >/dev/null 2>&1; } debian_install(){ ensure_sudo run_root apt-get update -y run_root apt-get install -y "$@" } arch_packages(){ echo "curl tar ca-certificates gzip libusb alsa-lib util-linux-libs systemd-libs lame hamlib"; } arch_check(){ pacman -Qi "$1" >/dev/null 2>&1; } arch_install(){ ensure_sudo run_root pacman -Sy --noconfirm "$@" } fedora_packages(){ echo "curl tar ca-certificates gzip libusb-compat-0.1.x86_64 libusb1.x86_64 alsa-lib libuuid systemd-libs lame-libs hamlib lame-devel hamlib-devel"; } fedora_check(){ rpm -q "$1" >/dev/null 2>&1; } fedora_install(){ ensure_sudo run_root dnf install -y "$@" } opensuse_packages(){ echo "curl tar ca-certificates gzip libusb-1_0-0 libasound2 libuuid1 libudev1 libmp3lame-devel hamlib-devel"; } opensuse_check(){ rpm -q "$1" >/dev/null 2>&1; } opensuse_install(){ ensure_sudo run_root zypper install -y "$@" } mandriva_packages(){ echo "curl tar ca-certificates gzip lib64usb1.0_0 lib64usb1.0-devel alsa-lib lib64uuid1 libsystemd lame lib64lame0 hamlib lame-devel hamlib-devel"; } mandriva_check(){ rpm -q "$1" >/dev/null 2>&1; } mandriva_install(){ ensure_sudo run_root dnf install -y "$@" } detect_distro_family(){ . /etc/os-release case "$ID" in debian|ubuntu|devuan) DISTRO_FAMILY="debian" ;; arch|manjaro|endeavouros|garuda|artix) DISTRO_FAMILY="arch" ;; fedora|rhel|centos|rocky|alma|nobara) DISTRO_FAMILY="fedora" ;; opensuse*|sles) DISTRO_FAMILY="opensuse";; openmandriva) DISTRO_FAMILY="mandriva";; *) # Fall back to ID_LIKE case "${ID_LIKE:-}" in *debian*|*ubuntu*) DISTRO_FAMILY="debian" ;; *arch*) DISTRO_FAMILY="arch" ;; *fedora*|*rhel*) DISTRO_FAMILY="fedora" ;; *suse*) DISTRO_FAMILY="opensuse";; *) error "Unsupported distro: $ID (ID_LIKE=${ID_LIKE:-none})" exit 1 ;; esac ;; esac info "Detected distro family: $DISTRO_FAMILY ($ID)" } check_dependencies(){ [[ "${NOTSUPPORTED:-0}" == "1" ]] && { info "Skipping dependency checks"; return; } detect_distro_family info "Checking dependencies" local pkg_list check_fn install_fn pkg_list=$(${DISTRO_FAMILY}_packages) check_fn="${DISTRO_FAMILY}_check" install_fn="${DISTRO_FAMILY}_install" local missing=() for p in $pkg_list; do "$check_fn" "$p" || missing+=("$p") done [[ ${#missing[@]} -eq 0 ]] && return warn "Installing missing dependencies: ${missing[*]}" "$install_fn" "${missing[@]}" } ####################################### # LICENSE ####################################### show_license() { if [[ "${ACCEPTLICENSE:-0}" == "1" ]]; then info "Licence auto-accepted via ACCEPTLICENSE=1" return fi local width="${COLUMNS:-80}" [[ "$width" =~ ^[0-9]+$ && "$width" -ge 20 ]] || width=80 # Only page if running interactively if [[ -t 0 && -t 1 ]]; then if command -v less >/dev/null 2>&1; then # -R: allow colours if present # -F: exit if fits on one screen # -X: don't clear screen on exit # -E: exit when EOF reached # -M: more verbose prompts # --mouse: enables mouse input printf "%s\n" "$LICENSE_TEXT" | fold -s -w "$width" | less -RFXEM --mouse elif command -v more >/dev/null 2>&1; then printf "%s\n" "$LICENSE_TEXT" | fold -s -w "$width" | more else printf "%s\n" "$LICENSE_TEXT" | fold -s -w "$width" fi else # Non-interactive terminal (CI, pipes, etc.) printf "%s\n" "$LICENSE_TEXT" | fold -s -w "$width" fi echo read -rp "Do you accept the licence? (yes/no): " reply case "$reply" in yes|y|Y) info "Licence accepted" ;; *) error "Licence not accepted" exit 1 ;; esac } ####################################### # UPSTREAM RESOLUTION ####################################### fetch_upstream(){ if [[ "${DONOTDOWNLOAD:-0}" == "1" ]]; then info "DONOTDOWNLOAD=1: skipping upstream lookup" return fi if [[ "$DRY_RUN" -eq 1 ]]; then info "[DRY-RUN] would fetch $UPSTREAM_INSTALLER_URL for current build hashes and licence" return fi info "Fetching current build hashes and licence from upstream..." local upstream if ! upstream=$(curl -fsSL --retry 2 "$UPSTREAM_INSTALLER_URL" 2>/dev/null); then warn "Could not fetch $UPSTREAM_INSTALLER_URL; using built-in fallback hashes" warn_license_fallback "Could not fetch $UPSTREAM_INSTALLER_URL" return fi local up_sdrc up_rig up_license up_sdrc=$(grep -E '^SDRCONNECT_GITBUILD=' <<<"$upstream" | head -1 | cut -d'"' -f2) up_rig=$(grep -E '^RIGCONTROL_GITBUILD=' <<<"$upstream" | head -1 | cut -d'"' -f2) up_license=$(awk '/^LICENSE_TEXT=\$\(cat/{flag=1; next} flag && /^EOF$/{flag=0; exit} flag' <<<"$upstream") if [[ "$_SDRCONNECT_GITBUILD_USER_SET" == "set" ]]; then info "Honouring SDRCONNECT_GITBUILD override: $SDRCONNECT_GITBUILD" elif [[ -n "$up_sdrc" ]]; then SDRCONNECT_GITBUILD="$up_sdrc" else warn "Could not parse SDRCONNECT_GITBUILD from upstream; using fallback $SDRCONNECT_GITBUILD" fi if [[ "$_RIGCONTROL_GITBUILD_USER_SET" == "set" ]]; then info "Honouring RIGCONTROL_GITBUILD override: $RIGCONTROL_GITBUILD" elif [[ -n "$up_rig" ]]; then RIGCONTROL_GITBUILD="$up_rig" else warn "Could not parse RIGCONTROL_GITBUILD from upstream; using fallback $RIGCONTROL_GITBUILD" fi if [[ -n "$up_license" ]] \ && [[ ${#up_license} -gt 500 ]] \ && grep -q "SDRPLAY LIMITED" <<<"$up_license"; then LICENSE_TEXT="$up_license" info "Licence text refreshed from upstream" else warn_license_fallback "Could not extract licence text from upstream" fi info "Resolved SDRconnect=$SDRCONNECT_GITBUILD, RigControl=$RIGCONTROL_GITBUILD" } resolve_artifacts(){ SDRCONNECT_TAR_X86_64="sdrconnect_linux-x64_${SDRCONNECT_GITBUILD}.tar.gz" SDRCONNECT_TAR_ARM64="sdrconnect_linux-arm64_${SDRCONNECT_GITBUILD}.tar.gz" RIGCONTROL_TAR_X86_64="rigcontrol_linux-x64_${RIGCONTROL_GITBUILD}.tar.gz" RIGCONTROL_TAR_ARM64="rigcontrol_linux-arm64_${RIGCONTROL_GITBUILD}.tar.gz" SDRCONNECT_URL_X86_64="https://www.sdrplay.com/software/${SDRCONNECT_TAR_X86_64}" SDRCONNECT_URL_ARM64="https://www.sdrplay.com/software/${SDRCONNECT_TAR_ARM64}" RIGCONTROL_URL_X86_64="https://www.sdrplay.com/software/${RIGCONTROL_TAR_X86_64}" RIGCONTROL_URL_ARM64="https://www.sdrplay.com/software/${RIGCONTROL_TAR_ARM64}" } ####################################### # DOWNLOAD ####################################### pushd(){ command pushd "$@" > /dev/null } popd(){ command popd "$@" > /dev/null } download(){ if [[ "${DONOTDOWNLOAD:-0}" == "1" ]]; then info "Using local install files via DONOTDOWNLOAD=1" if [ -e "$3" ]; then info "Using local $3" run cp "$3" "$2" else error "Cannot find $3" exit 1 fi if [ -e "$3.sha256" ]; then info "Using local $3.sha256" run cp "$3.sha256" "$2.sha256" else error "Cannot find $3.sha256" exit 1 fi else run curl -fL --retry 3 -o "$2" "$1" run curl -fL --retry 3 -o "$2.sha256" "$1.sha256" fi pushd "${TMP_DIR}" if sha256sum -c "$3.sha256"; then info "Checksum successful" popd else error "Checksum failed" popd exit 1 fi } ####################################### # INSTALL CORE ####################################### install_tar(){ run_root mkdir -p "$2" ROLLBACK+=("${SUDO:-} rm -rf '$2'") run_root tar -xzf "$1" -C "$2" --strip-components=1 } ####################################### # SYSTEM FILES ####################################### install_profile(){ run_root bash -c "cat > $PROFILE_SCRIPT <<'EOF' export SDRCONNECT_HOME=/opt/sdrconnect export RIGCONTROL_HOME=/opt/rigcontrol export PATH=\"\$SDRCONNECT_HOME:\$RIGCONTROL_HOME:\$PATH\" EOF" ROLLBACK+=("${SUDO:-} rm -f '$PROFILE_SCRIPT'") } install_udev(){ run_root bash -c "cat > $UDEV_RULES <<'EOF' SUBSYSTEM==\"usb\",ENV{DEVTYPE}==\"usb_device\",ATTRS{idVendor}==\"1df7\",ATTRS{idProduct}==\"2500\",MODE:=\"0666\" SUBSYSTEM==\"usb\",ENV{DEVTYPE}==\"usb_device\",ATTRS{idVendor}==\"1df7\",ATTRS{idProduct}==\"3000\",MODE:=\"0666\" SUBSYSTEM==\"usb\",ENV{DEVTYPE}==\"usb_device\",ATTRS{idVendor}==\"1df7\",ATTRS{idProduct}==\"3010\",MODE:=\"0666\" SUBSYSTEM==\"usb\",ENV{DEVTYPE}==\"usb_device\",ATTRS{idVendor}==\"1df7\",ATTRS{idProduct}==\"3020\",MODE:=\"0666\" SUBSYSTEM==\"usb\",ENV{DEVTYPE}==\"usb_device\",ATTRS{idVendor}==\"1df7\",ATTRS{idProduct}==\"3030\",MODE:=\"0666\" SUBSYSTEM==\"usb\",ENV{DEVTYPE}==\"usb_device\",ATTRS{idVendor}==\"1df7\",ATTRS{idProduct}==\"3040\",MODE:=\"0666\" SUBSYSTEM==\"usb\",ENV{DEVTYPE}==\"usb_device\",ATTRS{idVendor}==\"1df7\",ATTRS{idProduct}==\"3050\",MODE:=\"0666\" SUBSYSTEM==\"usb\",ENV{DEVTYPE}==\"usb_device\",ATTRS{idVendor}==\"1df7\",ATTRS{idProduct}==\"3060\",MODE:=\"0666\" EOF" run_root rm -f "$OLD_UDEV_RULES" ROLLBACK+=("${SUDO:-} rm -f '$UDEV_RULES'") } ####################################### # DESKTOP ####################################### install_desktop_entry(){ local id="$1" name="$2" exec="$3" icon="$4" cat="$5" local target="/usr/share/applications/${id}.desktop" run_root bash -c "cat > $target < $path </dev/null #!/usr/bin/env bash while read -r p; do [ -e "\$p" ] && sudo rm -rf "\$p"; done < "$MANIFEST" echo "SDRconnect & RigControl Uninstalled." echo "Logout and Login again for paths to update." EOF run_root chmod +x "$UNINSTALLER" } write_manifest(){ printf "%s\n" \ "$SDRCONNECT_DIR" "$RIGCONTROL_DIR" \ "$PROFILE_SCRIPT" \ "/usr/share/applications/sdrconnect.desktop" \ "/usr/share/applications/rigcontrol.desktop" \ "/usr/share/applications/nrspadministrator.desktop" \ "/usr/share/applications/nrspupdater.desktop" \ "$ICON_PATH/sdrconnect.png" \ "$ICON_PATH/rigcontrol.png" \ "$ICON_PATH/nrspadministrator.png" \ "$ICON_PATH/nrspupdater.png" \ "$DOC1" "$DOC2" \ "$UNINSTALLER" "$MANIFEST" \ | run_root tee "$MANIFEST" >/dev/null } ####################################### # REFRESH ####################################### refresh(){ command -v update-desktop-database >/dev/null && run_root update-desktop-database || true command -v gtk-update-icon-cache >/dev/null && run_root gtk-update-icon-cache /usr/share/icons/hicolor || true } ####################################### # MAIN ####################################### main(){ check_platform setup_sudo fetch_upstream resolve_artifacts show_license check_dependencies ensure_sudo [[ "$ARCH" == "x86_64" ]] && { U1="$SDRCONNECT_URL_X86_64"; U2="$RIGCONTROL_URL_X86_64" F1="$SDRCONNECT_TAR_X86_64"; F2="$RIGCONTROL_TAR_X86_64" } || { U1="$SDRCONNECT_URL_ARM64"; U2="$RIGCONTROL_URL_ARM64" F1="$SDRCONNECT_TAR_ARM64"; F2="$RIGCONTROL_TAR_ARM64" } T1="$TMP_DIR/$F1" T2="$TMP_DIR/$F2" info "Downloading software..." download "$U1" "$T1" "$F1" download "$U2" "$T2" "$F2" install_tar "$T1" "$SDRCONNECT_DIR" install_tar "$T2" "$RIGCONTROL_DIR" install_profile install_udev install_icon install_all_desktops install_docs handle_systemd create_uninstaller write_manifest refresh info "Install complete - logout and login for path update" info "To uninstall use: $UNINSTALLER" } main abort