1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-08-10 17:52:26 -04:00

Compare commits

..

No commits in common. "master" and "v7.22.2" have entirely different histories.

13257 changed files with 7631 additions and 72517 deletions

View File

@ -20,118 +20,118 @@ environment:
# -DBUILD_SERVER=OFF \
# -DCMAKE_PREFIX_PATH=C:\\Qt\\5.15.2\\msvc2019_64;C:\\Libraries\\boost_1_73_0"
# CMAKE_GENERATOR: Ninja
# - TARGET: ubuntu2204prod
# APPVEYOR_BUILD_WORKER_CLOUD: nasrock Docker
# APPVEYOR_BUILD_WORKER_IMAGE: Linux
# CC: "gcc-11"
# CXX: "g++-11"
# CMAKE_CUSTOM_OPTIONS: "-DCMAKE_BUILD_TYPE=Release \
# -DARCH_OPT=nehalem \
# -DDEBUG_OUTPUT=ON \
# -DENABLE_EXTERNAL_LIBRARIES=AUTO \
# -DBUILD_SERVER=OFF"
- TARGET: ubuntu2204prod
APPVEYOR_BUILD_WORKER_CLOUD: nasrock Docker
APPVEYOR_BUILD_WORKER_IMAGE: Linux
CC: "gcc-11"
CXX: "g++-11"
CMAKE_CUSTOM_OPTIONS: "-DCMAKE_BUILD_TYPE=Release \
-DARCH_OPT=nehalem \
-DDEBUG_OUTPUT=ON \
-DENABLE_EXTERNAL_LIBRARIES=AUTO \
-DBUILD_SERVER=OFF"
- TARGET: ubuntu2204docker
APPVEYOR_BUILD_WORKER_CLOUD: nasrock
APPVEYOR_BUILD_WORKER_IMAGE: Linux
APPVEYOR_CONSOLE_DISABLE_PTY: true
for:
# # - matrix:
# # only:
# # - TARGET: 'vs2019gui'
# # cache:
# # - C:\ProgramData\chocolatey\bin
# # - C:\ProgramData\chocolatey\lib
# # build_script:
# # - call "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
# # # Install GNU patch as applying patches with git fails in BladeRF tree
# # - choco install patch
# # - git submodule update --init --recursive
# # - mkdir build && cd build
# # - cmake .. -G "%CMAKE_GENERATOR%" %CMAKE_CUSTOM_OPTIONS%
# # - cmake --build . --config Release --target package
# # artifacts: # push installer executable
# # path: build\*.exe
# # name: installer
# # deploy:
# # release: sdrangel-v$(appveyor_build_version)
# # description: 'SDRangel Windows'
# # provider: GitHub
# # auth_token:
# # secure: kyU5TaXRoily6q/QLRLqal2xCFGWEdnb8AJIu7FknsUQyj1wjRGmqC2My+Wfszod
# # artifact: installer, portable
# # draft: false
# # prerelease: false
# # tag: $(APPVEYOR_REPO_TAG_NAME) # will not work until tag is pushed
# # on:
# # APPVEYOR_REPO_TAG: true # deploy on tag push only
# # branch: master # release from master branch only
# - matrix:
# only:
# - TARGET: ubuntu2204prod
# clone_folder: /home/appveyor/projects
# cache:
# - $HOME/external/
# install:
# - sh: sudo apt-get update
# - sh: echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections
# # not sdrplay with soapysdr; libairspyhf-dev is too old (no lna)
# - sh: |
# sudo apt-get -y install build-essential cmake git xxd \
# devscripts fakeroot debhelper libfftw3-dev qtbase5-dev libopengl-dev libqt5opengl5-dev \
# qttools5-dev qttools5-dev-tools qtmultimedia5-dev libqt5multimedia5-plugins libqt5websockets5-dev \
# libqt5quick5 qtwebengine5-dev qtbase5-private-dev \
# qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick-window2 qml-module-qtquick-dialogs \
# qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtgraphicaleffects \
# libqt5serialport5-dev qtdeclarative5-dev qtpositioning5-dev qtlocation5-dev \
# libqt5charts5-dev libqt5texttospeech5-dev libqt5gamepad5-dev libqt5svg5-dev libfaad-dev libflac-dev zlib1g-dev \
# libusb-1.0-0-dev libhidapi-dev libboost-all-dev libasound2-dev libopencv-dev libopencv-imgcodecs-dev \
# libxml2-dev bison flex ffmpeg libpostproc-dev libavcodec-dev libavformat-dev \
# libopus-dev libcodec2-dev libairspy-dev libhackrf-dev \
# libbladerf-dev libsoapysdr-dev libiio-dev libuhd-dev libhamlib-dev \
# python3-mako python3-cheetah python3-numpy \
# autoconf automake libtool ninja-build libclang1-11
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_cm256cc.sh; fi
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_mbelib.sh; fi
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_serialdv.sh; fi
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_dsdcc.sh; fi
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_perseus-sdr.sh; fi
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_xtrx-sdr.sh; fi
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_airspyhf.sh; fi
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_rtlsdr.sh; fi
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_limesuite.sh; fi
# - sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_ggmorse.sh; fi
# - sh: bash cmake/ci/build_sdrplay.sh
# before_build:
# - sh: bash -c export
# - sh: bash -c pwd
# build_script:
# - sh: ./cmake/ci/build_sdrangel.sh
# test_script:
# # debian build path
# - sh: ./obj-x86_64-linux-gnu/sdrangelbench
# after_build:
# - sh: mkdir sdrangel-${APPVEYOR_BUILD_VERSION}
# - sh: cp ../*.deb ../*.build ../*.buildinfo ../*.changes sdrangel-${APPVEYOR_BUILD_VERSION}
# - sh: tar -czf sdrangel-${APPVEYOR_BUILD_VERSION}.tar.gz sdrangel-${APPVEYOR_BUILD_VERSION}
# artifacts:
# - path: sdrangel-${APPVEYOR_BUILD_VERSION}.tar.gz
# name: package2204
# # deploy:
# # release: sdrangel-v$(appveyor_build_version)
# # description: 'SDRangel Ubuntu 22.04'
# # provider: GitHub
# # auth_token:
# # secure: kyU5TaXRoily6q/QLRLqal2xCFGWEdnb8AJIu7FknsUQyj1wjRGmqC2My+Wfszod
# # artifact: archive
# # draft: false
# # prerelease: false
# # on:
# # APPVEYOR_REPO_TAG: true # deploy on tag push only
# # branch: master # release from master branch only
# deploy:
# provider: Environment
# name: f4exb
# - matrix:
# only:
# - TARGET: 'vs2019gui'
# cache:
# - C:\ProgramData\chocolatey\bin
# - C:\ProgramData\chocolatey\lib
# build_script:
# - call "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
# # Install GNU patch as applying patches with git fails in BladeRF tree
# - choco install patch
# - git submodule update --init --recursive
# - mkdir build && cd build
# - cmake .. -G "%CMAKE_GENERATOR%" %CMAKE_CUSTOM_OPTIONS%
# - cmake --build . --config Release --target package
# artifacts: # push installer executable
# path: build\*.exe
# name: installer
# deploy:
# release: sdrangel-v$(appveyor_build_version)
# description: 'SDRangel Windows'
# provider: GitHub
# auth_token:
# secure: kyU5TaXRoily6q/QLRLqal2xCFGWEdnb8AJIu7FknsUQyj1wjRGmqC2My+Wfszod
# artifact: installer, portable
# draft: false
# prerelease: false
# tag: $(APPVEYOR_REPO_TAG_NAME) # will not work until tag is pushed
# on:
# APPVEYOR_REPO_TAG: true # deploy on tag push only
# branch: master # release from master branch only
- matrix:
only:
- TARGET: ubuntu2204prod
clone_folder: /home/appveyor/projects
cache:
- $HOME/external/
install:
- sh: sudo apt-get update
- sh: echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections
# not sdrplay with soapysdr; libairspyhf-dev is too old (no lna)
- sh: |
sudo apt-get -y install build-essential cmake git xxd \
devscripts fakeroot debhelper libfftw3-dev qtbase5-dev libopengl-dev libqt5opengl5-dev \
qttools5-dev qttools5-dev-tools qtmultimedia5-dev libqt5multimedia5-plugins libqt5websockets5-dev \
libqt5quick5 qtwebengine5-dev qtbase5-private-dev \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick-window2 qml-module-qtquick-dialogs \
qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtgraphicaleffects \
libqt5serialport5-dev qtdeclarative5-dev qtpositioning5-dev qtlocation5-dev \
libqt5charts5-dev libqt5texttospeech5-dev libqt5gamepad5-dev libqt5svg5-dev libfaad-dev libflac-dev zlib1g-dev \
libusb-1.0-0-dev libhidapi-dev libboost-all-dev libasound2-dev libopencv-dev libopencv-imgcodecs-dev \
libxml2-dev bison flex ffmpeg libpostproc-dev libavcodec-dev libavformat-dev \
libopus-dev libcodec2-dev libairspy-dev libhackrf-dev \
libbladerf-dev libsoapysdr-dev libiio-dev libuhd-dev libhamlib-dev \
python3-mako python3-cheetah python3-numpy \
autoconf automake libtool ninja-build libclang1-11
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_cm256cc.sh; fi
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_mbelib.sh; fi
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_serialdv.sh; fi
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_dsdcc.sh; fi
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_perseus-sdr.sh; fi
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_xtrx-sdr.sh; fi
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_airspyhf.sh; fi
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_rtlsdr.sh; fi
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_limesuite.sh; fi
- sh: if [[ ! "${CMAKE_CUSTOM_OPTIONS}" =~ "ENABLE_EXTERNAL_LIBRARIES" ]]; then bash cmake/ci/build_ggmorse.sh; fi
- sh: bash cmake/ci/build_sdrplay.sh
before_build:
- sh: bash -c export
- sh: bash -c pwd
build_script:
- sh: ./cmake/ci/build_sdrangel.sh
test_script:
# debian build path
- sh: ./obj-x86_64-linux-gnu/sdrangelbench
after_build:
- sh: mkdir sdrangel-${APPVEYOR_BUILD_VERSION}
- sh: cp ../*.deb ../*.build ../*.buildinfo ../*.changes sdrangel-${APPVEYOR_BUILD_VERSION}
- sh: tar -czf sdrangel-${APPVEYOR_BUILD_VERSION}.tar.gz sdrangel-${APPVEYOR_BUILD_VERSION}
artifacts:
- path: sdrangel-${APPVEYOR_BUILD_VERSION}.tar.gz
name: package2204
# deploy:
# release: sdrangel-v$(appveyor_build_version)
# description: 'SDRangel Ubuntu 22.04'
# provider: GitHub
# auth_token:
# secure: kyU5TaXRoily6q/QLRLqal2xCFGWEdnb8AJIu7FknsUQyj1wjRGmqC2My+Wfszod
# artifact: archive
# draft: false
# prerelease: false
# on:
# APPVEYOR_REPO_TAG: true # deploy on tag push only
# branch: master # release from master branch only
deploy:
provider: Environment
name: f4exb
- matrix:
only:
- TARGET: ubuntu2204docker

View File

@ -1,62 +0,0 @@
name: SDRangel Linux release build
on:
push:
branches:
- linux_github_release
tags:
- 'v*'
jobs:
build_deb:
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-24.04]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install build-essential cmake git xxd \
devscripts fakeroot debhelper libfftw3-dev qtbase5-dev libopengl-dev libqt5opengl5-dev \
qttools5-dev qttools5-dev-tools qtmultimedia5-dev libqt5multimedia5-plugins libqt5websockets5-dev \
libqt5quick5 qtwebengine5-dev qtbase5-private-dev \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick-window2 qml-module-qtquick-dialogs \
qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtgraphicaleffects \
libqt5serialport5-dev qtdeclarative5-dev qtpositioning5-dev qtlocation5-dev \
libqt5charts5-dev libqt5texttospeech5-dev libqt5gamepad5-dev libqt5svg5-dev libfaad-dev libflac-dev zlib1g-dev \
libusb-1.0-0-dev libhidapi-dev libboost-all-dev libasound2-dev libopencv-dev libopencv-imgcodecs-dev \
libxml2-dev bison flex ffmpeg libpostproc-dev libavcodec-dev libavformat-dev \
libopus-dev libcodec2-dev libairspy-dev libhackrf-dev \
libbladerf-dev libsoapysdr-dev libiio-dev libuhd-dev libhamlib-dev \
python3-mako python3-cheetah python3-numpy \
autoconf automake libtool ninja-build
bash cmake/ci/build_sdrplay.sh
- name: Build SDRangel
run: |
debuild -i -us -uc -b
- name: Get version
id: get_version
run: |
if [[ "${{github.ref_name}}" == "linux_github_release" ]]; then
echo "version=$(echo ${{github.sha}} | cut -c1-7)" >> $GITHUB_OUTPUT
else
echo "version=$(echo ${{github.ref_name}} | cut -c2-)" >> $GITHUB_OUTPUT
fi
- name: Rename
run: mv ../sdrangel_*_amd64.deb sdrangel_${{ steps.get_version.outputs.version }}_${{ matrix.os }}_amd64.deb
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: sdrangel_${{ steps.get_version.outputs.version }}_${{ matrix.os }}_amd64.deb
path: sdrangel_${{ steps.get_version.outputs.version }}_${{ matrix.os }}_amd64.deb
- name: Upload release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: sdrangel_${{ steps.get_version.outputs.version }}_${{ matrix.os }}_amd64.deb

View File

@ -1,161 +0,0 @@
name: SDRangel Mac release build
on:
push:
branches:
- mac_ci
tags:
- 'v*'
jobs:
build_mac_x64:
runs-on: macos-13
env:
MACOSX_DEPLOYMENT_TARGET: 12.0
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Update brew
run: brew update
- name: Install brew packages
run: brew install nasm subversion
- name: Install SDRplay API
run: |
wget https://www.sdrplay.com/software/SDRplayAPI-macos-installer-universal-3.15.0.pkg
sudo installer -pkg SDRplayAPI-macos-installer-universal-3.15.0.pkg -target /
- name: Install python
run: |
wget https://www.python.org/ftp/python/3.12.7/python-3.12.7-macos11.pkg
sudo installer -pkg python-3.12.7-macos11.pkg -target /
- name: Install python packages for UHD
run: |
/usr/local/bin/python3.12 -m pip install numpy mako requests Cheetah3 setuptools
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: '6.9.1'
host: 'mac'
arch: 'clang_64'
modules: 'qtcharts qtscxml qt5compat qtlocation qtmultimedia qtpositioning qtserialport qtspeech qtwebsockets qtwebengine qtshadertools qtwebchannel'
- name: Configure SDRangel
run: |
mkdir build && cd build
cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_QT6=ON -DCMAKE_BUILD_TYPE=Release -DARCH_OPT=nehalem -DDEBUG_OUTPUT=ON -DENABLE_USRP=ON -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DENABLE_EXTERNAL_LIBRARIES=ON -DBUNDLE=ON -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=TRUE -DPYTHON_EXECUTABLE=/usr/local/bin/python3.12
- name: Build SDRangel on Mac
run: |
cd build
make -j4
- name: Create dmg
run: |
cd build
RETRIES=5
COUNT=1
set +e
while [ $COUNT -lt $RETRIES ]; do
make package
if [ $? -eq 0 ]; then
RETRIES=0
break
fi
let COUNT=$COUNT+1
done
shell: bash
continue-on-error: true
- name: Get version
id: get_version
run: |
if [[ "${{github.ref_name}}" == "mac_ci" ]]; then
echo "version=$(echo ${{github.sha}} | cut -c1-7)" >> $GITHUB_OUTPUT
else
echo "version=$(echo ${{github.ref_name}} | cut -c2-)" >> $GITHUB_OUTPUT
fi
- name: Get filename
id: get_filename
run: echo "filename=$(grep CPACK_PACKAGE_FILE_NAME build/CMakeCache.txt | cut -d "=" -f2)" >> $GITHUB_OUTPUT
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: sdrangel-${{ steps.get_version.outputs.version }}-macx64.dmg
path: ${{ github.workspace }}/build/${{ steps.get_filename.outputs.filename }}.dmg
- name: Upload release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: ${{ github.workspace }}/build/${{ steps.get_filename.outputs.filename }}.dmg
build_mac_arm64:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Update brew
run: brew update
- name: Install brew packages
run: brew install nasm subversion
- name: Install SDRplay API
run: |
wget https://www.sdrplay.com/software/SDRplayAPI-macos-installer-universal-3.15.0.pkg
sudo installer -pkg SDRplayAPI-macos-installer-universal-3.15.0.pkg -target /
- name: Install python
run: |
wget https://www.python.org/ftp/python/3.12.7/python-3.12.7-macos11.pkg
sudo installer -pkg python-3.12.7-macos11.pkg -target /
- name: Install python packages for UHD
run: |
/usr/local/bin/python3.12 -m pip install numpy mako requests Cheetah3 setuptools
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: '6.9.1'
host: 'mac'
arch: 'clang_64'
modules: 'qtcharts qtscxml qt5compat qtlocation qtmultimedia qtpositioning qtserialport qtspeech qtwebsockets qtwebengine qtshadertools qtwebchannel'
- name: Configure SDRangel
run: |
mkdir build && cd build
cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_QT6=ON -DCMAKE_BUILD_TYPE=Release -DDEBUG_OUTPUT=ON -DENABLE_USRP=ON -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DENABLE_EXTERNAL_LIBRARIES=ON -DBUNDLE=ON -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=TRUE -DPYTHON_EXECUTABLE=/usr/local/bin/python3.12
- name: Build SDRangel on Mac
run: |
cd build
make -j3
- name: Create dmg
run: |
cd build
RETRIES=5
COUNT=1
set +e
while [ $COUNT -lt $RETRIES ]; do
make package
if [ $? -eq 0 ]; then
RETRIES=0
break
fi
let COUNT=$COUNT+1
done
shell: bash
continue-on-error: true
- name: Get version
id: get_version
run: |
if [[ "${{github.ref_name}}" == "mac_ci" ]]; then
echo "version=$(echo ${{github.sha}} | cut -c1-7)" >> $GITHUB_OUTPUT
else
echo "version=$(echo ${{github.ref_name}} | cut -c2-)" >> $GITHUB_OUTPUT
fi
- name: Get filename
id: get_filename
run: echo "filename=$(grep CPACK_PACKAGE_FILE_NAME build/CMakeCache.txt | cut -d "=" -f2)" >> $GITHUB_OUTPUT
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: sdrangel-${{ steps.get_version.outputs.version }}-macarm64.dmg
path: ${{ github.workspace }}/build/${{ steps.get_filename.outputs.filename }}.dmg
- name: Upload release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: ${{ github.workspace }}/build/${{ steps.get_filename.outputs.filename }}.dmg

View File

@ -24,7 +24,7 @@ jobs:
WIN_ARCH: "x64",
os: windows-latest,
QT_INST_DIR: "C:/",
QTDIR: "C:/Qt/6.7.3/msvc2019_64",
QTDIR: "C:/Qt/5.15.2/msvc2019_64",
QT_ARCH: win64_msvc2019_64,
boost_dl: "${{ github.workspace }}\\downloads\\boost",
lib_dir: "C:\\Libraries",
@ -41,9 +41,6 @@ jobs:
echo github.event_name: ${{ github.event_name }}
echo github.ref: ${{ github.ref }}
echo github.workspace: ${{ github.workspace }}
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install basic dependencies on Windows
if: startsWith(matrix.config.os, 'windows')
run: |
@ -72,20 +69,19 @@ jobs:
rm -rf boost_*/* download.tar.bz2 download.tar
shell: bash
- name: Install Qt
uses: jurplel/install-qt-action@v4
uses: jurplel/install-qt-action@v3
with:
version: '6.7.3'
dir: ${{matrix.config.QT_INST_DIR}}
arch: ${{matrix.config.QT_ARCH}}
setup-python: false
modules: 'qtcharts qtscxml qt5compat qtlocation qtmultimedia qtpositioning qtserialport qtspeech qtwebsockets qtwebengine qtshadertools qtwebchannel'
modules: 'qtcharts qtwebengine'
- name: build sdrangel on Windows
if: startsWith(matrix.config.os, 'windows')
run: |
cmd "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
cmd "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
choco install patch
mkdir build && cd build
cmake .. -G "${{ matrix.config.generators }}" -DCMAKE_BUILD_TYPE=Release -DENABLE_QT6=ON -DARCH_OPT=SSE4_2 -DDEBUG_OUTPUT=ON -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DCMAKE_PREFIX_PATH="C:\Qt\6.7.3\msvc2019_64;C:\Libraries\boost_1_73_0"
cmake .. -G "${{ matrix.config.generators }}" -DCMAKE_BUILD_TYPE=Release -DARCH_OPT=SSE4_2 -DDEBUG_OUTPUT=ON -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DCMAKE_PREFIX_PATH="C:\Qt\5.15.2\msvc2019_64;C:\Libraries\boost_1_73_0"
cmake --build . --config Release --target package
- name: Check disk space
run: Get-PSDrive
@ -93,13 +89,18 @@ jobs:
id: get_version
run: echo "version=$(grep sdrangel_VERSION build/CMakeCache.txt | cut -d "=" -f2)" >> $env:GITHUB_OUTPUT
- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: sdrangel-${{ steps.get_version.outputs.version }}-win64.exe
path: ${{ github.workspace }}/build/sdrangel-${{ steps.get_version.outputs.version }}-win64.exe
- name: Upload release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v0.1.13
with:
files: ${{ github.workspace }}/build/sdrangel-${{ steps.get_version.outputs.version }}-win64.exe
build_mac:
runs-on: macos-14
runs-on: macos-13
steps:
- uses: actions/checkout@v4
with:
@ -124,7 +125,10 @@ jobs:
- name: Configure SDRangel
run: |
mkdir build && cd build
cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_QT6=ON -DCMAKE_BUILD_TYPE=Release -DDEBUG_OUTPUT=ON -DENABLE_CHANNELRX_DEMODDATV=OFF -DENABLE_CHANNELTX_MODDATV=OFF -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DENABLE_EXTERNAL_LIBRARIES=AUTO -DBUNDLE=ON -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=TRUE -DCMAKE_PREFIX_PATH="/usr/local/opt/ffmpeg@5/"
cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_QT6=ON -DCMAKE_BUILD_TYPE=Release -DARCH_OPT=nehalem -DDEBUG_OUTPUT=ON -DENABLE_CHANNELRX_DEMODDATV=OFF -DENABLE_CHANNELTX_MODDATV=OFF -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DENABLE_EXTERNAL_LIBRARIES=AUTO -DBUNDLE=ON -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=TRUE -DCMAKE_PREFIX_PATH="/usr/local/opt/ffmpeg@5/"
- name: Get filename
id: get_filename
run: echo "filename=$(grep CPACK_PACKAGE_FILE_NAME build/CMakeCache.txt | cut -d "=" -f2)" >> $GITHUB_OUTPUT
- name: Build SDRangel on Mac
run: |
cd build

View File

@ -1,44 +0,0 @@
# See: https://github.com/snapcore/action-build
name: SDRangel snap release build
on:
push:
branches:
- snap
tags:
- 'v*'
jobs:
build_snap:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Get version
id: get_version
run: |
if [[ "${{github.ref_name}}" == "snap" ]]; then
echo "version=${{github.sha}}" >> $GITHUB_OUTPUT
else
echo "version=$(echo ${{github.ref_name}} | cut -c2-)" >> $GITHUB_OUTPUT
fi
- uses: snapcore/action-build@v1
id: build
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: sdrangel-${{ steps.get_version.outputs.version }}-amd64.snap
path: ${{ steps.build.outputs.snap }}
- name: Upload release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: ${{ steps.build.outputs.snap }}
- uses: snapcore/action-publish@v1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
with:
snap: ${{ steps.build.outputs.snap }}
release: stable

View File

