Releases: Xpiatio/GMRS-TTY
Release list
v1.9.0 — two-tier STT, calibration wizard, net history, TX safety
v1.8.0 — Tabbed settings, FCC Look Up in Add Station dialog
What's new
Tabbed Configuration dialog
The Settings → Configuration dialog is reorganized into five tabs — Identity, Audio, Voice, PTT, and Behavior — so related settings are grouped and the form is no longer a single long scroll.
FCC Look Up in Add Station dialog
The Add Station dialog (opened when you click a pending-station pill) now has a Look Up button next to the Callsign field. It queries the FCC license database on a background thread and pre-fills any empty Name or Location fields from the result. Works with:
- Callsign only — fills both Name and Location from the license record
- Callsign + name — runs the name-match check and shows a verified or mismatch status
- Callsign + location — fills Name from FCC; shows the FCC city alongside your entry
A color-coded status line shows the outcome (green = verified, amber = found/no match, red = not found, gray = offline). The button disables when the app is offline.
Updated user manual
docs/USER_MANUAL.pdf reflects both changes: section 6 (Configuration dialog) is reorganized by tab, and section 9 (Add Station dialog) documents the Look Up button.
Install
Debian 13 / LMDE 7 / Ubuntu 24.10+ — direct install:
sudo apt install ./gmrs-tty_1.8.0_amd64.debUbuntu 22.04 / 24.04 / Mint / Pop!_OS — use the install script:
sudo bash install.sh ./gmrs-tty_1.8.0_amd64.debSee the README for full installation instructions and voice model setup.
v1.7.0 — Touch-screen mode, contacts import/export, monitor passthrough
What's new
New features
-
Touch-screen mode — a ⊞/⊟ toggle on the service toolbar switches the app to a large-button, full-panel view designed for tablets, touchscreens, and Raspberry Pi displays. The touch view shows: pending-station pills at the top, the full chat log, then two rows of thumb-friendly buttons — Listen | Listen Only (80 px tall) and Monitor | Theme | Callsigns | Generate Log | View Logs (56 px tall). All dock panels hide automatically on entry and restore on exit. Button state, chat messages, and streaming transcriptions stay in sync between both views. Preference persists as `touch_mode` in `config.json`.
-
Contacts import/export — Import… (Alt+I) and Export… (Alt+X) buttons in the Contacts dialog. JSON export is a lossless round-trip (all fields including FCC-verified metadata); CSV exports the five user-editable columns for spreadsheet editing. Import merges by callsign + name — existing entries are updated with non-blank incoming fields while verified status is preserved; new callsigns are appended.
-
Monitor passthrough — a Passthrough toggle next to the Monitor button bypasses the bandpass filter so raw unfiltered audio plays through speakers; useful for wideband listening or debugging the audio path.
Documentation
- User manual (section 5.12) — full reference for touch-screen mode, layout, dock behaviour, and state sync. Service toolbar section updated with ⊞/⊟ entry. `touch_mode` added to config.json reference (§20).
- README — Touch-screen mode section updated to reflect the final two-row button layout.
Installation
Download gmrs-tty_1.7.0_amd64.deb and install:
sudo dpkg -i gmrs-tty_1.7.0_amd64.deb
sudo apt-get install -f # resolve any missing depsRequires: Debian 13 / Ubuntu 24.04+ (glibc ≥ 2.34), x86-64, Python 3.13
Whisper STT, speaker ID models, and all Python wheels are bundled — no internet needed after install. Drop Piper TTS voice models into /opt/gmrs-tty/Voices/ after install (see README §3.1.3).
v1.7.0-beta.1 — Contacts import/export, monitor passthrough
What's new
New features
- Contacts import/export — Import… (Alt+I) and Export… (Alt+X) buttons in the Contacts dialog. JSON export is a lossless round-trip (all fields including FCC-verified metadata); CSV exports the five user-editable columns (Callsign, Name, Location, GMRS, HAM) for spreadsheet editing. Import merges by callsign + name — existing entries are updated with non-blank incoming fields while verified status is preserved; new callsigns are appended.
- Monitor passthrough — a Passthrough toggle next to the Monitor button bypasses the bandpass filter so raw audio plays unprocessed; useful for wideband listening or debugging the audio path.
Documentation
- User manual updated — PDF reflects the new Passthrough toggle and Contacts import/export controls.
Installation
This is a pre-release — not recommended for production use.
Download gmrs-tty_1.7.0-beta.1_amd64.deb (if attached) and install:
sudo dpkg -i gmrs-tty_1.7.0-beta.1_amd64.deb
sudo apt-get install -f # resolve any missing depsRequires: Debian 13 / LMDE 7 (or compatible), x86-64, Python 3.13
v1.6.0 — YouTube auth, ADA polish, security hardening, architecture refactors
What's new
New features
- YouTube cookie authentication for age-restricted content (yt-dlp cookie support)
- YouTube journal timestamps now use the video's upload date
- ADA legibility: chat display font bumped +2pt
- ADA accessibility: explicit tab order and accessible descriptions added to Contacts and Journal dialogs
Security & reliability fixes
- Fix: cap pending FCC lookups at 50 to prevent unbounded worker accumulation
- Fix: cap response-body reads to 1 MB in Gemini client and FCC/crossref fetchers
- Fix: move Gemini API key from URL query param to
x-goog-api-keyheader - Fix: guard
delete_journalagainst path-traversal attacks - Fix: replace
print/traceback.print_excwithloggingthroughout - Fix: guard
test_voiceagainst racing with a live TX on_tx_busy - Fix: resolve all flake8 lint errors; improve yt-dlp error messages
Architecture refactors (SOLID / DRY)
- Extract
SpectrometerManager,PendingStationManager,JournalControllerfromMainWindowgod class - Add
AppConfig.save()to invertsave_jsondependency fromMainWindow - Replace
STTWorkerpublic model attrs with typedModelCachedataclass - Add
DEFAULT_OPERATOR_NAME/UNSET_FIELDconstants;attendance_enabledsetter - Extract
_build_*_rows()section builders fromConfigDialog.__init__ - Extract
_set_frs_gate(),validate_voice_path(),_reset_journal_ui()helpers - Define
AudioInputSourceProtocol for typedopen_input_sourcereturn - Register all PTT modes in
_FACTORIESdict (open/closed principle) - Replace
contacts_dialog._now_isowith sharedutc_now_isofrom constants
Installation
Download gmrs-tty_1.6.0_amd64.deb and install:
```bash
sudo dpkg -i gmrs-tty_1.6.0_amd64.deb
sudo apt-get install -f # resolve any missing deps
```
Requires: Debian 13 / LMDE 7 (or compatible), x86-64, Python 3.13
v1.5.0 — Audio quality, AI journals, Monitor fix
What's new
Audio quality improvements
- Bandpass filter, 48 kHz upsampling, and thread safety for the Monitor audio stream
- RMS normalisation before Whisper transcription and soft mute/unmute fade
AI session journals
- Enrich journal entries with per-callsign locations and full transcript
- Generate log entry button added next to Clear chat
- View menu items regrouped logically by feature
Bug fixes & polish
- Fix: Monitor button stays unchecked when Listen stops (ghost-on state)
- Fix: RuntimeWarning, journal thread leak, and Ctrl+C crash eliminated
- Fix: Piper voice models now bundled into .deb for offline install
- Docs: README and user manual updated throughout
Installation
Download gmrs-tty_1.5.0_amd64.deb and install:
```bash
sudo dpkg -i gmrs-tty_1.5.0_amd64.deb
sudo apt-get install -f # resolve any missing deps
```
Requires: Debian 13 / LMDE 7 (or compatible), x86-64, Python 3.13
v1.4.0 — Audio monitor, easier install
What's new in v1.4.0
Audio monitor
- Listen-through toggle — a Monitor button in the listen strip routes incoming radio audio to your speakers/headphones in real time. Uses a thread-safe ring buffer (~1 s) that drops oldest samples so playback never lags behind live audio.
- Monitor mutes automatically during transmissions and rewires correctly when the Listen toggle is cycled.
- Power-on default is persisted in
config.jsonand exposed in the Configuration dialog.
.deb installation hardening
install.shwrapper — adds the deadsnakes PPA on Ubuntu 22.04/24.04 (and Mint/Pop!_OS) so Python 3.13 is available before the package is installed. Runbash install.shinstead ofdpkg -ion those distros.postinstnow usespython3.13explicitly (notpython3, which resolves to 3.10/3.12 on older Ubuntu releases) and fails with an actionable error if Python 3.13 is absent.- Concrete
Depends: python3.13, python3.13-venvreplaces the vague virtualpython3 (>= 3.13). - Offline pip bootstrap uses
python -m pipso the venv install doesn't break whenensurepipcreatespip3/pip3.13but not a barepipsymlink. install.shis bundled inside the.debat/usr/share/doc/gmrs-tty/install.sh.
Upgrade notes
No config migration needed — drop-in replacement for v1.3.1.
v1.3.1 — Fix menus, add app icon
What's new in v1.3.1
Bug fix
- Menus not opening — Settings → Configuration (and any action routed through that dialog) threw a silent
AttributeError: 'MainWindow' object has no attribute 'tx_controller', making all menus appear non-functional. Fixed by correcting the stale attribute name introduced during the v1.3.0 SRP refactor (self.tx_controller→self.tx).
App icon
- GMRS-TTY now ships a multi-resolution icon (16–256 px) that appears in the OS taskbar, window title bar, and Alt+Tab switcher. The design shows a radio antenna tower with wave arcs on a navy background.
Upgrade notes
No config migration needed — drop-in replacement for v1.3.0.
v1.3.0 — AI session journals, YouTube source, Callsigns Detected improvements
What's new in v1.3.0
AI session journals
- Tools → Generate Session Journal (Ctrl+J / 📓 toolbar) — sends the current transcript and detected callsigns to Google Gemini 3.5 Flash; saves a titled AI-generated summary to
journals/YYYYMMDD_HHMMSS.json. Requires a free Gemini API key in Settings → Configuration → Gemini API Key. - Tools → View Session Journals (Ctrl+Shift+J / 📓 toolbar) — non-modal split-pane browser for reviewing past journal entries while listening. Includes per-entry delete with confirmation.
Callsigns Detected improvements
- Persist across Listen cycles — the Callsigns Detected grid no longer resets when Listen is toggled off/on; callsigns accumulate for the whole operating session. Only the Clear button or switching to FRS mode resets the list.
- Remove individual entries — right-click any row or select it and click Remove selected to drop a single callsign from the session without touching Contacts.
YouTube Stream audio source
- Select YouTube Stream (no speakers) in the Input Device dropdown and paste any YouTube URL to stream audio directly into the STT/VAD pipeline — useful for testing without a radio. Requires
yt-dlp≥ 2026.03.17 andffmpegon PATH.
Renamed: Attendance → Callsigns Detected
- The panel, menu toggles, config key label, and all UI copy now use the clearer name Callsigns Detected.
Internal code quality
- Extracted
TXControllerfromMainWindow(SRP) - Introduced
AppConfigwrapper to centralize config access (DRY) - Replaced PTT if/elif dispatch with a registry dict
- Added
normalize_callsignutility to consolidate callsign normalization - Introduced
WorkerBaseshared base class for background workers - Added pyserial and reportlab to NOTICES.md
Upgrade notes
- No database or config migration needed —
config.jsonis backward-compatible. - To use session journals, add a
gemini_api_keyentry toconfig.jsonor set it via Settings → Configuration. Leave it empty to keep the app fully offline. - For YouTube Stream testing:
pip install --upgrade yt-dlpand ensureffmpegis on PATH.
v1.2.0 — Listen-only, attendance grid, fuzzy callsigns
Feature release on top of v1.1.0. Source-only — air-gapped users on v1.1.0 already have the bundled Voices/ and Models/ directories; pull the updated source over the top, or clone fresh and copy those two directories from your existing v1.1.0 install.
New features
-
Listen-only / RX-only safety toggle (#44) — checkable Listen only button (Alt+O) beside the Listen toggle on the strip above the chat. When checked, every TX path is short-circuited: Transmit, This is, Enter-to-send on the message box, the quick-message preset buttons, and the Ctrl+Return / Ctrl+I / Alt+1…Alt+9 global shortcuts all refuse to fire (the buttons grey out so the gate is visible). Microphone capture, transcription, callsign detection, attendance, and chat keep working normally. Defense-in-depth: each TX entry point re-checks the flag because the global shortcuts fire regardless of button state. Persists to
config.json["listen_only"]so an operator who finishes a session in RX-only mode comes back up the same way. -
Attendance dock (#43) — opt-in roll-call grid that logs every callsign detected during the current Listen session. Columns Callsign | Name | Location | GMRS | HAM — all resizable by dragging the header dividers, autofitting to content on each new detection. Unknown callsigns appear with only the Callsign column filled; the moment that callsign is added to (or already in) Contacts, the remaining columns auto-populate from the contact row. Insertion-order deduplicated — re-hearing a callsign within the same session doesn't add a second row. Resets on every Listen on→off transition so each session starts fresh, plus a manual Clear attendance button. Off by default — enable from View → Show attendance (Ctrl+Shift+A) or Settings → Configuration → Attendance grid (Alt+A). Persisted at
config.json["attendance"]["enabled"]. GMRS only — disabled in FRS mode alongside every other callsign-dependent surface. -
Opt-in fuzzy callsign matching (#42) — when Whisper mishears a single character of a callsign (
WSLZ235forWSLZ233, orWSIZ233with an L/I swap), the chat can rewrite the near-miss to the canonical contact callsign so a single operator doesn't fragment into half a dozen near-duplicates. Match rules: same length, exactly one character differs, the differing characters are the same class (letter-for-letter or digit-for-digit), and unambiguous (two saved contacts equally close ⇒ leave alone). Affects chat display, callsign pill highlighting, and pending-pill suppression. Toggle mid-session retroactively rewrites near-misses on existing chat lines. Off by default — enable from Settings → Configuration → Fuzzy callsigns (Alt+U). Persisted atconfig.json["fuzzy_callsign"].
Bug fixes
-
Callsigns not recorded to attendance when utterance was abandoned — callsigns visible in the chat from partial transcripts were silently dropped from the attendance grid whenever the final segment never arrived. This happened when the operator pressed PTT mid-reception, toggled Listen off while a transmission was still in progress, or a new utterance started before the previous one completed. The accumulated text is now flushed through callsign detection in all three cases so attendance always matches what the chat shows.
-
Chat display background not following dark mode (#46) — once any
setStyleSheetcall is made on aQTextEdit, Qt ignores theQPalette.Baserole for the background. The padding-only stylesheet set at init was enough to break palette inheritance, leaving the conversation log stuck on a white background when dark mode was active. The stylesheet now includes an explicitbackground-colorthat is re-applied on every theme toggle.
Improvements
-
Attendance grid columns resizable and autofit (#47) — all five columns are now
Interactive(draggable dividers). Columns autofit to their content each time a new callsign is recorded. Manual width adjustments are preserved until the next detection refits. -
HAM/GMRS cross-reference dedup for pending pills (#43) — pending-station detection now considers all three callsign fields on every contact (
callsign,gmrs_callsign,ham_callsign), so a HAM call detected over the air won't trigger an "Add station" pill if the operator's GMRS call is already saved (and vice versa). Eliminates the double-add prompt for operators licensed for both services.
Docs
docs/USER_MANUAL.pdfupdated throughout this release — new §5.8 Attendance panel walkthrough (including column resize behavior), new §15.4 Fuzzy callsign matching section, RX-pipeline subsections for the squelch-open pre-trigger and streaming transcription (updated to reflect abandoned-utterance callsign scanning), Listen-only toggle coverage, shortcut tables (Ctrl+Shift+A, Alt+O, Alt+U, Alt+A),config.jsonreference keys, §5.1 theme toggle updated to name all repainted surfaces including the conversation log.
Upgrade notes
- From v1.1.0 — drop in the new source over your existing tree (or
git pull). Existingconfig.jsonis forward-compatible; new keys (listen_only,fuzzy_callsign,attendance) are populated lazily with defaults on first launch and saved on close. No model re-download required — the bundledModels/andVoices/directories from v1.0.0 / v1.1.0 are still valid. - First-launch defaults — Listen-only is off, fuzzy callsign matching is off, and the Attendance dock is hidden. Each is independently toggleable from either the Configuration dialog or, where applicable, the View menu.
- Versioning — minor release (v1.1.0 → v1.2.0): three new user-visible features, two bug fixes, two improvements. No breaking changes. The v1.2.0-rc1 prerelease is superseded by this tag.