The terminal board says what is overhead. This says where: a real map with the aircraft moving on it as the frames arrive, and beside each one a box carrying everything known about the flight -- type and registration, who operates it, where it came from and where it is going, height with a rate of climb, speed and heading, how far away and on what bearing, its position, how many frames it has sent and how long since the last one. Qt is asked for and not required. Four bindings are tried, the module imports on a machine with none of them, and asking for the window without one gets the instructions rather than a traceback -- before the receiver is opened, since nothing is gained by taking the dongle for a window that cannot be drawn. In the menu, "listen now" is now "passive capture" with a realtime display beside it. Closing the window leaves exactly the files pressing control-C leaves, because listen and watch share one read loop and one finishing step; the receiver runs on its own thread, so a slow repaint cannot cost a frame and a slow tile fetch cannot stall the picture. The animation's labels grew to match: flight level and speed, type and registration, and both ends of the route, each with a small flag of the country its airport is in. The flags are a table rather than a network -- twelve pixels by eight, where a flag is the arrangement that makes one recognisable rather than a rendering of the real thing -- and a country not in the table is named by its two letters, since a flag that is nearly another country's is worse than none. Where a route arrives as bare codes the country comes from the ICAO prefix. Four things found on the way. The window ignored --seconds, so "listen for ten minutes" meant something different with a window open; it closes itself now. The register was being asked twice per aircraft, once for labels and once for airport positions. Cached routes had no country in them, so the first real redraw drew no flags at all -- routes are versioned now. And past fourteen aircraft on one frame the labels go back to the callsign, the height and the speed, because five lines beside each of three hundred aircraft is a page of overlapping text with a map somewhere behind it. Long names are folded rather than allowed to stretch a box, breaking at the arrow of a route so the two ends stay whole; and the animation's label placement gained the same ring search the window uses, having only ever tried four spots. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016PsWPTweCT6pwxKngvVxcg
58 lines
2 KiB
TOML
58 lines
2 KiB
TOML
[build-system]
|
|
requires = ["setuptools>=64"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "bandsaunter"
|
|
dynamic = ["version"]
|
|
description = "Signal scanner, recorder and identifier for RTL-SDR receivers"
|
|
readme = "README.md"
|
|
requires-python = ">=3.10"
|
|
license = {text = "GPL-3.0-or-later"}
|
|
classifiers = [
|
|
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
"Topic :: Communications :: Ham Radio",
|
|
"Environment :: Console",
|
|
]
|
|
dependencies = [
|
|
"numpy>=1.22",
|
|
"scipy>=1.8",
|
|
"rich>=12.0",
|
|
"PyYAML>=5.4",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
# The realtime aircraft window. Optional on purpose: without it the passive
|
|
# capture, the terminal board and the drawn maps all work unchanged.
|
|
window = ["PyQt6>=6.4"]
|
|
plots = ["matplotlib>=3.5"]
|
|
# pyte is a terminal emulator, used by the resize tests to read back what
|
|
# a real terminal would show. Those tests skip without it.
|
|
dev = ["pytest>=7.0", "pyte>=0.8"]
|
|
# Speech recognition for --transcribe. Optional: transcription is off by
|
|
# default, and the scan says so plainly when no recogniser is installed.
|
|
transcribe = ["faster-whisper>=1.0"]
|
|
transcribe-small = ["vosk>=0.3"]
|
|
|
|
# System packages, which pip cannot install. Recorded here so packaging does
|
|
# not have to rediscover them:
|
|
# Depends: librtlsdr0 -- the dongle is unreachable without it
|
|
# Recommends: espeak-ng -- clearer spoken timestamps; a built-in
|
|
# synthesiser is used when absent
|
|
|
|
[project.scripts]
|
|
bandsaunter = "bandsaunter.cli:main"
|
|
saunterbrowse = "bandsaunter.browse:main"
|
|
|
|
[tool.setuptools.dynamic]
|
|
# The displayed version (2026-08-21_01) is not valid PEP 440, so packaging
|
|
# tools are given the converted form. One source of truth, converted at the
|
|
# edge, rather than two version strings that can drift apart.
|
|
version = {attr = "bandsaunter.pep440_version"}
|
|
|
|
[tool.setuptools.packages.find]
|
|
include = ["bandsaunter*"]
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|
|
filterwarnings = ["ignore::DeprecationWarning"]
|