@ -1,119 +0,0 @@
name: SDRangel Windows release build and signing
on:
push:
branches:
- master
tags:
- 'v*'
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- {
name: "Windows-x64",
WIN_ARCH: "x64",
os: windows-latest,
QT_INST_DIR: "C:/",
QTDIR: "C:/Qt/6.7.3/msvc2019_64",
QT_ARCH: win64_msvc2019_64,
boost_dl: "${{ github.workspace }}\\downloads\\boost",
lib_dir: "C:\\Libraries",
generators: Ninja
}
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Print env
run: |
echo github.event.action: ${{ github.event.action }}
echo github.event_name: ${{ github.event_name }}
echo github.ref: ${{ github.ref }}
echo github.workspace: ${{ github.workspace }}
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install basic dependencies on Windows
if: startsWith(matrix.config.os, 'windows')
run: |
choco install ninja cmake
ninja --version
cmake --version
- name: Install MSVC on Windows
if: startsWith(matrix.config.os, 'windows')
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Install Boost
env:
BOOST_ROOT: ${{ matrix.config.boost_dl }}
BOOST_DEST: ${{ matrix.config.lib_dir }}
BOOST_URL: https://archives.boost.io/release/1.73.0/source/boost_1_73_0.tar.bz2
run: |
mkdir -p $BOOST_ROOT
mkdir -p $BOOST_DEST
curl --progress-bar --location --output $BOOST_ROOT/download.tar.bz2 $BOOST_URL
7z -o$BOOST_ROOT x $BOOST_ROOT/download.tar.bz2 -y -bd
7z -o$BOOST_ROOT x $BOOST_ROOT/download.tar -y -bd
cd $BOOST_ROOT && cp -r boost_* $BOOST_DEST
ls -l $BOOST_DEST
ls -l "C:\\"
rm -rf boost_*/* download.tar.bz2 download.tar
shell: bash
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: '6.7.3'
dir: ${{matrix.config.QT_INST_DIR}}
arch: ${{matrix.config.QT_ARCH}}
setup-python: 'false'
modules: 'qtcharts qtscxml qt5compat qtlocation qtmultimedia qtpositioning qtserialport qtspeech qtwebsockets qtwebengine qtshadertools qtwebchannel'
- name: build sdrangel on Windows
if: startsWith(matrix.config.os, 'windows')
run: |
cmd "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
choco install patch
mkdir build && cd build
cmake .. -G "${{ matrix.config.generators }}" -DCMAKE_BUILD_TYPE=Release -DENABLE_QT6=ON -DARCH_OPT=SSE4_2 -DDEBUG_OUTPUT=ON -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DCMAKE_PREFIX_PATH="C:\Qt\6.7.3\msvc2019_64;C:\Libraries\boost_1_73_0"
cmake --build . --config Release --target package
- name: Check disk space
run: Get-PSDrive
- name: Get version
id: get_version
run: echo "version=$(grep sdrangel_VERSION build/CMakeCache.txt | cut -d "=" -f2)" >> $env:GITHUB_OUTPUT
- name: Upload unsigned artifact
id: upload-unsigned-artifact
uses: actions/upload-artifact@v4
with:
name: sdrangel-${{ steps.get_version.outputs.version }}-win64.exe
path: ${{ github.workspace }}/build/sdrangel-${{ steps.get_version.outputs.version }}-win64.exe
- name: Sign Code
id: sign_code
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '553b8f53-adf0-4fe5-be3d-283504a21a51'
project-slug: 'sdrangel'
signing-policy-slug: 'release-signing'
github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: 'build\signed'
wait-for-completion-timeout-in-seconds: 3600
- name: Upload signed artifact
id: upload-signed-artifact
uses: actions/upload-artifact@v4
with:
name: sdrangel-${{ steps.get_version.outputs.version }}-win64-signed.exe
path: ${{ github.workspace }}/build/signed/sdrangel-${{ steps.get_version.outputs.version }}-win64.exe
- name: Upload release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: ${{ github.workspace }}/build/signed/sdrangel-${{ steps.get_version.outputs.version }}-win64.exe

View File

@ -1,77 +1,3 @@
sdrangel (7.22.8-1) unstable; urgency=medium
* See Github release
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Wed, 02 Jul 2025 17:00:39 +0200
sdrangel (7.22.7-1) unstable; urgency=medium
* See Github release
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 04 May 2025 17:58:14 +0200
sdrangel (7.22.6-1) unstable; urgency=medium
* See Github release
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 02 Feb 2025 18:08:11 +0100
sdrangel (7.22.5-1) unstable; urgency=medium
* Windows: upload signed releases rather than unsigned releases to Github releases page. PR #2347
* Windows: fixed signed releases. PR #2344
* FT8 Demod: limit upper bandwidth to 5.8 kHz. Fixes #2339
* Stop device while changing channel set. Fixes #2332. PR #2342
* ADSB: Update URL of OpenSkyNetwork Aircraft database. PR #2341
* Don't stop source if being deleted. For #2315. PR #2340
* Send DSPSignalNotification in audio mods for #2336. PR #2340
* Radiosonde: limit precision of floating point numbers sent to SondeHub. PR #2338
* Windows signed releases: use relative path. Increase timeout to 30 minutes. PR #2335
* ADSB: Include adsbdemodsettings.h PR #2334
* Use release signing certificate for Windows installer. PR #2331
* Fix memory leak and race condition relating to DSP*Engines. Part of #2159 PR #2330
* FreeDV: Fix memory allocation/free issues. Part of #2315. PR #2330
* Wav Files: Add support for meta-data. PR #2328
* DemodAnalyzer: Ensure sample rate is set in worker. Fixes #2309. PR #2328
^ SDRplayv3: Mac: link with libsdrplay_api.so.3 rather than libsdrplay_api.so.3.15. PR #2327
* ADS-B: Fix memory use after delete. For #1734 and part of #2315 PR #2326
* Fixed Appveyor Docker image build
* Fix output-artifact-directory and unzip file. PR #2323
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Thu, 05 Dec 2024 01:07:27 +0100
sdrangel (7.22.4-1) unstable; urgency=medium
* Use macos-12 for Mac x86 build. PR #2321
* Workaround for "hdiutil: create failed - Resource busy"
* Pager: Add alpha and numeric columns. Implements #2319. PR #2320
* Added qtwebchannel dependecy to fix missing 3d Map and Sky Map from Windows release. PR #2316
* Removed .deb package build from Appveyor
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Mom, 11 Nov 2024 08:42:03 +0100
sdrangel (7.22.3-1) unstable; urgency=medium
* Add deb dependencies for pipewire. PR #2314
* Added compilation options for WebAssembly. PR #2313
* ADS-B: Use settings keys. PR #2310
* AIS Demod: Remove spacing around messages. PR #2310
* Freuqency Scanner: Add multiplex mode. PR #2310
* Build snap, MAC, Windows and Ubuntu .deb with Github actions. Various PRs
* Server: Use Sink/MIMO signals rather than Source. Part of #2294. PR #2304
* Updated some Python scripts to Python3. PR #2298
* RemoteTCPSink: Does use IQ only setting for RTL0. PR #2301
* Server: wait for set sample source/sink/MIMO to complete before loading the device settings. Fixes #2294
* Fix spectrum peak measurement for SSB spectra. Fixes #2282. PR #2299
* Upgrade C++ standard to c++17
* Fixes for Android . PR #2288
* Add qtshadertools. PR #2287
* Add more Qt modules and set ENABLE_QT6=ON. PR #2287
* Update Qt optional packages for 6.8 , PR #2287
* Use Qt 6.8 for Windows build. PR #2287
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sat, 09 Nov 2024 17:30:44 +0100
sdrangel (7.22.2-1) unstable; urgency=medium
* ChirpChat: increased preamble symbols limit from 20 to 32. Fixes #2284
@ -93,7 +19,7 @@ sdrangel (7.22.2-1) unstable; urgency=medium
* RemoteTCPInput: Add wss protocol support. PR #2270
* Fix DeviceAPI::deserialize. Fixes #2266. PR #2267
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 20 Oct 2024 08:26:38 +0200
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 20 Oct 2024 08:26:38 +0200
sdrangel (7.22.1-1) unstable; urgency=medium

View File

@ -11,7 +11,7 @@ endif()
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
# disable only when needed
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
@ -20,7 +20,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# configure version
set(sdrangel_VERSION_MAJOR "7")
set(sdrangel_VERSION_MINOR "22")
set(sdrangel_VERSION_PATCH "8")
set(sdrangel_VERSION_PATCH "2")
set(sdrangel_VERSION_SUFFIX "")
# SDRAngel cmake options
@ -277,7 +277,6 @@ set(INSTALL_PLUGINSSRV_DIR "${INSTALL_LIB_DIR}/pluginssrv")
if(ANDROID)
set(PLUGINS_PREFIX "sdrangel_plugins_")
set(PLUGINSSRV_PREFIX "sdrangel_pluginssrv_")
set(ANDROID_PACKAGE_SOURCE_DIR ${PROJECT_SOURCE_DIR}/android/qt6 CACHE INTERNAL "")
else()
set(PLUGINS_PREFIX "")
set(PLUGINSSRV_PREFIX "")
@ -429,7 +428,7 @@ elseif (WIN32)
elseif(ANDROID)
set(EXTERNAL_LIBRARY_FOLDER "${CMAKE_SOURCE_DIR}/external/android")
set(Boost_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/ndk_26b_boost_1.83.0/include" CACHE INTERNAL "")
set(Boost_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/ndk_21_boost_1.72.0/include" CACHE INTERNAL "")
set(FFTW3F_FOUND ON CACHE INTERNAL "")
set(FFTW3F_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/fftw-3/include" CACHE INTERNAL "")
@ -486,14 +485,6 @@ elseif(ANDROID)
set(SWSCALE_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/ffmpeg/include" CACHE INTERNAL "")
set(SWSCALE_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/ffmpeg/lib/libswscale.so" CACHE INTERNAL "")
set(GGMORSE_FOUND ON CACHE INTERNAL "")
set(GGMORSE_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/ggmorse/include/" CACHE INTERNAL "")
set(GGMORSE_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/ggmorse/lib/static/libggmorse.a" CACHE INTERNAL "")
set(FLAC_FOUND ON CACHE INTERNAL "")
set(FLAC_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/flac/include/" CACHE INTERNAL "")
set(FLAC_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/flac/lib/libFLAC.so" CACHE INTERNAL "")
set(LIBUSB_FOUND ON CACHE INTERNAL "")
set(LIBUSB_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/libusb/include/" CACHE INTERNAL "")
set(LIBUSB_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/libusb/lib/libusb1.0.so" CACHE INTERNAL "")
@ -516,6 +507,11 @@ elseif(ANDROID)
if (ENABLE_QT6)
set(ANDROID_EXTRA_LIBS
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6Charts_arm64-v8a.so
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6Concurrent_arm64-v8a.so
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6MultimediaWidgets_arm64-v8a.so
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6SerialPort_arm64-v8a.so
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6TextToSpeech_arm64-v8a.so
${EXTERNAL_LIBRARY_FOLDER}/android_openssl/latest/arm64/libssl_1_1.so
${EXTERNAL_LIBRARY_FOLDER}/android_openssl/latest/arm64/libcrypto_1_1.so
${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/ffmpeg/lib/libavcodec.so
@ -530,7 +526,6 @@ elseif(ANDROID)
${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/dsdcc/lib/libdsdcc.so
${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/libusb/lib/libunrooted_android.so
${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/libusb/lib/libusb1.0.so
${EXTERNAL_LIBRARY_FOLDER}/${ANDROID_ABI}/flac/lib/libFLAC.so
CACHE INTERNAL ""
)
else()
@ -581,7 +576,6 @@ elseif(ANDROID)
${EXTERNAL_LIBRARY_FOLDER}/arm64-v8a/dsdcc/lib/libdsdcc.so
${EXTERNAL_LIBRARY_FOLDER}/arm64-v8a/libusb/lib/libunrooted_android.so
${EXTERNAL_LIBRARY_FOLDER}/arm64-v8a/libusb/lib/libusb1.0.so
${EXTERNAL_LIBRARY_FOLDER}/arm64-v8a/flac/lib/libFLAC.so
${EXTERNAL_LIBRARY_FOLDER}/armeabi-v7a/ffmpeg/lib/libavcodec.so
${EXTERNAL_LIBRARY_FOLDER}/armeabi-v7a/ffmpeg/lib/libavdevice.so
${EXTERNAL_LIBRARY_FOLDER}/armeabi-v7a/ffmpeg/lib/libavfilter.so
@ -594,7 +588,6 @@ elseif(ANDROID)
${EXTERNAL_LIBRARY_FOLDER}/armeabi-v7a/dsdcc/lib/libdsdcc.so
${EXTERNAL_LIBRARY_FOLDER}/armeabi-v7a/libusb/lib/libunrooted_android.so
${EXTERNAL_LIBRARY_FOLDER}/armeabi-v7a/libusb/lib/libusb1.0.so
${EXTERNAL_LIBRARY_FOLDER}/armeabi-v7a/flac/lib/libFLAC.so
CACHE INTERNAL ""
)
endif()
@ -657,7 +650,8 @@ if(ENABLE_QT6)
MultimediaWidgets
Positioning
Charts
SerialPort)
SerialPort
Core5Compat)
else()
find_package(Qt5 5.15
REQUIRED COMPONENTS
@ -685,8 +679,7 @@ if (BUILD_GUI)
QuickWidgets
TextToSpeech
Svg
SvgWidgets
StateMachine)
SvgWidgets)
else()
find_package(Qt5
REQUIRED COMPONENTS
@ -1003,9 +996,6 @@ if (BUILD_GUI)
sdrgui/resources/sdrangel.rc
settings/settings.qrc
)
if (WIN32)
set(sdrangel_SOURCES ${sdrangel_SOURCES} app/crashhandlerwin.cpp)
endif()
if(APPLE)
set(sdrangel_SOURCES ${sdrangel_SOURCES} mac/auth.mm)
endif()
@ -1112,7 +1102,6 @@ endif()
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PROPERTY:${CMAKE_PROJECT_NAME},RUNTIME_OUTPUT_DIRECTORY>/${CMAKE_PROJECT_NAME}stripped.pdb CONFIGURATIONS Release DESTINATION ${INSTALL_LIB_DIR} RENAME ${CMAKE_PROJECT_NAME}.pdb)
install(FILES $<TARGET_PDB_FILE:${CMAKE_PROJECT_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_BIN_DIR} )
endif()

View File

@ -1,22 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2025 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "loggerwithfile.h"
void installCrashHandler(qtwebapp::LoggerWithFile *logger);

View File

@ -1,421 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2025 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "crashhandler.h"
#include <windows.h>
#include <dbghelp.h>
// Use common controls v6, rather than v5
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#define IDC_EXIT_BUTTON 1500
#define IDC_COPY_BUTTON 1501
#define IDC_GITHUB_BUTTON 1502
static HWND hWindow;
static HWND hLabel;
static HWND hEdit;
static HWND hGithubButton;
static HWND hCopyButton;
static HWND hExitButton;
static qtwebapp::LoggerWithFile *crashLogger;
static void ScaleWindow(HWND wnd, int x, int y, int w, int h)
{
int dpi = GetDpiForWindow(wnd);
int scaledX = MulDiv(x, dpi, USER_DEFAULT_SCREEN_DPI);
int scaledY = MulDiv(y, dpi, USER_DEFAULT_SCREEN_DPI);
int scaledW = MulDiv(w, dpi, USER_DEFAULT_SCREEN_DPI);
int scaledH = MulDiv(h, dpi, USER_DEFAULT_SCREEN_DPI);
SetWindowPos(wnd, wnd, scaledX, scaledY, scaledW, scaledH, SWP_NOZORDER | SWP_NOACTIVATE);
}
static void Scale(HWND wnd, int& w, int &h)
{
int dpi = GetDpiForWindow(wnd);
w = MulDiv(w, dpi, USER_DEFAULT_SCREEN_DPI);
h = MulDiv(h, dpi, USER_DEFAULT_SCREEN_DPI);
}
static void Unscale(HWND wnd, int& w, int &h)
{
int dpi = GetDpiForWindow(wnd);
w = MulDiv(w, USER_DEFAULT_SCREEN_DPI, dpi);
h = MulDiv(h, USER_DEFAULT_SCREEN_DPI, dpi);
}
static void ScaleControls()
{
RECT rect;
int w;
int h;
GetWindowRect(hWindow, &rect);
w = rect.right - rect.left;
h = rect.bottom - rect.top;
Unscale(hWindow, w, h);
int buttonY = h - 100;
int editW = w - 40;
int editH = h - 200;
if (hLabel) {
ScaleWindow(hLabel, 10, 10, editW, 70);
}
if (hEdit) {
ScaleWindow(hEdit, 10, 80, editW, editH);
}
if (hGithubButton) {
ScaleWindow(hGithubButton, 10, buttonY, 150, 30);
}
if (hCopyButton) {
ScaleWindow(hCopyButton, 170, buttonY, 150, 30);
}
if (hExitButton) {
ScaleWindow(hExitButton, w - 180, buttonY, 150, 30);
}
}
static void ScaleWindow()
{
if (hWindow)
{
RECT rect;
GetWindowRect(hWindow, &rect);
ScaleWindow(hWindow, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
}
}
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
switch (wmId)
{
case IDC_EXIT_BUTTON:
PostQuitMessage(0);
break;
case IDC_GITHUB_BUTTON:
// Open SDRangel GitHub issues page in web browser
ShellExecute(NULL, L"open", L"https://github.com/f4exb/sdrangel/issues", NULL, NULL, SW_SHOWNORMAL);
break;
case IDC_COPY_BUTTON:
{
// Copy contents of edit control to clipboard
int len = GetWindowTextLength(hEdit);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(wchar_t));
if (hMem)
{
void *text = GlobalLock(hMem);
if (text)
{
GetWindowText(hEdit, (LPWSTR) text, len);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, hMem);
CloseClipboard();
}
}
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
}
case WM_CREATE:
{
HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
LPCREATESTRUCT cs = (LPCREATESTRUCT) lParam;
hLabel = CreateWindow(L"Static",
L"SDRangel has crashed.\r\n\r\nPlease consider opening a bug report on GitHub, copying the text below and a screenshot.",
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0,
hWnd,
NULL,
hInst,
NULL);
hEdit = CreateWindowA("EDIT",
(LPCSTR) cs->lpCreateParams,
WS_BORDER | WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
0, 0, 0, 0,
hWnd,
NULL,
hInst,
NULL);
hGithubButton = CreateWindow(
L"BUTTON",
L"Open Github...",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
0, 0, 0, 0,
hWnd,
(HMENU) IDC_GITHUB_BUTTON,
hInst,
NULL);
hCopyButton = CreateWindow(
L"BUTTON",
L"Copy text",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
0, 0, 0, 0,
hWnd,
(HMENU) IDC_COPY_BUTTON,
hInst,
NULL);
hExitButton = CreateWindow(
L"BUTTON",
L"Exit SDRangel",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
0, 0, 0, 0,
hWnd,
(HMENU) IDC_EXIT_BUTTON,
hInst,
NULL);
ScaleControls();
break;
}
case WM_GETMINMAXINFO:
{
LPMINMAXINFO lpMMI = (LPMINMAXINFO) lParam;
int w = 500;
int h = 220;
Scale(hWindow, w, h);
lpMMI->ptMinTrackSize.x = w;
lpMMI->ptMinTrackSize.y = h;
break;
}
case WM_SIZE:
ScaleControls();
RedrawWindow(hWindow, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
break;
case WM_DPICHANGED:
ScaleControls();
ScaleWindow();
break;
case WM_CTLCOLORSTATIC:
SetBkMode((HDC) wParam, TRANSPARENT);
return (LRESULT) GetStockObject(NULL_BRUSH);
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Create and display crash log when an unhandled exception occurs
static LONG crashHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
const int reportBufferSize = 1024*1024;
char *reportBuffer = new char[reportBufferSize];
char *reportBufferPtr = reportBuffer;
int reportBufferRemaining = reportBufferSize;
int written = snprintf(reportBufferPtr, reportBufferRemaining,
"SDRangel crash data\r\n%s %s\r\nQt %s\r\n%s %s\r\nStack trace:\r\n",
APPLICATION_NAME,
SDRANGEL_VERSION,
QT_VERSION_STR,
qPrintable(QSysInfo::prettyProductName()),
qPrintable(QSysInfo::currentCpuArchitecture())
);
reportBufferPtr += written;
reportBufferRemaining -= written;
// Create stack trace
STACKFRAME64 stack;
CONTEXT context;
HANDLE process;
DWORD64 displacement;
ULONG frame;
BOOL symInit;
char symName[(MAX_PATH * sizeof(TCHAR))];
char storage[sizeof(IMAGEHLP_SYMBOL64) + (sizeof(symName))];
IMAGEHLP_SYMBOL64* symbol;
RtlCaptureContext(&context);
memset(&stack, 0, sizeof(STACKFRAME64));
#if defined(_AMD64_)
stack.AddrPC.Offset = context.Rip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = context.Rsp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = context.Rbp;
stack.AddrFrame.Mode = AddrModeFlat;
#else
stack.AddrPC.Offset = context.Eip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = context.Esp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = context.Ebp;
stack.AddrFrame.Mode = AddrModeFlat;
#endif
displacement = 0;
process = GetCurrentProcess();
symInit = SymInitialize(process, "plugins", TRUE);
symbol = (IMAGEHLP_SYMBOL64*) storage;
for (frame = 0; reportBufferRemaining > 0; frame++)
{
BOOL result = StackWalk(IMAGE_FILE_MACHINE_AMD64,
process,
GetCurrentThread(),
&stack,
&context,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL);
if (result)
{
symbol->SizeOfStruct = sizeof(storage);
symbol->MaxNameLength = sizeof(symName);
BOOL symResult = SymGetSymFromAddr64(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol);
if (symResult) {
UnDecorateSymbolName(symbol->Name, (PSTR)symName, sizeof(symName), UNDNAME_COMPLETE);
}
written = snprintf(
reportBufferPtr,
reportBufferRemaining,
"%02u 0x%p %s\r\n",
frame,
stack.AddrPC.Offset,
symResult ? symbol->Name : "Unknown"
);
if (written > 0)
{
if (written <= reportBufferRemaining)
{
reportBufferPtr += written;
reportBufferRemaining -= written;
}
else
{
reportBufferPtr += reportBufferRemaining;
reportBufferRemaining = 0;
}
}
}
else
{
break;
}
}
// Append log file
if (crashLogger)
{
QString log = crashLogger->getBufferLog();
log = log.replace('\n', "\r\n");
written = snprintf(reportBufferPtr, reportBufferRemaining, "Log:\r\n%s\r\n", qPrintable(log));
if (written > 0)
{
reportBufferPtr += written;
reportBufferRemaining -= written;
}
}
// Create a window to display the crash report
// Can't use QMessageBox here, as may not work depending where the crash was, so need to use Win32 API
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE); // Needed, otherwise GetDpiForWindow always returns 96, rather than the actual value
wchar_t windowClass[] = L"SDRangel Crash Window Class";
HMODULE hInstance = GetModuleHandle(NULL);
WNDCLASSEX wc = { };
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = windowClass;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1);
RegisterClassEx(&wc);
hWindow = CreateWindow(windowClass, L"SDRangel Crash", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 640, 500,
NULL, NULL, hInstance, (LPVOID) reportBuffer
);
if (hWindow)
{
ScaleWindow();
ShowWindow(hWindow, SW_SHOWNORMAL);
UpdateWindow(hWindow);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
fprintf(stderr, "Failed to create window\n");
fprintf(stderr, reportBuffer);
}
delete[] reportBuffer;
return EXCEPTION_EXECUTE_HANDLER;
}
void installCrashHandler(qtwebapp::LoggerWithFile *logger)
{
crashLogger = logger;
SetUnhandledExceptionFilter(crashHandler);
}

View File

@ -22,6 +22,7 @@
///////////////////////////////////////////////////////////////////////////////////
#include <QApplication>
#include <QTextCodec>
#include <QProxyStyle>
#include <QStyleFactory>
#include <QFontDatabase>
@ -44,10 +45,13 @@
#include "mainwindow.h"
#include "remotetcpsinkstarter.h"
#include "dsp/dsptypes.h"
#include "crashhandler.h"
static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *logger)
{
/*
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
*/
QCoreApplication::setOrganizationName(COMPANY);
QCoreApplication::setApplicationName(APPLICATION_NAME);
QCoreApplication::setApplicationVersion(SDRANGEL_VERSION);
@ -189,9 +193,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo
logger = nullptr;
}
MainWindow w(logger, parser);
w.show();
MainWindow w(logger, parser);
if (parser.getListDevices())
{
@ -200,6 +202,12 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo
return EXIT_SUCCESS;
}
if (parser.getRemoteTCPSink()) {
RemoteTCPSinkStarter::start(parser);
}
w.show();
return a.exec();
}
@ -237,10 +245,6 @@ int main(int argc, char* argv[])
logger->installMsgHandler();
#endif
#ifdef _WIN32
installCrashHandler(logger);
#endif
int res = runQtApplication(argc, argv, logger);
if (logger) {

View File

@ -19,23 +19,13 @@ if(WIN32)
endif()
if(NOT MSVC)
add_compile_options(-Wall -Wextra -Wvla -ffast-math -fno-finite-math-only -ftree-vectorize)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Woverloaded-virtual>)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options(-Wno-inconsistent-missing-override)
endif()
add_compile_options(-Wall -Wextra -Wvla -Woverloaded-virtual -Wno-inconsistent-missing-override -ffast-math -fno-finite-math-only -ftree-vectorize)
else()
# Disable some warnings, so more useful warnings aren't hidden in the noise
# 4996 'fopen': This function or variable may be unsafe. Consider using fopen_s instead.
# C4267: 'return': conversion from 'size_t' to 'int', possible loss of data
# C4305: 'initializing': truncation from 'double' to 'Real'
add_compile_options(/wd4996 /wd4267 /wd4305)
if(CMAKE_BUILD_TYPE MATCHES "Release")
# Include stripped debug info in release builds so crash handler can generate stack trace with function names
add_compile_options(/Zi)
add_link_options(/DEBUG /OPT:REF /OPT:ICF /PDBSTRIPPED:$<TARGET_PROPERTY:RUNTIME_OUTPUT_DIRECTORY>/$<TARGET_PROPERTY:NAME>stripped.pdb)
endif()
endif()
if (SANITIZE_ADDRESS)

View File

@ -36,7 +36,7 @@ if(APPLE AND BUNDLE AND BUILD_GUI)
set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/cmake/cpack/sdrangel_icon.icns")
set(CPACK_BUNDLE_PLIST "${CMAKE_BINARY_DIR}/Info.plist")
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/cmake/cpack/sdrangel_icon.icns")
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION}_mac-${CPACK_MACOS_PACKAGE_ARCHITECTURE}_${CMAKE_SYSTEM_PROCESSOR}" CACHE INTERNAL "")
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION}_${CPACK_MACOS_PACKAGE_ARCHITECTURE}_${CMAKE_SYSTEM_PROCESSOR}" CACHE INTERNAL "")
set(CPACK_PRE_BUILD_SCRIPTS "${PROJECT_BINARY_DIR}/deploy_mac.cmake")
# copy SoapySDR Modules

View File

@ -8,8 +8,7 @@
# Copy executable that will be run when icon in /Applications is clicked
message ("Copying default executable to SDRangel.app/Contents/MacOS/SDRangel")
execute_process (COMMAND mkdir ${CPACK_TEMPORARY_INSTALL_DIRECTORY}/SDRangel.app/Contents/MacOS/)
execute_process (COMMAND pwd)
execute_process (COMMAND cp sdrangel ${CPACK_TEMPORARY_INSTALL_DIRECTORY}/SDRangel.app/Contents/MacOS/SDRangel)
execute_process (COMMAND cp /opt/build/sdrangel/build/sdrangel ${CPACK_TEMPORARY_INSTALL_DIRECTORY}/SDRangel.app/Contents/MacOS/SDRangel)
# Add RPATHS to libraries so macdeployqt can find out and copy all dependencies

76
debian/changelog vendored
View File

@ -1,77 +1,3 @@
sdrangel (7.22.8-1) unstable; urgency=medium
* See Github release
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Wed, 02 Jul 2025 17:00:39 +0200
sdrangel (7.22.7-1) unstable; urgency=medium
* See Github release
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 04 May 2025 17:58:14 +0200
sdrangel (7.22.6-1) unstable; urgency=medium
* See Github release
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 02 Feb 2025 18:08:11 +0100
sdrangel (7.22.5-1) unstable; urgency=medium
* Windows: upload signed releases rather than unsigned releases to Github releases page. PR #2347
* Windows: fixed signed releases. PR #2344
* FT8 Demod: limit upper bandwidth to 5.8 kHz. Fixes #2339
* Stop device while changing channel set. Fixes #2332. PR #2342
* ADSB: Update URL of OpenSkyNetwork Aircraft database. PR #2341
* Don't stop source if being deleted. For #2315. PR #2340
* Send DSPSignalNotification in audio mods for #2336. PR #2340
* Radiosonde: limit precision of floating point numbers sent to SondeHub. PR #2338
* Windows signed releases: use relative path. Increase timeout to 30 minutes. PR #2335
* ADSB: Include adsbdemodsettings.h PR #2334
* Use release signing certificate for Windows installer. PR #2331
* Fix memory leak and race condition relating to DSP*Engines. Part of #2159 PR #2330
* FreeDV: Fix memory allocation/free issues. Part of #2315. PR #2330
* Wav Files: Add support for meta-data. PR #2328
* DemodAnalyzer: Ensure sample rate is set in worker. Fixes #2309. PR #2328
^ SDRplayv3: Mac: link with libsdrplay_api.so.3 rather than libsdrplay_api.so.3.15. PR #2327
* ADS-B: Fix memory use after delete. For #1734 and part of #2315 PR #2326
* Fixed Appveyor Docker image build
* Fix output-artifact-directory and unzip file. PR #2323
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Thu, 05 Dec 2024 01:07:27 +0100
sdrangel (7.22.4-1) unstable; urgency=medium
* Use macos-12 for Mac x86 build. PR #2321
* Workaround for "hdiutil: create failed - Resource busy"
* Pager: Add alpha and numeric columns. Implements #2319. PR #2320
* Added qtwebchannel dependecy to fix missing 3d Map and Sky Map from Windows release. PR #2316
* Removed .deb package build from Appveyor
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Mom, 11 Nov 2024 08:42:03 +0100
sdrangel (7.22.3-1) unstable; urgency=medium
* Add deb dependencies for pipewire. PR #2314
* Added compilation options for WebAssembly. PR #2313
* ADS-B: Use settings keys. PR #2310
* AIS Demod: Remove spacing around messages. PR #2310
* Freuqency Scanner: Add multiplex mode. PR #2310
* Build snap, MAC, Windows and Ubuntu .deb with Github actions. Various PRs
* Server: Use Sink/MIMO signals rather than Source. Part of #2294. PR #2304
* Updated some Python scripts to Python3. PR #2298
* RemoteTCPSink: Does use IQ only setting for RTL0. PR #2301
* Server: wait for set sample source/sink/MIMO to complete before loading the device settings. Fixes #2294
* Fix spectrum peak measurement for SSB spectra. Fixes #2282. PR #2299
* Upgrade C++ standard to c++17
* Fixes for Android . PR #2288
* Add qtshadertools. PR #2287
* Add more Qt modules and set ENABLE_QT6=ON. PR #2287
* Update Qt optional packages for 6.8 , PR #2287
* Use Qt 6.8 for Windows build. PR #2287
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sat, 09 Nov 2024 17:30:44 +0100
sdrangel (7.22.2-1) unstable; urgency=medium
* ChirpChat: increased preamble symbols limit from 20 to 32. Fixes #2284
@ -93,7 +19,7 @@ sdrangel (7.22.2-1) unstable; urgency=medium
* RemoteTCPInput: Add wss protocol support. PR #2270
* Fix DeviceAPI::deserialize. Fixes #2266. PR #2267
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 20 Oct 2024 08:26:38 +0200
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 20 Oct 2024 08:26:38 +0200
sdrangel (7.22.1-1) unstable; urgency=medium

7
debian/control vendored
View File

@ -42,10 +42,8 @@ Build-Depends: debhelper (>= 9),
libopencv-imgcodecs-dev,
libxml2-dev,
bison,
cmake,
flex,
ffmpeg,
ninja-build,
libfaad-dev,
libflac-dev,
libavcodec-dev,
@ -65,13 +63,12 @@ Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
libasound2,
libgl1,
libglx-mesa0,
libgl1-mesa-glx,
libqt5multimedia5-plugins,
libqt5gamepad5,
libqt5svg5,
qtspeech5-speechd-plugin,
pulseaudio | pipewire-pulse,
pulseaudio,
ffmpeg,
gstreamer1.0-libav,
qml-module-qtlocation,

View File

@ -40,6 +40,4 @@ if(ENABLE_USRP AND UHD_FOUND)
add_subdirectory(usrp)
endif()
if(ENABLE_METIS)
add_subdirectory(metis)
endif()
add_subdirectory(metis)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 640 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 KiB

After

