Repository navigation
Architecture
mprattmd edited this page May 31, 2026
·
1 revision
Handi-Talky Commander is a cross-platform port of the original Windows/WinForms HTCommander. The strategy: extract all platform-neutral logic into a shared Core, isolate OS-specific concerns behind interfaces, and build an Avalonia UI on top.
cross/HTCommander.Core (net9.0) ← portable: protocols, codecs, DSP, broker, abstractions
cross/HTCommander.Platform.Linux (net9.0) ← BlueZ/RFCOMM, PortAudio, SQLite, JSON config
cross/HTCommander.Platform.Mac (net9.0) ← IOBluetooth bridge, PortAudio, SQLite, JSON config
cross/HTCommander.UI.Avalonia (net9.0) ← the cross-platform UI (this app)
src/ (net9.0-windows) ← original WinForms app, shares the same Core
-
HTCommander.Core— portable, UI-agnostic logic: radio control, AX.25, APRS, the SBC voice codec, Winlink, BBS, channel import/export, and the DSP engines (AFSK/PSK/G3RUH/HDLC, Morse, DTMF). No platform dependencies — uses onlySystem.*. -
HTCommander.Platform.Linux— Linux backends: BlueZ/RFCOMM transport, PortAudio audio, SQLite mail store, JSON config. -
HTCommander.Platform.Mac— macOS backends: an IOBluetooth RFCOMM bridge (libhtbt) plus PortAudio / SQLite / JSON. -
HTCommander.UI.Avalonia— the Avalonia XAML UI.
A shared static DataBroker (publish/subscribe) connects the layers and
marshals to the UI thread.
Platform-specific behavior is hidden behind interfaces in
HTCommander.Core/Abstractions, so the Core and UI never reference an OS API
directly:
| Interface | Purpose |
|---|---|
IRadioTransport / IRadioTransportDiscovery
|
Bluetooth connect / discovery / read-write |
IRadioPlatform |
platform entry point that wires up a radio backend |
IRadioAudioChannel |
radio Bluetooth audio (SBC) stream |
IAudioCapture / IAudioPlayback / IAudioDeviceEnumerator
|
mic / speaker / device list (PortAudio) |
IConfigStore |
settings persistence (Registry on Windows, JSON elsewhere) |
IUiDispatcher |
thread marshalling (WinForms Invoke / Avalonia Dispatcher.UIThread) |
ILogger, IPlatformTimer / ITimerFactory
|
logging and injectable timers |
IAprsTransport / IRadioTransport
|
decouple protocol stacks from the host app |
The radios use Classic Bluetooth RFCOMM / SPP, not BLE GATT:
- Linux uses BlueZ (raw RFCOMM/SDP) directly.
- macOS can't use the public CoreBluetooth API (no classic-RFCOMM support), so the port ships a small IOBluetooth bridge to do RFCOMM. "Avalonia gets macOS for free" applies to the UI and build — not to radio connectivity, which needed dedicated work.
| Windows | Cross-platform |
|---|---|
| WinForms | Avalonia (XAML) |
Registry (Microsoft.Win32) |
JSON config store (XDG paths on Linux) |
| NAudio (WASAPI) | PortAudio |
| GMap.NET.WinForms | Mapsui (Avalonia-native) |
System.Drawing custom painting |
Avalonia DrawingContext / FormattedText
|
InvokeRequired / BeginInvoke
|
Dispatcher.UIThread via IUiDispatcher
|
| WinRT / IOBluetooth (RFCOMM) | BlueZ (Linux) / IOBluetooth bridge (macOS) |
- Building from Source — how to compile and package.
- Roadmap and Parity — feature status and the porting plan.
Cross-platform (Linux/macOS) port of Ylianst/HTCommander by Ylian Saint-Hilaire · Apache 2.0 · 📡 73!
Getting started
Using the app
Developers