Commit Graph

720 Commits

Author SHA1 Message Date
sjg c50f716390 [fix](trx-frontend-http): follow active channel in page title
Use the currently tuned virtual channel for the website title\ninstead of always showing channel 0 metadata.\n\nVerification: node --check assets/web/app.js\nVerification: node --check assets/web/plugins/vchan.js\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 13:21:04 +01:00
sjg dca01ead90 [fix](trx-frontend-http): reset scheduler step timing
Track the last applied scheduler entry so previous/next\ncycles correctly across active entries and resets the\ncountdown after manual entry changes.\n\nVerification: cargo test -p trx-frontend-http scheduler\nVerification: node --check assets/web/plugins/scheduler.js\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 13:17:45 +01:00
sjg badf7c0d0f [fix](trx-frontend-http): improve scheduler entry controls
Add previous/next scheduler entry controls for overlapping\ntime-span slots and fix interleave timing calculations so\nthe active slot and countdown align with the overlap window.\n\nVerification: cargo test -p trx-frontend-http scheduler\nVerification: node --check assets/web/plugins/scheduler.js\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 13:11:30 +01:00
sjg c4d1313625 [fix](trx-frontend-http): smooth decode history loading
Reduce main-thread stalls while decode history replays.\n\nCoalesce decoder list redraws and map maintenance so spectrum\nand controls stay responsive during history import.\n\nVerification: node --check on modified frontend JS files.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 12:56:02 +01:00
sjg 28d5494c3b [fix](trx-frontend-http): correct map auth and overlay behavior
Treat the SPA entry routes as public so direct requests to /map,\n/decoders, /settings, and /about return the app shell and let\nthe frontend show the login screen instead of a 403.\n\nMove the map filter overlay to the bottom-right corner and color\ndecode contact paths by their decoded band so they match the band\nlegend and locator overlays.\n\nVerified with cargo test -p trx-frontend-http.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 12:46:08 +01:00
sjg b9744ef8fd [feat](trx-frontend-http): color radio paths by band or mode
Radio paths and decode contact paths now use the same color as the
marker they belong to, respecting the active filter mode:
- Band mode: color follows the band (golden-angle HSL hue)
- Mode/source mode: color follows the source type (FT8/WSPR/bookmark)

APRS, AIS, and VDES paths use their fixed source colors unchanged.
Decode contact paths sync color when the filter mode is switched.