Width:  |  Height:  |  Size: 490 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 819 KiB

After

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 372 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 351 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 603 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 547 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 745 KiB

View File

@ -11,9 +11,9 @@
set(CODEC2_TAG "v1.0.3")
set(CM256CC_TAG c0e92b92aca3d1d36c990b642b937c64d363c559)
set(MBELIB_TAG fe83b32c6a60cdd7bce8cecf3c7a0b9ec87a7667)
set(SERIALDV_TAG "v1.1.5")
set(SERIALDV_TAG "v1.1.4")
set(DSDCC_TAG "v1.9.5")
set(LIMESUITE_TAG b39cb61ed03d74c35a2de757d495e901acbb6404)
set(LIMESUITE_TAG 70e3859a55d8d5353963a5318013c8454594769f)
set(BLADERF_TAG "2021.02")
set(LIBIIO_TAG 826563e41b5ce9890b75506f672017de8d76d52d)
set(AIRSPYHF_TAG "1af81c0ca18944b8c9897c3c98dc0a991815b686")
@ -29,11 +29,17 @@ set(SOAPYSDR_SDRPLAY_TAG "soapy-sdrplay-0.2.0")
set(SOAPYSDR_AUDIO_TAG "soapy-audio-0.1.1")
set(SOAPYSDR_REMOTE_TAG "soapy-remote-0.5.1")
set(AIRSPY_TAG "37c768ce9997b32e7328eb48972a7fda0a1f8554")
set(HACKRF_TAG "v2024.02.1")
set(HACKRF_TAG "v2022.09.1")
set(LIBXML2_TAG "v2.10.4")
set(UHD_TAG "v4.7.0.0")
set(BOOST_TAG "1.86.0")
set(BOOST_TAG2 "1_86_0")
set(UHD_TAG "v4.6.0.0")
if (APPLE AND (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL x86_64))
# UHD fails to load with 1.80+
set(BOOST_TAG "1.78.0")
set(BOOST_TAG2 "1_78_0")
else()
set(BOOST_TAG "1.83.0")
set(BOOST_TAG2 "1_83_0")
endif()
# For some external project macros
include(ExternalProject)
@ -54,7 +60,6 @@ if (WIN32)
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG=${SDRANGEL_BINARY_LIB_DIR}
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE=${SDRANGEL_BINARY_LIB_DIR}
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO=${SDRANGEL_BINARY_LIB_DIR}
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
)
elseif (LINUX)
set(COMMON_CMAKE_ARGS
@ -421,7 +426,6 @@ if (NOT FFMPEG_FOUND AND NOT USE_PRECOMPILED_LIBS)
if (NOT X265_FOUND OR X265_EXTERNAL)
ExternalProject_Add(x265
GIT_REPOSITORY https://bitbucket.org/multicoreware/x265_git.git
GIT_TAG 4.1
PREFIX "${EXTERNAL_BUILD_LIBRARIES}/x265"
SOURCE_SUBDIR "source"
CMAKE_ARGS ${COMMON_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
@ -542,7 +546,7 @@ endif (NOT FFMPEG_FOUND AND NOT USE_PRECOMPILED_LIBS)
if (NOT OpenCV_FOUND AND NOT USE_PRECOMPILED_LIBS AND ENABLE_CHANNELTX_MODATV)
ExternalProject_Add(opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.10.0
GIT_TAG 4.5.5
DEPENDS "${FFMPEG_DEPENDS}"
PREFIX "${EXTERNAL_BUILD_LIBRARIES}/opencv"
CMAKE_ARGS ${COMMON_CMAKE_ARGS} -DWITH_FFMPEG=ON -DCMAKE_PREFIX_PATH=${FFMPEG_INSTALL_DIR}
@ -860,7 +864,7 @@ if(ENABLE_CHANNELRX_REMOTETCPSINK)
ExternalProject_Add(flac
GIT_REPOSITORY https://github.com/xiph/flac.git
PREFIX "${EXTERNAL_BUILD_LIBRARIES}/flac"
CMAKE_ARGS ${COMMON_CMAKE_ARGS} -DINSTALL_MANPAGES=OFF -DBUILD_SHARED_LIBS=ON -DWITH_FORTIFY_SOURCE=OFF -DWITH_STACK_PROTECTOR=PFF -DBUILD_PROGRAMS=OFF -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF -DWITH_OGG=OFF -DBUILD_DOCS=OFF
CMAKE_ARGS ${COMMON_CMAKE_ARGS} -DINSTALL_MANPAGES=OFF -D=BUILD_SHARED_LIBS=ON -DWITH_FORTIFY_SOURCE=OFF -DWITH_STACK_PROTECTOR=PFF -DBUILD_PROGRAMS=OFF -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF -DWITH_OGG=OFF -DBUILD_DOCS=OFF
BUILD_BYPRODUCTS "${FLAC_LIBRARIES}"
INSTALL_COMMAND ""
TEST_COMMAND ""
@ -1574,8 +1578,6 @@ if (WIN32 OR APPLE)
-DLIBUSB_LIBRARIES=${LIBUSB_LIBRARIES}
-DLIBUSB_INCLUDE_DIR=${LIBUSB_INCLUDE_DIR}
${UHD_PYTHON_ARGS}
-DPython3_FIND_FRAMEWORK=NEVER
-DENABLE_PYTHON_API=OFF
-DCMAKE_INSTALL_NAME_DIR=<INSTALL_DIR>/lib
TEST_COMMAND ""
)

View File

@ -82,7 +82,7 @@ std::string Packing::unpackcall(int x)
if (x <= 1002)
{
snprintf(tmp, sizeof(tmp), "CQ %d", x - 3);
sprintf(tmp, "CQ %d", x - 3);
return std::string(tmp);
}
@ -96,7 +96,7 @@ std::string Packing::unpackcall(int x)
int ci3 = x / 27;
x %= 27;
int ci4 = x;
snprintf(tmp, sizeof(tmp), "CQ %c%c%c%c", c4[ci1], c4[ci2], c4[ci3], c4[ci4]);
sprintf(tmp, "CQ %c%c%c%c", c4[ci1], c4[ci2], c4[ci3], c4[ci4]);
return std::string(tmp);
}
@ -193,9 +193,9 @@ std::string Packing::unpackgrid15(int ng, int ir)
char tmp[16];
if (db >= 0) {
snprintf(tmp, sizeof(tmp), "%s+%02d", ir ? "R" : "", db);
sprintf(tmp, "%s+%02d", ir ? "R" : "", db);
} else {
snprintf(tmp, sizeof(tmp), "%s-%02d", ir ? "R" : "", 0 - db);
sprintf(tmp, "%s-%02d", ir ? "R" : "", 0 - db);
}
return std::string(tmp);
@ -396,7 +396,7 @@ std::string Packing::unpack_5(int a77[], std::string& call1str, std::string& cal
i += 3;
int qsonb = un64(a77, i, 11);
char report[16];
snprintf(report, sizeof(report), "%d%04d", rst, qsonb);
sprintf(report, "%d%04d", rst, qsonb);
i += 11;
// g25
int ng = un64(a77, i, 25);
@ -467,9 +467,9 @@ std::string Packing::unpack_0_1(int a77[], std::string& call1str, std::string& c
char tmp[32];
if (r >= 0) {
snprintf(tmp, sizeof(tmp), "+%02d", r);
sprintf(tmp, "+%02d", r);
} else {
snprintf(tmp, sizeof(tmp), "-%02d", -r);
sprintf(tmp, "-%02d", -r);
}
locstr = std::string(tmp);
@ -553,7 +553,7 @@ std::string Packing::unpack_3(int a77[], std::string& call1str, std::string& cal
else
{
char tmp[32];
snprintf(tmp, sizeof(tmp), "%04d", serial);
sprintf(tmp, "%04d", serial);
serialstr = std::string(tmp);
}
@ -571,7 +571,7 @@ std::string Packing::unpack_3(int a77[], std::string& call1str, std::string& cal
}
{
char tmp[16];
snprintf(tmp, sizeof(tmp), "%d ", rst);
sprintf(tmp, "%d ", rst);
msg += std::string(tmp);
}
@ -634,7 +634,7 @@ std::string Packing::unpack_0_3(int a77[], int n3, std::string& call1str, std::s
{
char tmp[16];
snprintf(tmp, sizeof(tmp), "%d%c ", n_transmitters + 1, clss + 'A');
sprintf(tmp, "%d%c ", n_transmitters + 1, clss + 'A');
msg += std::string(tmp);
}
@ -658,9 +658,9 @@ std::string Packing::unpack(int a77[], std::string& call1, std::string& call2, s
char tmp[64];
if (i3 == 0) {
snprintf(tmp, sizeof(tmp), "%d.%d", i3, n3);
sprintf(tmp, "%d.%d", i3, n3);
} else {
snprintf(tmp, sizeof(tmp), "%d", i3);
sprintf(tmp, "%d", i3);
}
type = std::string(tmp);
@ -714,7 +714,7 @@ std::string Packing::unpack(int a77[], std::string& call1, std::string& call2, s
}
call1 = "UNK";
snprintf(tmp, sizeof(tmp), "UNK i3=%d n3=%d", i3, n3);
sprintf(tmp, "UNK i3=%d n3=%d", i3, n3);
return std::string(tmp);
}

View File

@ -4,6 +4,6 @@ PLUGINS=$(git diff --name-only ${1}..${2} | grep plugins/ | cut -d'/' -f2,3 | so
for plugin in $PLUGINS
do
FILE=$(find $BASEDIR/plugins/$plugin -name "*plugin.cpp")
echo $FILE
sed -i -E "s/QStringLiteral\(\"7\.(.*)\"\)/QStringLiteral\(\"7\.22\.7\"\)/" $FILE
sed -i -E "s/QStringLiteral\(\"7\.(.*)\"\)/QStringLiteral\(\"7\.22\.2\"\)/" $FILE
done

View File

@ -1,7 +1,6 @@
project(logging)
set(logging_SOURCES
bufferlogger.cpp
dualfilelogger.cpp
loggerwithfile.cpp
filelogger.cpp
@ -10,7 +9,6 @@ set(logging_SOURCES
)
set(logging_HEADERS
bufferlogger.h
dualfilelogger.h
loggerwithfile.h
filelogger.h

View File

@ -1,49 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2025 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "bufferlogger.h"
using namespace qtwebapp;
BufferLogger::BufferLogger(int maxSize, QObject *parent) :
m_maxSize(maxSize)
{
}
BufferLogger::~BufferLogger()
{
}
void BufferLogger::write(const LogMessage* logMessage)
{
QString text = qPrintable(logMessage->toString("{timestamp} {type} {msg}", "yyyy-MM-dd HH:mm:ss.zzz"));
m_messages.enqueue(text);
while (m_messages.size() > m_maxSize) {
m_messages.dequeue();
}
}
QString BufferLogger::getLog() const
{
QString log;
for (const auto s : m_messages) {
log.append(s);
}
return log;
}

View File

@ -1,46 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2025 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QQueue>
#include "logger.h"
#include "export.h"
namespace qtwebapp {
// A ring-buffer like logger for holding m_maxSize recent log messages
class LOGGING_API BufferLogger : public Logger {
Q_OBJECT
Q_DISABLE_COPY(BufferLogger)
public:
BufferLogger(int maxSize, QObject *parent = nullptr);
virtual ~BufferLogger();
void write(const LogMessage* logMessage) override;
QString getLog() const; // Get last m_maxSize messages as one big string
private:
int m_maxSize; // Maximum number of messages to store
QQueue<QString> m_messages; // Queue containing last m_maxSize messages
};
}

View File

@ -13,14 +13,12 @@ LoggerWithFile::LoggerWithFile(QObject* parent)
:Logger(parent), fileLogger(0), useFileFlogger(false)
{
consoleLogger = new Logger(this);
bufferLogger = new BufferLogger(500, this);
}
LoggerWithFile::~LoggerWithFile()
{
destroyFileLogger();
delete consoleLogger;
delete bufferLogger;
}
void LoggerWithFile::createOrSetFileLogger(const FileLoggerSettings& settings, const int refreshInterval)
@ -44,7 +42,6 @@ void LoggerWithFile::destroyFileLogger()
void LoggerWithFile::log(const QtMsgType type, const QString& message, const QString &file, const QString &function, const int line)
{
consoleLogger->log(type,message,file,function,line);
bufferLogger->log(type,message,file,function,line);
if (fileLogger && useFileFlogger) {
fileLogger->log(type,message,file,function,line);
@ -61,7 +58,6 @@ void LoggerWithFile::logToFile(const QtMsgType type, const QString& message, con
void LoggerWithFile::clear(const bool buffer, const bool variables)
{
consoleLogger->clear(buffer,variables);
bufferLogger->clear(buffer,variables);
if (fileLogger && useFileFlogger) {
fileLogger->clear(buffer,variables);
@ -130,8 +126,3 @@ void LoggerWithFile::getLogFileName(QString& fileName)
{
fileName = fileLogger->getFileLoggerSettings().fileName;
}
QString LoggerWithFile::getBufferLog() const
{
return bufferLogger->getLog();
}

View File

@ -11,7 +11,6 @@
#include <QtGlobal>
#include "logger.h"
#include "filelogger.h"
#include "bufferlogger.h"
#include "export.h"
@ -80,9 +79,6 @@ public:
/** This will log to file only */
void logToFile(const QtMsgType type, const QString& message, const QString &file="", const QString &function="", const int line=0);
/** Gets last messages saved in buffer. */
QString getBufferLog() const;
private:
/** First console logger */
Logger* consoleLogger;
@ -90,8 +86,6 @@ private:
/** Second file logger */
FileLogger* fileLogger;
BufferLogger* bufferLogger;
/** Use file logger indicator */
bool useFileFlogger;
};

View File

@ -17,18 +17,10 @@ if (NOT SERVER_MODE)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINS_DIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINS_DIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${BUILD_PLUGINS_DIR}")
if(WIN32 AND Qt6_FOUND)
# https://bugreports.qt.io/browse/QTBUG-124589
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PLUGINS_RUNTIME_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINS_RUNTIME_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINS_RUNTIME_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${BUILD_PLUGINS_RUNTIME_DIR}")
else()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PLUGINS_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINS_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINS_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${BUILD_PLUGINS_DIR}")
endif()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PLUGINS_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINS_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINS_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${BUILD_PLUGINS_DIR}")
else()
if(WIN32)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_PLUGINSSRV_RUNTIME_DIR}")
@ -40,17 +32,10 @@ else()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINSSRV_DIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINSSRV_DIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${BUILD_PLUGINSSRV_DIR}")
if(WIN32 AND Qt6_FOUND)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PLUGINSSRV_RUNTIME_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINSSRV_RUNTIME_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINSSRV_RUNTIME_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${BUILD_PLUGINSSRV_RUNTIME_DIR}")
else()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PLUGINSSRV_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINSSRV_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINSSRV_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${BUILD_PLUGINSSRV_DIR}")
endif()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PLUGINSSRV_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PLUGINSSRV_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PLUGINSSRV_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${BUILD_PLUGINSSRV_DIR}")
endif()
if (ENABLE_CHANNELMIMO)

View File

@ -67,6 +67,5 @@ install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PROPERTY:${TARGET_NAME},RUNTIME_OUTPUT_DIRECTORY>/${TARGET_NAME}stripped.pdb CONFIGURATIONS Release DESTINATION ${INSTALL_FOLDER} RENAME ${TARGET_NAME}.pdb )
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -71,6 +71,5 @@ install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PROPERTY:${TARGET_NAME},RUNTIME_OUTPUT_DIRECTORY>/${TARGET_NAME}stripped.pdb CONFIGURATIONS Release DESTINATION ${INSTALL_FOLDER} RENAME ${TARGET_NAME}.pdb )
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -69,6 +69,5 @@ install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PROPERTY:${TARGET_NAME},RUNTIME_OUTPUT_DIRECTORY>/${TARGET_NAME}stripped.pdb CONFIGURATIONS Release DESTINATION ${INSTALL_FOLDER} RENAME ${TARGET_NAME}.pdb )
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -211,26 +211,6 @@ else()
message(STATUS "Not building wdsprx (ENABLE_CHANNELRX_WDSPRX=${ENABLE_CHANNELRX_WDSPRX} WDSP_SUPPORT=${WDSP_SUPPORT})")
endif()
# need ffmpeg 3.1 that correstonds to
# libavutil 55.27.100
# libavcodec 57.48.101
# libavformat 57.40.101
find_package(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE)
if (ENABLE_CHANNELRX_DEMODDATV AND FFMPEG_FOUND)
if(WIN32)
add_subdirectory(demoddatv)
else()
if(((AVUTIL_VERSION VERSION_GREATER "55.27.99") AND (AVCODEC_VERSION VERSION_GREATER "57.48.101")) OR FFMPEG_EXTERNAL OR FFMPEG_SKIP_CHECK)
message(STATUS "Include demoddatv")
add_subdirectory(demoddatv)
else()
message(STATUS "FFmpeg too old to compile demoddatv; needs at least avutil: 55.27.100, avcodec/avformat: 57.48.101")
endif()
endif()
else()
message(STATUS "Not building demoddatv (ENABLE_CHANNELRX_DEMODDATV=${ENABLE_CHANNELRX_DEMODDATV} FFMPEG_FOUND=${FFMPEG_FOUND})")
endif()
if(NOT SERVER_MODE)
if (ENABLE_CHANNELRX_HEATMAP)
@ -250,4 +230,25 @@ if(NOT SERVER_MODE)
else()
message(STATUS "Not building demodatv (ENABLE_CHANNELRX_DEMODATV=${ENABLE_CHANNELRX_DEMODATV})")
endif()
# need ffmpeg 3.1 that correstonds to
# libavutil 55.27.100
# libavcodec 57.48.101
# libavformat 57.40.101
find_package(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE)
if (ENABLE_CHANNELRX_DEMODDATV AND FFMPEG_FOUND)
if(WIN32)
add_subdirectory(demoddatv)
else()
if(((AVUTIL_VERSION VERSION_GREATER "55.27.99") AND (AVCODEC_VERSION VERSION_GREATER "57.48.101")) OR FFMPEG_EXTERNAL OR FFMPEG_SKIP_CHECK)
message(STATUS "Include demoddatv")
add_subdirectory(demoddatv)
else()
message(STATUS "FFmpeg too old to compile demoddatv; needs at least avutil: 55.27.100, avcodec/avformat: 57.48.101")
endif()
endif()
else()
message(STATUS "Not building demoddatv (ENABLE_CHANNELRX_DEMODDATV=${ENABLE_CHANNELRX_DEMODDATV} FFMPEG_FOUND=${FFMPEG_FOUND})")
endif()
endif()

View File

@ -50,6 +50,5 @@ install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PROPERTY:${TARGET_NAME},RUNTIME_OUTPUT_DIRECTORY>/${TARGET_NAME}stripped.pdb CONFIGURATIONS Release DESTINATION ${INSTALL_FOLDER} RENAME ${TARGET_NAME}.pdb )
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -88,7 +88,7 @@ ChannelAnalyzer::~ChannelAnalyzer()
delete m_networkManager;
m_deviceAPI->removeChannelSinkAPI(this);
m_deviceAPI->removeChannelSink(this, true);
m_deviceAPI->removeChannelSink(this);
if (m_basebandSink->isRunning()) {
stop();
@ -103,7 +103,7 @@ void ChannelAnalyzer::setDeviceAPI(DeviceAPI *deviceAPI)
if (deviceAPI != m_deviceAPI)
{
m_deviceAPI->removeChannelSinkAPI(this);
m_deviceAPI->removeChannelSink(this, false);
m_deviceAPI->removeChannelSink(this);
m_deviceAPI = deviceAPI;
m_deviceAPI->addChannelSink(this);
m_deviceAPI->addChannelSinkAPI(this);

View File

@ -27,7 +27,7 @@
const PluginDescriptor ChannelAnalyzerPlugin::m_pluginDescriptor = {
ChannelAnalyzer::m_channelId,
QStringLiteral("Channel Analyzer"),
QStringLiteral("7.22.5"),
QStringLiteral("7.22.1"),
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -65,7 +65,6 @@ install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PROPERTY:${TARGET_NAME},RUNTIME_OUTPUT_DIRECTORY>/${TARGET_NAME}stripped.pdb CONFIGURATIONS Release DESTINATION ${INSTALL_FOLDER} RENAME ${TARGET_NAME}.pdb )
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -84,7 +84,7 @@ ChannelPower::~ChannelPower()
);
delete m_networkManager;
m_deviceAPI->removeChannelSinkAPI(this);
m_deviceAPI->removeChannelSink(this, true);
m_deviceAPI->removeChannelSink(this);
if (m_basebandSink->isRunning()) {
stop();
@ -98,7 +98,7 @@ void ChannelPower::setDeviceAPI(DeviceAPI *deviceAPI)
if (deviceAPI != m_deviceAPI)
{
m_deviceAPI->removeChannelSinkAPI(this);
m_deviceAPI->removeChannelSink(this, false);
m_deviceAPI->removeChannelSink(this);
m_deviceAPI = deviceAPI;
m_deviceAPI->addChannelSink(this);
m_deviceAPI->addChannelSinkAPI(this);

View File

@ -29,7 +29,7 @@
const PluginDescriptor ChannelPowerPlugin::m_pluginDescriptor = {
ChannelPower::m_channelId,
QStringLiteral("Channel Power"),
QStringLiteral("7.22.5"),
QStringLiteral("7.22.1"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -28,6 +28,7 @@ set(adsb_HEADERS
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${Boost_INCLUDE_DIRS}
)
if(NOT SERVER_MODE)
@ -46,7 +47,6 @@ if(NOT SERVER_MODE)
adsbdemodicons.qrc
airlinelogos.qrc
flags.qrc
sideviews.qrc
)
set(adsb_HEADERS
${adsb_HEADERS}
@ -60,7 +60,7 @@ if(NOT SERVER_MODE)
)
set(TARGET_NAME ${PLUGINS_PREFIX}demodadsb)
set(TARGET_LIB Qt::Widgets Qt::Quick Qt::QuickWidgets Qt::Positioning Qt::Charts)
set(TARGET_LIB Qt::Widgets Qt::Quick Qt::QuickWidgets Qt::Positioning)
if(Qt${QT_DEFAULT_MAJOR_VERSION}Location_FOUND)
list(APPEND TARGET_LIB Qt::Location)
endif()
@ -86,7 +86,12 @@ if(NOT BUILD_SHARED_LIBS)
set_property(GLOBAL APPEND PROPERTY STATIC_PLUGINS_PROPERTY ${TARGET_NAME})
endif()
if (NOT WIN32)
link_directories(${Boost_LIBRARY_DIRS})
endif()
target_link_libraries(${TARGET_NAME} PRIVATE
Boost::disable_autolinking
Qt::Core
${TARGET_LIB}
sdrbase
@ -104,6 +109,10 @@ endif()
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PROPERTY:${TARGET_NAME},RUNTIME_OUTPUT_DIRECTORY>/${TARGET_NAME}stripped.pdb CONFIGURATIONS Release DESTINATION ${INSTALL_FOLDER} RENAME ${TARGET_NAME}.pdb )
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -17,6 +17,10 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#define BOOST_CHRONO_HEADER_ONLY
#include <boost/chrono/chrono.hpp>
#include <stdio.h>
#include <complex.h>
#include <QTime>
@ -45,7 +49,6 @@
MESSAGE_CLASS_DEFINITION(ADSBDemod::MsgConfigureADSBDemod, Message)
MESSAGE_CLASS_DEFINITION(ADSBDemod::MsgAircraftReport, Message)
MESSAGE_CLASS_DEFINITION(ADSBDemod::MsgResetStats, Message)
const char* const ADSBDemod::m_channelIdURI = "sdrangel.channel.adsbdemod";
const char* const ADSBDemod::m_channelId = "ADSBDemod";
@ -68,7 +71,7 @@ ADSBDemod::ADSBDemod(DeviceAPI *devieAPI) :
m_worker = new ADSBDemodWorker();
m_basebandSink->setMessageQueueToWorker(m_worker->getInputMessageQueue());
applySettings(m_settings, QStringList(), true);
applySettings(m_settings, true);
m_deviceAPI->addChannelSink(this);
m_deviceAPI->addChannelSinkAPI(this);
@ -101,9 +104,9 @@ ADSBDemod::~ADSBDemod()
);
delete m_networkManager;
m_deviceAPI->removeChannelSinkAPI(this);
m_deviceAPI->removeChannelSink(this, true);
delete m_basebandSink; // This results in a call to ADSBDemod::stop(), so need to delete before worker and thread
m_deviceAPI->removeChannelSink(this);
delete m_worker;
delete m_basebandSink;
delete m_thread;
}
@ -112,7 +115,7 @@ void ADSBDemod::setDeviceAPI(DeviceAPI *deviceAPI)
if (deviceAPI != m_deviceAPI)
{
m_deviceAPI->removeChannelSinkAPI(this);
m_deviceAPI->removeChannelSink(this, false);
m_deviceAPI->removeChannelSink(this);
m_deviceAPI = deviceAPI;
m_deviceAPI->addChannelSink(this);
m_deviceAPI->addChannelSinkAPI(this);
@ -144,7 +147,7 @@ void ADSBDemod::start()
m_basebandSink->startWork();
m_thread->start();
ADSBDemodWorker::MsgConfigureADSBDemodWorker *msg = ADSBDemodWorker::MsgConfigureADSBDemodWorker::create(m_settings, QStringList(), true);
ADSBDemodWorker::MsgConfigureADSBDemodWorker *msg = ADSBDemodWorker::MsgConfigureADSBDemodWorker::create(m_settings, true);
m_worker->getInputMessageQueue()->push(msg);
}
@ -166,7 +169,7 @@ bool ADSBDemod::handleMessage(const Message& cmd)
MsgConfigureADSBDemod& cfg = (MsgConfigureADSBDemod&) cmd;
qDebug() << "ADSBDemod::handleMessage: MsgConfigureADSBDemod";
applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce());
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
@ -191,25 +194,118 @@ bool ADSBDemod::handleMessage(const Message& cmd)
m_aircraftReport = msg.getReport();
return true;
}
else if (MsgResetStats::match(cmd))
{
MsgResetStats& msg = (MsgResetStats&) cmd;
MsgResetStats* rep = new MsgResetStats(msg);
m_basebandSink->getInputMessageQueue()->push(rep);
return true;
}
else
{
return false;
}
}
void ADSBDemod::applySettings(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force)
void ADSBDemod::applySettings(const ADSBDemodSettings& settings, bool force)
{
qDebug() << "ADSBDemod::applySettings:"
<< settings.getDebugString(settingsKeys, force)
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
<< " m_rfBandwidth: " << settings.m_rfBandwidth
<< " m_streamIndex: " << settings.m_streamIndex
<< " m_useReverseAPI: " << settings.m_useReverseAPI
<< " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
<< " m_reverseAPIPort: " << settings.m_reverseAPIPort
<< " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex
<< " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex
<< " force: " << force;
QList<QString> reverseAPIKeys;
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) {
reverseAPIKeys.append("inputFrequencyOffset");
}
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) {
reverseAPIKeys.append("rfBandwidth");
}
if ((settings.m_correlationThreshold != m_settings.m_correlationThreshold) || force) {
reverseAPIKeys.append("correlationThreshold");
}
if ((settings.m_samplesPerBit != m_settings.m_samplesPerBit) || force) {
reverseAPIKeys.append("samplesPerBit");
}
if ((settings.m_correlateFullPreamble != m_settings.m_correlateFullPreamble) || force) {
reverseAPIKeys.append("correlateFullPreamble");
}
if ((settings.m_demodModeS != m_settings.m_demodModeS) || force) {
reverseAPIKeys.append("demodModeS");
}
if ((settings.m_interpolatorPhaseSteps != m_settings.m_interpolatorPhaseSteps) || force) {
reverseAPIKeys.append("interpolatorPhaseSteps");
}
if ((settings.m_interpolatorTapsPerPhase != m_settings.m_interpolatorTapsPerPhase) || force) {
reverseAPIKeys.append("interpolatorTapsPerPhase");
}
if ((settings.m_removeTimeout != m_settings.m_removeTimeout) || force) {
reverseAPIKeys.append("removeTimeout");
}
if ((settings.m_feedEnabled != m_settings.m_feedEnabled) || force) {
reverseAPIKeys.append("feedEnabled");
}
if ((settings.m_exportClientEnabled != m_settings.m_exportClientEnabled) || force) {
reverseAPIKeys.append("exportClientEnabled");
}
if ((settings.m_exportClientHost != m_settings.m_exportClientHost) || force) {
reverseAPIKeys.append("exportClientHost");
}
if ((settings.m_exportClientPort != m_settings.m_exportClientPort) || force) {
reverseAPIKeys.append("exportClientPort");
}
if ((settings.m_exportClientFormat != m_settings.m_exportClientFormat) || force) {
reverseAPIKeys.append("exportClientFormat");
}
if ((settings.m_exportServerEnabled != m_settings.m_exportServerEnabled) || force) {
reverseAPIKeys.append("exportServerEnabled");
}
if ((settings.m_exportServerPort != m_settings.m_exportServerPort) || force) {
reverseAPIKeys.append("exportServerPort");
}
if ((settings.m_importEnabled != m_settings.m_importEnabled) || force) {
reverseAPIKeys.append("importEnabled");
}
if ((settings.m_importHost != m_settings.m_importHost) || force) {
reverseAPIKeys.append("importHost");
}
if ((settings.m_importUsername != m_settings.m_importUsername) || force) {
reverseAPIKeys.append("importUsername");
}
if ((settings.m_importPassword != m_settings.m_importPassword) || force) {
reverseAPIKeys.append("importPassword");
}
if ((settings.m_importParameters != m_settings.m_importParameters) || force) {
reverseAPIKeys.append("importParameters");
}
if ((settings.m_importPeriod != m_settings.m_importPeriod) || force) {
reverseAPIKeys.append("importPeriod");
}
if ((settings.m_importMinLatitude != m_settings.m_importMinLatitude) || force) {
reverseAPIKeys.append("importMinLatitude");
}
if ((settings.m_importMaxLatitude != m_settings.m_importMaxLatitude) || force) {
reverseAPIKeys.append("importMaxLatitude");
}
if ((settings.m_importMinLongitude != m_settings.m_importMinLongitude) || force) {
reverseAPIKeys.append("importMinLongitude");
}
if ((settings.m_importMaxLongitude != m_settings.m_importMaxLongitude) || force) {
reverseAPIKeys.append("importMaxLongitude");
}
if ((settings.m_logFilename != m_settings.m_logFilename) || force) {
reverseAPIKeys.append("logFilename");
}
if ((settings.m_logEnabled != m_settings.m_logEnabled) || force) {
reverseAPIKeys.append("logEnabled");
}
if ((settings.m_title != m_settings.m_title) || force) {
reverseAPIKeys.append("title");
}
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) {
reverseAPIKeys.append("rfBandwidth");
}
if (m_settings.m_streamIndex != settings.m_streamIndex)
{
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
@ -221,40 +317,38 @@ void ADSBDemod::applySettings(const ADSBDemodSettings& settings, const QStringLi
m_settings.m_streamIndex = settings.m_streamIndex; // make sure ChannelAPI::getStreamIndex() is consistent
emit streamIndexChanged(settings.m_streamIndex);
}
reverseAPIKeys.append("streamIndex");
}
ADSBDemodBaseband::MsgConfigureADSBDemodBaseband *msg = ADSBDemodBaseband::MsgConfigureADSBDemodBaseband::create(settings, settingsKeys, force);
ADSBDemodBaseband::MsgConfigureADSBDemodBaseband *msg = ADSBDemodBaseband::MsgConfigureADSBDemodBaseband::create(settings, force);
m_basebandSink->getInputMessageQueue()->push(msg);
ADSBDemodWorker::MsgConfigureADSBDemodWorker *workerMsg = ADSBDemodWorker::MsgConfigureADSBDemodWorker::create(settings, settingsKeys, force);
ADSBDemodWorker::MsgConfigureADSBDemodWorker *workerMsg = ADSBDemodWorker::MsgConfigureADSBDemodWorker::create(settings, force);
m_worker->getInputMessageQueue()->push(workerMsg);
if (settings.m_useReverseAPI)
{
bool fullUpdate = (settingsKeys.contains("useReverseAPI") && settings.m_useReverseAPI) ||
settingsKeys.contains("reverseAPIAddress") ||
settingsKeys.contains("reverseAPIPort") ||
settingsKeys.contains("reverseAPIDeviceIndex") ||
settingsKeys.contains("reverseAPIChannelIndex");
webapiReverseSendSettings(settingsKeys, settings, fullUpdate || force);
bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
(m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) ||
(m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) ||
(m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex) ||
(m_settings.m_reverseAPIChannelIndex != settings.m_reverseAPIChannelIndex);
webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
}
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
m_settings = settings;
}
void ADSBDemod::setCenterFrequency(qint64 frequency)
{
ADSBDemodSettings settings = m_settings;
settings.m_inputFrequencyOffset = frequency;
applySettings(settings, {"inputFrequencyOffset"}, false);
applySettings(settings);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureADSBDemod *msgToGUI = MsgConfigureADSBDemod::create(settings, {"inputFrequencyOffset"}, false);
MsgConfigureADSBDemod *msgToGUI = MsgConfigureADSBDemod::create(settings, false);
m_guiMessageQueue->push(msgToGUI);
}
}
@ -274,7 +368,7 @@ bool ADSBDemod::deserialize(const QByteArray& data)
success = false;
}
MsgConfigureADSBDemod *msg = MsgConfigureADSBDemod::create(m_settings, QStringList(), true);
MsgConfigureADSBDemod *msg = MsgConfigureADSBDemod::create(m_settings, true);
m_inputMessageQueue.push(msg);
return success;
@ -310,12 +404,12 @@ int ADSBDemod::webapiSettingsPutPatch(
ADSBDemodSettings settings = m_settings;
webapiUpdateChannelSettings(settings, channelSettingsKeys, response);
MsgConfigureADSBDemod *msg = MsgConfigureADSBDemod::create(settings, channelSettingsKeys, force);
MsgConfigureADSBDemod *msg = MsgConfigureADSBDemod::create(settings, force);
m_inputMessageQueue.push(msg);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureADSBDemod *msgToGUI = MsgConfigureADSBDemod::create(settings, channelSettingsKeys, force);
MsgConfigureADSBDemod *msgToGUI = MsgConfigureADSBDemod::create(settings, force);
m_guiMessageQueue->push(msgToGUI);
}
@ -341,6 +435,9 @@ void ADSBDemod::webapiUpdateChannelSettings(
if (channelSettingsKeys.contains("samplesPerBit")) {
settings.m_samplesPerBit = response.getAdsbDemodSettings()->getSamplesPerBit();
}
if (channelSettingsKeys.contains("correlateFullPreamble")) {
settings.m_correlateFullPreamble = response.getAdsbDemodSettings()->getCorrelateFullPreamble() != 0;
}
if (channelSettingsKeys.contains("demodModeS")) {
settings.m_demodModeS = response.getAdsbDemodSettings()->getDemodModeS() != 0;
}
@ -459,6 +556,7 @@ void ADSBDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& res
response.getAdsbDemodSettings()->setRfBandwidth(settings.m_rfBandwidth);
response.getAdsbDemodSettings()->setCorrelationThreshold(settings.m_correlationThreshold);
response.getAdsbDemodSettings()->setSamplesPerBit(settings.m_samplesPerBit);
response.getAdsbDemodSettings()->setCorrelateFullPreamble(settings.m_correlateFullPreamble ? 1 : 0);
response.getAdsbDemodSettings()->setDemodModeS(settings.m_demodModeS ? 1 : 0);
response.getAdsbDemodSettings()->setInterpolatorPhaseSteps(settings.m_interpolatorPhaseSteps);
response.getAdsbDemodSettings()->setInterpolatorTapsPerPhase(settings.m_interpolatorTapsPerPhase);
@ -563,7 +661,7 @@ void ADSBDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respons
}
}
void ADSBDemod::webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const ADSBDemodSettings& settings, bool force)
void ADSBDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const ADSBDemodSettings& settings, bool force)
{
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
swgChannelSettings->setDirection(0); // single sink (Rx)
@ -587,6 +685,9 @@ void ADSBDemod::webapiReverseSendSettings(const QList<QString>& channelSettingsK
if (channelSettingsKeys.contains("samplesPerBit") || force) {
swgADSBDemodSettings->setSamplesPerBit(settings.m_samplesPerBit);
}
if (channelSettingsKeys.contains("correlateFullPreamble") || force) {
swgADSBDemodSettings->setCorrelateFullPreamble(settings.m_correlateFullPreamble ? 1 : 0);
}
if (channelSettingsKeys.contains("demodModeS") || force) {
swgADSBDemodSettings->setDemodModeS(settings.m_demodModeS ? 1 : 0);
}

View File

@ -20,6 +20,8 @@
#ifndef INCLUDE_ADSBDEMOD_H
#define INCLUDE_ADSBDEMOD_H
#include <vector>
#include <QNetworkRequest>
#include "dsp/basebandsamplesink.h"
@ -42,23 +44,20 @@ public:
public:
const ADSBDemodSettings& getSettings() const { return m_settings; }
const QStringList& getSettingsKeys() const { return m_settingsKeys; }
bool getForce() const { return m_force; }
static MsgConfigureADSBDemod* create(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force)
static MsgConfigureADSBDemod* create(const ADSBDemodSettings& settings, bool force)
{
return new MsgConfigureADSBDemod(settings, settingsKeys, force);
return new MsgConfigureADSBDemod(settings, force);
}
private:
ADSBDemodSettings m_settings;
QStringList m_settingsKeys;
bool m_force;
MsgConfigureADSBDemod(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force) :
MsgConfigureADSBDemod(const ADSBDemodSettings& settings, bool force) :
Message(),
m_settings(settings),
m_settingsKeys(settingsKeys),
m_force(force)
{ }
};
@ -92,21 +91,6 @@ public:
{ }
};
class MsgResetStats : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgResetStats* create()
{
return new MsgResetStats();
}
private:
MsgResetStats() :
Message()
{ }
};
ADSBDemod(DeviceAPI *deviceAPI);
virtual ~ADSBDemod();
virtual void destroy() { delete this; }
@ -200,9 +184,9 @@ private:
QNetworkRequest m_networkRequest;
virtual bool handleMessage(const Message& cmd); //!< Processing of a message. Returns true if message has actually been processed
void applySettings(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force = false);
void applySettings(const ADSBDemodSettings& settings, bool force = false);
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
void webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const ADSBDemodSettings& settings, bool force);
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const ADSBDemodSettings& settings, bool force);
private slots:
void networkManagerFinished(QNetworkReply *reply);

