Commit Graph

235 Commits

Author SHA1 Message Date
sjg e26b8dd6a1 [feat](trx-frontend-http): refresh favicon from logo
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 17:09:51 +01:00
sjg 1f3bdb988a [fix](trx-frontend-http): avoid rerendering unchanged rds af list
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 16:46:55 +01:00
sjg ce25751c5d [feat](trx-rds,trx-frontend-http): add af tuning and dynamic page title
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 16:41:25 +01:00
sjg a18ef33ee2 [feat](trx-frontend-http): enrich and align rds details
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 16:31:45 +01:00
sjg eed5673f95 [feat](trx-frontend-http): smooth spectrum waveform
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 16:13:10 +01:00
sjg 5096e01a60 [feat](trx-client,trx-frontend-http): raise spectrum update rate
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 16:04:15 +01:00
sjg ea6830e343 [feat](trx-frontend-http): add rds raw json copy action
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:51:08 +01:00
sjg 42f61de502 [style](trx-frontend-http): tighten overview spacing
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:30:02 +01:00
sjg cf8d0743ce [feat](trx-rds,trx-frontend-http): expand rds metadata display
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:27:26 +01:00
sjg 8827131264 [fix](trx-frontend-http): copy formatted rds ps text
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:11:29 +01:00
sjg b1fab91e0e [fix](trx-frontend-http): shrink rds pi fallback display
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:08:53 +01:00
sjg 27c8018d89 [feat](trx-frontend-http): show rds pi before ps arrives
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:55:38 +01:00
sjg 017b7be8a8 [fix](trx-rds,trx-backend-soapysdr,trx-frontend-http): relax rds filtering
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:26:11 +01:00
sjg 778e695941 [fix](trx-frontend-http): sanitize stale tune step options
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:21:39 +01:00
sjg 0329be6124 [fix](trx-frontend-http): clarify jog step controls
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:16:09 +01:00
sjg 8f7afed132 [fix](trx-backend-soapysdr,trx-frontend-http): keep rds state on bw changes
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:13:06 +01:00
sjg 976f66d383 [feat](trx-frontend-http): format copied rds overlay text
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:08:20 +01:00
sjg f48e2a6a81 [feat](trx-frontend-http): improve rds pty and ps display
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:03:46 +01:00
sjg adadcb4a77 [fix](trx-backend-soapysdr,trx-frontend-http): preserve raw rds ps text
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:01:27 +01:00
sjg abab89b89c [feat](trx-frontend-http): refine rds overlay interactions
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:58:12 +01:00
sjg 2cd33386ef [fix](trx-frontend-http): add rx audio jitter buffer
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:53:50 +01:00
sjg f509500877 [fix](trx-frontend-http): restore synced frequency and rds badge
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:48:20 +01:00
sjg b0bf9e3ee0 [feat](trx-rds,trx-frontend-http): reset rds on tune changes
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:31:42 +01:00
sjg ee9add1b53 [feat](trx-frontend-http): move map into dedicated tab
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:22:14 +01:00
sjg 855d21fd8a [debug](trx-backend-soapysdr,trx-frontend-http): add RDS diagnostics
Add server-side debug log when RDS data is decoded (PI, PS, PTY).
Extend the RDS panel with active mode, frame counter, and a raw JSON
dump of the last spectrum frame (bins excluded) to help diagnose why
RDS remains absent from the SSE stream.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:31:24 +01:00
sjg 88e0be0cdd [feat](trx-frontend-http): mark spectrum peaks
Draw small peak markers on strong visible spectrum maxima\nso snap-tune targets are easier to spot.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:25:56 +01:00
sjg ff8625f04e [style](trx-frontend-http): align auto bw button sizing
Apply the same explicit height and padding rules to the\nAuto BW button as the Set button in the spectrum\ncontrols, including the mobile layout.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:17:47 +01:00
sjg f7367e6270 [feat](trx-frontend-http): add RDS debug panel in Plugins tab
Add an RDS sub-tab to the Plugins panel showing PI code, PS name, PTY
number and name, decoder status, and a raw JSON dump of the latest RDS
data received via SSE. Also list the RDS decoder in the Overview tab.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:16:15 +01:00
sjg 8b3951d99d [fix](trx-frontend-http): show peak level in tooltip
Include the snapped peak signal level in the spectrum\nhover tooltip alongside the peak frequency.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:11:09 +01:00
sjg e1ab2ae9dc [feat](trx-frontend-http): add automatic bandwidth sizing
Add an Auto BW control that estimates a suitable\nreceive bandwidth from the live spectrum around the\ncurrently tuned peak and applies it to the server.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:09:39 +01:00
sjg 454cf33d6b [fix](trx-frontend-http): sync tuned marker after set_freq
Update the local tuned-frequency state immediately after\nsuccessful set_freq requests so the marker and display stay\nin sync with click-to-tune, manual entry, and jog tuning.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:07:22 +01:00
sjg bfb09213e0 [fix](trx-frontend-http): improve spectrum hover feedback
Show snapped peak frequencies in the spectrum hover tooltip\nand move the bandwidth label to the bottom of the tuned\nfrequency marker.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:03:44 +01:00
sjg 3ab8ca8c1e [fix](trx-frontend-http): snap tuning clicks to peaks
Improve spectrum click-to-tune by snapping the selected\nfrequency to a nearby dominant local peak, making signals\neasier to select.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:59:35 +01:00
sjg c7b99f6fa9 [fix](trx-frontend-http): hide rig selector when logged out
Keep the top bar visible for unauthenticated users, but\nhide the rig selector until a session is established.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:57:02 +01:00
sjg b27c2f8d73 [feat](trx-frontend-http): adjust auth header and style ids
Keep the top bar visible while logged out, limit access to\nthe Main tab, and leave theme controls available while the\nrig selector stays disabled.\n\nRename the internal style ids from nord/arctic and\nmonokai/lime, including a compatibility remap for saved\nsettings.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:53:51 +01:00
sjg 4b93e8ff97 [feat](trx-frontend-http): rename theme labels
Rename the Nord and Monokai theme labels in the web UI\nto Arctic and Brownie, and update the matching CSS\nsection comments.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:46:10 +01:00
sjg b5a1b4af33 [feat](trx-frontend-rigctl): per-rig rigctl listeners for multi-rig setups
Add rig_ports map to RigctlFrontendConfig. When non-empty, one rigctl
TCP listener is spawned per entry instead of the single shared listener,
each routing commands to its assigned rig via rig_id_override on RigRequest.