CSS stroke/stroke-opacity removed from path classes so Leaflet's
color option takes effect; dasharray and flow animation are retained.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 12:31:56 +01:00
sjg 1dec2c2663 [chore](trx-rs): centralize version in workspace.package
Add [workspace.package] version = "0.1.0" to the root Cargo.toml and
switch all 21 member crates to version.workspace = true so the entire
workspace is versioned from a single place.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 09:13:06 +01:00
sjg 0b0e86f496 [fix](trx-frontend-http): sync map legend with filter mode
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 19:38:34 +01:00
sjg fb83e3cade [feat](trx-frontend-http): default map filtering to band
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 16:31:40 +01:00
sjg cb824d20ec [fix](trx-frontend-http): separate map corner controls
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 15:48:28 +01:00
sjg 968dc84997 [fix](trx-frontend-http): honor scheduler explicit center freq
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 15:13:04 +01:00
sjg e4487d9037 [feat](trx-frontend-http): add map filter panel toggle
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 14:29:29 +01:00
sjg a82a7ab668 [feat](trx-frontend-http): overlay map controls
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 14:18:18 +01:00
sjg fc954fd27c [fix](trx-frontend-http): stop headless background spectrum polling
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 11:28:41 +01:00
sjg 8be8e798c6 [fix](trx-frontend-http): drop orphaned vchans on disconnect
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 08:14:34 +01:00
sjg c014f5cdc2 [fix](trx-frontend-http): refresh map sources on live APRS
Rebuild the visible-source chips when live APRS, AIS, or VDES markers are first added so the map filter list updates without a page refresh.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 07:24:09 +01:00
sjg 66987a4070 [fix](trx-client): preserve vchan commands under scheduler churn
Use an unbounded virtual-channel command queue so background decode and scheduler transitions do not silently drop subscribe or remove commands.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 07:10:40 +01:00
sjg 4cac91e36a [fix](trx-frontend-http): show scheduler interleave timing
Replace the misleading scheduler task countdown with the actual time-span interleave switch timing in the main controls row.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 01:08:31 +01:00
sjg be4844c710 [fix](trx-client): speed up remote spectrum polling
Raise remote spectrum polling from 100 ms to 50 ms while keeping the relaxed timeout and subscriber gating.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 01:03:38 +01:00
sjg 4f4cd4647d [fix](trx-client): reduce remote spectrum timeout churn
Relax the remote spectrum timeout, poll at the backend update cadence, and stop polling when no spectrum subscribers are connected.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 00:59:59 +01:00
sjg b679ff0282 [feat](trx-frontend-http): refine map and scheduler controls
Add separate map path toggles, move scheduler handoff into the channels row, and show a live countdown to the next scheduler cycle.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 00:52:00 +01:00
sjg 4cca188d9f [feat](trx-frontend-http): improve scheduler and decode map controls
Remove settings rig pickers, restore the last scheduler cycle on release, fix FT8 locator role parsing, and add toggleable decode contact paths on the map.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 00:45:12 +01:00
sjg f7cbc0cb02 [fix](trx-frontend-http): move scheduler handoff out of channels row
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 00:28:25 +01:00
sjg 5c28ed1269 [feat](trx-frontend-http): add scheduler control handoff
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 00:22:18 +01:00
sjg f8fd4572c7 [feat](trx-frontend-http): paginate bookmarks tab
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 23:57:02 +01:00
sjg 963d527dfe [feat](trx-frontend-http): add direct tab routes
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 23:54:25 +01:00
sjg bdd3d29374 [fix](trx-frontend-http): show aprs and ais bookmarks in background decode
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 23:03:57 +01:00
sjg 95fccd3da6 [feat](trx-frontend-http): expand background decode selection
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 22:57:25 +01:00
sjg a91a1868d8 [fix](trx-frontend-http): refresh background decode settings UI
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 22:48:24 +01:00
sjg 2462f1dd47 [feat](trx-frontend-http): add background decode settings
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 22:42:50 +01:00
sjg 21a534bdb6 [feat](trx-client): support background decode subscriptions
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 22:42:43 +01:00
sjg 6c9ff33d68 [feat](trx-frontend): add background decode audio commands
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 22:42:33 +01:00
sjg fc24dc37ed [feat](trx-rs): add settings tab and virtual audio plan
Move Scheduler under a new Settings tab in the HTTP frontend.
Add the virtual-channel audio implementation plan document.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 21:55:54 +01:00
sjg 6d18f5e1d4 [fix](trx-frontend): enable BW drag handles on vchans
Use the active channel frequency for spectrum bandwidth edge hit-testing.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 20:49:43 +01:00
sjg e8326b4822 [fix](trx-frontend): align spectrum RDS overlays vertically
Keep virtual-channel RDS overlays on a shared vertical axis.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 20:44:21 +01:00
sjg add0a93424 [feat](trx-frontend-http): frequency-ordered z-index and hover-to-front for RDS overlay layers
Each RDS PS overlay item (position: absolute within the shared #rds-ps-overlay
container) now receives a z-index derived from its channel frequency: items are
sorted by freq_hz ascending so higher-frequency layers sit on top of
lower-frequency ones by default.

Hovering any layer temporarily assigns it the maximum z-index (entry count + 10)
to bring it to the front; mouseleave restores the frequency-derived default
stored in data-default-z.