View File

@ -23,7 +23,6 @@
#include "dsp/downchannelizer.h"
#include "adsbdemodbaseband.h"
#include "adsbdemod.h"
#include "adsb.h"
MESSAGE_CLASS_DEFINITION(ADSBDemodBaseband::MsgConfigureADSBDemodBaseband, Message)
@ -118,7 +117,7 @@ bool ADSBDemodBaseband::handleMessage(const Message& cmd)
MsgConfigureADSBDemodBaseband& cfg = (MsgConfigureADSBDemodBaseband&) cmd;
qDebug() << "ADSBDemodBaseband::handleMessage: MsgConfigureADSBDemodBaseband";
applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce());
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
@ -133,35 +132,25 @@ bool ADSBDemodBaseband::handleMessage(const Message& cmd)
return true;
}
else if (ADSBDemod::MsgResetStats::match(cmd))
{
m_sink.resetStats();
return true;
}
else
{
return false;
}
}
void ADSBDemodBaseband::applySettings(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force)
void ADSBDemodBaseband::applySettings(const ADSBDemodSettings& settings, bool force)
{
if ( (settingsKeys.contains("inputFrequencyOffset") && (settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset))
|| (settingsKeys.contains("samplesPerBit") && (settings.m_samplesPerBit != m_settings.m_samplesPerBit))
|| force)
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset)
|| (settings.m_samplesPerBit != m_settings.m_samplesPerBit) || force)
{
int requestedRate = ADS_B_BITS_PER_SECOND * settings.m_samplesPerBit;
m_channelizer->setChannelization(requestedRate, settings.m_inputFrequencyOffset);
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
}
m_sink.applySettings(settings, settingsKeys, force);
m_sink.applySettings(settings, force);
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
m_settings = settings;
}
int ADSBDemodBaseband::getChannelSampleRate() const

View File

@ -39,23 +39,20 @@ public:
public:
const ADSBDemodSettings& getSettings() const { return m_settings; }
const QStringList& getSettingsKeys() const { return m_settingsKeys; }
bool getForce() const { return m_force; }
static MsgConfigureADSBDemodBaseband* create(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force)
static MsgConfigureADSBDemodBaseband* create(const ADSBDemodSettings& settings, bool force)
{
return new MsgConfigureADSBDemodBaseband(settings, settingsKeys, force);
return new MsgConfigureADSBDemodBaseband(settings, force);
}
private:
ADSBDemodSettings m_settings;
QStringList m_settingsKeys;
bool m_force;
MsgConfigureADSBDemodBaseband(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force) :
MsgConfigureADSBDemodBaseband(const ADSBDemodSettings& settings, bool force) :
Message(),
m_settings(settings),
m_settingsKeys(settingsKeys),
m_force(force)
{ }
};
@ -83,7 +80,7 @@ private:
QRecursiveMutex m_mutex;
bool handleMessage(const Message& cmd);
void applySettings(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force = false);
void applySettings(const ADSBDemodSettings& settings, bool force = false);
private slots:
void handleInputMessages();

View File

@ -50,6 +50,7 @@ ADSBDemodDisplayDialog::ADSBDemodDisplayDialog(ADSBDemodSettings *settings, QWid
ui->airportSize->setCurrentIndex((int)settings->m_airportMinimumSize);
ui->heliports->setChecked(settings->m_displayHeliports);
ui->units->setCurrentIndex((int)settings->m_siUnits);
ui->displayStats->setChecked(settings->m_displayDemodStats);
ui->autoResizeTableColumns->setChecked(settings->m_autoResizeTableColumns);
ui->aviationstackAPIKey->setText(settings->m_aviationstackAPIKey);
ui->checkWXAPIKey->setText(settings->m_checkWXAPIKey);
@ -66,17 +67,12 @@ ADSBDemodDisplayDialog::ADSBDemodDisplayDialog(ADSBDemodSettings *settings, QWid
ui->mapProvider->setCurrentText(settings->m_mapProvider);
}
ui->mapType->setCurrentIndex((int)settings->m_mapType);
ui->maptilerAPIKey->setText(m_settings->m_maptilerAPIKey);
ui->navAids->setChecked(settings->m_displayNavAids);
ui->atcCallsigns->setChecked(settings->m_atcCallsigns);
ui->photos->setChecked(settings->m_displayPhotos);
ui->verboseModelMatching->setChecked(settings->m_verboseModelMatching);
ui->favourLivery->setChecked(settings->m_favourLivery);
ui->airfieldElevation->setValue(settings->m_airfieldElevation);
ui->transitionAltitude->setValue(settings->m_transitionAlt);
for (auto i = ADSBDemodSettings::m_palettes.cbegin(), end = ADSBDemodSettings::m_palettes.cend(); i != end; ++i) {
ui->flightPathPalette->addItem(i.key());
}
ui->flightPathPalette->setCurrentText(settings->m_flightPathPaletteName);
}
ADSBDemodDisplayDialog::~ADSBDemodDisplayDialog()
@ -86,130 +82,35 @@ ADSBDemodDisplayDialog::~ADSBDemodDisplayDialog()
void ADSBDemodDisplayDialog::accept()
{
if (m_settings->m_removeTimeout != ui->timeout->value())
{
m_settings->m_removeTimeout = ui->timeout->value();
m_settingsKeys.append("removeTimeout");
}
if (m_settings->m_aircraftMinZoom != ui->aircraftMinZoom->value())
{
m_settings->m_aircraftMinZoom = ui->aircraftMinZoom->value();
m_settingsKeys.append("aircraftMinZoom");
}
if (m_settings->m_airportRange != ui->airportRange->value())
{
m_settings->m_airportRange = ui->airportRange->value();
m_settingsKeys.append("airportRange");
}
if (m_settings->m_airportMinimumSize != (ADSBDemodSettings::AirportType)ui->airportSize->currentIndex())
{
m_settings->m_airportMinimumSize = (ADSBDemodSettings::AirportType)ui->airportSize->currentIndex();
m_settingsKeys.append("airportMinimumSize");
}
if (m_settings->m_displayHeliports != ui->heliports->isChecked())
{
m_settings->m_displayHeliports = ui->heliports->isChecked();
m_settingsKeys.append("displayHeliports");
}
if (m_settings->m_siUnits != (ui->units->currentIndex() == 0 ? false : true))
{
m_settings->m_siUnits = ui->units->currentIndex() == 0 ? false : true;
m_settingsKeys.append("siUnits");
}
if (m_settings->m_autoResizeTableColumns != ui->autoResizeTableColumns->isChecked())
{
m_settings->m_autoResizeTableColumns = ui->autoResizeTableColumns->isChecked();
m_settingsKeys.append("autoResizeTableColumns");
}
if (m_settings->m_aviationstackAPIKey != ui->aviationstackAPIKey->text())
{
m_settings->m_aviationstackAPIKey = ui->aviationstackAPIKey->text();
m_settingsKeys.append("aviationstackAPIKey");
}
if (m_settings->m_checkWXAPIKey != ui->checkWXAPIKey->text())
{
m_settings->m_checkWXAPIKey = ui->checkWXAPIKey->text();
m_settingsKeys.append("checkWXAPIKey");
}
QStringList airspaces;
m_settings->m_removeTimeout = ui->timeout->value();
m_settings->m_aircraftMinZoom = ui->aircraftMinZoom->value();
m_settings->m_airportRange = ui->airportRange->value();
m_settings->m_airportMinimumSize = (ADSBDemodSettings::AirportType)ui->airportSize->currentIndex();
m_settings->m_displayHeliports = ui->heliports->isChecked();
m_settings->m_siUnits = ui->units->currentIndex() == 0 ? false : true;
m_settings->m_displayDemodStats = ui->displayStats->isChecked();
m_settings->m_autoResizeTableColumns = ui->autoResizeTableColumns->isChecked();
m_settings->m_aviationstackAPIKey = ui->aviationstackAPIKey->text();
m_settings->m_checkWXAPIKey = ui->checkWXAPIKey->text();
m_settings->m_airspaces = QStringList();
for (int i = 0; i < ui->airspaces->count(); i++)
{
QListWidgetItem *item = ui->airspaces->item(i);
if (item->checkState() == Qt::Checked) {
airspaces.append(item->text());
m_settings->m_airspaces.append(item->text());
}
}
if (m_settings->m_airspaces != airspaces)
{
m_settings->m_airspaces = airspaces;
m_settingsKeys.append("airspaces");
}
if (m_settings->m_airspaceRange != ui->airspaceRange->value())
{
m_settings->m_airspaceRange = ui->airspaceRange->value();
m_settingsKeys.append("airspaceRange");
}
if (m_settings->m_mapProvider != ui->mapProvider->currentText())
{
m_settings->m_mapProvider = ui->mapProvider->currentText();
m_settingsKeys.append("mapProvider");
}
if (m_settings->m_mapType != (ADSBDemodSettings::MapType)ui->mapType->currentIndex())
{
m_settings->m_mapType = (ADSBDemodSettings::MapType)ui->mapType->currentIndex();
m_settingsKeys.append("mapType");
}
if (m_settings->m_maptilerAPIKey != ui->maptilerAPIKey->text())
{
m_settings->m_maptilerAPIKey = ui->maptilerAPIKey->text();
m_settingsKeys.append("maptilerAPIKey");
}
if (m_settings->m_displayNavAids != ui->navAids->isChecked())
{
m_settings->m_displayNavAids = ui->navAids->isChecked();
m_settingsKeys.append("displayNavAids");
}
if (m_settings->m_atcCallsigns != ui->atcCallsigns->isChecked())
{
m_settings->m_atcCallsigns = ui->atcCallsigns->isChecked();
m_settingsKeys.append("atcCallsigns");
}
if (m_settings->m_displayPhotos != ui->photos->isChecked())
{
m_settings->m_displayPhotos = ui->photos->isChecked();
m_settingsKeys.append("displayPhotos");
}
if (m_settings->m_verboseModelMatching != ui->verboseModelMatching->isChecked())
{
m_settings->m_verboseModelMatching = ui->verboseModelMatching->isChecked();
m_settingsKeys.append("verboseModelMatching");
}
if (m_settings->m_favourLivery != ui->favourLivery->isChecked())
{
m_settings->m_favourLivery = ui->favourLivery->isChecked();
m_settingsKeys.append("favourLivery");
}
if (m_settings->m_transitionAlt != ui->transitionAltitude->value())
{
m_settings->m_transitionAlt = ui->transitionAltitude->value();
m_settingsKeys.append("transitionAlt");
}
if (m_settings->m_tableFontName != m_fontName)
{
m_settings->m_tableFontName = m_fontName;
m_settingsKeys.append("tableFontName");
}
if (m_settings->m_tableFontSize != m_fontSize)
{
m_settings->m_tableFontSize = m_fontSize;
m_settingsKeys.append("tableFontSize");
}
if (m_settings->m_flightPathPaletteName != ui->flightPathPalette->currentText())
{
m_settings->m_flightPathPaletteName = ui->flightPathPalette->currentText();
m_settingsKeys.append("flightPathPaletteName");
m_settings->applyPalette();
}
m_settings->m_airspaceRange = ui->airspaceRange->value();
m_settings->m_mapProvider = ui->mapProvider->currentText();
m_settings->m_mapType = (ADSBDemodSettings::MapType)ui->mapType->currentIndex();
m_settings->m_displayNavAids = ui->navAids->isChecked();
m_settings->m_atcCallsigns = ui->atcCallsigns->isChecked();
m_settings->m_displayPhotos = ui->photos->isChecked();
m_settings->m_verboseModelMatching = ui->verboseModelMatching->isChecked();
m_settings->m_airfieldElevation = ui->airfieldElevation->value();
m_settings->m_transitionAlt = ui->transitionAltitude->value();
m_settings->m_tableFontName = m_fontName;
m_settings->m_tableFontSize = m_fontSize;
QDialog::accept();
}

View File