Add rig_id_override: Option<String> to RigRequest so the remote client
can route individual requests to a specific rig without changing the
globally selected rig. build_envelope prefers the override when set.

Example config:
  [frontends.rigctl]
  enabled = true
  listen = "127.0.0.1"
  port = 4532
  rig_ports.ft817 = 4532
  rig_ports.airspyhf = 4533

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:41:39 +01:00
sjg 6a47fb00ad [fix](trx-frontend-http,trx-backend-soapysdr): fix audio rate and stereo copy
JS: fix stereo AudioData channel copy — frame.copyTo with planeIndex:0
only fills the left plane; reading it as interleaved data caused every
other sample to be zero, making WFM stereo play at half speed.  Now
calls copyTo per channel with the correct planeIndex.

Rust WFM: replace integer output_decim/output_counter in WfmStereoDecoder
with a fractional phase accumulator (output_phase_inc = audio_rate /
composite_rate).  Integer division caused the effective output rate to
drift from audio_sample_rate when the SDR rate is not an exact multiple
(e.g. 2 MHz SDR → 250 kHz composite → ~50 kHz output instead of 48 kHz,
making audio play 4% slow).

Rust non-WFM: add resample_phase/resample_phase_inc to ChannelDsp and
use a fractional-phase resampler in process_block for non-WFM paths,
ensuring exactly audio_sample_rate samples/sec regardless of SDR rate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 07:57:42 +01:00
sjg 7fa4f5d133 [fix](trx-frontend-http): fix jog multiplier reset and rename unit label
Fix updateJogStepSupport to snap jogUnit (not jogStep) to nearest
supported unit, then recompute jogStep = jogUnit * jogMult so the
multiplier is preserved across rig connect/reconnect.

Rename "Mult" label to "Unit Multiplier" for clarity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 02:37:16 +01:00
sjg 4f8658b773 [fix](trx-frontend-http): fix waterfall freeze, RDS bandwidth, add jog multiplier
Fix waterfall overview freezing at steady state by tracking a monotonic
push counter instead of row array length — the array size stays constant
once the waterfall is full, so the previous row-count comparison never
triggered the incremental draw path.

Fix WFM RDS not decoding when switching to WFM from a narrowband mode:
set_mode now resets audio_bandwidth_hz to the mode-appropriate default
(180 kHz for WFM) before rebuilding the FIR, preventing the 57 kHz RDS
subcarrier from being filtered out.

Add 1×/10×/100× multiplier button group next to the jog unit selector.
jogUnit × jogMult gives the effective jog step; both are persisted to
localStorage independently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 02:25:39 +01:00
sjg eb3b45da64 [perf](trx-frontend-http): reduce spectrum rate to 5 Hz and cache waterfall offscreen
Lower SPECTRUM_POLL_INTERVAL and SSE tick from 100 ms to 200 ms to halve
the number of spectrum frames pushed to the browser.