Also reverts the incorrectly applied vchan picker layer changes from the
previous commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 20:12:23 +01:00
sjg 1fe7dc88c6 [feat](trx-frontend-http): add frequency layers display for virtual channels
Render virtual channels as absolutely-positioned layer strips inside a
shared relative container (#vchan-freq-layers). Layers are sorted by
frequency ascending so higher-frequency channels receive a higher z-index
and sit on top by default. Hovering any layer temporarily assigns it the
maximum z-index to bring it to the front; leaving restores the original
stacking order. Each layer is offset by 11 px vertically so all channels
remain visible as a staggered card stack.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 20:04:27 +01:00
sjg 93ff35a824 Add per-channel RDS overlays for WFM vchans 2026-03-11 22:39:02 +01:00
sjg 21972c27d2 [test](trx-client): fix fixtures for updated rig snapshot
Update test fixtures to include hf_aprs_decode_enabled and use the current spectrum watch sender type in remote client tests.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 21:41:39 +01:00
sjg daa0631b35 [feat](trx-client): support virtual channel bandwidth control
Add client-side command plumbing, HTTP endpoint handling, and frontend interception so bandwidth changes are applied per active virtual channel and survive reconnects.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 21:41:32 +01:00
sjg 894739bbab [chore](trx-rs): resolve all compiler and clippy warnings
- trx-server/rig_handle: remove dead vchan_manager field (was set but
  never read after the virtual-channel refactor)
- trx-server/listener: remove now-missing vchan_manager initializer
- trx-server/main: remove vchan_manager_for_handle intermediates that
  only fed the dropped field
- trx-server/audio: suppress too_many_arguments on run_audio_listener
- trx-frontend-http/server: suppress too_many_arguments on build_server
- trx-core/vchan: update module doc comment to not reference the
  removed RigHandle::vchan_manager field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 21:01:38 +01:00
sjg 19ab3b3931 [feat](trx-rs): remove MARINE mode (superseded by virtual channels)
MARINE was a composite mode that ran both AIS and VDES decoders
simultaneously. It is now fully replaced by allocating two virtual
channels — one tuned to the AIS frequencies and one to VDES — each
decoded independently.

- trx-core/state: remove RigMode::MARINE variant
- trx-protocol/codec: remove MARINE parse/serialize
- trx-backend-ft817: remove MARINE from unsupported-mode guard
- trx-backend-ft450d: remove MARINE from FM CAT code mapping
- trx-backend-soapysdr: remove MARINE from bandwidth table, supported
  modes list, AIS channel activity check, parse_rig_mode, vchan_impl
  bandwidth table, demod selection, dsp/channel bandwidth / sample-rate
  / IQ-tap guards
- trx-server/audio: remove MARINE from AIS and VDES decoder activation
- trx-server/rig_task: remove MARINE from audio-streaming mode list
- trx-server/main: remove MARINE from bandwidth table, mode parser,
  VDES channel subscription match
- app.js: remove isMarineMode(), MARINE entry in MODE_BW_SPECS, MARINE
  bandwidth specs block in visibleBandwidthSpecs(), MARINE from
  decoder status mode lists, MARINE BW-edge drag guard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 20:58:20 +01:00
sjg 60267d450b [feat](trx-rs): persistent multi-channel virtual channels with OOB eviction
Allow users to allocate multiple virtual channels independently of
browser tab count. Channels survive SDR center-frequency retuning as
long as they stay within the capture bandwidth; channels that fall
outside the SDR span are automatically destroyed.

Changes:
- trx-core: add AUDIO_MSG_VCHAN_DESTROYED (0x12) wire constant;
  add default subscribe_destroyed() to VirtualChannelManager trait
- trx-backend-soapysdr: update_center_hz() detects OOB channels,
  removes them, fires destroyed_tx broadcast; add destroyed_sender()
  and subscribe_destroyed() override
- trx-server/audio: recv_destroyed() helper avoids select! busy-loop
  for non-SDR backends; send AUDIO_MSG_VCHAN_DESTROYED to client when
  a channel is evicted server-side
- trx-client/audio_client: persist active_subs across TCP reconnects,
  re-subscribe on reconnect; handle AUDIO_MSG_VCHAN_DESTROYED by
  pruning vchan_audio map and forwarding UUID via vchan_destroyed_tx
- trx-frontend/lib: add vchan_destroyed broadcast field to
  FrontendRuntimeContext
- trx-client/main: wire vchan_destroyed_tx into audio client and
  frontend runtime context
- trx-frontend-http/vchan: remove per-session one-channel limit in
  allocate(); replace auto-evict in release_session_on_rig() with
  subscriber-count-only update; add remove_by_uuid() for server-
  triggered OOB destruction (skips redundant VChanAudioCmd::Remove)
- trx-frontend-http/server: spawn background task that forwards
  vchan_destroyed broadcast to ClientChannelManager.remove_by_uuid()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 20:50:49 +01:00
sjg 4e93dcc82a [fix](trx-frontend-http): fix virtual channel audio streaming
Three bugs prevented vchan audio from working reliably:

1. vchan.js: `vchanReconnectAudio` returned before updating
   `_audioChannelOverride` when audio was inactive. Switching to
   a virtual channel with audio off then starting audio manually
   would connect to the primary channel instead. Move the override
   update before the rxActive guard so it always reflects the
   active channel.

2. audio.rs: `audio_ws` returned 404 immediately if the channel
   was not yet in `vchan_audio`. The entry is populated when
   `AUDIO_MSG_VCHAN_ALLOCATED` arrives from the audio TCP client,
   which can lag the HTTP allocation by up to ~100 ms. Replace the
   instant 404 with a 2-second polling loop (50 ms intervals) so
   the WebSocket upgrade waits for the channel to be ready.

3. vchan.rs: `release_session_on_rig` evicted zero-subscriber
   channels silently — no `VChanAudioCmd::Remove` was sent.
   Collect evicted channel IDs before retain() and send Remove
   commands so the server-side DSP pipeline and Opus encoder are
   torn down properly on session disconnect.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 20:24:48 +01:00
sjg 6131d7a1d6 [feat](trx-rs): per-virtual-channel audio streaming
Add end-to-end audio routing for virtual DSP channels:

Server (trx-server):
- New wire protocol: AUDIO_MSG_RX_FRAME_CH (0x0b), VCHAN_ALLOCATED (0x0c),
  VCHAN_SUB (0x0d), VCHAN_UNSUB (0x0e), VCHAN_FREQ (0x0f), VCHAN_MODE (0x10),
  VCHAN_REMOVE (0x11) frame types in trx-core audio.rs
- Add frame helpers: write_vchan_uuid_msg, write_vchan_audio_frame,
  parse_vchan_audio_frame, parse_vchan_uuid_msg
- Add ensure_channel_pcm() to VirtualChannelManager trait; implement in
  SdrVirtualChannelManager with create-or-subscribe semantics using client UUID
- Extend audio.rs handle_audio_client: VChanCmd dispatcher, per-channel Opus
  encoder tasks, VCHAN_SUB/UNSUB/FREQ/MODE/REMOVE reader loop handlers
- Thread vchan_manager through run_audio_listener / spawn_rig_audio_stack

Client (trx-client):
- Add VChanAudioCmd enum to trx-frontend; add vchan_audio and vchan_audio_cmd
  fields to FrontendRuntimeContext
- Extend audio_client: demux AUDIO_MSG_RX_FRAME_CH to per-channel broadcasters,
  handle VCHAN_ALLOCATED; forward VChanAudioCmd over TCP write loop
- Wire vchan_cmd_tx/rx channel in main.rs; pass vchan_audio map to audio_client
- ClientChannelManager.set_audio_cmd() / send_audio_cmd(): dispatch
  Subscribe/Remove/SetFreq/SetMode on allocate/delete/freq/mode operations
- Wire audio_cmd sender in server.rs serve() after creating vchan_mgr

HTTP frontend:
- /audio?channel_id=<uuid>: route WebSocket to per-channel Opus broadcaster
- vchan.js: vchanReconnectAudio() stops/restarts RX audio on channel switch;
  _audioChannelOverride in app.js selects primary vs virtual WS endpoint
- app.js: _audioChannelOverride variable; startRxAudio appends channel param

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 08:06:18 +01:00
sjg 28036ab589 [feat](trx-frontend-http): sync mode picker to active virtual channel
- Add vchanSyncModeDisplay() in vchan.js; called from vchanSyncAccentUI()
  and vchanSubscribe() so the mode picker always reflects the active
  virtual channel's mode on switch and on channel-list refresh
- Guard the rig-state mode picker update in render() so it is skipped
  when vchanIsOnVirtual() is true, preventing primary-channel mode from
  overwriting the virtual channel selection

Note: per-channel audio and decoder output require server-side protocol
changes (separate Opus streams per virtual channel) and are not yet
implemented.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 07:37:52 +01:00
sjg 3d284abab6 [fix](trx-frontend-http): center BW overlay on active virtual channel freq
When subscribed to a non-primary virtual channel the bandwidth overlay
was still anchored to lastFreqHz (channel 0).  Resolve the effective
center from the active vchan when vchanIsOnVirtual() is true.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 07:30:24 +01:00
sjg 4bb7248257 [feat](trx-frontend-http): draw virtual channel markers on spectrum + OOB error
- Draw sky-blue dashed/solid lines on spectrum overlay for each vchan
- Active virtual channel gets a solid line; inactive ones are dashed
- Validate freq against SDR capture window in vchanSetChannelFreq and
  show a showHint error when tuning out of bandwidth

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 07:27:51 +01:00
sjg af45c32222 [feat](trx-frontend-http): vchan freq display sync, BW accent, scheduler multi-channel
Virtual channel display:
- vchan.js: wrap refreshFreqDisplay() so the main freq field always shows
  the active virtual channel's frequency instead of channel 0's; expose
  vchanSyncAccentUI() to add vchan-ch-active CSS class (colored border) to
  #freq and #spectrum-bw-input when on a non-primary channel
- style.css: --vchan-color (#38bdf8 sky-blue), .vchan-ch-active box-shadow,
  vchan-picker active button left-border accent

Scheduler multi-channel slots:
- scheduler.rs: add center_hz (Option<u64>) and bookmark_ids (Vec<String>)
  to ScheduleEntry; SchedulerStatus gains last_center_hz and
  last_bookmark_ids; background task sends SetCenterFreq before SetFreq
  when center_hz is set and records extra bookmark_ids in status
- scheduler.js: center-freq input and extra-channel bookmark picker (tag
  list with + / × buttons) in the add-entry form; extra channels shown in
  the entries table
- index.html: center freq field + extra bookmark picker widgets; table
  gains Center freq and Extra channels columns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 07:22:36 +01:00
sjg cef1741e40 [feat](trx-frontend-http): intercept freq/mode changes for virtual channels
When on a non-primary (virtual) channel, redirect freq and mode changes
to the channel metadata API instead of the server:

- vchan.js: add vchanIsOnVirtual(), vchanSetChannelFreq/Mode(); expose
  window.vchanInterceptMode() hook; wrap window.setRigFrequency so all
  callers (jog, freq input, bookmarks, spectrum click) are automatically
  redirected without modification
- app.js: check vchanInterceptMode() in applyModeFromPicker() before
  posting /set_mode
- bookmarks.js: check vchanInterceptMode() for mode in bmApply();
  setRigFrequency() redirect is automatic via the vchan.js wrapper;
  bandwidth and decoder toggles still apply regardless of channel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 07:08:36 +01:00