@ -28,8 +28,6 @@ public:
explicit ADSBDemodDisplayDialog(ADSBDemodSettings *settings, QWidget* parent = 0);
~ADSBDemodDisplayDialog();
const QStringList& getSettingsKeys() const { return m_settingsKeys; };
private slots:
void accept();
void on_font_clicked();
@ -37,7 +35,6 @@ private slots:
private:
Ui::ADSBDemodDisplayDialog* ui;
ADSBDemodSettings *m_settings;
QStringList m_settingsKeys;
QString m_fontName;
int m_fontSize;
};

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>417</width>
<height>505</height>
<height>467</height>
</rect>
</property>
<property name="font">
@ -124,16 +124,22 @@
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="verboseModelMatchingLabel">
<widget class="QLabel" name="displayStatsLabel">
<property name="text">
<string>Log 3D model matching information</string>
<string>Display demodulator statistics</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="verboseModelMatching">
<widget class="QCheckBox" name="displayStats">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Log information about how aircraft are matched to 3D models</string>
<string>Display demodulator statistics</string>
</property>
<property name="text">
<string/>
@ -141,16 +147,16 @@
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="favourLiveryLabel">
<widget class="QLabel" name="verboseModelMatchingLabel">
<property name="text">
<string>Favour airline livery over aircraft type</string>
<string>Log 3D model matching information</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="favourLivery">
<widget class="QCheckBox" name="verboseModelMatching">
<property name="toolTip">
<string>Favour airline livery over aircraft type for 3D models</string>
<string>Log information about how aircraft are matched to 3D models</string>
</property>
<property name="text">
<string/>
@ -186,13 +192,36 @@
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="airfieldElevationLabel">
<property name="text">
<string>Airfield barometric altitude (ft)</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QSpinBox" name="airfieldElevation">
<property name="toolTip">
<string>Barometric altitude reported by aircraft when on airfield surface</string>
</property>
<property name="minimum">
<number>-10000</number>
</property>
<property name="maximum">
<number>30000</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="transitionAltitudeLabel">
<property name="text">
<string>Transition altitude (ft)</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QSpinBox" name="transitionAltitude">
<property name="toolTip">
<string>Transition altitude in feet</string>
@ -203,9 +232,6 @@
<property name="maximum">
<number>20000</number>
</property>
<property name="value">
<number>6000</number>
</property>
</widget>
</item>
</layout>
@ -277,14 +303,14 @@
</item>
</widget>
</item>
<item row="3" column="0">
<item row="2" column="0">
<widget class="QLabel" name="aircraftMinZoomLabel">
<property name="text">
<string>Zoom level for aircraft scaling</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1">
<widget class="QSpinBox" name="aircraftMinZoom">
<property name="toolTip">
<string>When map zoom (0 min zoom - 15 max zoom) is higher than this value, aircraft icon size will be scaled</string>
@ -294,14 +320,14 @@
</property>
</widget>
</item>
<item row="4" column="0">
<item row="3" column="0">
<widget class="QLabel" name="airportSizeLabel">
<property name="text">
<string>Display airports with size</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="3" column="1">
<widget class="QComboBox" name="airportSize">
<property name="toolTip">
<string>Sets the minimum airport size that will be displayed on the map</string>
@ -323,14 +349,14 @@
</item>
</widget>
</item>
<item row="5" column="0">
<item row="4" column="0">
<widget class="QLabel" name="heliportsLabel">
<property name="text">
<string>Display heliports</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="4" column="1">
<widget class="QCheckBox" name="heliports">
<property name="toolTip">
<string>When checked, heliports are displayed on the map</string>
@ -340,14 +366,14 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="5" column="0">
<widget class="QLabel" name="airportRangeLabel">
<property name="text">
<string>Airport display distance (km)</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="5" column="1">
<widget class="QSpinBox" name="airportRange">
<property name="toolTip">
<string>Displays airports within the specified distance in kilometres from My Position</string>
@ -357,14 +383,14 @@
</property>
</widget>
</item>
<item row="7" column="0">
<item row="6" column="0">
<widget class="QLabel" name="airspacesLabel">
<property name="text">
<string>Airspaces to display</string>
</property>
</widget>
</item>
<item row="7" column="1">
<item row="6" column="1">
<widget class="QListWidget" name="airspaces">
<property name="toolTip">
<string>Airspace categories to display</string>
@ -521,14 +547,14 @@
</item>
</widget>
</item>
<item row="8" column="0">
<item row="7" column="0">
<widget class="QLabel" name="airspaceRangeLabel">
<property name="text">
<string>Airspace display distance (km)</string>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="7" column="1">
<widget class="QSpinBox" name="airspaceRange">
<property name="toolTip">
<string>Displays airspace within the specified distance in kilometres from My Position</string>
@ -538,14 +564,14 @@
</property>
</widget>
</item>
<item row="9" column="0">
<item row="8" column="0">
<widget class="QLabel" name="displayNavAids">
<property name="text">
<string>Display NAVAIDs</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="8" column="1">
<widget class="QCheckBox" name="navAids">
<property name="toolTip">
<string>Display NAVAIDs such as VORs and NDBs</string>
@ -555,7 +581,7 @@
</property>
</widget>
</item>
<item row="10" column="1">
<item row="9" column="1">
<widget class="QCheckBox" name="atcCallsigns">
<property name="toolTip">
<string>Use ATC callsigns (SPEEDBIRD) rather than ICAO (BAW) for aircraft labels on map</string>
@ -565,44 +591,13 @@
</property>
</widget>
</item>
<item row="10" column="0">
<item row="9" column="0">
<widget class="QLabel" name="atcCallsignsLabel">
<property name="text">
<string>Use ATC callsigns on map</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QComboBox" name="flightPathPalette">
<property name="toolTip">
<string>Colour palette to use for aircraft flight paths</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="flightPathPaletteLabel">
<property name="text">
<string>Flight path palette</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>Maptiler API key</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="maptilerAPIKey">
<property name="toolTip">
<string>API key for Maptiler (https://maptiler.com) for satellite map</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@ -612,10 +607,10 @@
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,6 @@
#include <QTextToSpeech>
#include <QRandomGenerator>
#include <QNetworkAccessManager>
#include <QtCharts>
#include "channel/channelgui.h"
#include "dsp/dsptypes.h"
@ -57,17 +56,11 @@ class WebAPIAdapterInterface;
class HttpDownloadManager;
class ADSBDemodGUI;
class ADSBOSMTemplateServer;
class CheckList;
class AircraftModel;
namespace Ui {
class ADSBDemodGUI;
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
using namespace QtCharts;
#endif
// Custom widget to allow formatted decimal numbers to be sorted numerically
class CustomDoubleTableWidgetItem : public QTableWidgetItem
{
@ -96,16 +89,12 @@ struct Aircraft {
QString m_icaoHex;
QString m_callsign; // Flight callsign
QString m_flight; // Guess at flight number
bool m_globalPosition; // Position has been determined from global decode
Real m_latitude; // Latitude in decimal degrees
Real m_longitude; // Longitude in decimal degrees
float m_radius; // Horizontal containment radius limit (Rc) in metres
int m_altitude; // Altitude in feet (will be 0 if on surface)
int m_pressureAltitude; // Pressure altitude in feet for Map PFD altimeter (can be negative on surface)
int m_altitude; // Altitude in feet
bool m_onSurface; // Indicates if on surface or airborne
bool m_altitudeGNSS; // Altitude is GNSS HAE (Height above WGS-84 ellipsoid) rather than barometric alitute (relative to 29.92 Hg)
float m_heading; // Heading in degrees magnetic
float m_track; // Track in degrees true?
float m_heading; // Heading or track in degrees
int m_verticalRate; // Vertical climb rate in ft/min
QString m_emitterCategory; // Aircraft type
QString m_status; // Aircraft status
@ -113,37 +102,23 @@ struct Aircraft {
Real m_range; // Distance from station to aircraft
Real m_azimuth; // Azimuth from station to aircraft
Real m_elevation; // Elevation from station to aircraft
QDateTime m_rxTime; // When last frame received (can be long ago if reading from log file)
QDateTime m_updateTime; // Last time we updated data for this aircraft (used for determining when to remove an aircraft)
QDateTime m_time; // When last updated
int m_selAltitude; // Selected altitude in MCP/FCU or FMS in feet
int m_selHeading; // Selected heading in MCP/FCU in degrees
float m_baro; // Aircraft baro setting in mb (Mode-S)
int m_baro; // Aircraft baro setting in mb (Mode-S)
float m_roll; // In degrees
int m_groundspeed; // In knots
float m_turnRate; // In degrees per second
int m_trueAirspeed; // In knots
int m_indicatedAirspeed; // In knots
float m_mach; // Mach number
bool m_autopilot;
bool m_vnavMode;
bool m_altHoldMode;
bool m_approachMode;
bool m_lnavMode;
bool m_tcasOperational; // Appears only to be true if TA/RA, false if TA ONLY
bool m_bdsCapabilities[16][16]; // BDS capabilities are indicaited by BDS 1.7
int m_adsbVersion;
bool m_nicSupplementA;
bool m_nicSupplementB;
bool m_nicSupplementC;
bool m_positionValid; // Indicates if we have valid data for the above fields
bool m_altitudeValid;
bool m_pressureAltitudeValid;
bool m_onSurfaceValid;
bool m_headingValid;
bool m_trackValid;
bool m_verticalRateValid;
bool m_selAltitudeValid;
bool m_selHeadingValid;
@ -154,30 +129,16 @@ struct Aircraft {
bool m_trueAirspeedValid;
bool m_indicatedAirspeedValid;
bool m_machValid;
bool m_autopilotValid;
bool m_vnavModeValid;
bool m_altHoldModeValid;
bool m_approachModeValid;
bool m_lnavModeValid;
bool m_tcasOperationalValid;
bool m_bdsCapabilitiesValid;
bool m_adsbVersionValid;
bool m_nicSupplementAValid;
bool m_nicSupplementBValid;
bool m_nicSupplementCValid;
// State for calculating position using two CPR frames
bool m_cprValid[2];
double m_cprLat[2];
double m_cprLong[2];
Real m_cprLat[2];
Real m_cprLong[2];
QDateTime m_cprTime[2];
int m_adsbFrameCount; // Number of ADS-B frames for this aircraft
int m_modesFrameCount; // Number of Mode-S frames for this aircraft
int m_nonTransponderFrameCount;
int m_tisBFrameCount;
int m_adsrFrameCount;
float m_minCorrelation;
float m_maxCorrelation;
float m_correlation;
@ -187,12 +148,8 @@ struct Aircraft {
bool m_isHighlighted; // Are we highlighting this aircraft in the table and map
bool m_showAll;
QList<QVariantList> m_coordinates; // Coordinates we've recorded the aircraft at, split up in to altitude ranges
QList<QVariantList> m_recentCoordinates; // Last 20 seconds of coordinates for ATC mode
QVariantList m_coordinates; // Coordinates we've recorded the aircraft at
QList<QDateTime> m_coordinateDateTimes;
QList<int> m_coordinateColors; // 0-7 index to 8 color palette according to altitude
QList<int> m_recentCoordinateColors;
int m_lastColor;
AircraftInformation *m_aircraftInfo; // Info about the aircraft from the database
QString m_aircraft3DModel; // 3D model for map based on aircraft type
@ -202,7 +159,6 @@ struct Aircraft {
ADSBDemodGUI *m_gui;
QString m_flagIconURL;
QString m_airlineIconURL;
QString m_sideviewIconURL;
// For animation on 3D map
float m_runwayAltitude;
@ -212,14 +168,10 @@ struct Aircraft {
bool m_rotorStarted; // Rotors started on 'Rotorcraft'
bool m_engineStarted; // Engines started (typically propellors)
QDateTime m_positionDateTime;
QDateTime m_orientationDateTime; // FIXME
QDateTime m_orientationDateTime;
QDateTime m_headingDateTime;
QDateTime m_trackDateTime;
QDateTime m_altitudeDateTime;
QDateTime m_indicatedAirspeedDateTime;
QDateTime m_prevTrackDateTime;
int m_prevTrack;
float m_trackWhenHeadingSet;
QDateTime m_prevHeadingDateTime;
int m_prevHeading;
float m_pitchEst; // Estimated pitch based on vertical rate
float m_rollEst; // Estimated roll based on rate of change in heading
@ -230,48 +182,30 @@ struct Aircraft {
QTableWidgetItem *m_callsignItem;
QTableWidgetItem* m_atcCallsignItem;
QTableWidgetItem *m_modelItem;
QTableWidgetItem *m_typeItem;
QTableWidgetItem *m_sideviewItem;
QTableWidgetItem *m_airlineItem;
QTableWidgetItem *m_latitudeItem;
QTableWidgetItem *m_longitudeItem;
QTableWidgetItem *m_altitudeItem;
QTableWidgetItem *m_headingItem;
QTableWidgetItem *m_trackItem;
QTableWidgetItem *m_verticalRateItem;
CustomDoubleTableWidgetItem *m_rangeItem;
QTableWidgetItem *m_azElItem;
QTableWidgetItem *m_emitterCategoryItem;
QTableWidgetItem *m_statusItem;
QTableWidgetItem *m_squawkItem;
QTableWidgetItem *m_identItem;
QTableWidgetItem *m_registrationItem;
QTableWidgetItem *m_countryItem;
QTableWidgetItem *m_registeredItem;
QTableWidgetItem *m_manufacturerNameItem;
QTableWidgetItem *m_ownerItem;
QTableWidgetItem *m_operatorICAOItem;
QTableWidgetItem *m_interogatorCodeItem;
QTableWidgetItem *m_timeItem;
QTableWidgetItem *m_totalFrameCountItem;
QTableWidgetItem *m_adsbFrameCountItem;
QTableWidgetItem *m_modesFrameCountItem;
QTableWidgetItem *m_nonTransponderItem;
QTableWidgetItem *m_tisBFrameCountItem;
QTableWidgetItem *m_adsrFrameCountItem;
QTableWidgetItem *m_radiusItem;
QTableWidgetItem *m_nacpItem;
QTableWidgetItem *m_nacvItem;
QTableWidgetItem *m_gvaItem;
QTableWidgetItem *m_nicItem;
QTableWidgetItem *m_nicBaroItem;
QTableWidgetItem *m_silItem;
QTableWidgetItem *m_correlationItem;
QTableWidgetItem *m_rssiItem;
QTableWidgetItem *m_flightStatusItem;
QTableWidgetItem *m_depItem;
QTableWidgetItem *m_arrItem;
QTableWidgetItem *m_stopsItem;
QTableWidgetItem *m_stdItem;
QTableWidgetItem *m_etdItem;
QTableWidgetItem *m_atdItem;
@ -284,13 +218,6 @@ struct Aircraft {
QTableWidgetItem *m_apItem;
QTableWidgetItem *m_vModeItem;
QTableWidgetItem *m_lModeItem;
QTableWidgetItem *m_tcasItem;
QTableWidgetItem *m_acasItem;
QTableWidgetItem *m_raItem;
QTableWidgetItem *m_maxSpeedItem;
QTableWidgetItem *m_versionItem;
QTableWidgetItem *m_lengthItem;
QTableWidgetItem *m_widthItem;
QTableWidgetItem *m_rollItem;
QTableWidgetItem *m_groundspeedItem;
QTableWidgetItem *m_turnRateItem;
@ -304,18 +231,16 @@ struct Aircraft {
QTableWidgetItem *m_staticPressureItem;
QTableWidgetItem *m_staticAirTempItem;
QTableWidgetItem *m_humidityItem;
QTableWidgetItem *m_tisBItem;
Aircraft(ADSBDemodGUI *gui) :
m_icao(0),
m_globalPosition(false),
m_latitude(0),
m_longitude(0),
m_radius(0.0f),
m_altitude(0),
m_onSurface(false),
m_altitudeGNSS(false),
m_heading(0),
m_track(0),
m_verticalRate(0),
m_azimuth(0),
m_elevation(0),
@ -328,22 +253,9 @@ struct Aircraft {
m_trueAirspeed(0),
m_indicatedAirspeed(0),
m_mach(0.0f),
m_autopilot(false),
m_vnavMode(false),
m_altHoldMode(false),
m_approachMode(false),
m_lnavMode(false),
m_tcasOperational(false),
m_adsbVersion(0),
m_nicSupplementA(false),
m_nicSupplementB(false),
m_nicSupplementC(false),
m_positionValid(false),
m_altitudeValid(false),
m_pressureAltitudeValid(false),
m_onSurfaceValid(false),
m_headingValid(false),
m_trackValid(false),
m_verticalRateValid(false),
m_selAltitudeValid(false),
m_selHeadingValid(false),
@ -354,22 +266,9 @@ struct Aircraft {
m_trueAirspeedValid(false),
m_indicatedAirspeedValid(false),
m_machValid(false),
m_autopilotValid(false),
m_vnavModeValid(false),
m_altHoldModeValid(false),
m_approachModeValid(false),
m_lnavModeValid(false),
m_tcasOperationalValid(false),
m_bdsCapabilitiesValid(false),
m_adsbVersionValid(false),
m_nicSupplementAValid(false),
m_nicSupplementBValid(false),
m_nicSupplementCValid(false),
m_adsbFrameCount(0),
m_modesFrameCount(0),
m_nonTransponderFrameCount(0),
m_tisBFrameCount(0),
m_adsrFrameCount(0),
m_minCorrelation(INFINITY),
m_maxCorrelation(-INFINITY),
m_correlation(0.0f),
@ -403,12 +302,9 @@ struct Aircraft {
m_callsignItem = new QTableWidgetItem();
m_atcCallsignItem = new QTableWidgetItem();
m_modelItem = new QTableWidgetItem();
m_typeItem = new QTableWidgetItem();
m_sideviewItem = new QTableWidgetItem();
m_airlineItem = new QTableWidgetItem();
m_altitudeItem = new QTableWidgetItem();
m_headingItem = new QTableWidgetItem();
m_trackItem = new QTableWidgetItem();
m_verticalRateItem = new QTableWidgetItem();
m_rangeItem = new CustomDoubleTableWidgetItem();
m_azElItem = new QTableWidgetItem();
@ -417,34 +313,19 @@ struct Aircraft {
m_emitterCategoryItem = new QTableWidgetItem();
m_statusItem = new QTableWidgetItem();
m_squawkItem = new QTableWidgetItem();
m_identItem = new QTableWidgetItem();
m_registrationItem = new QTableWidgetItem();
m_countryItem = new QTableWidgetItem();
m_registeredItem = new QTableWidgetItem();
m_manufacturerNameItem = new QTableWidgetItem();
m_ownerItem = new QTableWidgetItem();
m_operatorICAOItem = new QTableWidgetItem();
m_interogatorCodeItem = new QTableWidgetItem();
m_timeItem = new QTableWidgetItem();
m_totalFrameCountItem = new QTableWidgetItem();
m_adsbFrameCountItem = new QTableWidgetItem();
m_modesFrameCountItem = new QTableWidgetItem();
m_nonTransponderItem = new QTableWidgetItem();
m_tisBFrameCountItem = new QTableWidgetItem();
m_adsrFrameCountItem = new QTableWidgetItem();
m_radiusItem = new QTableWidgetItem();
m_nacpItem = new QTableWidgetItem();
m_nacvItem = new QTableWidgetItem();
m_gvaItem = new QTableWidgetItem();
m_nicItem = new QTableWidgetItem();
m_nicBaroItem = new QTableWidgetItem();
m_silItem = new QTableWidgetItem();
m_correlationItem = new QTableWidgetItem();
m_rssiItem = new QTableWidgetItem();
m_flightStatusItem = new QTableWidgetItem();
m_depItem = new QTableWidgetItem();
m_arrItem = new QTableWidgetItem();
m_stopsItem = new QTableWidgetItem();
m_stdItem = new QTableWidgetItem();
m_etdItem = new QTableWidgetItem();
m_atdItem = new QTableWidgetItem();
@ -457,13 +338,6 @@ struct Aircraft {
m_apItem = new QTableWidgetItem();
m_vModeItem = new QTableWidgetItem();
m_lModeItem = new QTableWidgetItem();
m_tcasItem = new QTableWidgetItem();
m_acasItem = new QTableWidgetItem();
m_raItem = new QTableWidgetItem();
m_maxSpeedItem = new QTableWidgetItem();
m_versionItem = new QTableWidgetItem();
m_lengthItem = new QTableWidgetItem();
m_widthItem = new QTableWidgetItem();
m_rollItem = new QTableWidgetItem();
m_groundspeedItem = new QTableWidgetItem();
m_turnRateItem = new QTableWidgetItem();
@ -477,15 +351,16 @@ struct Aircraft {
m_staticPressureItem = new QTableWidgetItem();
m_staticAirTempItem = new QTableWidgetItem();
m_humidityItem = new QTableWidgetItem();
m_tisBItem = new QTableWidgetItem();
}
QString getImage() const;
QString getText(const ADSBDemodSettings *settings, bool all=false) const;
// Label to use for aircraft on map
QString getLabel(const ADSBDemodSettings *settings, QDateTime& dateTime) const;
QString getLabel(const ADSBDemodSettings *settings) const;
// Name to use when selected as a target (E.g. for use as target name in Rotator Controller)
QString targetName() const
QString targetName()
{
if (!m_callsign.isEmpty())
return QString("Callsign: %1").arg(m_callsign);
@ -493,71 +368,6 @@ struct Aircraft {
return QString("ICAO: %1").arg(m_icao, 0, 16);
}
void setOnSurface(const QDateTime& dateTime);
void setAltitude(int altitudeFt, bool gnss, const QDateTime& dateTime, const ADSBDemodSettings& settings);
void setVerticalRate(int verticalRate, const ADSBDemodSettings& settings);
void setGroundspeed(float groundspeed, const ADSBDemodSettings& settings);
void setTrueAirspeed(int airspeed, const ADSBDemodSettings& settings);
void setIndicatedAirspeed(int airspeed, const QDateTime& dateTime, const ADSBDemodSettings& settings);
void setTrack(float track, const QDateTime& dateTime);
void setHeading(float heading, const QDateTime& dateTime);
void addCoordinate(const QDateTime& dateTime, AircraftModel *model);
void clearCoordinates(AircraftModel *model);
};
class AircraftPathModel : public QAbstractListModel {
Q_OBJECT
public:
using QAbstractListModel::QAbstractListModel;
enum MarkerRoles{
coordinatesRole = Qt::UserRole + 1,
colorRole = Qt::UserRole + 2,
};
AircraftPathModel(AircraftModel *aircraftModel, Aircraft *aircraft) :
m_aircraftModel(aircraftModel),
m_aircraft(aircraft),
m_paths(0),
m_showFullPath(false),
m_showATCPath(false)
{
settingsUpdated();
}
int rowCount(const QModelIndex &parent = QModelIndex()) const override {
(void) parent;
return m_paths;
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
void add();
void updateLast();
void removed();
void clear();
void settingsUpdated();
Qt::ItemFlags flags(const QModelIndex &index) const override
{
(void) index;
return Qt::ItemIsEnabled;
}
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[coordinatesRole] = "coordinates";
roles[colorRole] = "color";
return roles;
}
private:
AircraftModel *m_aircraftModel;
Aircraft *m_aircraft;
int m_paths; // Should match m_aircraft->m_coordinates.count()
bool m_showFullPath;
bool m_showATCPath;
};
// Aircraft data model used by QML map item
@ -575,16 +385,12 @@ public:
aircraftPathRole = Qt::UserRole + 6,
showAllRole = Qt::UserRole + 7,
highlightedRole = Qt::UserRole + 8,
targetRole = Qt::UserRole + 9,
radiusRole = Qt::UserRole + 10,
showRadiusRole = Qt::UserRole + 11,
aircraftPathModelRole = Qt::UserRole + 12,
targetRole = Qt::UserRole + 9
};
Q_INVOKABLE void addAircraft(Aircraft *aircraft) {
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_aircrafts.append(aircraft);
m_pathModels.append(new AircraftPathModel(this, aircraft));
endInsertRows();
}
@ -603,8 +409,7 @@ public:
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}
void aircraftUpdated(Aircraft *aircraft)
{
void aircraftUpdated(Aircraft *aircraft) {
int row = m_aircrafts.indexOf(aircraft);
if (row >= 0)
{
@ -613,72 +418,30 @@ public:
}
}
void highlightChanged(Aircraft *aircraft)
{
int row = m_aircrafts.indexOf(aircraft);
if (row >= 0)
void allAircraftUpdated() {
/*
// Not sure why this doesn't work - it should be more efficient
// than the following code
emit dataChanged(index(0), index(rowCount()));
*/
for (int i = 0; i < m_aircrafts.count(); i++)
{
m_pathModels[row]->settingsUpdated();
QModelIndex idx = index(row);
QModelIndex idx = index(i);
emit dataChanged(idx, idx);
}
}
void clearCoords(Aircraft *aircraft)
{
int row = m_aircrafts.indexOf(aircraft);
if (row >= 0) {
m_pathModels[row]->clear();
}
}
void aircraftCoordsUpdated(Aircraft *aircraft)
{
int row = m_aircrafts.indexOf(aircraft);
if (row >= 0) {
m_pathModels[row]->updateLast();
}
}
void aircraftCoordsAdded(Aircraft *aircraft)
{
int row = m_aircrafts.indexOf(aircraft);
if (row >= 0) {
m_pathModels[row]->add();
}
}
void aircraftCoordsRemoved(Aircraft *aircraft)
{
int row = m_aircrafts.indexOf(aircraft);
if (row >= 0) {
m_pathModels[row]->removed();
}
}
void allAircraftUpdated()
{
emit dataChanged(index(0), index(rowCount()-1));
for (int i = 0; i < m_aircrafts.count(); i++) {
m_pathModels[i]->settingsUpdated();
}
}
void removeAircraft(Aircraft *aircraft)
{
void removeAircraft(Aircraft *aircraft) {
int row = m_aircrafts.indexOf(aircraft);
if (row >= 0)
{
beginRemoveRows(QModelIndex(), row, row);
m_aircrafts.removeAt(row);
delete m_pathModels.takeAt(row);
endRemoveRows();
}
}
QHash<int, QByteArray> roleNames() const
{
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[positionRole] = "position";
roles[headingRole] = "heading";
@ -689,12 +452,22 @@ public:
roles[showAllRole] = "showAll";
roles[highlightedRole] = "highlighted";
roles[targetRole] = "target";
roles[radiusRole] = "containmentRadius";
roles[aircraftPathModelRole] = "aircraftPathModel";
return roles;
}
void setSettings(const ADSBDemodSettings *settings)
void setFlightPaths(bool flightPaths)
{
m_flightPaths = flightPaths;
allAircraftUpdated();
}
void setAllFlightPaths(bool allFlightPaths)
{
m_allFlightPaths = allFlightPaths;
allAircraftUpdated();
}
void setSettings(const ADSBDemodSettings *settings)
{
m_settings = settings;
allAircraftUpdated();
@ -714,11 +487,11 @@ public:
}
}
const ADSBDemodSettings *m_settings;
private:
QList<Aircraft *> m_aircrafts;
QList<AircraftPathModel *> m_pathModels;
bool m_flightPaths;
bool m_allFlightPaths;
const ADSBDemodSettings *m_settings;
};
// Airport data model used by QML map item
@ -894,34 +667,26 @@ public:
airspacePolygonRole = Qt::UserRole + 6
};
Q_INVOKABLE void addAirspace(Airspace *airspace)
{
Q_INVOKABLE void addAirspace(Airspace *airspace) {
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_airspaces.append(airspace);
updatePolygon(airspace, -1);
// Convert QPointF to QVariantList of QGeoCoordinates
QVariantList polygon;
for (const auto p : airspace->m_polygon)
{
QGeoCoordinate coord(p.y(), p.x(), airspace->topHeightInMetres());
polygon.push_back(QVariant::fromValue(coord));
}
m_polygons.append(polygon);
endInsertRows();
}
int rowCount(const QModelIndex &parent = QModelIndex()) const override
{
int rowCount(const QModelIndex &parent = QModelIndex()) const override {
Q_UNUSED(parent)
return m_airspaces.count();
}
void removeAirspace(Airspace *airspace)
{
int idx = m_airspaces.indexOf(airspace);
if (idx >= 0)
{
beginRemoveRows(QModelIndex(), idx, idx);
m_airspaces.removeAt(idx);
m_polygons.removeAt(idx);
endRemoveRows();
}
}
void removeAllAirspaces()
{
void removeAllAirspaces() {
if (m_airspaces.count() > 0)
{
beginRemoveRows(QModelIndex(), 0, m_airspaces.count() - 1);
@ -931,23 +696,6 @@ public:
}
}
void airspaceUpdated(const Airspace *airspace)
{
int row = m_airspaces.indexOf(airspace);
if (row >= 0)
{
updatePolygon(airspace, row);
QModelIndex idx = index(row);
emit dataChanged(idx, idx);
}
}
bool contains(const Airspace *airspace)
{
return m_airspaces.contains(airspace);
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant& value, int role = Qt::EditRole) override;
@ -958,8 +706,7 @@ public:
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}
QHash<int, QByteArray> roleNames() const
{
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[nameRole] = "name";
roles[detailsRole] = "details";
@ -971,25 +718,8 @@ public:
}
private:
QList<const Airspace *> m_airspaces;
QList<Airspace *> m_airspaces;
QList<QVariantList> m_polygons;
void updatePolygon(const Airspace *airspace, int row)
{
// Convert QPointF to QVariantList of QGeoCoordinates
QVariantList polygon;
for (const auto p : airspace->m_polygon)
{
QGeoCoordinate coord(p.y(), p.x(), airspace->topHeightInMetres());
polygon.push_back(QVariant::fromValue(coord));
}
if (row == -1) {
m_polygons.append(polygon);
} else {
m_polygons.replace(row, polygon);
}
}
};
// NavAid model used for each NavAid on the map
@ -1137,23 +867,6 @@ protected:
class ADSBDemodGUI : public ChannelGUI {
Q_OBJECT
struct Interogator {
Real m_minLatitude;
Real m_maxLatitude;
Real m_minLongitude;
Real m_maxLongitude;
bool m_valid;
Airspace m_airspace;
Interogator() :
m_valid(false)
{
}
void update(int ic, Aircraft *aircraft, AirspaceModel *airspaceModel, CheckList *checkList, bool display);
void calcPoly();
};
public:
static ADSBDemodGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
virtual void destroy();
@ -1198,7 +911,6 @@ private:
ChannelMarker m_channelMarker;
RollupState m_rollupState;
ADSBDemodSettings m_settings;
QStringList m_settingsKeys;
qint64 m_deviceCenterFrequency;
int m_basebandSampleRate;
bool m_basicSettingsShown;
@ -1210,7 +922,6 @@ private:
QHash<int, Aircraft *> m_aircraft; // Hashed on ICAO
QSharedPointer<const QHash<int, AircraftInformation *>> m_aircraftInfo;
QSharedPointer<const QHash<QString, AircraftRouteInformation *>> m_routeInfo; // Hashed on callsign
QSharedPointer<const QHash<int, AirportInformation *>> m_airportInfo; // Hashed on id
AircraftModel m_aircraftModel;
AirportModel m_airportModel;
@ -1224,85 +935,12 @@ private:
Aircraft *m_trackAircraft; // Aircraft we want to track in Channel Report
MovingAverageUtil<float, double, 10> m_correlationAvg;
MovingAverageUtil<float, double, 10> m_correlationOnesAvg;
MovingAverageUtil<float, double, 100> m_qnhAvg;
Aircraft *m_highlightAircraft; // Aircraft we want to highlight, when selected in table
float m_currentAirportRange; // Current settings, so we only update if changed
ADSBDemodSettings::AirportType m_currentAirportMinimumSize;
bool m_currentDisplayHeliports;
static const int m_maxRangeDeg = 5;
QList<float> m_maxRange[2];
Airspace m_coverageAirspace[2];
Interogator m_interogators[ADSB_IC_MAX];
enum StatsRow {
ADSB_FRAMES,
MODE_S_FRAMES,
TOTAL_FRAMES,
ADSB_RATE,
MODE_S_RATE,
TOTAL_RATE,
DATA_RATE,
CORRELATOR_MATCHES,
PERCENT_VALID,
PREAMBLE_FAILS,
CRC_FAILS,
TYPE_FAILS,
INVALID_FAILS,
ICAO_FAILS,
RANGE_FAILS,
ALT_FAILS,
AVERAGE_CORRELATION,
TC_0,
TC_1_4,
TC_5_8,
TC_9_18,
TC_19,
TC_20_22,
TC_24,
TC_28,
TC_29,
TC_31,
TC_UNUSED,
DF0,
DF4,
DF5,
DF11,
DF16,
DF17,
DF18,
DF19,
DF20_21,
DF22,
DF24,
MAX_RANGE,
MAX_ALTITUDE,
MAX_RATE
};
qint64 m_rangeFails;
qint64 m_altFails;
QDateTime m_frameRateTime;
qint64 m_adsbFrameRateCount;
qint64 m_modesFrameRateCount;
qint64 m_totalBytes;
float m_maxRangeStat;
float m_maxAltitudeStat;
float m_maxRateState;
qint64 m_dfStats[32];
qint64 m_tcStats[32];
QChart *m_chart;
QLineSeries *m_adsbFrameRateSeries;
QLineSeries *m_modesFrameRateSeries;
QLineSeries *m_aircraftSeries;
QDateTimeAxis *m_xAxis;
QValueAxis *m_fpsYAxis;
QValueAxis *m_aircraftYAxis;
QDateTime m_averageTime;
#ifdef QT_TEXTTOSPEECH_FOUND
QTextToSpeech *m_speech;
#endif
@ -1338,22 +976,19 @@ private:
static const QString m_flightStatuses[];
static const QString m_hazardSeverity[];
static const QString m_fomSources[];
static const QString m_nacvStrings[];
explicit ADSBDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
virtual ~ADSBDemodGUI();
QString maptilerAPIKey() const;
void blockApplySettings(bool block);
void applySetting(const QString& settingsKey);
void applySettings(const QStringList& settingsKeys, bool force = false);
void applyAllSettings();
void displaySettings(const QStringList& settingsKeys, bool force);
void applySettings(bool force = false);
void displaySettings();
bool handleMessage(const Message& message);
void makeUIConnections();
void updateAbsoluteCenterFrequency();
void updatePosition(Aircraft *aircraft);
bool updateLocalPosition(Aircraft *aircraft, double latitude, double longitude, bool surfacePosition);
void clearFromMap(const QString& name);
void sendToMap(Aircraft *aircraft, QList<SWGSDRangel::SWGMapAnimation *> *animations);
Aircraft *getAircraft(int icao, bool &newAircraft);
@ -1368,24 +1003,10 @@ private:
float correlationOnes,
unsigned crc,
bool updateModel);
void decodeID(const QByteArray& data, QString& emitterCategory, QString& callsign);
void decodeGroundspeed(const QByteArray& data, float& v, float& h);
void decodeAirspeed(const QByteArray& data, bool& tas, int& as, bool& hdgValid, float& hdg);
void decodeVerticalRate(const QByteArray& data, int& verticalRate);
void updateAircraftPosition(Aircraft *aircraft, double latitude, double longitude, const QDateTime& dateTime);
bool validateGlobalPosition(double latitude, double longitude, bool countFailure);
bool validateLocalPosition(double latitude, double longitude, bool surfacePosition, bool countFailure);
bool decodeGlobalPosition(int f, const double cprLat[2], const double cprLong[2], const QDateTime cprTime[2], double& latitude, double& longitude, bool countFailure);
bool decodeLocalPosition(int f, double cprLat, double cprLong, bool onSurface, const Aircraft *aircraft, double& latitude, double& longitude, bool countFailure);
void decodeCpr(const QByteArray& data, int& f, double& latCpr, double& lonCpr) const;
bool decodeAltitude(const QByteArray& data, int& altFt) const;
void decodeModeSAltitude(const QByteArray& data, const QDateTime dateTime, Aircraft *aircraft);
void decodeModeS(const QByteArray data, const QDateTime dateTime, int df, Aircraft *aircraft);
void decodeModeS(const QByteArray data, int df, Aircraft *aircraft);
void decodeCommB(const QByteArray data, const QDateTime dateTime, int df, Aircraft *aircraft, bool &updatedCallsign);
QList<SWGSDRangel::SWGMapAnimation *> *animate(QDateTime dateTime, Aircraft *aircraft);
SWGSDRangel::SWGMapAnimation *gearAnimation(QDateTime startDateTime, bool up);
SWGSDRangel::SWGMapAnimation *gearAngle(QDateTime startDateTime, bool flat);
SWGSDRangel::SWGMapAnimation *flapsAnimation(QDateTime startDateTime, float currentFlaps, float flaps);
SWGSDRangel::SWGMapAnimation *slatsAnimation(QDateTime startDateTime, bool retract);
SWGSDRangel::SWGMapAnimation *rotorAnimation(QDateTime startDateTime, bool stop);
@ -1398,18 +1019,18 @@ private:
QString subAircraftString(Aircraft *aircraft, const QString &string);
void resizeTable();
QString getDataDir();
void readAirportDB(const QString& filename);
void readAirportFrequenciesDB(const QString& filename);
void update3DModels();
void updateAirports();
void updateAirspaces();
void updateNavAids();
void updateChannelList();
void removeAircraft(QHash<int, Aircraft *>::iterator& i, Aircraft *aircraft);
QAction *createCheckableItem(QString& text, int idx, bool checked);
Aircraft* findAircraftByFlight(const QString& flight);
QString dataTimeToShortString(QDateTime dt);
void initFlightInformation();
void initAviationWeather();
void setShowContainmentRadius(bool show);
void applyMapSettings();
void updatePhotoText(Aircraft *aircraft);
void updatePhotoFlightInformation(Aircraft *aircraft);
@ -1421,33 +1042,16 @@ private:
void applyImportSettings();
void sendAircraftReport();
void updatePosition(float latitude, float longitude, float altitude);
void clearOldHeading(Aircraft *aircraft, const QDateTime& dateTime, float newTrack);
void updateQNH(const Aircraft *aircraft, float qnh);
void setCallsign(Aircraft *aircraft, const QString& callsign);
void initCoverageMap();
void clearCoverageMap();
void updateCoverageMap(float azimuth, float elevation, float distance, float altitude);
void leaveEvent(QEvent*);
void enterEvent(EnterEventType*);
void updateDFStats(int df);
bool updateTCStats(int tc, int row, int low, int high);
void resetStats();
void plotChart();
int countActiveAircraft();
void averageSeries(QLineSeries *series, const QDateTime& startTime, const QDateTime& endTime);
void legendMarkerClicked();
private slots:
void on_deltaFrequency_changed(qint64 value);
void on_rfBW_valueChanged(int value);
void on_threshold_valueChanged(int value);
void on_chipsThreshold_valueChanged(int value);
void on_phaseSteps_valueChanged(int value);
void on_tapsPerPhase_valueChanged(int value);
void statsTable_customContextMenuRequested(QPoint pos);
void adsbData_customContextMenuRequested(QPoint point);
void on_adsbData_cellClicked(int row, int column);
void on_adsbData_cellDoubleClicked(int row, int column);
@ -1456,24 +1060,18 @@ private slots:
void columnSelectMenu(QPoint pos);
void columnSelectMenuChecked(bool checked = false);
void on_spb_currentIndexChanged(int value);
void on_correlateFullPreamble_clicked(bool checked);
void on_demodModeS_clicked(bool checked);
void on_feed_clicked(bool checked);
void on_notifications_clicked();
void on_flightInfo_clicked();
void on_findOnMapFeature_clicked();
void on_deleteAircraft_clicked();
void on_getAircraftDB_clicked();
void on_getOSNDB_clicked();
void on_getAirportDB_clicked();
void on_getAirspacesDB_clicked();
void on_coverage_clicked(bool checked);
void on_displayChart_clicked(bool checked);
void on_stats_clicked(bool checked);
void on_flightPaths_clicked(bool checked);
void on_allFlightPaths_clicked(bool checked);
void on_atcLabels_clicked(bool checked);
void on_displayOrientation_clicked(bool checked);
void on_displayRadius_clicked(bool checked);
void on_ic_globalCheckStateChanged(int state);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void handleInputMessages();
@ -1500,12 +1098,6 @@ private slots:
void devicePositionChanged(float latitude, float longitude, float altitude);
void requestMetar(const QString& icao);
void weatherUpdated(const AviationWeather::METAR &metar);
void on_manualQNH_clicked(bool checked);
void on_qnh_valueChanged(int value);
void clearCoverage(const QPoint& p);
void clearStats(const QPoint& p);
void clearChart(const QPoint& p);
void resetChartAxes();
signals:
void homePositionChanged();

File diff suppressed because it is too large Load Diff

View File

@ -3,13 +3,7 @@
<file>icons/aircraft.png</file>
<file>icons/airport.png</file>
<file>icons/controltower.png</file>
<file>icons/coverage.png</file>
<file>icons/allflightpaths.png</file>
<file>icons/vor.png</file>
<file>icons/stats.png</file>
<file>icons/chart.png</file>
<file>icons/horizontal.png</file>
<file>icons/vertical.png</file>
<file>icons/radius.png</file>
</qresource>
</RCC>

View File

@ -5,22 +5,14 @@
<file>map/map_6_strict.qml</file>
<file>map/ModifiedMapView.qml</file>
<file>map/MapStation.qml</file>
<file>map/aircraft_small.png</file>
<file>map/aircraft_large.png</file>
<file>map/aircraft_heavy_2engine.png</file>
<file>map/aircraft_heavy_4engine.png</file>
<file>map/aircraft_2engine.png</file>
<file>map/aircraft_2enginesmall.png</file>
<file>map/aircraft_4engine.png</file>
<file>map/aircraft_helicopter.png</file>
<file>map/aircraft_light.png</file>
<file>map/aircraft_space.png</file>
<file>map/aircraft_drone.png</file>
<file>map/aircraft_fighter.png</file>
<file>map/aircraft_glider.png</file>
<file>map/spitfire.png</file>
<file>map/a400m.png</file>
<file>map/f35.png</file>
<file>map/apache.png</file>
<file>map/chinook.png</file>
<file>map/eurofighter.png</file>
<file>map/airport_large.png</file>
<file>map/airport_medium.png</file>
<file>map/airport_small.png</file>

View File

@ -25,7 +25,7 @@
// Map main ADS-B table column numbers to combo box indices
std::vector<int> ADSBDemodNotificationDialog::m_columnMap = {
ADSB_COL_ICAO, ADSB_COL_CALLSIGN, ADSB_COL_MODEL, ADSB_COL_TYPE,
ADSB_COL_ICAO, ADSB_COL_CALLSIGN, ADSB_COL_MODEL,
ADSB_COL_ALTITUDE, ADSB_COL_GROUND_SPEED, ADSB_COL_RANGE,
ADSB_COL_CATEGORY, ADSB_COL_STATUS, ADSB_COL_SQUAWK,
ADSB_COL_REGISTRATION, ADSB_COL_MANUFACTURER, ADSB_COL_OWNER, ADSB_COL_OPERATOR_ICAO
@ -117,7 +117,6 @@ void ADSBDemodNotificationDialog::addRow(ADSBDemodSettings::NotificationSettings
match->addItem("ICAO ID");
match->addItem("Callsign");
match->addItem("Aircraft");
match->addItem("Type");
match->addItem("Alt (ft)");
match->addItem("GS (kn)");
match->addItem("D (km)");

View File

@ -36,8 +36,7 @@ void ADSBDemodSettings::resetToDefaults()
{
m_inputFrequencyOffset = 0;
m_rfBandwidth = 2*1300000;
m_correlationThreshold = 7.0f; //<! ones/zero powers correlation threshold in dB
m_chipsThreshold = 0;
m_correlationThreshold = 10.0f; //<! ones/zero powers correlation threshold in dB
m_samplesPerBit = 4;
m_removeTimeout = 60;
m_feedEnabled = false;
@ -74,13 +73,13 @@ void ADSBDemodSettings::resetToDefaults()
m_tableFontName = "Liberation Sans";
m_tableFontSize = 9;
m_displayDemodStats = false;
m_correlateFullPreamble = true;
m_demodModeS = true;
m_autoResizeTableColumns = false;
m_interpolatorPhaseSteps = 4; // Higher than these two values will struggle to run in real-time
m_interpolatorTapsPerPhase = 3.5f; // without gaining much improvement in PER
m_aviationstackAPIKey = "";
m_checkWXAPIKey = "";
m_maptilerAPIKey = "";
for (int i = 0; i < ADSBDEMOD_COLUMNS; i++)
{
m_columnIndexes[i] = i;
@ -99,24 +98,13 @@ void ADSBDemodSettings::resetToDefaults()
m_displayNavAids = true;
m_displayPhotos = true;
m_verboseModelMatching = false;
m_airfieldElevation = 0;
m_aircraftMinZoom = 11;
m_workspaceIndex = 0;
m_hidden = false;
m_atcLabels = true;
m_atcCallsigns = true;
m_transitionAlt = 6000; // Depends on airport. 18,000 in USA
m_qnh = 1013.25;
m_manualQNH = false;
m_displayCoverage = false;
m_displayChart = false;
m_displayOrientation = false;
m_displayRadius = false;
for (int i = 0; i < ADSB_IC_MAX; i++) {
m_displayIC[i] = false;
}
m_flightPathPaletteName = "Spectral";
applyPalette();
m_favourLivery = true;
}
QByteArray ADSBDemodSettings::serialize() const
@ -153,6 +141,7 @@ QByteArray ADSBDemodSettings::serialize() const
s.writeString(25, m_tableFontName);
s.writeS32(26, m_tableFontSize);
s.writeBool(27, m_displayDemodStats);
s.writeBool(28, m_correlateFullPreamble);
s.writeBool(29, m_demodModeS);
s.writeBool(30, m_autoResizeTableColumns);
s.writeS32(31, m_interpolatorPhaseSteps);
@ -176,6 +165,7 @@ QByteArray ADSBDemodSettings::serialize() const
}
s.writeBool(44, m_verboseModelMatching);
s.writeS32(45, m_airfieldElevation);
s.writeBool(46, m_exportClientEnabled);
s.writeBool(47, m_exportServerEnabled);
@ -202,19 +192,6 @@ QByteArray ADSBDemodSettings::serialize() const
s.writeS32(67, m_transitionAlt);
s.writeString(68, m_amDemod);
s.writeFloat(69, m_qnh);
s.writeBool(70, m_manualQNH);
s.writeBool(71, m_displayCoverage);
s.writeBool(72, m_displayChart);
s.writeBool(73, m_displayOrientation);
s.writeBool(74, m_displayRadius);
s.writeString(75, m_flightPathPaletteName);
s.writeS32(76, m_chipsThreshold);
s.writeBool(77, m_favourLivery);
s.writeString(78, m_maptilerAPIKey);
for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) {
s.writeS32(100 + i, m_columnIndexes[i]);
}
@ -252,7 +229,7 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data)
d.readS32(1, &tmp, 0);
m_inputFrequencyOffset = tmp;
d.readReal(2, &m_rfBandwidth, 2*1300000);
d.readReal(3, &m_correlationThreshold, 7.0f);
d.readReal(3, &m_correlationThreshold, 0.0f);
d.readS32(4, &m_samplesPerBit, 4);
d.readS32(5, &m_removeTimeout, 60);
d.readBool(6, &m_feedEnabled, false);
@ -291,6 +268,7 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data)
d.readString(25, &m_tableFontName, "Liberation Sans");
d.readS32(26, &m_tableFontSize, 9);
d.readBool(27, &m_displayDemodStats, false);
d.readBool(28, &m_correlateFullPreamble, true);
d.readBool(29, &m_demodModeS, true);
d.readBool(30, &m_autoResizeTableColumns, false);
d.readS32(31, &m_interpolatorPhaseSteps, 4);
@ -318,6 +296,7 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data)
}
d.readBool(44, &m_verboseModelMatching, false);
d.readS32(45, &m_airfieldElevation, 0);
d.readBool(46, &m_exportClientEnabled, true);
d.readBool(47, &m_exportServerEnabled, true);
@ -349,21 +328,6 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data)
d.readS32(67, &m_transitionAlt, 6000);
d.readString(68, &m_amDemod);
d.readFloat(69, &m_qnh, 1013.25);
d.readBool(70, &m_manualQNH, false);
d.readBool(71, &m_displayCoverage, false);
d.readBool(72, &m_displayChart, false);
d.readBool(73, &m_displayOrientation, false);
d.readBool(74, &m_displayRadius, false);
d.readString(75, &m_flightPathPaletteName, "Spectral");
d.readS32(76, &m_chipsThreshold, 0);
d.readBool(77, &m_favourLivery, true);
d.readString(78, &m_maptilerAPIKey, "");
applyPalette();
#ifdef LINUX
if (m_mapProvider == "osm") {
m_mapProvider = "mapboxgl";
@ -437,509 +401,3 @@ void ADSBDemodSettings::NotificationSettings::updateRegularExpression()
qDebug() << "ADSBDemod: Regular expression is not valid: " << m_regExp;
}
}
void ADSBDemodSettings::applySettings(const QStringList& settingsKeys, const ADSBDemodSettings& settings)
{
if (settingsKeys.contains("inputFrequencyOffset")) {
m_inputFrequencyOffset = settings.m_inputFrequencyOffset;
}
if (settingsKeys.contains("rfBandwidth")) {
m_rfBandwidth = settings.m_rfBandwidth;
}
if (settingsKeys.contains("correlationThreshold")) {
m_correlationThreshold = settings.m_correlationThreshold;
}
if (settingsKeys.contains("chipsThreshold")) {
m_chipsThreshold = settings.m_chipsThreshold;
}
if (settingsKeys.contains("samplesPerBit")) {
m_samplesPerBit = settings.m_samplesPerBit;
}
if (settingsKeys.contains("removeTimeout")) {
m_removeTimeout = settings.m_removeTimeout;
}
if (settingsKeys.contains("feedEnabled")) {
m_feedEnabled = settings.m_feedEnabled;
}
if (settingsKeys.contains("exportClientEnabled")) {
m_exportClientEnabled = settings.m_exportClientEnabled;
}
if (settingsKeys.contains("exportClientHost")) {
m_exportClientHost = settings.m_exportClientHost;
}
if (settingsKeys.contains("exportClientPort")) {
m_exportClientPort = settings.m_exportClientPort;
}
if (settingsKeys.contains("exportClientFormat")) {
m_exportClientFormat = settings.m_exportClientFormat;
}
if (settingsKeys.contains("exportServerEnabled")) {
m_exportServerEnabled = settings.m_exportServerEnabled;
}
if (settingsKeys.contains("exportServerPort")) {
m_exportServerPort = settings.m_exportServerPort;
}
if (settingsKeys.contains("importEnabled")) {
m_importEnabled = settings.m_importEnabled;
}
if (settingsKeys.contains("importHost")) {
m_importHost = settings.m_importHost;
}
if (settingsKeys.contains("importUsername")) {
m_importUsername = settings.m_importUsername;
}
if (settingsKeys.contains("importPassword")) {
m_importPassword = settings.m_importPassword;
}
if (settingsKeys.contains("importParameters")) {
m_importParameters = settings.m_importParameters;
}
if (settingsKeys.contains("importPeriod")) {
m_importPeriod = settings.m_importPeriod;
}
if (settingsKeys.contains("importMinLatitude")) {
m_importMinLatitude = settings.m_importMinLatitude;
}
if (settingsKeys.contains("importMaxLatitude")) {
m_importMaxLatitude = settings.m_importMaxLatitude;
}
if (settingsKeys.contains("importMinLongitude")) {
m_importMinLongitude = settings.m_importMinLongitude;
}
if (settingsKeys.contains("importMaxLongitude")) {
m_importMaxLongitude = settings.m_importMaxLongitude;
}
if (settingsKeys.contains("rgbColor")) {
m_rgbColor = settings.m_rgbColor;
}
if (settingsKeys.contains("title")) {
m_title = settings.m_title;
}
if (settingsKeys.contains("useReverseAPI")) {
m_useReverseAPI = settings.m_useReverseAPI;
}
if (settingsKeys.contains("reverseAPIAddress")) {
m_reverseAPIAddress = settings.m_reverseAPIAddress;
}
if (settingsKeys.contains("reverseAPIPort")) {
m_reverseAPIPort = settings.m_reverseAPIPort;
}
if (settingsKeys.contains("reverseAPIDeviceIndex")) {
m_reverseAPIDeviceIndex = settings.m_reverseAPIDeviceIndex;
}
if (settingsKeys.contains("columnIndexes")) {
std::copy(std::begin(settings.m_columnIndexes), std::end(settings.m_columnIndexes), std::begin(m_columnIndexes));
}
if (settingsKeys.contains("columnSizes")) {
std::copy(std::begin(settings.m_columnSizes), std::end(settings.m_columnIndexes), std::begin(m_columnSizes));
}
if (settingsKeys.contains("airportRange")) {
m_airportRange = settings.m_airportRange;
}
if (settingsKeys.contains("airportMinimumSize")) {
m_airportMinimumSize = settings.m_airportMinimumSize;
}
if (settingsKeys.contains("displayHeliports")) {
m_displayHeliports = settings.m_displayHeliports;
}
if (settingsKeys.contains("flightPaths")) {
m_flightPaths = settings.m_flightPaths;
}
if (settingsKeys.contains("allFlightPaths")) {
m_allFlightPaths = settings.m_allFlightPaths;
}
if (settingsKeys.contains("siUnits")) {
m_siUnits = settings.m_siUnits;
}
if (settingsKeys.contains("tableFontName")) {
m_tableFontName = settings.m_tableFontName;
}
if (settingsKeys.contains("tableFontSize")) {
m_tableFontSize = settings.m_tableFontSize;
}
if (settingsKeys.contains("displayDemodStats")) {
m_displayDemodStats = settings.m_displayDemodStats;
}
if (settingsKeys.contains("demodModeS")) {
m_demodModeS = settings.m_demodModeS;
}
if (settingsKeys.contains("amDemod")) {
m_amDemod = settings.m_amDemod;
}
if (settingsKeys.contains("autoResizeTableColumns")) {
m_autoResizeTableColumns = settings.m_autoResizeTableColumns;
}
if (settingsKeys.contains("interpolatorPhaseSteps")) {
m_interpolatorPhaseSteps = settings.m_interpolatorPhaseSteps;
}
if (settingsKeys.contains("interpolatorTapsPerPhase")) {
m_interpolatorTapsPerPhase = settings.m_interpolatorTapsPerPhase;
}
if (settingsKeys.contains("notificationSettings")) {
m_notificationSettings = settings.m_notificationSettings;
}
if (settingsKeys.contains("aviationstackAPIKey")) {
m_aviationstackAPIKey = settings.m_aviationstackAPIKey;
}
if (settingsKeys.contains("checkWXAPIKey")) {
m_checkWXAPIKey = settings.m_checkWXAPIKey;
}
if (settingsKeys.contains("maptilerAPIKey")) {
m_maptilerAPIKey = settings.m_maptilerAPIKey;
}
if (settingsKeys.contains("logFilename")) {
m_logFilename = settings.m_logFilename;
}
if (settingsKeys.contains("logEnabled")) {
m_logEnabled = settings.m_logEnabled;
}
if (settingsKeys.contains("airspaces")) {
m_airspaces = settings.m_airspaces;
}
if (settingsKeys.contains("airspaceRange")) {
m_airspaceRange = settings.m_airspaceRange;
}
if (settingsKeys.contains("mapProvider")) {
m_mapProvider = settings.m_mapProvider;
}
if (settingsKeys.contains("mapType")) {
m_mapType = settings.m_mapType;
}
if (settingsKeys.contains("displayNavAids")) {
m_displayNavAids = settings.m_displayNavAids;
}
if (settingsKeys.contains("displayPhotos")) {
m_displayPhotos = settings.m_displayPhotos;
}
if (settingsKeys.contains("verboseModelMatching")) {
m_verboseModelMatching = settings.m_verboseModelMatching;
}
if (settingsKeys.contains("aircraftMinZoom")) {
m_aircraftMinZoom = settings.m_aircraftMinZoom;
}
if (settingsKeys.contains("atcLabels")) {
m_atcLabels = settings.m_atcLabels;
}
if (settingsKeys.contains("atcCallsigns")) {
m_atcCallsigns = settings.m_atcCallsigns;
}
if (settingsKeys.contains("transitionAlt")) {
m_transitionAlt = settings.m_transitionAlt;
}
if (settingsKeys.contains("qnh")) {
m_qnh = settings.m_qnh;
}
if (settingsKeys.contains("manualQNH")) {
m_manualQNH = settings.m_manualQNH;
}
if (settingsKeys.contains("displayCoverage")) {
m_displayCoverage = settings.m_displayCoverage;
}
if (settingsKeys.contains("displayChart")) {
m_displayChart = settings.m_displayChart;
}
if (settingsKeys.contains("displayOrientation")) {
m_displayOrientation = settings.m_displayOrientation;
}
if (settingsKeys.contains("displayRadius")) {
m_displayRadius = settings.m_displayRadius;
}
if (settingsKeys.contains("flightPathPaletteName"))
{
m_flightPathPaletteName = settings.m_flightPathPaletteName;
applyPalette();
}
if (settingsKeys.contains("favourLivery")) {
m_favourLivery = settings.m_favourLivery;
}
}
QString ADSBDemodSettings::getDebugString(const QStringList& settingsKeys, bool force) const
{
std::ostringstream ostr;
if (settingsKeys.contains("inputFrequencyOffset") || force) {
ostr << " m_inputFrequencyOffset: " << m_inputFrequencyOffset;
}
if (settingsKeys.contains("rfBandwidth") || force) {
ostr << " m_rfBandwidth: " << m_rfBandwidth;
}
if (settingsKeys.contains("correlationThreshold") || force) {
ostr << " m_correlationThreshold: " << m_correlationThreshold;
}
if (settingsKeys.contains("chipsThreshold") || force) {
ostr << " m_chipsThreshold: " << m_chipsThreshold;
}
if (settingsKeys.contains("samplesPerBit") || force) {
ostr << " m_samplesPerBit: " << m_samplesPerBit;
}
if (settingsKeys.contains("removeTimeout") || force) {
ostr << " m_removeTimeout: " << m_removeTimeout;
}
if (settingsKeys.contains("feedEnabled") || force) {
ostr << " m_feedEnabled: " << m_feedEnabled;
}
if (settingsKeys.contains("exportClientEnabled") || force) {
ostr << " m_exportClientEnabled: " << m_exportClientEnabled;
}
if (settingsKeys.contains("exportClientHost") || force) {
ostr << " m_exportClientHost: " << m_exportClientHost.toStdString();
}
if (settingsKeys.contains("exportClientPort") || force) {
ostr << " m_exportClientPort: " << m_exportClientPort;
}
if (settingsKeys.contains("exportClientFormat") || force) {
ostr << " m_exportClientFormat: " << m_exportClientFormat;
}
if (settingsKeys.contains("exportServerEnabled") || force) {
ostr << " m_exportServerEnabled: " << m_exportServerEnabled;
}
if (settingsKeys.contains("exportServerPort") || force) {
ostr << " m_exportServerPort: " << m_exportServerPort;
}
if (settingsKeys.contains("importEnabled") || force) {
ostr << " m_importEnabled: " << m_importEnabled;
}
if (settingsKeys.contains("importHost") || force) {
ostr << " m_importHost: " << m_importHost.toStdString();
}
if (settingsKeys.contains("importUsername") || force) {
ostr << " m_importUsername: " << m_importUsername.toStdString();
}
if (settingsKeys.contains("importPassword") || force) {
ostr << " m_importPassword: " << m_importPassword.toStdString();
}
if (settingsKeys.contains("importParameters") || force) {
ostr << " m_importParameters: " << m_importParameters.toStdString();
}
if (settingsKeys.contains("importPeriod") || force) {
ostr << " m_importPeriod: " << m_importPeriod;
}
if (settingsKeys.contains("importMinLatitude") || force) {
ostr << " m_importMinLatitude: " << m_importMinLatitude.toStdString();
}
if (settingsKeys.contains("importMaxLatitude") || force) {
ostr << " m_importMaxLatitude: " << m_importMaxLatitude.toStdString();
}
if (settingsKeys.contains("importMinLongitude") || force) {
ostr << " m_importMinLongitude: " << m_importMinLongitude.toStdString();
}
if (settingsKeys.contains("importMaxLongitude") || force) {
ostr << " m_importMaxLongitude: " << m_importMaxLongitude.toStdString();
}
if (settingsKeys.contains("title") || force) {
ostr << " m_title: " << m_title.toStdString();
}
if (settingsKeys.contains("useReverseAPI") || force) {
ostr << " m_useReverseAPI: " << m_useReverseAPI;
}
if (settingsKeys.contains("reverseAPIAddress") || force) {
ostr << " m_reverseAPIAddress: " << m_reverseAPIAddress.toStdString();
}
if (settingsKeys.contains("reverseAPIPort") || force) {
ostr << " m_reverseAPIPort: " << m_reverseAPIPort;
}
if (settingsKeys.contains("reverseAPIDeviceIndex") || force) {
ostr << " m_reverseAPIDeviceIndex: " << m_reverseAPIDeviceIndex;
}
if (settingsKeys.contains("airportRange") || force) {
ostr << " m_airportRange: " << m_airportRange;
}
if (settingsKeys.contains("airportMinimumSize") || force) {
ostr << " m_airportMinimumSize: " << m_airportMinimumSize;
}
if (settingsKeys.contains("displayHeliports") || force) {
ostr << " m_displayHeliports: " << m_displayHeliports;
}
if (settingsKeys.contains("flightPaths") || force) {
ostr << " m_flightPaths: " << m_flightPaths;
}
if (settingsKeys.contains("allFlightPaths") || force) {
ostr << " m_allFlightPaths: " << m_allFlightPaths;
}
if (settingsKeys.contains("siUnits") || force) {
ostr << " m_siUnits: " << m_siUnits;
}
if (settingsKeys.contains("tableFontName") || force) {
ostr << " m_tableFontName: " << m_tableFontName.toStdString();
}
if (settingsKeys.contains("tableFontSize") || force) {
ostr << " m_tableFontSize: " << m_tableFontSize;
}
if (settingsKeys.contains("displayDemodStats") || force) {
ostr << " m_displayDemodStats: " << m_displayDemodStats;
}
if (settingsKeys.contains("demodModeS") || force) {
ostr << " m_demodModeS: " << m_demodModeS;
}
if (settingsKeys.contains("amDemod") || force) {
ostr << " m_amDemod: " << m_amDemod.toStdString();
}
if (settingsKeys.contains("autoResizeTableColumns") || force) {
ostr << " m_autoResizeTableColumns: " << m_autoResizeTableColumns;
}
if (settingsKeys.contains("interpolatorPhaseSteps") || force) {
ostr << " m_interpolatorPhaseSteps: " << m_interpolatorPhaseSteps;
}
if (settingsKeys.contains("notificationSettings") || force) {
//ostr << " m_notificationSettings: " << m_notificationSettings.join(",").toStdString();
}
if (settingsKeys.contains("aviationstackAPIKey") || force) {
ostr << " m_aviationstackAPIKey: " << m_aviationstackAPIKey.toStdString();
}
if (settingsKeys.contains("checkWXAPIKey") || force) {
ostr << " m_checkWXAPIKey: " << m_checkWXAPIKey.toStdString();
}
if (settingsKeys.contains("maptilerAPIKey") || force) {
ostr << " m_maptilerAPIKey: " << m_maptilerAPIKey.toStdString();
}
if (settingsKeys.contains("logFilename") || force) {
ostr << " m_logFilename: " << m_logFilename.toStdString();
}
if (settingsKeys.contains("logEnabled") || force) {
ostr << " m_logEnabled: " << m_logEnabled;
}
if (settingsKeys.contains("airspaces") || force) {
ostr << " m_airspaces: " << m_airspaces.join(",").toStdString();
}
if (settingsKeys.contains("airspaceRange") || force) {
ostr << " m_airspaceRange: " << m_airspaceRange;
}
if (settingsKeys.contains("mapProvider") || force) {
ostr << " m_mapProvider: " << m_mapProvider.toStdString();
}
if (settingsKeys.contains("mapType") || force) {
ostr << " m_mapType: " << m_mapType;
}
if (settingsKeys.contains("displayNavAids") || force) {
ostr << " m_displayNavAids: " << m_displayNavAids;
}
if (settingsKeys.contains("displayPhotos") || force) {
ostr << " m_displayPhotos: " << m_displayPhotos;
}
if (settingsKeys.contains("verboseModelMatching") || force) {
ostr << " m_verboseModelMatching: " << m_verboseModelMatching;
}
if (settingsKeys.contains("aircraftMinZoom") || force) {
ostr << " m_aircraftMinZoom: " << m_aircraftMinZoom;
}
if (settingsKeys.contains("atcLabels") || force) {
ostr << " m_atcLabels: " << m_atcLabels;
}
if (settingsKeys.contains("atcCallsigns") || force) {
ostr << " m_atcCallsigns: " << m_atcCallsigns;
}
if (settingsKeys.contains("transitionAlt") || force) {
ostr << " m_transitionAlt: " << m_transitionAlt;
}
if (settingsKeys.contains("qnh") || force) {
ostr << " m_qnh: " << m_qnh;
}
if (settingsKeys.contains("manualQNH") || force) {
ostr << " m_manualQNH: " << m_manualQNH;
}
if (settingsKeys.contains("displayCoverage") || force) {
ostr << " m_displayCoverage: " << m_displayCoverage;
}
if (settingsKeys.contains("displayChart") || force) {
ostr << " m_displayChart: " << m_displayChart;
}
if (settingsKeys.contains("displayOrientation") || force) {
ostr << " m_displayOrientation: " << m_displayOrientation;
}
if (settingsKeys.contains("displayRadius") || force) {
ostr << " m_displayRadius: " << m_displayRadius;
}
if (settingsKeys.contains("flightPathPaletteName") || force) {
ostr << " m_flightPathPaletteName: " << m_flightPathPaletteName.toStdString();
}
if (settingsKeys.contains("favourLivery") || force) {
ostr << " m_favourLivery: " << m_favourLivery;
}
return QString(ostr.str().c_str());
}
void ADSBDemodSettings::applyPalette()
{
if (m_palettes.contains(m_flightPathPaletteName)) {
m_flightPathPalette = m_palettes.value(m_flightPathPaletteName);
} else {
m_flightPathPalette = m_rainbowPalette;
}
}
const QVariant ADSBDemodSettings::m_rainbowPalette[8] = {
QVariant(QColor(0xff, 0x00, 0x00)),
QVariant(QColor(0xff, 0x7f, 0x00)),
QVariant(QColor(0xff, 0xff, 0x00)),
QVariant(QColor(0xf7, 0xff, 0x00)),
QVariant(QColor(0x00, 0xff, 0x00)),
QVariant(QColor(0x00, 0xff, 0x7f)),
QVariant(QColor(0x00, 0xff, 0xff)),
QVariant(QColor(0x00, 0x7f, 0xff)),
};
const QVariant ADSBDemodSettings::m_pastelPalette[8] = {
QVariant(QColor(0xff, 0xad, 0xad)),
QVariant(QColor(0xff, 0xd6, 0xa5)),
QVariant(QColor(0xfd, 0xff, 0xb6)),
QVariant(QColor(0xca, 0xff, 0xbf)),
QVariant(QColor(0x9b, 0xf6, 0xff)),
QVariant(QColor(0xa0, 0xc4, 0xff)),
QVariant(QColor(0xbd, 0xb2, 0xff)),
QVariant(QColor(0xff, 0xc6, 0xff)),
};
const QVariant ADSBDemodSettings::m_spectralPalette[8] = {
QVariant(QColor(0xd5, 0x3e, 0x4f)),
QVariant(QColor(0xf4, 0x6d, 0x43)),
QVariant(QColor(0xfd, 0xae, 0x61)),
QVariant(QColor(0xfe, 0xe0, 0x8b)),
QVariant(QColor(0xe6, 0xf5, 0x98)),
QVariant(QColor(0xab, 0xdd, 0xa4)),
QVariant(QColor(0x66, 0xc2, 0xa5)),
QVariant(QColor(0x32, 0x88, 0xbd)),
};
const QVariant ADSBDemodSettings::m_bluePalette[8] = {
QVariant(QColor(0xde, 0xeb, 0xf7)),
QVariant(QColor(0xc6, 0xdb, 0xef)),
QVariant(QColor(0x9e, 0xca, 0xe1)),
QVariant(QColor(0x6b, 0xae, 0xd6)),
QVariant(QColor(0x42, 0x92, 0xc6)),
QVariant(QColor(0x21, 0x71, 0xb5)),
QVariant(QColor(0x08, 0x51, 0x9c)),
QVariant(QColor(0x08, 0x30, 0x6b)),
};
const QVariant ADSBDemodSettings::m_purplePalette[8] = {
QVariant(QColor(0xcc, 0xaf, 0xf2)),
QVariant(QColor(0xb6, 0x99, 0xe0)),
QVariant(QColor(0xa0, 0x84, 0xcf)),
QVariant(QColor(0x8a, 0x6f, 0xbd)),
QVariant(QColor(0x76, 0x5a, 0xac)),
QVariant(QColor(0x62, 0x45, 0x9a)),
QVariant(QColor(0x4f, 0x30, 0x89)),
QVariant(QColor(0x3e, 0x18, 0x78)),
};
const QVariant ADSBDemodSettings::m_greyPalette[8] = {
QVariant(QColor(0x80, 0x80, 0x80)),
QVariant(QColor(0x80, 0x80, 0x80)),
QVariant(QColor(0x80, 0x80, 0x80)),
QVariant(QColor(0x80, 0x80, 0x80)),
QVariant(QColor(0x80, 0x80, 0x80)),
QVariant(QColor(0x80, 0x80, 0x80)),
QVariant(QColor(0x80, 0x80, 0x80)),
QVariant(QColor(0x80, 0x80, 0x80)),
};
const QHash<QString, const QVariant *> ADSBDemodSettings::m_palettes = {
{"Rainbow", &ADSBDemodSettings::m_rainbowPalette[0]},
{"Pastel", &ADSBDemodSettings::m_pastelPalette[0]},
{"Spectral", &ADSBDemodSettings::m_spectralPalette[0]},
{"Blues", &ADSBDemodSettings::m_bluePalette[0]},
{"Purples", &ADSBDemodSettings::m_purplePalette[0]},
{"Grey", &ADSBDemodSettings::m_greyPalette[0]},
};

View File

@ -29,89 +29,63 @@
class Serializable;
// Number of columns in the table
#define ADSBDEMOD_COLUMNS 78
#define ADSBDEMOD_COLUMNS 54
// ADS-B table columns
#define ADSB_COL_ICAO 0
#define ADSB_COL_CALLSIGN 1
#define ADSB_COL_ATC_CALLSIGN 2
#define ADSB_COL_MODEL 3
#define ADSB_COL_TYPE 4
#define ADSB_COL_SIDEVIEW 5
#define ADSB_COL_AIRLINE 6
#define ADSB_COL_COUNTRY 7
#define ADSB_COL_GROUND_SPEED 8
#define ADSB_COL_TRUE_AIRSPEED 9
#define ADSB_COL_INDICATED_AIRSPEED 10
#define ADSB_COL_MACH 11
#define ADSB_COL_SEL_ALTITUDE 12
#define ADSB_COL_ALTITUDE 13
#define ADSB_COL_VERTICALRATE 14
#define ADSB_COL_SEL_HEADING 15
#define ADSB_COL_HEADING 16
#define ADSB_COL_TRACK 17
#define ADSB_COL_TURNRATE 18
#define ADSB_COL_ROLL 19
#define ADSB_COL_RANGE 20
#define ADSB_COL_AZEL 21
#define ADSB_COL_CATEGORY 22
#define ADSB_COL_STATUS 23
#define ADSB_COL_SQUAWK 24
#define ADSB_COL_IDENT 25
#define ADSB_COL_REGISTRATION 26
#define ADSB_COL_REGISTERED 27
#define ADSB_COL_MANUFACTURER 28
#define ADSB_COL_OWNER 29
#define ADSB_COL_OPERATOR_ICAO 30
#define ADSB_COL_AP 31
#define ADSB_COL_V_MODE 32
#define ADSB_COL_L_MODE 33
#define ADSB_COL_TCAS 34
#define ADSB_COL_ACAS 35
#define ADSB_COL_RA 36
#define ADSB_COL_MAX_SPEED 37
#define ADSB_COL_VERSION 38
#define ADSB_COL_LENGTH 39
#define ADSB_COL_WIDTH 40
#define ADSB_COL_BARO 41
#define ADSB_COL_HEADWIND 42
#define ADSB_COL_EST_AIR_TEMP 43
#define ADSB_COL_WIND_SPEED 44
#define ADSB_COL_WIND_DIR 45
#define ADSB_COL_STATIC_PRESSURE 46
#define ADSB_COL_STATIC_AIR_TEMP 47
#define ADSB_COL_HUMIDITY 48
#define ADSB_COL_LATITUDE 49
#define ADSB_COL_LONGITUDE 50
#define ADSB_COL_IC 51
#define ADSB_COL_TIME 52
#define ADSB_COL_FRAMECOUNT 53
#define ADSB_COL_ADSB_FRAMECOUNT 54
#define ADSB_COL_MODES_FRAMECOUNT 55
#define ADSB_COL_NON_TRANSPONDER 56
#define ADSB_COL_TIS_B_FRAMECOUNT 57
#define ADSB_COL_ADSR_FRAMECOUNT 58
#define ADSB_COL_RADIUS 59
#define ADSB_COL_NACP 60
#define ADSB_COL_NACV 61
#define ADSB_COL_GVA 62
#define ADSB_COL_NIC 63
#define ADSB_COL_NIC_BARO 64
#define ADSB_COL_SIL 65
#define ADSB_COL_CORRELATION 66
#define ADSB_COL_RSSI 67
#define ADSB_COL_FLIGHT_STATUS 68
#define ADSB_COL_DEP 69
#define ADSB_COL_ARR 70
#define ADSB_COL_STOPS 71
#define ADSB_COL_STD 72
#define ADSB_COL_ETD 73
#define ADSB_COL_ATD 74
#define ADSB_COL_STA 75
#define ADSB_COL_ETA 76
#define ADSB_COL_ATA 77
#define ADSB_IC_MAX 63
#define ADSB_COL_AIRLINE 4
#define ADSB_COL_COUNTRY 5
#define ADSB_COL_GROUND_SPEED 6
#define ADSB_COL_TRUE_AIRSPEED 7
#define ADSB_COL_INDICATED_AIRSPEED 8
#define ADSB_COL_MACH 9
#define ADSB_COL_SEL_ALTITUDE 10
#define ADSB_COL_ALTITUDE 11
#define ADSB_COL_VERTICALRATE 12
#define ADSB_COL_SEL_HEADING 13
#define ADSB_COL_HEADING 14
#define ADSB_COL_TURNRATE 15
#define ADSB_COL_ROLL 16
#define ADSB_COL_RANGE 17
#define ADSB_COL_AZEL 18
#define ADSB_COL_CATEGORY 19
#define ADSB_COL_STATUS 20
#define ADSB_COL_SQUAWK 21
#define ADSB_COL_REGISTRATION 22
#define ADSB_COL_REGISTERED 23
#define ADSB_COL_MANUFACTURER 24
#define ADSB_COL_OWNER 25
#define ADSB_COL_OPERATOR_ICAO 26
#define ADSB_COL_AP 27
#define ADSB_COL_V_MODE 28
#define ADSB_COL_L_MODE 29
#define ADSB_COL_BARO 30
#define ADSB_COL_HEADWIND 31
#define ADSB_COL_EST_AIR_TEMP 32
#define ADSB_COL_WIND_SPEED 33
#define ADSB_COL_WIND_DIR 34
#define ADSB_COL_STATIC_PRESSURE 35
#define ADSB_COL_STATIC_AIR_TEMP 36
#define ADSB_COL_HUMIDITY 37
#define ADSB_COL_LATITUDE 38
#define ADSB_COL_LONGITUDE 39
#define ADSB_COL_TIME 40
#define ADSB_COL_FRAMECOUNT 41
#define ADSB_COL_TIS_B 42
#define ADSB_COL_CORRELATION 43
#define ADSB_COL_RSSI 44
#define ADSB_COL_FLIGHT_STATUS 45
#define ADSB_COL_DEP 46
#define ADSB_COL_ARR 47
#define ADSB_COL_STD 48
#define ADSB_COL_ETD 49
#define ADSB_COL_ATD 50
#define ADSB_COL_STA 51
#define ADSB_COL_ETA 52
#define ADSB_COL_ATA 53
struct ADSBDemodSettings
{
@ -130,7 +104,6 @@ struct ADSBDemodSettings
int32_t m_inputFrequencyOffset;
Real m_rfBandwidth;
Real m_correlationThreshold; //!< Correlation power threshold in dB
int m_chipsThreshold; //!< How many chips in preamble can be incorrect for Mode S
int m_samplesPerBit;
int m_removeTimeout; //!< Time in seconds before removing an aircraft, unless a new frame is received
@ -186,6 +159,7 @@ struct ADSBDemodSettings
QString m_tableFontName; //!< Font to use for table
int m_tableFontSize;
bool m_displayDemodStats;
bool m_correlateFullPreamble;
bool m_demodModeS; //!< Demodulate all Mode-S frames, not just ADS-B
QString m_amDemod; //!< AM Demod to tune to selected ATC frequency
bool m_autoResizeTableColumns;
@ -195,7 +169,6 @@ struct ADSBDemodSettings
QList<NotificationSettings *> m_notificationSettings;
QString m_aviationstackAPIKey; //!< aviationstack.com API key
QString m_checkWXAPIKey; //!< checkwxapi.com API key
QString m_maptilerAPIKey; //!< maptiler.com API key (for osm/satellite map)
QString m_logFilename;
bool m_logEnabled;
@ -213,24 +186,13 @@ struct ADSBDemodSettings
bool m_displayPhotos;
Serializable *m_rollupState;
bool m_verboseModelMatching;
int m_airfieldElevation; //!< QFE in ft so aircraft takeoff/land from correct position
int m_aircraftMinZoom;
bool m_atcLabels;
bool m_atcCallsigns;
int m_transitionAlt;
float m_qnh;
bool m_manualQNH;
bool m_displayCoverage;
bool m_displayChart;
bool m_displayOrientation;
bool m_displayRadius;
bool m_displayIC[ADSB_IC_MAX];
QString m_flightPathPaletteName;
bool m_favourLivery; //!< Favour airline livery over aircraft type when exact 3D model isn't available
const QVariant *m_flightPathPalette;
ADSBDemodSettings();
void resetToDefaults();
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
@ -239,18 +201,6 @@ struct ADSBDemodSettings
bool deserialize(const QByteArray& data);
QByteArray serializeNotificationSettings(QList<NotificationSettings *> notificationSettings) const;
void deserializeNotificationSettings(const QByteArray& data, QList<NotificationSettings *>& notificationSettings);
void applySettings(const QStringList& settingsKeys, const ADSBDemodSettings& settings);
QString getDebugString(const QStringList& settingsKeys, bool force = false) const;
void applyPalette();
static const QVariant m_rainbowPalette[8];
static const QVariant m_pastelPalette[8];
static const QVariant m_spectralPalette[8];
static const QVariant m_bluePalette[8];
static const QVariant m_purplePalette[8];
static const QVariant m_greyPalette[8];
static const QHash<QString, const QVariant *> m_palettes;
};
#endif /* PLUGINS_CHANNELRX_DEMODADSB_ADSBDEMODSETTINGS_H_ */

View File

@ -19,16 +19,14 @@
#include <QTime>
#include <QDebug>
#include "util/profiler.h"
#include "adsbdemodsink.h"
#include "adsbdemodsinkworker.h"
#include "adsbdemod.h"
#include "adsb.h"
ADSBDemodSink::ADSBDemodSink() :
m_channelSampleRate(6000000),
m_channelFrequencyOffset(0),
m_feedTime(0.0),
m_sampleBuffer{nullptr, nullptr, nullptr},
m_worker(this),
m_writeBuffer(0),
@ -39,7 +37,7 @@ ADSBDemodSink::ADSBDemodSink() :
m_magsqCount(0),
m_messageQueueToGUI(nullptr)
{
applySettings(m_settings, QStringList(), true);
applySettings(m_settings, true);
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
for (int i = 0; i < m_buffers; i++)
m_bufferWrite[i].release(1);
@ -55,7 +53,7 @@ ADSBDemodSink::~ADSBDemodSink()
void ADSBDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
{
// Start timing how long we are in this function
PROFILER_START();
m_startPoint = boost::chrono::steady_clock::now();
// Optimise for common case, where no resampling or frequency offset
if ((m_interpolatorDistance == 1.0f) && (m_channelFrequencyOffset == 0))
@ -115,7 +113,8 @@ void ADSBDemodSink::feed(const SampleVector::const_iterator& begin, const Sample
}
// Calculate number of seconds in this function
PROFILER_STOP("ADSB feed");
boost::chrono::duration<double> sec = boost::chrono::steady_clock::now() - m_startPoint;
m_feedTime += sec.count();
}
void ADSBDemodSink::processOneSample(Real magsq)
@ -128,17 +127,8 @@ void ADSBDemodSink::processOneSample(Real magsq)
m_writeIdx++;
if (!m_bufferDateTimeValid[m_writeBuffer])
{
QDateTime dateTime = QDateTime::currentDateTime();
if (m_minFirstSampleDateTime.isValid() && (dateTime < m_minFirstSampleDateTime)) {
dateTime = m_minFirstSampleDateTime;
}
m_bufferFirstSampleDateTime[m_writeBuffer] = dateTime;
m_bufferFirstSampleDateTime[m_writeBuffer] = QDateTime::currentDateTime();
m_bufferDateTimeValid[m_writeBuffer] = true;
// Make sure timestamps from different buffers are in order, even if we receive samples faster than real time
const qint64 samplesPerSecondMSec = ADS_B_BITS_PER_SECOND * m_settings.m_samplesPerBit / 1000;
const qint64 offsetMSec = m_bufferSize / samplesPerSecondMSec;
m_minFirstSampleDateTime = dateTime.addMSecs(offsetMSec);
}
if (m_writeIdx >= m_bufferSize)
{
@ -148,9 +138,15 @@ void ADSBDemodSink::processOneSample(Real magsq)
if (m_writeBuffer >= m_buffers)
m_writeBuffer = 0;
// Don't include time spent waiting for a buffer
boost::chrono::duration<double> sec = boost::chrono::steady_clock::now() - m_startPoint;
m_feedTime += sec.count();
if (m_worker.isRunning())
m_bufferWrite[m_writeBuffer].acquire();
m_startPoint = boost::chrono::steady_clock::now();
m_writeIdx = m_samplesPerFrame - 1; // Leave space for copying samples from previous buffer
m_bufferDateTimeValid[m_writeBuffer] = false;
@ -251,46 +247,37 @@ void ADSBDemodSink::applyChannelSettings(int channelSampleRate, int channelFrequ
m_channelFrequencyOffset = channelFrequencyOffset;
}
void ADSBDemodSink::applySettings(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force)
void ADSBDemodSink::applySettings(const ADSBDemodSettings& settings, bool force)
{
qDebug() << "ADSBDemodSink::applySettings:"
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
<< " m_rfBandwidth: " << settings.m_rfBandwidth
<< " m_correlationThreshold: " << settings.m_correlationThreshold
<< " m_correlateFullPreamble: " << settings.m_correlateFullPreamble
<< " m_demodModeS: " << settings.m_demodModeS
<< " m_samplesPerBit: " << settings.m_samplesPerBit
<< " force: " << force;
if ((settingsKeys.contains("rfBandwidth") && (settings.m_rfBandwidth != m_settings.m_rfBandwidth))
|| (settingsKeys.contains("samplesPerBit") && (settings.m_samplesPerBit != m_settings.m_samplesPerBit))
|| (settingsKeys.contains("interpolatorPhaseSteps") && (settings.m_interpolatorPhaseSteps != m_settings.m_interpolatorPhaseSteps))
|| (settingsKeys.contains("interpolatorTapsPerPhase") && (settings.m_interpolatorTapsPerPhase != m_settings.m_interpolatorTapsPerPhase))
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth)
|| (settings.m_samplesPerBit != m_settings.m_samplesPerBit)
|| (settings.m_interpolatorPhaseSteps != m_settings.m_interpolatorPhaseSteps)
|| (settings.m_interpolatorTapsPerPhase != m_settings.m_interpolatorTapsPerPhase)
|| force)
{
m_interpolator.create(m_settings.m_interpolatorPhaseSteps, m_channelSampleRate, settings.m_rfBandwidth / 2.2, m_settings.m_interpolatorTapsPerPhase);
m_interpolatorDistanceRemain = 0;
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) (ADS_B_BITS_PER_SECOND * settings.m_samplesPerBit);
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) (ADS_B_BITS_PER_SECOND * settings.m_samplesPerBit);
}
if ((settingsKeys.contains("samplesPerBit") && (settings.m_samplesPerBit != m_settings.m_samplesPerBit)) || force)
if ((settings.m_samplesPerBit != m_settings.m_samplesPerBit) || force)
{
init(settings.m_samplesPerBit);
}
// Forward to worker
ADSBDemodSinkWorker::MsgConfigureADSBDemodSinkWorker *msg = ADSBDemodSinkWorker::MsgConfigureADSBDemodSinkWorker::create(
settings, settingsKeys, force);
settings, force);
m_worker.getInputMessageQueue()->push(msg);
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
}
void ADSBDemodSink::resetStats()
{
ADSBDemod::MsgResetStats* msg = ADSBDemod::MsgResetStats::create();
m_worker.getInputMessageQueue()->push(msg);
m_settings = settings;
}

View File

@ -19,6 +19,9 @@
#ifndef INCLUDE_ADSBDEMODSINK_H
#define INCLUDE_ADSBDEMODSINK_H
#define BOOST_CHRONO_HEADER_ONLY
#include <boost/chrono/chrono.hpp>
#include "dsp/channelsamplesink.h"
#include "dsp/nco.h"
#include "dsp/interpolator.h"
@ -52,12 +55,11 @@ public:
}
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
void applySettings(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force = false);
void applySettings(const ADSBDemodSettings& settings, bool force = false);
void setMessageQueueToGUI(MessageQueue *messageQueue) { m_messageQueueToGUI = messageQueue; }
void setMessageQueueToWorker(MessageQueue *messageQueue) { m_messageQueueToWorker = messageQueue; }
void startWorker();
void stopWorker();
void resetStats();
private:
friend ADSBDemodSinkWorker;
@ -81,6 +83,9 @@ private:
Real m_interpolatorDistance;
Real m_interpolatorDistanceRemain;
boost::chrono::steady_clock::time_point m_startPoint;
double m_feedTime; //!< Time spent in feed()
// Triple buffering for sharing sample data between two threads
// Top area of each buffer is not used by writer, as it's used by the reader
// for copying the last few samples of the previous buffer, so it can
@ -91,7 +96,6 @@ private:
QSemaphore m_bufferWrite[3]; //!< Semaphore to control write access to the buffers
QSemaphore m_bufferRead[3]; //!< Semaphore to control read access from the buffers
QDateTime m_bufferFirstSampleDateTime[3]; //!< Time for first sample in the buffer
QDateTime m_minFirstSampleDateTime;
bool m_bufferDateTimeValid[3];
ADSBDemodSinkWorker m_worker; //!< Worker thread that does the actual demodulation
int m_writeBuffer; //!< Which of the 3 buffers we're writing in to

View File

@ -15,288 +15,30 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#define BOOST_CHRONO_HEADER_ONLY
#include <boost/chrono/chrono.hpp>
#include <QDebug>
#include "util/db.h"
#include "util/profiler.h"
#include "util/units.h"
#include "util/osndb.h"
#include "util/popcount.h"
#include "adsbdemodreport.h"
#include "adsbdemodsink.h"
#include "adsbdemodsinkworker.h"
#include "adsbdemod.h"
#include "adsbdemodsettings.h"
#include "adsb.h"
MESSAGE_CLASS_DEFINITION(ADSBDemodSinkWorker::MsgConfigureADSBDemodSinkWorker, Message)
const Real ADSBDemodSinkWorker::m_correlationScale = 3.0f;
static int grayToBinary(int gray, int bits)
{
int binary = 0;
for (int i = bits - 1; i >= 0; i--) {
binary = binary | ((((1 << (i+1)) & binary) >> 1) ^ ((1 << i) & gray));
}
return binary;
}
static int gillhamToFeet(int n)
{
int c1 = (n >> 10) & 1;
int a1 = (n >> 9) & 1;
int c2 = (n >> 8) & 1;
int a2 = (n >> 7) & 1;
int c4 = (n >> 6) & 1;
int a4 = (n >> 5) & 1;
int b1 = (n >> 4) & 1;
int b2 = (n >> 3) & 1;
int d2 = (n >> 2) & 1;
int b4 = (n >> 1) & 1;
int d4 = n & 1;
int n500 = grayToBinary((d2 << 7) | (d4 << 6) | (a1 << 5) | (a2 << 4) | (a4 << 3) | (b1 << 2) | (b2 << 1) | b4, 4);
int n100 = grayToBinary((c1 << 2) | (c2 << 1) | c4, 3) - 1;
if (n100 == 6) {
n100 = 4;
}
if (n500 %2 != 0) {
n100 = 4 - n100;
}
return -1200 + n500*500 + n100*100;
}
static int decodeModeSAltitude(const QByteArray& data)
{
int altitude = 0; // Altitude in feet
int altitudeCode = ((data[2] & 0x1f) << 8) | (data[3] & 0xff);
if (altitudeCode & 0x40) // M bit indicates metres
{
int altitudeMetres = ((altitudeCode & 0x1f80) >> 1) | (altitudeCode & 0x3f);
altitude = Units::metresToFeet(altitudeMetres);
}
else
{
// Remove M and Q bits
int altitudeFix = ((altitudeCode & 0x1f80) >> 2) | ((altitudeCode & 0x20) >> 1) | (altitudeCode & 0xf);
// Convert to feet
if (altitudeCode & 0x10) {
altitude = altitudeFix * 25 - 1000;
} else {
altitude = gillhamToFeet(altitudeFix);
}
}
return altitude;
}
void ADSBDemodSinkWorker::handleModeS(unsigned char *data, int bytes, unsigned icao, int df, int firstIndex, unsigned short preamble, Real preambleCorrelation, Real correlationOnes, const QDateTime& dateTime, unsigned crc)
{
// Ignore downlink formats we can't decode / unlikely
if ((df != 19) && (df != 22) && (df < 24))
{
QList<RXRecord> l;
if (m_modeSOnlyIcaos.contains(icao))
{
l = m_modeSOnlyIcaos.value(icao);
if (abs(l.last().m_firstIndex - firstIndex) < 4) {
return; // Duplicate
}
}
else
{
// Stop hash table from getting too big - clear every 10 seconds or so
QDateTime currentDateTime = QDateTime::currentDateTime();
if (m_lastClear.secsTo(currentDateTime) >= 10)
{
//qDebug() << "Clearing ModeS only hash. size=" << m_modeSOnlyIcaos.size();
m_modeSOnlyIcaos.clear();
m_lastClear = currentDateTime;
}
}
RXRecord rx;
rx.m_data = QByteArray((char*)data, bytes);
rx.m_firstIndex = firstIndex;
rx.m_preamble = preamble;
rx.m_preambleCorrelation = preambleCorrelation;
rx.m_correlationOnes = correlationOnes;
rx.m_dateTime = dateTime;
rx.m_crc = crc;
l.append(rx);
m_modeSOnlyIcaos.insert(icao, l);
// Have we heard from the same address several times in the last 10 seconds?
if (l.size() >= 5)
{
// Check all frames have consistent altitudes and identifiers
bool idConsistent = true;
bool altitudeConsistent = true;
int altitude = -1;
int id = -1;
for (int i = 0; i < l.size(); i++)
{
int df2 = ((l[i].m_data[0] >> 3) & ADS_B_DF_MASK);
if ((df2 == 0) || (df2 == 4) || (df2 == 16) || (df2 == 20))
{
int curAltitude = decodeModeSAltitude(l[i].m_data);
if (altitude == -1)
{
altitude = curAltitude;
}
else
{
if (abs(curAltitude - altitude) > 1000) {
altitudeConsistent = false;
}
}
}
else if ((df2 == 5) || (df2 == 21))
{
int curId = ((data[2] & 0x1f) << 8) | (data[3] & 0xff); // No decode - we just want to know if it changes
if (id == -1)
{
id = curId;
}
else
{
if (id != curId) {
idConsistent = false;
}
}
}
}
// FIXME: We could optionally check to see if aircraft ICAO is in db, but the db isn't complete
if (altitudeConsistent && idConsistent)
{
// Forward all frames
for (int i = 0; i < l.size(); i++) {
forwardFrame((const unsigned char *) l[i].m_data.data(), l[i].m_data.size(), l[i].m_preambleCorrelation, l[i].m_correlationOnes, l[i].m_dateTime, l[i].m_crc);
}
m_icaos.insert(icao, l.back().m_dateTime.toMSecsSinceEpoch());
}
else
{
m_modeSOnlyIcaos.remove(icao);
}
}
}
}
// Check if a Mode S frame has reserved bits set or reserved field values
// Refer: Annex 10 Volume IV
bool ADSBDemodSinkWorker::modeSValid(unsigned char *data, unsigned df)
{
bool invalid = false;
if (df == 0)
{
invalid = ((data[0] & 0x1) | (data[1] & 0x18) | (data[2] & 0x60)) != 0;
}
else if ((df == 4) || (df == 20))
{
unsigned fs = data[0] & 0x3;
unsigned dr = (data[1] >> 3) & 0x1f;
invalid = (fs == 6) || (fs == 7) || ((dr >= 8) && (dr <= 15));
}
else if ((df == 5) || (df == 21))
{
unsigned fs = data[0] & 0x3;
unsigned dr = (data[1] >> 3) & 0x1f;
invalid = (fs == 6) || (fs == 7) || ((dr >= 8) && (dr <= 15)) || ((data[3] & 0x40) != 0);
}
else if (df == 11)
{
unsigned ca = data[0] & 0x7;
invalid = ((ca >= 1) && (ca <= 3));
}
else if (df == 16)
{
invalid = ((data[0] & 0x3) | (data[1] & 0x18) | (data[2] & 0x60)) != 0;
}
return invalid;
}
// Check if valid ICAO address - i.e. not a reserved address - see Table 9-1 in Annex X Volume III
bool ADSBDemodSinkWorker::icaoValid(unsigned icao)
{
unsigned msn = (icao >> 20) & 0xf;
return (icao != 0) && (msn != 0xf) && (msn != 0xb) && (msn != 0xd);
}
// Is it less than a minute since the last received frame for this ICAO
bool ADSBDemodSinkWorker::icaoHeardRecently(unsigned icao, const QDateTime &dateTime)
{
const int timeLimitMSec = 60*1000;
if (m_icaos.contains(icao))
{
if ((dateTime.toMSecsSinceEpoch() - m_icaos.value(icao)) < timeLimitMSec) {
return true;
} else {
m_icaos.remove(icao);
}
}
return false;
}
void ADSBDemodSinkWorker::forwardFrame(const unsigned char *data, int size, float preambleCorrelation, float correlationOnes, const QDateTime& dateTime, unsigned crc)
{
// Pass to GUI
if (m_sink->getMessageQueueToGUI())
{
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, size),
preambleCorrelation,
correlationOnes,
dateTime,
crc);
m_sink->getMessageQueueToGUI()->push(msg);
}
// Pass to worker to feed to other servers
if (m_sink->getMessageQueueToWorker())
{
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, size),
preambleCorrelation,
correlationOnes,
dateTime,
crc);
m_sink->getMessageQueueToWorker()->push(msg);
}
}
void ADSBDemodSinkWorker::run()
{
int readBuffer = 0;
m_lastClear = QDateTime::currentDateTime();
// Acquire first buffer
m_sink->m_bufferRead[readBuffer].acquire();
if (isInterruptionRequested()) {
return;
}
// Start recording how much time is spent processing in this method
PROFILER_START();
boost::chrono::steady_clock::time_point startPoint = boost::chrono::steady_clock::now();
// Check for updated settings
handleInputMessages();
@ -310,6 +52,8 @@ void ADSBDemodSinkWorker::run()
<< " samplesPerFrame: " << samplesPerFrame
<< " samplesPerChip: " << samplesPerChip
<< " samplesPerBit: " << samplesPerBit
<< " correlateFullPreamble: " << m_settings.m_correlateFullPreamble
<< " correlationScale: " << m_correlationScale
<< " correlationThreshold: " << m_settings.m_correlationThreshold;
int readIdx = m_sink->m_samplesPerFrame - 1;
@ -320,33 +64,61 @@ void ADSBDemodSinkWorker::run()
// Correlate received signal with expected preamble
// chip+ indexes are 0, 2, 7, 9
// correlating over first 6 bits gives a reduction in per-sample
// processing, but more than doubles the number of false matches
Real preambleCorrelationOnes = 0.0;
Real preambleCorrelationZeros = 0.0;
for (int i = 0; i < samplesPerChip; i++)
if (m_settings.m_correlateFullPreamble)
{
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 0*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 1*samplesPerChip + i];
for (int i = 0; i < samplesPerChip; i++)
{
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 0*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 1*samplesPerChip + i];
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 2*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 3*samplesPerChip + i];
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 2*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 3*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 4*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 5*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 4*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 5*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 6*samplesPerChip + i];
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 7*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 6*samplesPerChip + i];
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 7*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 8*samplesPerChip + i];
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 9*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 8*samplesPerChip + i];
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 9*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 10*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 11*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 10*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 11*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 12*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 13*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 12*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 13*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 14*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 15*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 14*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 15*samplesPerChip + i];
}
}
else
{
for (int i = 0; i < samplesPerChip; i++)
{
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 0*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 1*samplesPerChip + i];
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 2*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 3*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 4*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 5*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 6*samplesPerChip + i];
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 7*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 8*samplesPerChip + i];
preambleCorrelationOnes += m_sink->m_sampleBuffer[readBuffer][startIdx + 9*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 10*samplesPerChip + i];
preambleCorrelationZeros += m_sink->m_sampleBuffer[readBuffer][startIdx + 11*samplesPerChip + i];
}
}
// Use the ratio of ones power over zeros power, as we don't care how powerful the signal
@ -367,7 +139,6 @@ void ADSBDemodSinkWorker::run()
int firstIdx = startIdx;
m_demodStats.m_correlatorMatches++;
// Skip over preamble
startIdx += samplesPerBit*ADS_B_PREAMBLE_BITS;
@ -377,7 +148,6 @@ void ADSBDemodSinkWorker::run()
int currentBit;
unsigned char currentByte = 0;
int df;
int firstIndex = 0;
for (int bit = 0; bit < ADS_B_ES_BITS; bit++)
{
@ -396,9 +166,6 @@ void ADSBDemodSinkWorker::run()
currentByte |= currentBit << (7-(bit & 0x7));
if ((bit & 0x7) == 0x7)
{
if (byteIdx == 0) {
firstIndex = startIdx;
}
data[byteIdx++] = currentByte;
currentByte = 0;
// Don't try to demodulate any further, if this isn't an ADS-B frame
@ -412,10 +179,6 @@ void ADSBDemodSinkWorker::run()
}
}
Real preambleCorrelationScaled = preambleCorrelation * m_correlationScale;
Real correlationOnes = preambleCorrelationOnes / samplesPerChip;
QDateTime dateTime = rxDateTime(firstIdx, readBuffer);
// Is ADS-B?
df = ((data[0] >> 3) & ADS_B_DF_MASK);
if ((df == 17) || (df == 18))
@ -426,177 +189,109 @@ void ADSBDemodSinkWorker::run()
m_crc.calculate(data, ADS_B_ES_BYTES-3);
if (parity == m_crc.get())
{
// Get 24-bit ICAO
// Got a valid frame
m_demodStats.m_adsbFrames++;
// Get 24-bit ICAO and save in hash of ICAOs that have been seen
unsigned icao = ((data[1] & 0xff) << 16) | ((data[2] & 0xff) << 8) | (data[3] & 0xff);
if (icaoValid(icao))
m_icaos.insert(icao, true);
// Don't try to re-demodulate the same frame
// We could possibly allow a partial overlap here
readIdx += (ADS_B_ES_BITS+ADS_B_PREAMBLE_BITS)*ADS_B_CHIPS_PER_BIT*samplesPerChip - 1;
// Pass to GUI
if (m_sink->getMessageQueueToGUI())
{
// Got a valid frame
m_demodStats.m_adsbFrames++;
// Save in hash of ICAOs that have been seen
m_icaos.insert(icao, dateTime.toMSecsSinceEpoch());
// Don't try to re-demodulate the same frame
// We could possibly allow a partial overlap here
readIdx += (ADS_B_ES_BITS+ADS_B_PREAMBLE_BITS)*ADS_B_CHIPS_PER_BIT*samplesPerChip - 1;
forwardFrame(data, sizeof(data), preambleCorrelationScaled, correlationOnes, dateTime, m_crc.get());
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, sizeof(data)),
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip,
rxDateTime(firstIdx, readBuffer),
m_crc.get());
m_sink->getMessageQueueToGUI()->push(msg);
}
else
// Pass to worker to feed to other servers
if (m_sink->getMessageQueueToWorker())
{
m_demodStats.m_icaoFails++;
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, sizeof(data)),
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip,
rxDateTime(firstIdx, readBuffer),
m_crc.get());
m_sink->getMessageQueueToWorker()->push(msg);
}
}
else
{
m_demodStats.m_crcFails++;
}
}
else if (m_settings.m_demodModeS)
{
// Decode premable, as correlation alone results in too many false positives for Mode S frames
startIdx = readIdx;
unsigned short preamble = 0;
QVector<float> preambleChips(16);
int bytes;
for (int bit = 0; bit < ADS_B_PREAMBLE_BITS; bit++)
{
preambleChips[bit*2] = 0.0f;
preambleChips[bit*2+1] = 0.0f;
for (int i = 0; i < samplesPerChip; i++)
{
preambleChips[bit*2] += m_sink->m_sampleBuffer[readBuffer][startIdx+i];
preambleChips[bit*2+1] += m_sink->m_sampleBuffer[readBuffer][startIdx+samplesPerChip+i];
}
startIdx += samplesPerBit;
// Determine number of bytes in frame depending on downlink format
if ((df == 0) || (df == 4) || (df == 5) || (df == 11)) {
bytes = 56/8;
} else if ((df == 16) || (df == 20) || (df == 21) || (df >= 24)) {
bytes = 112/8;
} else {
bytes = 0;
}
startIdx = firstIdx;
float onesAvg = (preambleChips[0] + preambleChips[2] + preambleChips[7] + preambleChips[9]) / 4.0f;
float zerosAvg = (preambleChips[1] + preambleChips[3] + preambleChips[4] + preambleChips[5] + preambleChips[6] + preambleChips[8]
+ preambleChips[10] + + preambleChips[11] + preambleChips[12] + preambleChips[13] + preambleChips[14] + preambleChips[15]) / 12.0f;
float midPoint = zerosAvg + (onesAvg - zerosAvg) / 2.0f;
for (int i = 0; i < 16; i++)
if (bytes > 0)
{
unsigned chip = preambleChips[i] > midPoint;
preamble |= chip << (15-i);
}
// qDebug() << "Preamble" << preambleChips << "zerosAvg" << zerosAvg << "onesAvg" << onesAvg << "midPoint" << midPoint << "chips" << Qt::hex << preamble;
const unsigned short expectedPreamble = 0xa140;
int preambleDifferences = popcount(expectedPreamble ^ preamble);
if (preambleDifferences <= m_settings.m_chipsThreshold)
{
int bytes;
// Determine number of bytes in frame depending on downlink format
if ((df == 0) || (df == 4) || (df == 5) || (df == 11)) {
bytes = 56/8;
} else if ((df == 16) || (df == 19) || (df == 20) || (df == 21) || (df == 22) || ((df >= 24) && (df <= 27))) {
bytes = 112/8;
} else {
bytes = 0;
}
if (bytes > 0)
// Extract received parity
int parity = (data[bytes-3] << 16) | (data[bytes-2] << 8) | data[bytes-1];
// Calculate CRC on received frame
m_crc.init();
m_crc.calculate(data, bytes-3);
int crc = m_crc.get();
// DF4 / DF5 / DF20 / DF21 have ICAO address XORed in to parity.
// Extract ICAO from parity and see if it matches an aircraft we've already
// received an ADS-B frame from
if ((df == 4) || (df == 5) || (df == 20) || (df == 21))
{
bool invalid = modeSValid(data, df);
if (!invalid)
{
// Extract received parity
int parity = (data[bytes-3] << 16) | (data[bytes-2] << 8) | data[bytes-1];
// Calculate CRC on received frame
m_crc.init();
m_crc.calculate(data, bytes-3);
int crc = m_crc.get();
bool forward = false;
// ICAO address XORed in to parity, apart from DF11
// Extract ICAO from parity and see if it matches an aircraft we've already
// received an ADS-B or Mode S frame from
// For DF11, the last 7 bits may have an iterogration code (II/SI)
// XORed in, so we ignore those bits. This does sometimes lead to false-positives
if (df != 11)
{
unsigned icao = (parity ^ crc) & 0xffffff;
if (icaoValid(icao))
{
if (icaoHeardRecently(icao, dateTime)) {
forward = true;
} else {
handleModeS(data, bytes, icao, df, firstIndex, preamble, preambleCorrelationScaled, correlationOnes, dateTime, m_crc.get());
}
}
else
{
m_demodStats.m_icaoFails++;
}
}
else
{
// Ignore IC bits
parity &= 0xffff80;
crc &= 0xffff80;
if (parity == crc)
{
// Get 24-bit ICAO
unsigned icao = ((data[1] & 0xff) << 16) | ((data[2] & 0xff) << 8) | (data[3] & 0xff);
if (icaoValid(icao))
{
if (icaoHeardRecently(icao, dateTime)) {
forward = true;
} else {
handleModeS(data, bytes, icao, df, firstIndex, preamble, preambleCorrelationScaled, correlationOnes, dateTime, m_crc.get());
}
}
else
{
m_demodStats.m_icaoFails++;
}
}
else
{
m_demodStats.m_crcFails++;
}
}
if (forward)
{
m_demodStats.m_modesFrames++;
// Don't try to re-demodulate the same frame
// We could possibly allow a partial overlap here
readIdx += ((bytes*8)+ADS_B_PREAMBLE_BITS)*ADS_B_CHIPS_PER_BIT*samplesPerChip - 1;
forwardFrame(data, bytes, preambleCorrelationScaled, correlationOnes, dateTime, m_crc.get());
}
else
{
m_demodStats.m_crcFails++;
}
unsigned icao = (parity ^ crc) & 0xffffff;
if (m_icaos.contains(icao)) {
crc ^= icao;
}
else
}
// For DF11, the last 7 bits may have an address/interogration identifier (II)
// XORed in, so we ignore those bits
if ((parity == crc) || ((df == 11) && ((parity & 0xffff80) == (crc & 0xffff80))))
{
m_demodStats.m_modesFrames++;
// Pass to GUI (only pass formats it can decode)
if (m_sink->getMessageQueueToGUI() && ((df == 4) || (df == 5) || (df == 20) || (df == 21)))
{
m_demodStats.m_invalidFails++;
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, bytes),
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip,
rxDateTime(firstIdx, readBuffer),
m_crc.get());
m_sink->getMessageQueueToGUI()->push(msg);
}
// Pass to worker to feed to other servers
if (m_sink->getMessageQueueToWorker())
{
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, bytes),
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip,
rxDateTime(firstIdx, readBuffer),
m_crc.get());
m_sink->getMessageQueueToWorker()->push(msg);
}
}
else
{
m_demodStats.m_typeFails++;
m_demodStats.m_crcFails++;
}
}
else
{
m_demodStats.m_preambleFails++;
}
m_demodStats.m_typeFails++;
}
else
{
m_demodStats.m_typeFails++;
}
}
readIdx++;
if (readIdx > m_sink->m_bufferSize - samplesPerFrame)
{
@ -605,7 +300,9 @@ void ADSBDemodSinkWorker::run()
nextBuffer = 0;
// Update amount of time spent processing (don't include time spend in acquire)
PROFILER_STOP("ADS-B demod");
boost::chrono::duration<double> sec = boost::chrono::steady_clock::now() - startPoint;
m_demodStats.m_demodTime += sec.count();
m_demodStats.m_feedTime = m_sink->m_feedTime;
// Send stats to GUI
if (m_sink->getMessageQueueToGUI())
@ -623,7 +320,7 @@ void ADSBDemodSinkWorker::run()
handleInputMessages();
// Resume timing how long we are processing
PROFILER_RESTART();
startPoint = boost::chrono::steady_clock::now();
int samplesRemaining = m_sink->m_bufferSize - readIdx;
if (samplesRemaining > 0)
@ -660,27 +357,24 @@ void ADSBDemodSinkWorker::handleInputMessages()
MsgConfigureADSBDemodSinkWorker* cfg = (MsgConfigureADSBDemodSinkWorker*)message;
ADSBDemodSettings settings = cfg->getSettings();
QStringList settingsKeys = cfg->getSettingsKeys();
bool force = cfg->getForce();
if ((settingsKeys.contains("correlationThreshold") && (m_settings.m_correlationThreshold != settings.m_correlationThreshold)) || force)
if (settings.m_correlateFullPreamble) {
m_correlationScale = 3.0;
} else {
m_correlationScale = 2.0;
}
if ((m_settings.m_correlationThreshold != settings.m_correlationThreshold) || force)
{
m_correlationThresholdLinear = CalcDb::powerFromdB(settings.m_correlationThreshold);
m_correlationThresholdLinear /= m_correlationScale;
qDebug() << "m_correlationThresholdLinear: " << m_correlationThresholdLinear;
}
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
m_settings = settings;
delete message;
}
else if (ADSBDemod::MsgResetStats::match(*message))
{
m_demodStats.reset();
}
}
}