Introduce an OffscreenCanvas cache for the overview waterfall: at steady
state only the new row is painted and the existing image is scrolled up,
reducing per-frame work from O(rows × cols) to O(cols).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 02:13:00 +01:00
sjg f65135cb5e [feat](trx-frontend-http): display RDS PS name overlay on overview strip
When a WFM/SDR spectrum stream carries RDS data, show the Program
Service name (8-char station name) centered on the visible waveform
area in DSEG14 monospace — the same font as the frequency display.

- Add #rds-ps-overlay div inside .overview-strip (pointer-events: none,
  z-index: 2, absolutely positioned at the center of the visible canvas)
- updateRdsPsOverlay(rds) shows/hides and updates text on every spectrum
  frame; trims trailing spaces common in RDS PS strings
- Overlay cleared on spectrum disconnect / null frame
- text-shadow uses CSS color-mix against --bg for legibility across all
  style/theme combinations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 02:04:51 +01:00
sjg ff885dd5fd [fix](trx-frontend-http): match center frequency input color to wavelength
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 01:57:46 +01:00
sjg 51c1d6b912 [fix](trx-frontend-http): style theme toggle button as the opposite theme
When in dark mode the button has a light appearance; when in light mode
it has a dark appearance. This makes the button a preview of what
clicking will switch to, rather than mirroring the current theme.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 01:55:21 +01:00
sjg 4930e5cc45 [fix](trx-frontend-http): fix TDZ on lastSpectrumData at style init
Same root cause as the overviewDrawPending TDZ: setStyle() references
lastSpectrumData at module init time but it was declared far below.
Hoist let lastSpectrumData = null to the top variable block and remove
the now-duplicate declaration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 01:53:08 +01:00
sjg 4f650f5ffb [fix](trx-frontend-http): fix TDZ on overviewDrawPending at style init
setStyle() was called at module init time (to restore the saved style
from localStorage) before the let overviewDrawPending declaration, which
caused a ReferenceError: Cannot access 'overviewDrawPending' before
initialization.

Fix: hoist let overviewDrawPending = false to the top of the variable
declarations block, before any top-level code that may call
scheduleOverviewDraw(). Remove the now-duplicate declaration from its
original location.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 01:51:43 +01:00
sjg 7520796869 [feat](trx-frontend-http): add style picker with Nord, Monokai, Contrast themes
Add a style picker dropdown to the tab bar (right of rig picker) with
four styles — Original, Nord, Monokai, Contrast — each with full
light/dark variants.

CSS: define data-style attribute overrides for all CSS custom properties
(bg, card-bg, borders, text, accents, jog, audio level, filter, spectrum
background) for each of the three new styles × two themes (6 new blocks).

JS: introduce CANVAS_PALETTE lookup table covering spectrum/waveform/
waterfall colors for all style×theme combinations. Add currentStyle(),
canvasPalette(), setStyle() helpers. Persist selection to localStorage.

Replace all isLight ternaries in drawing code with palette lookups:
- drawOverviewWaterfall, drawOverviewSignalHistory, waterfallColor
  signatures changed from isLight flag to pal object
- drawSpectrum uses canvasPalette() for grid lines, labels, fill, line
- spectrumBgColor() now delegates to canvasPalette().bg

Theme toggle also triggers a spectrum redraw so canvas colors update
immediately when switching light/dark.

Also fix light-theme spectrum rendering broken since canvas drawing used
hardcoded dark-only colors (white grid lines invisible on light bg).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 01:48:45 +01:00
sjg 4e9516871f [feat](trx-frontend-http): improve mobile UX and fix S0/S9 label offset
- Add viewport meta tag so mobile browsers use device width instead of
  the default 980px desktop viewport
- Add 520px breakpoint: remove controls-tray forced min-width (was
  52–58rem, causing horizontal scroll on phones), stack controls-row
  into a single column with jog wheel first (order: -1)
- Scale frequency DSEG14 display with clamp() on narrow screens
- Make volume sliders responsive width with larger 20px thumb
- Raise spectrum Set/Auto button and input heights to 2.2rem (overrides
  the min-height: 0 that blocked the existing 760px touch-size rule)
- Add overflow-x: auto + flex-shrink: 0 to sub-tab-bar so all six
  plugin tabs are reachable on small screens without clipping
- Swap spectrum hint text based on input device: mouse/keyboard hint
  hidden on touch devices, touch-specific hint shown instead
- Offset S0/S9/S9+ signal history labels 6px below their grid lines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 01:37:04 +01:00
sjg 449663ddd7 [feat](trx-frontend-http): refine decoder and SDR displays
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 01:22:30 +01:00
sjg b67fdeef8c [feat](trx-frontend-http): offset header blur panel
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 01:18:56 +01:00