Commit Graph

6851 Commits (9134a59d1dfa5105661a07c2a0f70b379a26a81a)

Author SHA1 Message Date
Mooneer Salem 9134a59d1d Minor cleanup for .pot file. 2026-11-02 16:40:00 -08:00
Mooneer Salem e4b4751606 latest user manual PDF 2026-11-01 00:57:25 +00:00
Mooneer Salem 710af8ce70
Merge pull request #1612 from freedv/test-reporter-focus-selection
Test that the Reporter list gaining the focus doesn't select a row
2026-10-31 17:31:44 -07:00
Mooneer Salem 4afdc48aba Merge branch 'master' into test-reporter-focus-selection 2026-10-31 17:30:59 -07:00
Mooneer Salem 56da90b9b1 latest user manual PDF 2026-11-01 00:22:19 +00:00
Mooneer Salem 1e062689da
User manual: Update reference to Experimental Features section. (#1613)
* User manual: Update reference to Experimental Features section.

* Add PR #1613 to changelog.
2026-10-31 17:18:57 -07:00
Mooneer Salem 102aa6e483
FreeDV Reporter: don't select the row under the mouse on focus without a click; begin 2.4.2 development (#1611)
* FreeDV Reporter: only select the row under the mouse on focus if a button is down.

OnSetFocus() selected whatever row the mouse was over whenever the list
gained the focus, including when that came from the window being brought
to the front or a tooltip closing rather than a click. On Linux the
selection guard doesn't stop this either, as hovering over a row already
allows selections. This caused an occasional gui_reporter_row_actions
failure on v3.0-dev ("Selected stations after hovering messages is
['K1ABC']").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add PR #1611 to changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Re-enable dev version tag and six-month build expiry now that 2.4.1 is out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Increment version to 2.4.2 to begin development.

Also builds against freedv-backend's main branch again instead of the
v1.0.1 release, as was done when 2.4.1 development began (#1473).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 17:11:38 -07:00
Mooneer Salem 1cb1f8db9a Test that the Reporter list gaining the focus doesn't select a row.
Gives the list the focus while the pointer rests over a row, as bringing
the window to the front or a tip window closing can, and checks that
nothing ends up selected (#1611).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN
2026-10-31 14:26:25 -07:00
Mooneer Salem f045506c9f FreeDV Reporter: only select the row under the mouse on focus if a button is down.
OnSetFocus() selected whatever row the mouse was over whenever the list
gained the focus, including when that came from the window being brought
to the front or a tooltip closing rather than a click. On Linux the
selection guard doesn't stop this either, as hovering over a row already
allows selections. This caused an occasional gui_reporter_row_actions
failure on v3.0-dev ("Selected stations after hovering messages is
['K1ABC']").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN
(cherry picked from commit 6d2c9e5fc1)
2026-10-31 14:25:09 -07:00
Mooneer Salem d6bc416230 Restore v3.0-dev's dev version tag and build expiry.
The master merge brought over the 2.4.1 release settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN
2026-10-30 22:58:53 -07:00
Mooneer Salem 727fec3a39 Fix v3.0-dev's low sample rate messages and tests after the master merge.
The merge took master's validateSoundCardSetup() wholesale, which dropped
v3.0-dev's translation wrappers and brought back "Tools->Audio Config..."
in place of "Tools->Settings". The GUI tests also still expected
microphone/speaker devices below 16 kHz to be refused.

- Restore _() around the messages and point to Tools->Settings.
- test_low_sample_rate: below 8 kHz is refused for every device; with
  everything at 8 kHz FreeDV starts with one Low Sample Rate warning that
  lists only the microphone and speaker, and doesn't repeat it on the
  next Start.
- test_partly_configured: the 8 kHz mic/speaker cases now start with the
  warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN
2026-10-30 22:58:52 -07:00
Mooneer Salem 957795c377 Merge branch 'master' into v3.0-dev 2026-10-30 17:21:08 -07:00
Mooneer Salem 321db15f63
Add freedv-backend bug fixes to the 2.4.1 changelog (#1608)
* Add freedv-backend bug fixes to the 2.4.1 changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add freedv-backend PR #78 fixes to the 2.4.1 changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Prepare for 2.4.1 release.

* Update freedv-backend to point to newly tagged release.

* Warn instead of refusing to start when a mic/speaker device is below 16 kHz.

FreeDV resamples every device to the rate each step needs, so an 8 kHz
mic or speaker (e.g. a Bluetooth headset using HFP's narrowband codec)
still works; it just loses audio above 4 kHz. Devices below 8 kHz are
still rejected. The warning lists the affected devices and is shown at
most once per session; each Start also logs it.

Fixes #1610.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Avoid listing duplicate device names for the Low Sample Rate warning.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 16:36:05 -07:00
Mooneer Salem bb71eedca7 Merge branch 'master' into v3.0-dev
# Conflicts:
#	USER_MANUAL.html
#	USER_MANUAL.pdf
2026-10-27 17:14:30 -07:00
Mooneer Salem 932b90e15f latest user manual PDF 2026-10-28 00:13:12 +00:00
Mooneer Salem 657516e0d6
test_tone: listen until the test and VOX tones are heard (#1607)
* test_tone: listen until the test and VOX tones are heard

The 1500 Hz check and the VOX tone check each judged a single
one-second capture, so one gap in what was played (seen on Windows CI,
and the VOX check once on Linux) failed the test. Listen for up to 10 s,
as the 700 Hz check already does, and report the last capture if the
tone never shows up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add #1607 to the release notes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:11:27 -07:00
Mooneer Salem 5834e2f45f
Initialize FreeDV Reporter's selection flag; fix RecordStepTest flake (#1606)
* Initialize FreeDV Reporter's selection flag; make RecordStepTest wait for the writer

isSelectionPossible_ was never initialized, so on Linux whether a
selection was honored before the pointer had been over a row depended
on whatever was in memory (caught by UBSan in gui_reporter_numeric_filters).

recordsSamplesInOrder queued bursts faster than real time with a fixed
5 ms sleep between them; on Windows runners the writer thread fell far
enough behind for the 1 s FIFO to fill and drop blocks. Wait for each
burst to be written instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add release note for #1606

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:10:50 -07:00
Mooneer Salem 9e7d24c244 latest user manual PDF 2026-10-27 16:04:43 +00:00
Mooneer Salem 9734dd1f67 latest user manual PDF 2026-10-27 15:51:03 +00:00
Mooneer Salem fca4edc24a
Add an option to disable saving and restoring the frequency on start and stop (#1600)
* Add an option to not restore the last used frequency on start

Settings->Rig Control gets "Set the radio to the last used frequency on
start" (/Hamlib/RestoreLastFrequency, on by default, which keeps the
current behavior). Unchecked, pushing Start leaves the radio on its current
frequency, for both Hamlib and OmniRig, and FreeDV shows that frequency
once connected; the mode is still set if FreeDV is allowed to change it.
The option is greyed out with "No frequency or mode changes" and while
running.

Also regenerates freedv.pot and merges it into pt_BR.po (which picks up
the strings changed by #1532 too), and documents the option in the manual.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add release note for #1600

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Make the option control returning the radio to its frequency on stop

The option added in the previous commit stopped FreeDV setting the radio to
the last used frequency on start, but what it was meant to control is the
other direction: both rig controllers save the radio's frequency and mode
when they connect and set them back when FreeDV stops. Undo the start-time
change and pass the option through to the controllers' restore-on-disconnect
flag instead.

The option is now "Return the radio to its previous frequency and mode on
stop" (/Hamlib/RestoreFreqModeOnStop, on by default), and the rig control
test checks the radio after Stop with it on and off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Make the option cover both Start and Stop

The option now controls both directions: "Save and restore the frequency
on start and stop" (/Hamlib/SaveRestoreFrequency, on by default, which
keeps the current behavior). Unchecked, Start no longer sets the radio to
the frequency FreeDV last used (FreeDV shows the radio's current
frequency instead), and Stop no longer returns the radio to the frequency
and mode it had before Start. This brings back the Start-time change from
the first commit alongside the Stop-time one.

The rig control test checks both, with the option on and off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 08:48:00 -07:00
Mooneer Salem 8fc6ba70d7
Merge pull request #1602 from freedv/fix-rx-mute-latency
Don't believe implausible audio latencies when going from TX to RX (#1601)
2026-10-27 08:46:27 -07:00
Mooneer Salem 8fac756502 Merge branch 'master' into fix-rx-mute-latency 2026-10-27 08:46:12 -07:00
Mooneer Salem 296143dd6a
Fix linting issue from previous PR. (#1605) 2026-10-27 08:44:51 -07:00
Mooneer Salem 559985496e
Save the config on Stop from the UI thread (#1604)
* Save the config on Stop from the UI thread

The save added by #1532 ran on the thread doing the Stop and read
settings (e.g. the reporting frequency) that the UI thread can change at
the same time, which TSan reports in the rig control tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add #1604 to the release notes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 08:39:21 -07:00
Mooneer Salem b3745a5ecb Build the serial test shim with CMake too
Both shims are now built by one CMake function into test/gui in the build
folder, and found with freedvtest.shim_path() (
overrides where).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN
2026-10-27 07:50:38 -07:00
Mooneer Salem 8571ece1a8 Build the PulseAudio test shim with CMake instead of from the test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN
2026-10-27 07:48:15 -07:00
Mooneer Salem 19e2604ab0 Merge remote-tracking branch 'origin/master' into fix-rx-mute-latency
# Conflicts:
#	USER_MANUAL.pdf
2026-10-27 07:45:39 -07:00
Mooneer Salem dbbc7aec41 latest user manual PDF 2026-10-27 14:39:49 +00:00
Mooneer Salem 04a5228d2e
Don't believe implausible audio latencies when going from TX to RX (#1601) (#1603)
* Don't believe implausible audio latencies when going from TX to RX (#1601)

Some PipeWire versions report about 2055 seconds of latency for record
streams. FreeDV resumes RX that long after the radio confirms PTT off, so RX
stayed muted, and as the mute wasn't cleared on Start, Stop and Start didn't
help either.

Treat any latency over a second (or below zero) as a second (or zero), with
a warning in the log. This applies to the output device's latency before
dropping PTT too, which a bogus value would have held up in the same way.
Also clear any leftover RX mute when starting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add release note for #1602/#1603

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* PR is a fix for a previous bugfix, update changelog accordingly.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 07:37:30 -07:00
Mooneer Salem 09465acd95 Add release note for #1602/#1603
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN
2026-10-27 00:59:56 -07:00
Mooneer Salem 8cbce93f48 Test that RX resumes after TX when PulseAudio reports a bogus latency
New rig control scenario, receive_after_transmit: with PTT through Hamlib
(rigctld), FreeDV transmits, and the transmission is then played back to it
as a reply, which it has to sync on; again after Stop and Start. On Linux,
pulse_shim.c (loaded with LD_PRELOAD) makes PulseAudio report the 2055 s
record latency from #1601; elsewhere the scenario checks RX after TX with
the real latency.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN
2026-10-27 00:56:53 -07:00
Mooneer Salem 9bef2c22ee Don't believe implausible audio latencies when going from TX to RX (#1601)
Some PipeWire versions report about 2055 seconds of latency for record
streams. FreeDV resumes RX that long after the radio confirms PTT off, so RX
stayed muted, and as the mute wasn't cleared on Start, Stop and Start didn't
help either.

Treat any latency over a second (or below zero) as a second (or zero), with
a warning in the log. This applies to the output device's latency before
dropping PTT too, which a bogus value would have held up in the same way.
Also clear any leftover RX mute when starting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN
2026-10-27 00:56:53 -07:00
Mooneer Salem 7ad7cc4fe6 latest user manual PDF 2026-10-27 03:27:23 +00:00
Mooneer Salem 7e9a237352
Fix the wxWidgets 3.0 build of LevelMeterLed; retry the AudioDeviceCmdlets install (#1599)
* Fix the wxWidgets 3.0 build of LevelMeterLed; retry the AudioDeviceCmdlets install

wxWidgets 3.0 (Ubuntu 22.04) has no wxWindow::UseBackgroundColour(); use
UseBgCol(), which 3.0 has and which newer versions keep (UseBackgroundColour()
just calls it).

The Windows CI's one-shot Install-Module of AudioDeviceCmdlets from the
PowerShell Gallery failed in two jobs of the same run; retry it up to five
times with a growing delay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add PR #1599 to changelog.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 20:25:09 -07:00
Mooneer Salem ff257393ca latest user manual PDF 2026-10-26 23:27:53 +00:00
Barry Jackson cad625156f
TX AGC: PI leveler + look-ahead limiter, LED level meter (#1532)
* Use freedv-backend's LevelerStep + CompressorLimiterStep for TX AGC.

- Replace AgcStep in the TX pipeline with the new leveler + limiter pair
  (still switched by the existing AGC checkbox).
- Pass RNNoise's live on/off state to both steps.
- Save leveler gain state at the end of each session and restore it at
  the next Start (new /Filter/levelerGainDb and levelerIntegralErrorDb).
- Config-only settings for leveler target (/Filter/levelerTargetLufs,
  default -26 LUFS for limiter headroom) and pause grace period
  (/Filter/levelerPauseGracePeriodSec, default 0.3s).
- build_linux.sh: ENABLE_AUDIO_DIAG_LOGGING passthrough for the
  backend's diagnostic CSV logging.
- TEMPORARY: BuildFreeDVBackend.cmake points at
  barjac/freedv-backend bcj-leveler-limiter until the backend PR merges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Replace the Level gauge with an LED-style meter.

- New LevelMeterLed widget: 10 x 3dB segments across -30..0dBFS,
  custom-drawn so it behaves the same on all platforms. A wxGauge's
  integer steps make a steady dB/sec decay look jittery.
- TX: green, amber from -9dBFS, red from -3dBFS (the red segment is
  centred on the limiter's -1.5dBFS ceiling). Replaces the separate
  target-marker strip.
- RX: all segments a fixed blue. The right RX level is low on this scale
  and is best set from the spectrum display. Fixed colours rather than
  theme colours keep the meter visible when the window is unfocused.
- TX reads raw mic samples from the sound card callback on its own 25ms
  timer, rather than the pipeline's pre-EQ plot tap, whose data arrives
  in bursts paced by the modem frame size. The pre-EQ tap is removed.
- TX ballistics follow BBC/IEC Type I PPM: instant attack, 8.7dB/sec
  constant decay. RX decay slowed from 12 to 6dB/sec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add "AGC dB" plot tab (evaluation aid).

Plots the leveler's applied gain live during TX (10s window, +/-12dB),
updated on the TX level meter's 25ms tick.

Included to help evaluate the leveler/limiter behaviour while testing
this PR. It is not expected to be needed in normal use now that the
Level meter shows TX level directly, and can be dropped from a final
implementation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Remove the leveler pause grace period setting.

freedv-backend's LevelerStep no longer has a pause grace period (it
consistently pushed gain up in every pause); drop the
/Filter/levelerPauseGracePeriodSec config setting and its constructor
argument.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix black background around the Level meter LEDs.

The meter was added to the Level box's sizer with proportion 1, so it
was stretched taller than its segments, and the extra area was cleared
with the parent wxStaticBox's background colour -- black on GTK, where
an unstyled static box doesn't report a usable colour. Add it with
proportion 0 so it stays exactly segment-sized, and fall back to the
system button-face colour unless the parent has an explicit background.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Level meter: show unlit LED segments in neutral grey.

Unlit segments were a dimmed (22%) version of their lit colour, which
read as black on both light and dark themes. Use a fixed mid grey.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Level meter: slightly lighter RX blue, for dark themes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep the TX peak limiter in circuit when AGC is off.

The AGC checkbox used to bypass the leveler and limiter together, leaving
no peak protection with AGC off. It now switches only the leveler (via
LevelerStep's new enabledFn); the limiter is always in the TX path.
Tooltip updated to say so.

Requires freedv-backend bcj-leveler-limiter ceab28c or later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Use freedv-backend's merged LevelerLimiterStep.

The leveler and limiter are now one backend step (tmiw/freedv-backend#66
review). The AGC gain plot reads the live applied gain via a global
atomic updated by the TX thread, since the step's accessor is now
per-instance rather than static.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Pass the leveler's saved state through TxRxThreadUiHooks.

#1542 took the app/config access out of TxRxThread so it can be unit
tested. The leveler's saved gain, integral term and target now come in
through TxRxThreadUiHooks, and the end-of-session state goes back through
a saveLevelerState callback.

TxRxThreadTest:
- define g_agcAppliedGainDb (AGC dB plot).
- toneFrequency() ignores samples near zero: the limiter's look-ahead
  delay starts the output with a few ms that resampling leaves wobbling
  between -1 and +1, which added false crossings.
- automaticGainControlRaisesQuietMicrophone uses a -30 LUFS tone; the
  old 300-peak tone (about -44 LUFS) is below the leveler's pause
  threshold, where the gain is held by design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Use the backend's AgcStep (renamed back from LevelerLimiterStep).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add GUI tests for the level meter and TX AGC.

The test agent now reports the LED level meter's reading and scale, the
AGC's applied gain and its target. test_level_meter_agc.py checks the
meter against tones from the radio and microphone, that the AGC brings
quiet and loud microphones to the target and holds its gain in pauses,
and that with the AGC off the output follows the microphone. Tone()
takes an amplitude for this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Start the leveler from 0dB when the microphone has changed.

The leveler's saved gain is now stored with the TX input device it was
saved with, and only restored for that device. State saved before this
(no device recorded) is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep the TX level meter's timer out of the once-per-DT updates.

OnTimer's final else ran for the 25ms level meter timer as well, so the
spectrum averaging, stats and voice keyer state machine ran about five
times as often as intended. Found by the voice_keyer GUI test: the
keyer no longer transmitted again after its pause.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* GUI tests: include the AGC dB tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Clarify that the leveler's saved state follows the selected TX device.

Comments only: a different microphone on the same device, or a mixer gain
change, isn't detectable this way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* AGC dB plot: draw the trace 2px wide so it shows up on the dark background.

PlotScalar gets setLineWidth() (default 1, so other plots are unchanged).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* TxRxThreadTest: allow for the AGC limiter's 4ms look-ahead in the newer TX tests.

transmitterPrimesWithSpeechBeforeItsFirstFrame and
transmitterSendsOnlyWhatTheMicrophoneMade (#1568) expect sample-exact
passthrough; the limiter holds back its last 4ms until more audio arrives
or the over ends. toneFrequency also skips the brief resampler ringing at
the start of the tone (now up to 64 counts), which added zero crossings in
recordsWhatIsSentToRadio.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Level meter: draw separate LEDs, with a dark version of each colour when unlit.

Each LED is centred in its segment with a 2px gap to its neighbours, and
the meter is 12px high instead of 8px. An unlit LED shows its own colour
darkened rather than a shared grey, like a real LED when it's off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Level meter: outline each LED in its own colour, and leave unlit LEDs empty.

The darkened fill for unlit LEDs was too close to black on screen. An
outline in the LED's own colour keeps unlit LEDs visible, and keeps the
amber and red zones visible on TX, while on and off stay distinct.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Level meter: show the voice keyer's level while it plays.

The TX meter reads the mic straight from the sound card, so during the voice
keyer (or any file played to the mic) it showed the idle mic. The played
file's audio is now copied to the meter as it's read, before any processing,
so the meter shows the recording's own level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add PR #1532 to changelog.

* Voice keyer level for the meter: copy it in the audio path, without a TapStep; ENABLE_AUDIO_DIAG_LOGGING for build_osx.sh too.

GenericFIFO is real-time safe, so FifoWriteStep now passes the audio on and
sits directly after the playback step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* PlotScalar: give the first sample's pixels a value too, so a plot wider than its sample count draws on macOS.

With more pixels than samples (the AGC dB plot: 400 samples over 10s, in a plot
wider than 400 pixels), the pixels before the second sample were skipped and
kept INT_MAX, so the trace started from a point far outside the plot. On macOS
nothing of it was drawn; cairo (Linux) coped. The other scalar plots always have
more samples than pixels, which is why only this one showed it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: merge-test <test@test.local>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
2026-10-26 15:12:47 -07:00
Mooneer Salem a8dd52ad37 Merge branch 'master' into v3.0-dev 2026-10-26 13:20:04 -07:00
Mooneer Salem a2d5365fbb
Add missed attribution to changelog. (#1598) 2026-10-26 13:16:05 -07:00
Barry Jackson 5103bfd531
PlotScalar: draw the trace when the plot is wider than its sample count (#1597)
* PlotScalar: give the first sample's pixels a value too, so a plot wider than its sample count draws on macOS.

With more pixels than samples, the pixels before the second sample were
skipped and kept INT_MAX, so the trace started from a point far outside the
plot. On macOS nothing of it was drawn; cairo (Linux) coped. On master this
can happen to the Audio Config test plots (800 samples), the SNR plot (1800)
and the Demod In/Speech In/Speech Out plots (2000) when drawn wider than that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add PR #1597 to changelog.

---------

Co-authored-by: Barry Jackson <barjac@mageia.org>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Mooneer Salem <mooneer@gmail.com>
2026-10-26 13:13:59 -07:00
Mooneer Salem f80b68be79 latest user manual PDF 2026-10-26 01:01:29 +00:00
Mooneer Salem e50c4efc56 Merge branch 'master' into v3.0-dev
# Conflicts:
#	USER_MANUAL.pdf
2026-10-25 17:55:07 -07:00
Mooneer Salem 2d14abf691
WASAPI: only request raw mode on devices that support it (#1594)
* WASAPI: only request raw mode on devices that support it

Requesting AUDCLNT_STREAMOPTIONS_RAW on an endpoint without raw mode
support can make IAudioClient::Initialize() fail with E_INVALIDARG
(0x80070057), reported as "Could not initialize AudioClient". Check
PKEY_Devices_AudioDevice_RawProcessingSupported first and fall back to
AUDCLNT_STREAMOPTIONS_NONE when it is absent or false.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add PR #1594 to changelog.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 17:53:31 -07:00
Mooneer Salem 71eb68eebd
Make the Hamlib test's "VFO unavailable" fault flag atomic (#1596)
setsFrequencyDespiteUnavailableVfoInformation sets and clears
RadioFaults::getVfoUnavailable on the main thread while the fake
get_vfo reads it on the controller's Hamlib thread, which may still be
polling the radio. The fault counters beside it are already atomic;
this flag was left a plain bool, so TSan reported a race on Linux.


Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 17:53:09 -07:00
Mooneer Salem 60398b9188 latest user manual PDF 2026-10-25 20:46:41 +00:00
Mooneer Salem 8bb9997bbe
Fix two TSan-reported test races; show the notary log when macOS notarization fails (#1595)
* Fix two data races in tests that TSan reports

- PulseAudioDeviceTest read a running device's name without the
  mainloop lock that StreamMovedCallback_ holds while changing it on
  PulseAudio's thread. Read it under that lock.
- logsHamlibDebugMessagesAtEachLevel turned ulog's quiet flag back on
  while the async logger's thread could be reading it. Wait for that
  thread to go idle first. TSan aborted the test on macOS, and since
  stderr was redirected at the time, the report never reached the log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Show Apple's notary log when macOS notarization fails

notarytool submit --wait exits successfully even when the submission is
rejected, so the release target went on to staple and failed there with
"Record not found", without saying why Apple rejected the build. Submit
through a script that checks the result's status, prints the notary log
when it isn't Accepted, and fails the build at that point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add PR #1595 to changelog.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 13:43:12 -07:00
Mooneer Salem 1f764ca9b4 latest user manual PDF 2026-10-25 19:17:28 +00:00
Mooneer Salem 61d687683d latest user manual PDF 2026-10-25 18:38:15 +00:00
Mooneer Salem 4ba5966d10
AppImage: stop forcing GDK_BACKEND=x11 (#1593)
* AppImage: stop forcing GDK_BACKEND=x11.

linuxdeploy's GTK plugin adds an AppRun hook that exports GDK_BACKEND=x11,
overwriting any value the user set. On Wayland desktops this runs the bundled
GTK 3.24.33 (from the Ubuntu 22.04 build host) under XWayland, where a user on
Ubuntu 26.04 saw plot panels flicker after pressing Start and the Settings
dialog draw text over itself after switching tabs. Removing just that export
from the extracted AppImage fixed both; a native build (system or bootstrapped
wxWidgets) under X11 was fine, so the problem is the bundled GTK stack on X11.

Delete the export from the plugin before linuxdeploy runs it so GTK chooses
the backend itself (Wayland when available, else X11) and GDK_BACKEND is
respected again, and fail the build if the hook still sets it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Add PR #1593 to changelog.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:32:14 -07:00
Mooneer Salem b8d92621dc
Extend branch coverage of FreeDV to ~92% (#1588)
* Recover branch coverage with extended reporter and settings GUI scenarios.

- Rewrite ConfigurationDataElementTest around a DefineConfigUnitTest macro
  registered per element in src/config.
- Add reporter scenarios/probes: filters and saved messages, status-message
  combo behaviour, row actions including message-column hovering and list
  mouse behaviour; frequency-list keyboard probes in the settings scenario.
- Fix MsgListPopup PageUp selection when the popup list is open.

CI-chain branch coverage: 89.6% -> 90.1% (12891/14311).

* Extend rig and audio unit tests to fault paths; open serial ports without stealing the terminal

* Cover PTT input port fault paths; open serial ports without stealing the terminal

* Recover configuration store and element conversion branches in unit tests.

* Recover plot fault, colour and translated-layout branches with new GUI scenarios.

* Cover reporter rows, voice keyer cache, TxRxThread and clean shutdown paths

* Cover kHz unit switching, none-output input test and RTS keying test

* Extend setup wizard coverage: none/unplug audio paths, baud fallback and range filtering, toggle handlers, network-rig and partial WSJT-X imports

* Extend GUI tests for ongui.cpp branches

* Extend unit recording test with timed and feature-capture runs

* Cover heard-list updates when a logged entry is heard again

* Keep wxWidgets log messages' UTF-8 text alive while logging them.

msg.ToUTF8() returns a temporary buffer, so the pointer taken from it
was left dangling by the time it reached the log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Don't assert when quitting with a message/frequency list open.

Destroying a combo whose list is open makes ~wxComboCtrlBase() hide the
popup, which asks MsgListPopup for its value. By then the wxComboCtrl
part of the object is gone, so GetComboCtrl()'s cast asserts, and the
assert dialog keeps FreeDV from exiting. Use the base class pointer.

With that, and wxWidgets' log messages no longer shown in dialogs, the
GUI tests no longer need to close the frequency list or give back the
settings folder before quitting, so they now cover both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Let three tests fail when they should.

- test_ut_recording.sh checked tee's exit status rather than FreeDV's,
  so a FreeDV run that crashed partway through still passed. Its ctest
  pass expression was also just "PASS", which anything FreeDV printed
  could match, and its sync check looked at every run's output rather
  than the receive run's.
- gui_rig_control_serial_ptt was never registered with ctest.
- aMovedStreamCarriesOnWithTheNewDeviceName failed now and then because
  PipeWire sometimes accepts a move without carrying it out; ask again
  until the stream has moved, and fail if it never does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Put back the GUI test checks the rewrites dropped.

- column_filters: the menu's exact contents and order, which comparison
  is ticked, Clear Column Filter being enabled once there's a filter,
  filters on two columns at once, Cancel leaving the filter alone, and
  clearing one filter leaving the other.
- status_message: editing a saved message after adding one has moved
  it down, rather than before.
- audio: refreshing the TX Audio tab's lists refreshes the RX Audio
  tab's too, and starting with the transmit devices unset as well as
  saved as "none".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Keep a typed status message when the saved list closes, and fix tests failing on macOS and Windows.

FreeDV: opening the saved status messages and closing them again without
picking one emptied the message box on Linux and Windows, since with
nothing highlighted the list's value was "". It's now what's in the box.
status_message expected the old behaviour; macOS already kept the text.

Tests that only failed outside Linux:
- selected_khz, frequency_in_khz and frequency_list_from_main_window
  expected kHz frequencies without the thousands separators that the
  region adds on macOS and Windows (e.g. 14,236.0); leave them out, as
  the other tests already do.
- config_migration_failure is skipped where there's no migration (only
  Linux has one).
- missing_port named a /dev port on Windows, where FreeDV only checks
  COM names, so Hamlib reported it instead; use a COM port there.
- logsHamlibDebugMessagesAtEachLevel captured to /tmp, which Windows
  doesn't have; use the temporary folder, in binary mode so that no
  carriage returns are added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Keep the plots' arrow key checks' double-click clear of the Spectrum's labels.

On macOS the Spectrum is narrower (407 px against 451 on Linux) and its
dB labels take up its first 13%, so a double-click at 12% across landed
on them and tuned nowhere. The Down presses then started from the top
and ran out at 2400 Hz. Double-click a quarter of the way across, as the
wheel checks already do, and allow enough presses to get to the bottom
from there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Don't use a PulseAudio stream the sound server put on another device.

Streams aren't connected with PA_STREAM_DONT_MOVE, so that they can be
moved between devices later, but that also lets the sound server put a
new one elsewhere when the device it's asked for isn't there: PipeWire
plays to the default device instead of a sink that's missing (1.6.9),
and on 1.6.2 recording from a speaker's name isn't refused either. Once
a stream is ready, check that it's on the device asked for; if not, say
so and disconnect it.

aPlaybackDeviceWithNoSinkReportsTheRefusal covers the playback case,
which kept playing on the default device before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Only log when a PulseAudio stream ends up on another device, as on master.

Match #1591: leave the stream connected and don't report an audio error,
just note in the log where the sound server put it. The playback test
for a missing sink goes, as nothing's refused any more, and the
recording test accepts what PipeWire 1.6.2 does (recording from another
device instead of refusing) so long as the stream is somewhere and
nothing else was reported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Skip config_migration_failure where FreeDV is built without migration.

Configuration files are only migrated with wxWidgets 3.3 or later, and
the ubuntu-26.04 jobs build with the system's 3.2. Those jobs never got
as far as the GUI tests before, as the unit tests failed first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Stop the radio recording budget at zero instead of wrapping it.

g_recFromRadioSamples is unsigned, so a write that ran past the end of the
budget wrapped it around and the "<= 0" check never saw the end. Writes after
the end also kept wrapping it, which is what failed
radioRecordingStopsWhenItsBudgetIsUsedUp on macOS CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Don't assert on macOS when quitting with the frequency list open.

Destroying the main window destroys the frequency box, and ~wxComboCtrlBase()
then closes its open list. On macOS that works out where the mouse is relative
to the window, which by then is no longer a wxTopLevelWindow, so it asserts
("TopLevel Window missing") and the assert dialog keeps FreeDV from exiting.
Close the list at the start of ~MainFrame() instead.

Also, on macOS a key the list doesn't use closes it (wxPopupFocusHandler::OnChar),
so frequency_list_from_main_window now reopens the empty list for each key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Update tests for the fixes merged from master.

- Drop this branch's radioRecordingStopsWhenItsBudgetIsUsedUp, which #1592
  brought in again (in a version that always ends the budget mid-write).
- no_udp: Log QSO now stays off without UDP, even with callsigns heard (#1589).
- receive_reports: a restart no longer lists the station twice (#1589).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYMA9QiGksM1Dox6TuavLZ

* Add PR #1588 to changelog.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:25:34 -07:00
Mooneer Salem 503c8c7702 latest user manual PDF 2026-10-25 03:12:20 +00:00