View File

@ -26,9 +26,10 @@
#include "util/message.h"
#include "util/messagequeue.h"
#include "adsbdemodstats.h"
#include "adsbdemodsettings.h"
class ADSBDemodSink;
struct ADSBDemodSettings;
struct ADSBDemodStats;
class ADSBDemodSinkWorker : public QThread {
Q_OBJECT
@ -39,23 +40,20 @@ public:
public:
const ADSBDemodSettings& getSettings() const { return m_settings; }
const QStringList& getSettingsKeys() const { return m_settingsKeys; }
bool getForce() const { return m_force; }
static MsgConfigureADSBDemodSinkWorker* create(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force)
static MsgConfigureADSBDemodSinkWorker* create(const ADSBDemodSettings& settings, bool force)
{
return new MsgConfigureADSBDemodSinkWorker(settings, settingsKeys, force);
return new MsgConfigureADSBDemodSinkWorker(settings, force);
}
private:
ADSBDemodSettings m_settings;
QStringList m_settingsKeys;
bool m_force;
MsgConfigureADSBDemodSinkWorker(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force) :
MsgConfigureADSBDemodSinkWorker(const ADSBDemodSettings& settings, bool force) :
Message(),
m_settings(settings),
m_settingsKeys(settingsKeys),
m_force(force)
{ }
};
@ -77,29 +75,11 @@ private:
ADSBDemodSink *m_sink;
ADSBDemodStats m_demodStats;
Real m_correlationThresholdLinear;
static const Real m_correlationScale;
Real m_correlationScale;
crcadsb m_crc; //!< Have as member to avoid recomputing LUT
QHash<unsigned, qint64> m_icaos; //!< ICAO addresses that have been received and msecsSinceEpoch last heard
QDateTime m_lastClear;
struct RXRecord {
QByteArray m_data;
int m_firstIndex;
unsigned short m_preamble;
Real m_preambleCorrelation;
Real m_correlationOnes;
QDateTime m_dateTime;
unsigned m_crc;
};
QHash<int, QList<RXRecord>> m_modeSOnlyIcaos;
QHash<int, bool> m_icaos; //!< ICAO addresses that have been received
QDateTime rxDateTime(int firstIdx, int readBuffer) const;
void handleModeS(unsigned char *data, int bytes, unsigned icao, int df, int firstIndex, unsigned short preamble, Real preambleCorrelation, Real correlationOnes, const QDateTime& dateTime, unsigned crc);
void forwardFrame(const unsigned char *data, int size, float preambleCorrelation, float correlationOnes, const QDateTime& dateTime, unsigned crc);
bool icaoHeardRecently(unsigned icao, const QDateTime &dateTime);
static bool icaoValid(unsigned icao);
static bool modeSValid(unsigned char *data, unsigned df);
};

