* Fix compiler error with Hamlib 5.0.
* Fix typo.
* Bring back old code for Ubuntu 22.04.
* Update CMake to explicitly look for rig_state.h.
* Add PR #1477 to changelog.
* Fix typo.
* Remove deprecated macos-14, test only on macos-26 due to GitHub issues.
* Work around dyld error when enabling sanitizers.
* Readd macOS 14 and 15 to tests.
* Add PR #1478 to changelog.
* Fix waterfall/spectrum filling solid colour during half-duplex TX
The half-duplex-TX "blank the display" path memset() the spectrum
arrays to zero bytes, but this display's dB scale runs 0 (loudest) to
MIN_MAG_DB (quietest) -- zero meant "loudest possible", not silence,
so it painted the waterfall solid instead of blanking it (yellow,
occasionally clamping to red at the top of the colour scale).
Filling with MIN_MAG_DB alone wasn't sufficient either: the
waterfall's colour scale is relative to each row's own peak (peak
minus a fixed 20dB window), so a perfectly flat row -- regardless of
its absolute level -- always reads as "loud relative to itself". This
showed up live as a green-to-red fade as the auto-ranging baseline
(m_max_mag) caught up to the new flat level.
Fixed properly by detecting a row where every bin sits exactly at the
floor (real spectra essentially never do) and rendering it as plain
black directly, bypassing the relative intensity scale and leaving
the auto-ranging baseline untouched, rather than running synthetic
placeholder data through logic designed for real spectra.
Confirmed identical on master and v3.0-dev; tested live against a
real half-duplex TX/RX cycle.
* Add PR #1462 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Fix issue preventing TX thread from sleeping.
* Forgot additional change.
* Try 40ms frames.
* 10ms
* Probably still need to feed zeroes as needed.
* Revert frame duration back to 20ms.
* Add PR #1465 to changelog.
* Enable CCache to make CI builds run more quickly.
* Ensure Hamlib is also part of ccache.
* Try creating symlink.
* Increase ccache max size limit.
* Add ccache for Windows builds.
* Add cache for lint as well.
* Make sure PGO is covered by ccache.
* Dummy change to make sure build is cached.
* macOS: Ensure node 24 is used for ccache
* Windows: use node 24.
* Increase max cache size on macOS to 5G.
* Add Windows debugging for ccache.
* Use CMake compiler launcher to launch ccache.
* Use symlinks for PGO builds.
* Don't cache PGO use steps, we can't afford to with only 10GB available.
* Fix issue causing cache misses.
* Forgot that we need to use single quotes.
* Revert previous whitespace change.
* Enable ccache for Linux builds.
* Fix shell command error.
* Add PR #1328 to changelog.
* Fix FreeDV Reporter column-order repair to detect gaps, not just trailing entries
If a persisted freedvReporterColumnOrder value was missing an index
from the middle of its range (not just missing new indices appended
after a NUM_COLS increase), the old repair logic never noticed --
it only ever appended indices above the current max element. A
column permanently missing from the list means the wxDataViewCtrl
never creates it, so any later getColumnForModelColId_() lookup for
that column asserts/crashes (e.g. while sorting on it as new spots
arrive).
Reproduced and fixed against a real corrupted config
(ColumnOrder missing index 12/SNR_COL from the middle, confirmed to
crash on assert `item != nullptr` in getColumnForModelColId_ during
live FreeDV Reporter use) -- also explains a previously-unexplained
symptom of an extra empty column appearing when dragging the
rightmost column divider.
* Fix column-order gap detection, sentinel-column drag corruption, and Last TX width
Brings this branch's earlier column-order fix up to the same final
state as testing surfaced on v3.0-dev, since all three are general
bugs unrelated to the LAST_RX_MODE_COL difference between the two
branches:
- Validate/repair the persisted column order unconditionally rather
than only when its length looks wrong -- a config value can have
the right length while still containing an out-of-range/duplicate
entry and missing a genuine one, which the old size()-only check
never caught.
- OnColumnReordered's save path assumed the trailing sentinel spacer
column always stays in the last visual position; nothing enforces
that, so a drag could leave it captured as if it were one of the
real NUM_COLS columns, silently dropping a real one and persisting
the sentinel's invalid model ID instead -- the actual cause of an
"empty column" appearing after reordering.
- Keep the Last TX column at least as wide as Last Update's actual
current width (both use the same date/time format), checked
periodically via the dialog's existing timer rather than once at
construction time, since neither column's real autosized width is
known reliably that early.
Confirmed working live on the desktop against a real corrupted
config with a real radio.
* Minor style tweak.
* Add PR #1458 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Enable PGO for Windows builds.
* instrumented prefix wasn't actually being added.
* Port generate_pgo_profiles.sh to PowerShell (thanks Claude).
* Try disabling RX so we can at least debug rest of pipeline.
* Fix profraw path.
* Try enabling RX code again.
* See if we can get some extra debugging.
* Bound process wait.
* Use Reporting sox invocation.
* Redo config file prior to RX run.
* Fix LLVM profile merge error.
* Add PR #1457 to changelog.
* Experiment: Enable LTO/PGO for macOS .app build.
* PGO: Fix tab layout to match new encoding.
* Try disabling LTO during instrumented build.
* Revert "Try disabling LTO during instrumented build."
This reverts commit e6b4e1a191.
* Try disabling temporal profiles.
* Need to run profiling on both x86_64 and arm64.
* Disable universal builds for the PGO instrumented build.
* Revert "Try disabling temporal profiles."
This reverts commit 89036a3ed6.
* Add PR #1456 to changelog.
* Fake change to force rebuild.
* Revert "Fake change to force rebuild."
This reverts commit a2a8886377.
* Add Intel checks for .app.
* No torch on Intel anymore.
* Fix crash on repeat main-window close while shutdown is in progress
topFrame_OnClose() unconditionally dereferenced m_reporterDialog, but a
second wxEVT_CLOSE_WINDOW arriving while the async RX/PTT shutdown from
a first close is still running (e.g. during a slow Hamlib rig disconnect
against an unresponsive radio) re-enters the handler after
m_reporterDialog has already been set to null on the first pass --
SIGSEGV in wxWindowBase::GetPosition(). Guard re-entry via terminating_
and null-check m_reporterDialog, matching the pattern already used in
the destructor and setConfiguration_().
* Don't block on rig disconnect against an unresponsive radio when turning modem off
Dropping the last shared_ptr reference to a rig controller runs its
destructor, which blocks until the rig actually finishes disconnecting.
Against an unresponsive radio (e.g. powered off, connected via rigctld)
this can take far longer than Hamlib's own client-side timeout/retry
settings suggest, since those don't bound however long rigctld itself
waits on the physical radio -- observed over a minute with no feedback
to the user. Move the last reference onto a detached thread for both
rig controllers so that wait can't hold up turning the modem off or
app shutdown.
* Bound the wait for rig-disconnect threads during app-close shutdown
The detached rig PTT/frequency controller disconnect threads added in
the previous commit have no upper bound on app-close: MainFrame::Destroy()
fires right after performFreeDVOff_() returns, with nothing joining those
threads, so an unresponsive rig still mid-disconnect when the process
actually exits gets its thread killed outright -- e.g. a queued ptt(false)
might never reach the radio. Have each detached thread signal completion
via a future, and on the terminating path wait up to 3s (shared deadline
across both) before proceeding to Destroy() -- long enough for a merely
slow rig to finish cleanly, still bounded so a truly unresponsive one
can't hang shutdown.
Also expand the terminating_ guard comment in topFrame_OnClose() to note
it prevents more than the m_reporterDialog crash: m_RxRunning stays true
until deep inside the same async shutdown, so a repeat close request
could otherwise re-enter OnTogBtnOnOff() a second time concurrently with
the shutdown already in progress.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
* Add PR #1452 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Fix CMAKE_REQUIRED_DEFINITIONS missing -D prefix in GTK3 wx probe (#1449)
wxWidgets_DEFINITIONS is a list of bare macro tokens (correct for the
COMPILE_DEFINITIONS property UsewxWidgets.cmake sets it via), but
CMAKE_REQUIRED_DEFINITIONS requires full "-DFOO" strings. Without the
prefix, check_cxx_symbol_exists()'s probe compile passes each bare
token as a raw command-line argument, which the compiler treats as a
(nonexistent) input filename and errors out on -- silently failing the
whole check closed (WX_BUILT_FOR_GTK3 always false) even against a
genuinely GTK3-built wxWidgets.
With HAS_GTK3 then never defined, topFrame.cpp's GTK3 guard takes the
non-GTK3 fallback branch and creates a stray 1x1 reference wxWindow
directly on the main frame -- disabling wx's "auto-resize sole child
to fill the frame" behaviour and freezing the entire main window's
layout on resize.
Verified on a real GTK3 wxWidgets 3.3.1 build (Mageia 10): reproduced
the false negative on a completely fresh configure (no stale cache
involved), then confirmed the fix resolves it on the first try.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add PR #1450 to changelog.
* Revert accidental commit.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Fix stale selection index crash in wxListViewComboPopup
OnMouseMove() deselected the previously hot-tracked row (m_value)
without checking it was still a valid index, so any external
DeleteAllItems() on the underlying list left a stale index that
crashed the next mouse-move over the popup.
* Fix heard-stations callsign combo stuck-highlight and right-click behaviour
OnCloseCallsignList/OnRightClickCallsignList moved keyboard focus away
from the read-only combo synchronously, but the popup window overlaps
the combo's own value area while open and GTK doesn't always repaint
that region on dismiss, leaving it showing a stale "focused/selected"
highlight. Defer the focus change via CallAfter and force a repaint
once the popup's dismissal has fully finished.
Also stop OnRightClickCallsignList from clearing the displayed
callsign text on deselect -- it should only remove the selection,
consistent with how right-click deselect works in the FreeDV Reporter
list.
* Add PR #1448 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Require C++20 support when building FreeDV.
* Fix Windows compiler errors.
* Add PR #1440 to changelog.
* Fix compiler errors due to wxWidgets 3.0 and C++20.
* Fix Voice Keyer/PTT context menu positioning under native Wayland
The manual left-offset used to keep these menus on-screen on X11
(added 2023, commit 98c43d83) doesn't translate to Wayland's
surface-relative xdg_popup anchor model -- it was landing at the
toplevel's origin instead of next to the button. Added
LeftOffsetContextMenuPosition() which detects a Wayland GDK display at
runtime and returns wxDefaultPosition there, letting GTK's own popup
placement handle screen-edge avoidance (as already happens for the
Reporter Send/Clear menus, which never used a manual offset). X11
keeps the original offset unchanged.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add PR #1438 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Defer Voice Keyer right-click menu popup via CallAfter
On GTK, PopupMenu() called synchronously from the wxEVT_CONTEXT_MENU
handler opens the menu while the originating right-click's implicit
pointer grab is still active, so the matching button-up is delivered
straight to the menu, selecting whatever is under the cursor before it
can be read. Deferring via CallAfter lets the initiating click fully
complete first.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fix Voice Keyer/PTT right-click menu using established RIGHT_UP workaround
The CallAfter approach in the previous commit didn't help: on a fast
click, GDK often has both the button-press and its paired release
already queued and dispatches both before any idle-priority callback
runs, so the menu still opened with the click already spent.
This file already has the correct fix for the identical issue on other
widgets (m_txLevelBox, m_txtTxLevelNum, m_btnTogTune, added earlier):
on wxGTK 3.3+, wxEVT_CONTEXT_MENU is generated from button-press, so
showing a menu from it opens while that click's release is still
pending and GTK delivers the release straight to the menu as a
selection. Bind wxEVT_RIGHT_UP instead for wx>=3.3 (keeping
wxEVT_CONTEXT_MENU on older wx, matching the existing widgets), which
only fires once the click has genuinely finished.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fix FreeDV Reporter Send/Clear button right-click menus (same RIGHT_UP fix)
Same class of bug as the Voice Keyer/PTT buttons: wxEVT_CONTEXT_MENU is
generated from button-press on wxGTK 3.3+, so the menu opens while the
click's release is still pending and GTK delivers it straight to the
menu as a selection. Was only visible when the item under the cursor
happened to be enabled -- a disabled item just closes the menu
silently on release, masking the bug.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Scope the RIGHT_UP context-menu workaround to GTK only
The wxEVT_CONTEXT_MENU-on-button-press behaviour this works around is
GTK-specific: MSW already generates the event on button-up, and OSX
uses ctrl-click. The version-only guard (wxCHECK_VERSION(3,3,0)) would
otherwise apply the same override on Windows/Mac builds using wx 3.3+,
which could drop keyboard-invoked (Menu key/Shift+F10) context menus
on MSW since that only comes through wxEVT_CONTEXT_MENU. Add
defined(__WXGTK__) to all six guard sites, including the pre-existing
one for m_txLevelBox/m_txtTxLevelNum/m_btnTogTune this pattern was
copied from.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Drop version gate: dismiss-on-release bug confirmed present on wx 3.2 too
Direct testing on a wxGTK 3.2 build showed the same context-menu
dismiss-on-release bug the wxCHECK_VERSION(3,3,0) guard assumed was
3.3-specific (copied from the pre-existing txLevel/tune pattern this
was based on). Reading wx 3.2 vs 3.3 source confirmed the press-side
event synthesis is identical in both versions, so the fix now applies
on all wxGTK versions for these real windowed button widgets. The
original txLevel/tune block's version gate is left untouched since its
stated rationale (windowless widgets not generating RIGHT_UP pre-3.3)
is a separate, more specific concern.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add PR #1437 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Harden experimental tab layout persistence
Fix three defect classes found in the AUI tab-layout save/restore feature
(still gated behind Tools->Options->Debugging->Enable Experimental Features):
- SavePerspective()/LoadPerspective() (topFrame.cpp) keyed each saved tab by
its positional AddPage() index, so any future reordering/insertion/removal
of a tab silently corrupted previously-saved layouts (this already caused
a shipped hang, fixed ad hoc in a7aab5d7 when the SNR plot was added). Tabs
are now keyed by their (stable, unique) caption text instead.
- LoadPerspective() had an assert(dest_tabs != nullptr) that compiles out in
release builds (NDEBUG), so a saved layout that parses to zero tab groups
would null-deref instead of failing safely. It now falls back to a single
default tab group holding every page.
- togglePTT() and OnTogBtnVoiceKeyerClick() each guessed which tab to restore
by scanning a hardcoded list of 5 plot windows for one sharing "Frm Mic"'s
tab group, because wxAuiNotebook::GetSelection() is ambiguous once tabs are
split into multiple simultaneously-visible groups. Replaced both copies
with a shared captureCurrentMicGroupTab_() helper that asks the specific
tab group directly (wxAuiTabCtrl::GetActivePage()) instead of guessing.
The Experimental Features gate itself is unchanged; this only hardens the
feature while it's still under that flag.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fix tab layout being clobbered by off-then-on Experimental Features toggle
Both the load (main.cpp, in loadConfiguration_()) and save (exportConfiguration_())
of the AUI tab layout were independently gated on the live experimentalFeatures
value. LoadPerspective() only ever runs once, at startup, so toggling the checkbox
mid-session has no effect on the current layout. But the exit-time save re-read the
live (possibly since-toggled) flag, so: start with the flag off (load skipped, tabs
render as one flat group), flip it back on, then exit -> the flat layout gets saved
right over a previously-good split layout.
Cache the flag value at the point the load decision is made
(tabLayoutPersistenceEnabledAtStartup_) and use that same cached value to gate the
exit-time save, instead of the live value.
Found via live testing of the previous commit's fixes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fix assertion crash dragging a tab near a group left empty by an old saved layout
LoadPerspective() created a live tab-group pane for every '|'-delimited entry in
the saved layout string before this commit's caption fix, even when every one of
that group's saved tokens failed to resolve to a current tab (as happens for any
pre-existing saved layout from before tabs were keyed by caption instead of
position - see 49ec38c1). The result was a zero-page wxAuiTabCtrl left sitting in
the AUI layout. wxAuiNotebook's own drag-and-drop handling doesn't tolerate that:
dragging a tab near the empty group crashed with
"./src/aui/auibook.cpp(371): assert "idx < m_pages.GetCount()" failed in
GetPage(): Invalid Page index" (reported from live testing on the desktop, which
still had an old-format two-group saved layout).
Track the last group known to hold at least one page separately from the group
just created each loop iteration, and sweep up any that ended up empty via
RemoveEmptyTabFrames() (the same cleanup the function already uses for the
previous session's tabs) instead of leaving them in the layout.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Update changelog for drag-and-drop crash fix
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* Fix HAS_GTK3 not reaching fdv_gui_util, silently disabling window position restore
add_subdirectory(gui) runs before the GTK3 detection block's
add_definitions(-DHAS_GTK3), so directory-scoped propagation never
reaches fdv_gui_util (where WindowPositionRestore.cpp actually lives).
The freedv executable target got HAS_GTK3 fine since it's the target
this block sets things on directly, but fdv_gui_util silently always
fell back to the plain deferred Move() with no re-assertion against a
window manager's asynchronous placement override -- i.e. window position
restore never used its intended mechanism on any Linux/GTK3 build.
Confirmed via flags.make: freedv.dir had -DHAS_GTK3, fdv_gui_util.dir
did not. After this fix, both do, and the compiled object file now
references the real GTK signal-handling symbols (g_timeout_add,
g_signal_connect_data, "map-event") instead of compiling out that
whole branch.
* Add PR #1433 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Fix main window position not restoring on startup under KWin
Some window managers/compositors (observed: KWin on Plasma 6, labwc on
Wayland) apply their own asynchronous initial-placement policy shortly
after a window is mapped, silently overriding whatever position the
client already requested -- regardless of how early or late the
client's own Move() happens, and sometimes even after the position has
already happened to match once. Fix by re-asserting the requested
position for a couple of seconds after mapping, which is long enough
to catch and correct a delayed override, then stopping so it won't
fight the user's own later repositioning.
Also warn loudly at configure time if GTK3 development files are
missing, since that silently disables this and other Linux-specific
GUI workarounds with no other signal that anything was skipped.
* Fix FreeDV Reporter window position not restoring, and a close-time drift bug
Applies the same RestoreWindowPosition() fix to the FreeDV Reporter
dialog, which had the identical restore-on-startup issue.
Fixing that exposed a second, pre-existing bug: the Reporter's saved
position crept up by roughly a title-bar height on every close/restart
cycle. MainFrame::topFrame_OnClose()/~MainFrame() correctly grab and
save the Reporter's final position immediately before closing it, but
Close()/Destroy() themselves trigger one more wxEVT_MOVE reporting a
position with the title bar's height already stripped off, and
FreeDVReporterDialog::OnMove unconditionally overwrites the saved
config value on every move event -- so that stray event silently
clobbered the correct save. Fixed via a new stopTrackingPosition()
method that disconnects OnMove right after the deliberate save, before
Close()/Destroy().
* Add PR #1431 to changelog.
* Remove #pragma once to match rest of .h files in tree.
* Move WindowPositionRestore reference to correct CMakeLists.txt file.
---------
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Fix Y-axis min/max label misalignment on scalar/spectrum plots
The Frm Radio/Frm Mic/Frm Decoder amplitude plots gave their min/max
(1.0/-1.0) labels an extra half-line-height push intended to avoid
clipping against the plot border. Since every other label was plain
centered on its gridline, this instead misaligned the extremes and
pushed them toward their neighbouring label, causing overlap as the
window shrank. The existing margin already comfortably fits plain
centering, so drop the special case and center all labels the same
way (matching how the Waterfall's Y-axis already did it correctly).
Also fixes a floating point drift artifact ("-0.0" on the 0.0 gridline
from accumulating -1.0 + 0.2 in float) and re-enables the SNR plot's
extremes and the Spectrum's dB extremes now that the underlying
alignment bug is fixed, instead of hiding them.
Confirmed working on wxGTK 3.3 and 3.2 (built a second tree pinned to
wx 3.2 via -DwxWidgets_CONFIG_OPTIONS="--version=3.2" to check). Also
found a separate, pre-existing wxGTK-3.2-only bug where plot panels
don't expand past ~1/4 window height under GDK_BACKEND=x11 - confirmed
present on unmodified master too, unrelated to this change.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add PR #1429 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Only preserve previously selected tab on TX if it's in the same group as 'From Mic'.
* Change currently selected tab in page changed handler instead of RX->TX transition.
* Initialize tab objects to NULL.
* Check visibility status of each page.
* Fix lint failures.
* Copy current save logic to voice keyer record feature.
* Add PR #1428 to changelog.
* Block '/' in recording suffix and sanitize automatic values
'/' is not valid in a filename suffix. Manual entry of '/' in the
Start Recording dialog's suffix field is now blocked, and any value
passed in automatically (e.g. a portable callsign like G4MKT/P from
the drop-down list or FreeDV Reporter) has '/' replaced with '_'.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Whitelist recording suffix to alphanumerics/underscore instead of blocking '/'
The suffix is used verbatim in a filename and can be auto-populated from
another user's callsign via FreeDV Reporter, so it isn't purely local
input. Replacing only '/' left other filesystem-significant characters
(backslash path separator on Windows, ':' for NTFS alternate data
streams, etc.) unhandled. Now anything outside [A-Za-z0-9_] is replaced
with '_' on the fly, both for manual typing and the auto-populated
default value.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Show .mp3 alongside .wav in Voice Keyer file selector
The "Choose alternate file" dialog only listed .wav by default, hiding
.mp3 recordings (now possible via the recording dialog) unless the
user manually switched to "All files". Add a combined "Sound files"
filter plus separate WAV/MP3 entries, gated behind the same
SNDFILE_NO_MP3_SUPPORT check used elsewhere for MP3 support.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add PR #1424 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Suppress GTK button :active press-flash on Linux (Breeze theme)
Queries the theme's normal button background colour at startup and
installs a screen-level CSS rule so button:active renders the same as
the resting state, eliminating the pale-blue flicker visible on
Plasma 6 / Breeze GTK theme. Fails gracefully on themes that don't
expose the named colour variables.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix GTK3 include path for button-flash suppression code
Add explicit GTK3 include dirs via pkg-config to the freedv target on
Linux. The wxWidgets USE_FILE does not always propagate GTK transitive
include paths to dependent targets, causing gtk/gtk.h to be missing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Link GTK3 libraries for button-flash suppression code
target_include_directories was added but target_link_libraries was
missed, causing an undefined reference to gtk_container_add at link.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Avoid GTK workaround if needed development files don't exist.
* Add PR #1419 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Fix corruption of string config arrays containing commas
String arrays were stored as comma-joined values without escaping,
so any string element containing a comma (e.g. a FreeDV Reporter
status message) was split into multiple entries on reload.
Escapes commas and backslashes on save; unescapes on load.
Existing saved values without commas are unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add PR #1417 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Add momentary PTT option to FreeDV.
* Revert PTT button in window to latching, rename to XMIT.
* Add PR #1393 to changelog.
* Adjust XMIT button tooltip.
* Releasing Space bar during TOT warning should stop TX.
* Add shortcut for Tune.
* Avoid operating on PTT key down if it's a repeat.
* Try different way of filtering out duplicate PTT keypresses.
* Disable previously merged PR on macOS.
* Fix spacebar PTT restarting TX immediately after TOT fires while key is held (#1406)
* Revert "Try different way of filtering out duplicate PTT keypresses"
This reverts commit add9e6e4e8.
That commit was a second attempt to fix the pre-existing bug where
holding the spacebar PTT through the Time-Out Timer immediately
restarts TX. It compounded the problem instead: TX now interrupts
the TOT warning countdown after a couple of seconds and restarts
immediately (confirmed by testing against this commit).
The following commit replaces it with a fix based on polling the
actual OS key state, rather than inferring "still held" from the
KEY_UP/KEY_DOWN event stream, which is unreliable for this purpose
on Linux/GTK.
* Block spacebar PTT restart when TOT fires while key is still held
OnTOTTimer force-stops TX without regard to whether the spacebar PTT
key is still physically held down. On Linux/GTK, a key held under
sustained pressure (e.g. something resting on the keyboard) can
generate real KEY_UP/KEY_DOWN event pairs at the OS repeat rate
rather than a single sustained KEY_DOWN, and IsAutoRepeat() is
unreliable at the point wxApp::FilterEvent intercepts them. This let
the next repeat-driven KEY_DOWN immediately re-key TX right after the
timeout fired, defeating the safety purpose of the TOT.
Poll wxGetKeyState() directly after a TOT-forced stop and latch out
spacebar restart until it confirms a genuine release, rather than
relying on the key event stream.
Tested via freedv-rade-update against pr:1393 @ a868ad19.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
* Remove comment missed by previous commit.
* Fix Ubuntu 22.04 compile failure.
* Manually track PTT key down/up instead of using wxGetKeyState.
* Latching mode: don't repeatedly toggle TX and RX.
* Stop missed momentary PTT release when TX is still starting (#1409)
togglePTT() keys the radio immediately on TX start, but doesn't set
g_tx true until after the configured TX/RX delay (txRxDelayMilliseconds)
completes -- it pumps the event loop via Yield() the whole time so the
UI stays responsive during that wait.
If the momentary spacebar PTT key is tapped fast enough, the matching
KEY_UP can be processed (re-entrantly, via that Yield()) before g_tx
catches up. The momentary-stop check only acts when g_tx is true, so
the release is silently dropped -- the radio is left keyed with no
audio flowing and no further KEY_UP to catch it, until some later key
event happens to land after g_tx finally goes true.
Confirmed via diagnostic logging on Mageia 10 with
TxRxDelayMilliseconds=150: a fast tap showed g_tx still false at the
KEY_UP that should have stopped TX.
Fix: when KEY_UP sees g_tx still false but the PTT button already
shows pressed, record the release in a new flag
(m_momentaryKeyReleasedDuringChangeover_) instead of dropping it.
togglePTT() checks that flag right after its own re-entrancy guard
(txChangeoverOccurring_) clears -- queued as a second CallAfter, after
the existing one -- and immediately stops TX if the key was released
mid-start.
Tested via freedv-rade-update against pr:1393 @ 82b9971c, both with
and without TX/RX delay configured.
Co-authored-by: Barry Jackson <barjac@mageia.org>
* TOT warning dialog: use same logic as used in FreeDV Reporter to give it focus.
* Fix intermittent beep silence/clipping.
* Toggle PTT button color on mouse up.
* Fix null pointer segfault accidentally discovered during testing.
* Start TX on XMIT button press rather than release; fix related edge cases (#1414)
* Start TX immediately on XMIT button press rather than release.
Rebinds to LEFT_DOWN (reverting 767a7979) and calls togglePTT() directly
there. A m_suppressNextPTTClick_ flag causes OnTogBtnPTT to discard the
redundant wxEVT_COMMAND_TOGGLEBUTTON_CLICKED that wxToggleButton fires on
LEFT_UP, undoing its auto-toggle so state remains consistent. The button
value is pre-set to the intended post-toggle direction before togglePTT()
runs, making the suppress/undo timing-safe regardless of where togglePTT()
is in its TX delay when LEFT_UP arrives. OnTogBtnPTTMouseLeave gains a
txChangeoverOccurring_ guard so it cannot reset the pre-empt colour while
togglePTT() is running its start delay.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix suppress flag stuck and momentary mouse stop on release.
Three fixes:
- OnTogBtnPTTMouseLeave: unconditionally clear m_suppressNextPTTClick_.
wxToggleButton only fires TOGGLEBUTTON_CLICKED when released over the
button; if the mouse leaves first the flag would stay set and silently
consume the next click or spacebar event.
- OnTogBtnPTTMouseDown: only set suppress in latching mode. Momentary
mode needs the click event on LEFT_UP to stop TX, mirroring how the
spacebar momentary path works.
- OnTogBtnPTT: handle momentary mouse release during TX start changeover
with m_momentaryKeyReleasedDuringChangeover_, exactly as the keyboard
momentary handler does for mid-changeover key releases.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix XMIT button blue hover after TX cycle on wxGTK.
Resetting SetBackgroundColour(wxNullColour) removes the CSS provider that
was installed when the button was coloured red for TX. This leaves the GTK
widget in a different internal state from buttons that were never styled,
causing GTK's hover/prelight to apply a blue tint on mouseover. The tint
only appears after the first TX->RX transition, not before, and disappears
after a modem restart -- exactly matching removal/reinstallation of the
CSS provider.
Fix: replace all wxNullColour resets on m_btnTogPTT with explicit
wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE/BTNTEXT). This keeps an
invisible CSS provider on the widget at all times so the hover state has
no opening to apply a tint, matching the visual behaviour of other buttons.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix momentary mode XMIT button restarting TX after TOT expiry.
When TOT fires and stops TX while the XMIT button is held in momentary
mode, releasing the button fired OnTogBtnPTT unchecked, calling
togglePTT() and restarting TX. The keyboard path is guarded by
m_pttKeyRequireRelease_ + a poll timer; for mouse we set
m_suppressNextPTTClick_ in OnTOTTimer which causes OnTogBtnPTT to
discard the release click. Setting it unconditionally is safe because
OnTogBtnPTTMouseDown clears any stale suppress at the start of each
fresh press, so it cannot accidentally eat a later intentional click.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix PTT button not greying when modem stopped after TX cycle.
SetBackgroundColour() installs a GTK CSS provider that overrides the
:disabled pseudo-class, so explicit colours set during a TX cycle
persisted and prevented GTK from rendering the button greyed-out after
modem stop. Reset background/foreground to wxNullColour at each
disable site so GTK's native disabled appearance is restored.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix PTT button not greying at program start or after hover on disabled button.
Two gaps: (1) the constructor's initial Disable() lacked the wxNullColour
reset added to the other disable sites, so GTK never re-evaluated the
:disabled state on first show; (2) OnTogBtnPTTMouseLeave had no IsEnabled()
guard — GTK still delivers crossing events to disabled widgets, so hovering
over/off the disabled button re-installed the CSS provider and killed the
grey appearance.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix spellcheck.
* Revert previous PR and event handler change.
* Move PTT enable color setting to top of togglePTT().
* s/PTT/XMIT/ in user manual.
---------
Co-authored-by: Barry Jackson <barjac@users.noreply.github.com>
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Tighten remaining audio settings to improve CI pass rate.
* Try some more changes.
* Windows: make sure mock radio is up before starting FreeDV.
* Windows: Use HP power plan on ARM.
* Don't force specific torch release.
* Revert test config file changes.
* Add PR #1412 to changelog.
* FreeDV Reporter: Round frequency to nearest 100 Hz when double-clicking on row.
* Only adjust frequency if double-clicking on the Frequency column.
* Revert "Only adjust frequency if double-clicking on the Frequency column."
This reverts commit 4ce254922a.
* Revert "FreeDV Reporter: Round frequency to nearest 100 Hz when double-clicking on row."
This reverts commit 32342eebd5.
* Round received frequency from radio instead of doing it on the FreeDV Reporter side.
* Disable previously merged PR on macOS.
* Add PR #1373 to changelog.
* Pin PTT button text colour explicitly instead of relying on GTK theme
m_btnTogPTT only ever had SetBackgroundColour() called on it (red for
TX, amber for the TX->RX drain, null for idle); the text colour was
always left to the active GTK theme to decide. This is fragile across
themes/wx versions: on wxGTK < 3.3 (e.g. Mageia 9), the main frame
losing window activation while the TOT warning dialog has focus puts
the button into GTK's "backdrop" state, dimming the black text to
grey; on other themes the default foreground resolves to white,
making it unreadable against the red/amber background in all states.
Explicitly pin SetForegroundColour(*wxBLACK) alongside every place the
background is set to red/amber, and reset it back to wxNullColour
(theme default) alongside every place the background is reset to
idle, mirroring the existing background-colour pattern.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add PR #1405 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Hamlib: Switch off memory channel before setting frequency/mode
rig_set_freq/rig_set_mode fail with "Invalid parameter" when the rig's
current VFO is MEM, since most CAT protocols can't set an arbitrary
frequency while a memory channel is selected. This breaks startup for
users who park the rig on a memory channel before launching FreeDV
(e.g. as the only way to reach 60m on rigs without a direct band
button for it) since FreeDV pushes its saved frequency/mode on
connect. Add getWritableVfo_(), which switches to VFO A first if the
current VFO is MEM, and use it in the two write paths (setFrequencyImpl_,
setModeImpl_). Read-only paths (periodic polling, disconnect-time
restore) are left alone since querying works fine on any VFO.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add PR #1403 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Hamlib/OmniRig: Set mode first, then frequency.
* Fix missed call in FreeDV Reporter window.
* Revert higher level changes, do second frequency change in Hamlib logic.
* Update comment to reflect actual delta from FTDX10.
* Add PR #1395 to changelog.
* Fix PTT button stuck red when mouse slides off before release
If the user clicks the PTT button and slides the mouse off before
releasing, the button colour was set red on press (cosmetic fix for
GTK blue-flash) but the TX command event never fired, leaving the
button stuck red with TX not active.
Add OnTogBtnPTTMouseLeave() bound to wxEVT_LEAVE_WINDOW: resets the
button colour to wxNullColour if the mouse leaves while TX has not
actually started (g_tx false, button value false).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add PR #1398 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
* Add Time-Out Timer (TOT) capability to FreeDV.
* Add PR #1366 to changelog.
* Add main window indication + time extension button.
* Flash Extend Timeout button 2x/second for visibility.
* Have Claude replace the main window box with a popup window.
* Add missed files.
* Fix lint errors.
* Fix segfault when closing TOT warning window.
* Fix Space bar operation when TOT window is displayed.
* Enable audio beep during TX when TOT is about to fire.
* Ensure beep is audible when TX monitoring is off.
* Shorten beep to 250ms.
* Remove unneeded Stop button from TOT popup window.
* TOT reset button should reset to configured timeout, not just add 60s.
* Warning beep should only occur once.
* Create BeepStep pipeline step to improve audio quality of warning beep.
* Fix Windows compile failure.
* Avoid partial audio writes to improve TOT beep quality.
* Always run RX pipeline even if transmitting.
Additionally, mix TOT beep into resulting RX audio (even if muted) so we
always have a constant stream of audio for our output audio device.
* Emit CW '5' at 15 WPM/750 Hz instead of single beep @ 1000 Hz.
* Need to use mute pipeline, not mute step.
* Fix Tune button failure previously reported.
* Pass min(left, right) number of samples through mixer.
* Add ramp up/down for beeps.
* Disable PTT button during changeover, make color change more consistent.
* Update MuteStep instantiation to reduce need for resampling.
* Clear PTT button background color during transition to RX.
* Add TOT related info to user manual.
* Use 'orange red' for intermediate background color.
* Space bar should not trigger PTT if tuning.
* Reduce TOT warning beep latency.
* Apply @barjac's patch with minor changes.
* Add double-click handler for PTT button to avoid macOS rendering issue.
* Right-justify SNR column in FreeDV Reporter, with trailing padding
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add PR #1387 to changelog.
---------
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>