View File

@ -25,27 +25,20 @@ struct ADSBDemodStats {
qint64 m_correlatorMatches; //!< Total number of correlator matches
qint64 m_adsbFrames; //!< How many ADS-B frames with correct CRCs
qint64 m_modesFrames; //!< How many non-ADS-B Mode-S frames with correct CRCs
qint64 m_preambleFails; //!< How many non-ADS-B Mode S frames with errors in preamble
qint64 m_crcFails; //!< How many frames we've demoded with incorrect CRCs
qint64 m_typeFails; //!< How many frames we've demoded with unknown type (DF) so we can't check CRC
qint64 m_invalidFails; //!< How many frames we've demoded with reserved bits set
qint64 m_icaoFails; //!< How many frames we've demoded with reserved ICAO
double m_demodTime; //!< How long we've spent in run()
double m_feedTime; //!< How long we've spent in feed()
ADSBDemodStats()
ADSBDemodStats() :
m_correlatorMatches(0),
m_adsbFrames(0),
m_modesFrames(0),
m_crcFails(0),
m_typeFails(0),
m_demodTime(0.0),
m_feedTime(0.0)
{
reset();
}
void reset()
{
m_correlatorMatches = 0;
m_adsbFrames = 0;
m_modesFrames = 0;
m_preambleFails = 0;
m_crcFails = 0;
m_typeFails = 0;
m_invalidFails = 0;
m_icaoFails = 0;
}
};

View File

@ -150,7 +150,7 @@ bool ADSBDemodWorker::handleMessage(const Message& message)
QMutexLocker mutexLocker(&m_mutex);
MsgConfigureADSBDemodWorker& cfg = (MsgConfigureADSBDemodWorker&) message;
applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce());
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (ADSBDemodReport::MsgReportADSB::match(message))
@ -165,7 +165,7 @@ bool ADSBDemodWorker::handleMessage(const Message& message)
}
}
void ADSBDemodWorker::applySettings(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force)
void ADSBDemodWorker::applySettings(const ADSBDemodSettings& settings, bool force)
{
qDebug() << "ADSBDemodWorker::applySettings:"
<< " m_feedEnabled: " << settings.m_feedEnabled
@ -179,10 +179,10 @@ void ADSBDemodWorker::applySettings(const ADSBDemodSettings& settings, const QSt
<< " m_logFilename: " << settings.m_logFilename
<< " force: " << force;
if ((settingsKeys.contains("feedEnabled") && (settings.m_feedEnabled != m_settings.m_feedEnabled))
|| (settingsKeys.contains("exportClientEnabled") && (settings.m_exportClientEnabled != m_settings.m_exportClientEnabled))
|| (settingsKeys.contains("exportClientHost") && (settings.m_exportClientHost != m_settings.m_exportClientHost))
|| (settingsKeys.contains("exportClientPort") && (settings.m_exportClientPort != m_settings.m_exportClientPort))
if ((settings.m_feedEnabled != m_settings.m_feedEnabled)
|| (settings.m_exportClientEnabled != m_settings.m_exportClientEnabled)
|| (settings.m_exportClientHost != m_settings.m_exportClientHost)
|| (settings.m_exportClientPort != m_settings.m_exportClientPort)
|| force)
{
// Close any existing connection
@ -195,9 +195,9 @@ void ADSBDemodWorker::applySettings(const ADSBDemodSettings& settings, const QSt
}
}
if ((settingsKeys.contains("feedEnabled") && (settings.m_feedEnabled != m_settings.m_feedEnabled))
|| (settingsKeys.contains("exportServerEnabled") && (settings.m_exportServerEnabled != m_settings.m_exportServerEnabled))
|| (settingsKeys.contains("exportServerPort") && (settings.m_exportServerPort != m_settings.m_exportServerPort))
if ((settings.m_feedEnabled != m_settings.m_feedEnabled)
|| (settings.m_exportServerEnabled != m_settings.m_exportServerEnabled)
|| (settings.m_exportServerPort != m_settings.m_exportServerPort)
|| force)
{
if (m_beastServer.isListening()) {
@ -208,8 +208,8 @@ void ADSBDemodWorker::applySettings(const ADSBDemodSettings& settings, const QSt
}
}
if ((settingsKeys.contains("logEnabled") && (settings.m_logEnabled != m_settings.m_logEnabled))
|| (settingsKeys.contains("logFilename") && (settings.m_logFilename != m_settings.m_logFilename))
if ((settings.m_logEnabled != m_settings.m_logEnabled)
|| (settings.m_logFilename != m_settings.m_logFilename)
|| force)
{
if (m_logFile.isOpen())
@ -238,11 +238,7 @@ void ADSBDemodWorker::applySettings(const ADSBDemodSettings& settings, const QSt
}
}
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
m_settings = settings;
}
void ADSBDemodWorker::connected()

View File

@ -61,23 +61,20 @@ public:
public:
const ADSBDemodSettings& getSettings() const { return m_settings; }
const QStringList& getSettingsKeys() const { return m_settingsKeys; }
bool getForce() const { return m_force; }
static MsgConfigureADSBDemodWorker* create(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force)
static MsgConfigureADSBDemodWorker* create(const ADSBDemodSettings& settings, bool force)
{
return new MsgConfigureADSBDemodWorker(settings, settingsKeys, force);
return new MsgConfigureADSBDemodWorker(settings, force);
}
private:
ADSBDemodSettings m_settings;
QStringList m_settingsKeys;
bool m_force;
MsgConfigureADSBDemodWorker(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force) :
MsgConfigureADSBDemodWorker(const ADSBDemodSettings& settings, bool force) :
Message(),
m_settings(settings),
m_settingsKeys(settingsKeys),
m_force(force)
{ }
};
@ -104,7 +101,7 @@ private:
ADSBBeastServer m_beastServer;
bool handleMessage(const Message& cmd);
void applySettings(const ADSBDemodSettings& settings, const QStringList& settingsKeys, bool force = false);
void applySettings(const ADSBDemodSettings& settings, bool force = false);
void send(const char *data, int length);
char *escape(char *p, char c);
void handleADSB(QByteArray data, const QDateTime dateTime, float correlation);

View File

@ -67,14 +67,14 @@ private slots:
{
xml = QString("\
{\
\"UrlTemplate\" : \"https://tile.openstreetmap.org/%z/%x/%y.png\",\
\"UrlTemplate\" : \"https://maps.wikimedia.org/osm-intl/%z/%x/%y%1.png\",\
\"ImageFormat\" : \"png\",\
\"QImageFormat\" : \"Indexed8\",\
\"ID\" : \"osm-%1x\",\
\"ID\" : \"wmf-intl-%2x\",\
\"MaximumZoomLevel\" : 18,\
\"MapCopyRight\" : \"<a href='https://wikimediafoundation.org/wiki/Terms_of_Use'>WikiMedia Foundation</a>\",\
\"DataCopyRight\" : \"<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors\"\
}").arg(hires ? 1 : 2);
}").arg(hiresURL).arg(hires ? 1 : 2);
}
else if (tokens[1] == "/satellite")
{

View File

@ -30,7 +30,7 @@
const PluginDescriptor ADSBPlugin::m_pluginDescriptor = {
ADSBDemod::m_channelId,
QStringLiteral("ADS-B Demodulator"),
QStringLiteral("7.22.7"),
QStringLiteral("7.22.1"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Some files were not shown because too many files have changed in this diff Show More