rigplane 2.0.2__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rigplane-2.0.2 → rigplane-2.0.3}/PKG-INFO +1 -1
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/CHANGELOG.md +10 -1
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/audio.md +13 -6
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/profiles.md +1 -1
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/wsjtx-setup.md +16 -2
- rigplane-2.0.3/docs/plans/2026-05-07-audio-route-resolver-design.md +120 -0
- rigplane-2.0.3/docs/plans/issue-drafts/2026-05-07-core-audio-pipeline-test-harness.md +98 -0
- rigplane-2.0.3/docs/plans/issue-drafts/2026-05-07-core-audio-route-resolver.md +34 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/pyproject.toml +1 -1
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/lan_stream.py +9 -9
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/cli/__init__.py +16 -1
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/config.py +6 -6
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/contract.py +2 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/handler.py +35 -4
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/server.py +53 -3
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_audio_runtime_mixin.py +59 -14
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_control_phase.py +2 -1
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/profiles_runtime.py +3 -4
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/radio.py +1 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/radio_state_snapshot.py +3 -4
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/handlers/audio.py +1 -2
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_transcoder.py +22 -26
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cli.py +164 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_commands.py +17 -5
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_data_mode.py +6 -6
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_ic705.py +1 -1
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_pcm_e2e.py +15 -2
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_profiles_runtime.py +3 -3
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_radio_coverage.py +1 -1
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rigctld_handler.py +70 -3
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rigctld_server.py +23 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rigctld_server_coverage.py +36 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/uv.lock +1 -1
- {rigplane-2.0.2 → rigplane-2.0.3}/.claude/commands/next.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.claude/commands/scan-issues.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.claude/commands/solve-issue.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.claude/skills/release/SKILL.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/ISSUE_TEMPLATE/epic.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/ISSUE_TEMPLATE/feature.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/ISSUE_TEMPLATE/radio_report.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/ISSUE_TEMPLATE/ui-component.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/scripts/check-rebrand-allowlist.sh +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/workflows/docs.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/workflows/full.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/workflows/publish.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/workflows/quick.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.github/workflows/rebrand-gate.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.gitignore +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/.importlinter +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/AGENTS.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/ARCHITECTURE.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/CHANGELOG.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/CLAUDE.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/CONTRIBUTING.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/LICENSE +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/README.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/ROADMAP.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/band-plans/_config.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/band-plans/arrl-hf.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/band-plans/broadcast.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/band-plans/iaru-r1.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/band-plans/utility.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/AUDIO_STREAMING_PROFILE.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/CNAME +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/EXTENDED_PROTOCOL_RESEARCH.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/PERFORMANCE.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/PROJECT.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/SECURITY.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/auth.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/backends-icom7610-drivers.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/backends-icom7610.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/backends.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/commander.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/commands.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/exceptions.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/public-api-surface.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/radio.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/radios.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/rig-loader.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/rigctld.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/scope.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/sync.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/transport.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/types.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/api/web.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/architecture/open-core-policy.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/assets/scope-example.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/capabilities-matrix.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/contracts/diagnostic-bundle-v1.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/contracts/diagnostic-bundle-v2.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/audio-recipes.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/cli.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/commands.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/configuration.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/connection.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/diagnostic-reports.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/ic705-usb-setup.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/ic7300-usb-setup.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/ic7610-usb-setup.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/ic9700-usb-setup.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/installation.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/quickstart.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/radios.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/rig-profiles.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/troubleshooting.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/guide/web-ui.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/index.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/internals/architecture.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/internals/cli-design.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/internals/contributing.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/internals/github-project-workflow.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/internals/protocol.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/internals/reliability-semantics.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/internals/rfc-audio-v1-mini.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/opuslib-macos-fix.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/parity/README.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/parity/ic7610_command_matrix.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/parity/test_mapping.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-03-07-ui-architecture.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-05-desktop-companion-architecture.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-09-audio-backend-design.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-11-frontend-migration-plan.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-11-parity-matrix.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-11-presentation-architecture.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-11-rx-audio-trace.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-11-shared-frontend-runtime-contract.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-11-v2-lcd-runtime-audit.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-12-architecture-presentation.html +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-12-target-frontend-architecture.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-18-desktop-meters-panel.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-18-lcd-display-enhancements.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-18-mobile-ia.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-18-receiver-activation.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-18-spectrum-controls.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-18-ui-refinements-execution.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-19-lcd-layout-redesign-v2.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-19-lcd-layout-redesign.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-29-modularization-discovery.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-29-modularization-plan.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-29-panel-adapter-migration.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-04-29-ui-v1-deprecation-audit.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/2026-05-03-diagnostic-data-collection-design.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/archive/2026-03-04-dx-cluster.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/archive/2026-03-m5-m6-roadmap.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/archive/2026-04-19-lcd-twin-skins.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/build_orphan_report.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/classify_cycle_edges.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/cycles-classified.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/cycles.txt +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/discovery_graph.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/external-usage.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/file-inventory.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/file-inventory.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/import-graph.dot +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/importlinter-config-draft.ini +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/init-snapshot.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/orphan-candidates.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/tach-config-draft.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/test-inventory.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/discovery-artifacts/tooling-assessment.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/00-epic-final.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/00-epic.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/01-skeleton.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/02-core-foundationals.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/03-core-contracts.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/04-commands.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/05-profiles.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/06-scope.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/07-audio.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/08-runtime-radio.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/09-runtime-mixins.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/10-runtime-pollers.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/11-discovery-to-backends.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/12-cli.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/13-import-linter.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/14-followup-tests.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/plans/issue-drafts/15-followup-web-startup.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/radio-protocol.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/screenshots/amber-lcd.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/screenshots/hero.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/docs/screenshots/lcd-scope.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/.gitignore +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/README.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/eslint.config.js +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/index.html +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/package-lock.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/package.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/playwright.config.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/pnpm-lock.yaml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/apple-touch-icon.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/lockup-dark.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/lockup-light.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/lockup-mono.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/mark-dark.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/mark-light.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/mark-mono.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/marketing/github-social-preview.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/marketing/readme-banner.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/wordmark-dark.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/wordmark-light.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/brand/wordmark-mono.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicon-16.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicon-32.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicon-48.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicon.ico +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon-128.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon-16.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon-180.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon-192.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon-256.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon-32.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon-48.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon-512.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon-64.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/ink/favicon.ico +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon-128.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon-16.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon-180.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon-192.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon-256.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon-32.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon-48.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon-512.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon-64.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/paper/favicon.ico +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/transparent/favicon-128.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/transparent/favicon-16.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/transparent/favicon-180.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/transparent/favicon-192.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/transparent/favicon-256.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/transparent/favicon-32.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/transparent/favicon-48.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/transparent/favicon-512.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/favicons/transparent/favicon-64.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/manifest.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/og-image.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/pwa-192x192.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/pwa-512x512.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/public/twitter-card.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/App.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/app.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/assets/svelte.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/shared/Toast.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/BandPlanOverlay.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/DxOverlay.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/EiBiBrowser.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/ScopeSettingsPopover.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/SpectrumCanvas.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/SpectrumPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/SpectrumToolbar.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/WaterfallCanvas.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/BandPlanOverlay.component.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/DxOverlay.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/EiBiBrowser.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/SpectrumPanel.component.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/SpectrumToolbar.component.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/band-plan-overlay.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/click-to-tune.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/passband-geometry.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/spectrum-panel-logic.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/spectrum-toolbar.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/__tests__/tuning-indicator.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/band-plan-logic.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/passband-geometry.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/spectrum-logic.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components/spectrum/spectrum-toolbar-logic.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/AttenuatorControl.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/BandSelector.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/BottomSheet.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/CollapsiblePanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/ControlButtonDemo.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/InstallPrompt.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/PttFab.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/PullToRefresh.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/SegmentedButton.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/StatusBadge.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/ThemePicker.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/ValueControlLab.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/__tests__/AttenuatorControl.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/__tests__/BandSelector.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/__tests__/BottomSheet.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/__tests__/CollapsiblePanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/__tests__/InstallPrompt.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/__tests__/PullToRefresh.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/__tests__/SegmentedButton.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/__tests__/StatusBadge.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/__tests__/broadcast-presets.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/band-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/broadcast-presets.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/button-tokens.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/control-button.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/install-prompt-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/status-badge-style.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/BipolarRenderer.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/DiscreteRenderer.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/DualParamRenderer.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/HBarRenderer.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/KnobRenderer.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/ValueControl.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/__tests__/ValueControl.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/__tests__/value-control-core.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/index.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/skin.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/skins/ProfessionalKnob.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/skins/index.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/value-control-core.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/controls/value-control/value-control.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/dialogs/SendReportDialog.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/dialogs/__tests__/SendReportDialog.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/display/FrequencyDisplay.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/display/FrequencyDisplayInteractive.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/display/__tests__/FrequencyDisplay.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/display/__tests__/frequency-tuning.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/display/frequency-format.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/display/frequency-tuning.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/KeyboardHandler.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/LcdLayout.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/LeftSidebar.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/MobileNav.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/MobileRadioLayout.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/RadioLayout.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/RightSidebar.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/StatusBar.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/VfoHeader.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/KeyboardHandler.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/LeftSidebar.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/MobileRadioLayout.component.svelte.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/RadioLayout.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/SpectrumPanelStub.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/keyboard-map.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/mobile-layout-logic.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/mobile-nav.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/top-row-visual-regression.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/vfo-header.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/__tests__/vfo-layout-tokens.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/keyboard-map.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/layout-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/mobile-chip-bar.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/mobile-layout-logic.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/mobile-nav-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/responsive.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/shortcut-hints.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/layout/vfo-layout-tokens.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/BarGauge.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/LinearSMeter.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/NeedleGauge.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/SMeterDemo.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/__tests__/BarGauge.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/__tests__/LinearSMeter.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/__tests__/NeedleGauge.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/bar-gauge-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/needle-gauge-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/meters/smeter-scale.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/AgcPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/AntennaPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/AudioRoutingControl.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/CwPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/DockMeterPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/DspPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/EssentialsPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/FilterPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/MemoryPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/MeterPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/MetersDockPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/ModePanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/RfFrontEnd.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/RitXitPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/RxAudioPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/ScanPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/TxPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/VoxPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/AgcPanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/AudioRoutingControl.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/CwPanel.component.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/DspPanel.component.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/DspPanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/FilterPanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/MeterPanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/MetersDockPanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/ModePanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/RfFrontEnd.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/RitXitPanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/RxAudioPanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/TxPanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/cw-panel-logic.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/dsp-panel-logic.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/__tests__/filter-controls.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/agc-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/audio-scope/AudioSpectrumCanvas.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/audio-scope/AudioSpectrumPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/audio-scope/__tests__/audio-spectrum-renderer.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/audio-scope/audio-spectrum-renderer.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/audio-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/cw-panel-logic.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/dsp-panel-logic.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/dsp-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/filter-controls.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/filter-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberAfScope.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberCockpit.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberFilterGhost.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberFrequency.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberIndStrip.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberLcdDisplay.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberMemoryStrip.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberScope.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberSmeter.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberSparkline.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/AmberTelemetryStrip.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/LcdContrastControl.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/LcdDisplayModeControl.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/VfoControlPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/__tests__/lcd-components.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/__tests__/scope-frame.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/lcd/lcd-vintage.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/meter-utils.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/meter-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/rf-frontend-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/rit-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/tx-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/vfo/DualVfoDisplay.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/panels/vfo/__tests__/DualVfoDisplay.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/fonts-digital.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/fonts.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/index.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/theme-switcher.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/amoled-black.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/ayu-dark.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/catppuccin-latte.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/catppuccin-mocha.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/crt-green.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/custom-ic7610.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/dracula.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/github-light.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/gruvbox-dark.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/gruvbox-light.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/high-contrast.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/index.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/lcd-blue.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/lcd-warm.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/nixie-tube.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/nord-light.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/nord.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/one-dark.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/solarized-dark.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/solarized-light.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/themes/tokyo-night.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/tokens.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/vfo-themes/crt-green.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/vfo-themes/index.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/vfo-themes/lcd-blue.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/theme/vfo-themes/nixie-tube.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/vfo/ActiveReceiverToggle.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/vfo/VfoOps.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/vfo/VfoPanel.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/vfo/__tests__/ActiveReceiverToggle.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/vfo/__tests__/VfoOps.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/vfo/__tests__/VfoPanel.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/vfo/vfo-ops-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/vfo/vfo-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/wiring/__tests__/double-click.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/wiring/__tests__/focus-mode-race.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/wiring/__tests__/keyboard-wiring.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/wiring/__tests__/state-adapter.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/wiring/__tests__/vfo-wiring.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/wiring/command-bus.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/wiring/double-click.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/components-v2/wiring/state-adapter.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/ControlButton.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/DotButton.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/FillButton.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/HardwareButton.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/HardwarePlainButton.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/StatusIndicator.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/__tests__/ControlButton.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/__tests__/ControlledHarness.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/index.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/roleMapping.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/Button/types.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/SegmentedControl/index.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/__tests__/drag-reorder.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/__tests__/migrate-legacy-storage.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/actions/keyboard.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/api/__tests__/diagnostics.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/api/diagnostics.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/audio/__tests__/constants.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/audio/__tests__/rx-player.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/audio/__tests__/tx-mic.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/audio/audio-manager.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/audio/constants.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/audio/rx-player.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/audio/tx-mic.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/data/__tests__/arrl-band-plan.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/data/arrl-band-plan.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/drag-reorder.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/gestures/gesture-recognizer.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/gestures/use-gesture.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/local-extensions/LocalExtensionsHost.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/local-extensions/__tests__/dock-layout.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/local-extensions/__tests__/host-api.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/local-extensions/__tests__/manifest.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/local-extensions/dock-layout.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/local-extensions/host-api.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/local-extensions/keyboard-scope.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/local-extensions/manifest.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/media/__tests__/media-session.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/media/media-session.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/migrate-legacy-storage.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/radio/filter-controls.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/radio/pending-focus.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/radio/pending-focus.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/renderers/__tests__/spectrum-renderer.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/renderers/__tests__/waterfall-renderer.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/renderers/spectrum-renderer.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/renderers/waterfall-renderer.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/__tests__/frontend-runtime.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/__tests__/scope-controller.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/adapters/audio-adapter.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/adapters/capabilities-adapter.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/adapters/lcd-chrome-adapter.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/adapters/panel-adapters.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/adapters/qsy-history-adapter.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/adapters/scope-adapter.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/adapters/tx-adapter.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/adapters/vfo-adapter.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/commands/panel-commands.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/frontend-runtime.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/index.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/props/panel-props.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/scope-controller.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/runtime/system-controller.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/__tests__/audio.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/__tests__/capabilities.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/__tests__/commands.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/__tests__/connection.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/__tests__/radio.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/__tests__/ui.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/audio.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/capabilities.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/commands.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/connection.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/connection.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/layout.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/lcd-contrast.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/lcd-display-mode.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/qsy-history.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/radio.svelte.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/radio.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/tuning.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/stores/ui.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/transport/__tests__/http-client.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/transport/__tests__/ws-client.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/transport/http-client.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/transport/ws-client.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/types/capabilities.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/types/protocol.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/types/state.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/utils/__tests__/battery.test.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/utils/battery.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/utils/filter-width.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/utils/haptics.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/utils/meter-utils.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/utils/smoothing.svelte.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/utils/tx-permit.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/lib/utils/uuid.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/main.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/skins/amber-lcd/LcdSkin.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/skins/desktop-v2/DesktopSkin.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/skins/lcd-cockpit/LcdCockpitSkin.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/skins/lcd-scope/LcdScopeSkin.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/skins/mobile/MobileSkin.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/skins/registry.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/skins/sdr-test/SdrTestSkin.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/skins/sdr-test/SdrVfoScreen.svelte +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/styles/animations.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/styles/tokens.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/types/pwa.d.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/src/types/webcodecs.d.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/static/fonts/DSEG7Classic-Bold.woff2 +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/svelte.config.js +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/tests/e2e/v2-ui-interactive.impl.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/tsconfig.app.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/tsconfig.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/tsconfig.node.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/frontend/vite.config.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/mkdocs.yml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/_keyboard-default.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/_schema.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/_schema_v2.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/examples/ftx1.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/examples/lab599_tx500.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/examples/sdrplay_rspdx.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/examples/xiegu_x6200.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/ftx1.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/ic705.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/ic7300.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/ic7610.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/ic9700.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/tx500.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/rigs/x6100.toml +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/icom_lan/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/icom_lan/_cli_shim.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/__main__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_audio_codecs.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_audio_recovery.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_audio_runtime_mixin.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_audio_transcoder.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_bounded_queue.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_bridge_metrics.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_bridge_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_civ_rx.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_connection_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_control_phase.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_dual_rx_runtime.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_optional_deps.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_platformdirs_migration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_poller_types.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_queue_pressure.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_runtime_protocols.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_scope_runtime.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_shared_state_runtime.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_state_cache.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/_state_queries.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/_bridge_metrics.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/_bridge_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/_codecs.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/_macos_uid.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/_transcoder.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/_usb_resolve.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/analyzer.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/backend.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/bridge.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/bus.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/config.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/dsp.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/fft_scope.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/resample.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio/usb_driver.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio_analyzer.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio_bridge.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio_bus.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/audio_fft_scope.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/auth.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/_icom_serial_base.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/config.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/discovery.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/factory.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/ic705/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/ic705/core.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/ic705/serial.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/ic7300/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/ic7300/core.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/ic7300/serial.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/ic9700/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/ic9700/core.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/ic9700/serial.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/icom7610/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/icom7610/drivers/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/icom7610/drivers/contracts.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/icom7610/drivers/serial_civ_link.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/icom7610/drivers/serial_session.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/icom7610/drivers/serial_stub.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/icom7610/drivers/usb_audio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/icom7610/lan.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/icom7610/serial.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/yaesu_cat/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/yaesu_cat/parser.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/yaesu_cat/poller.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/yaesu_cat/radio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/backends/yaesu_cat/transport.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/capabilities.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/civ.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/cli/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/cli/_diagnose.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/command_map.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/command_spec.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commander.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/_builders.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/_codec.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/_frame.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/antenna.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/command_map.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/command_spec.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/commander.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/cw.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/dsp.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/freq.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/levels.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/memory.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/meters.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/mode.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/power.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/ptt.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/scope.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/speech.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/system.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/tone.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/tx_band.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/commands/vfo.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/_bounded_queue.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/_optional_deps.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/_queue_pressure.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/_state_cache.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/auth.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/capabilities.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/civ.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/env_config.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/exceptions.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/radio_protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/radio_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/transport.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/core/types.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/cw_auto_tuner.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/_discovery.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/_error_ring.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/_errors.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/_logging.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/_manifest.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/bundle.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributor.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/audio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/config.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/dependencies.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/errors.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/invocation.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/logs.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/radio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/contributors/system.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/redaction.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/diagnostics/upload.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/discovery.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/dsp/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/dsp/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/dsp/exceptions.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/dsp/nodes/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/dsp/nodes/base.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/dsp/nodes/nr_scipy.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/dsp/pipeline.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/dsp/resample.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/dsp/tap_registry.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/env_config.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/exceptions.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/ic705.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/meter_cal.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/profiles/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/profiles/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/profiles/rig_loader.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/profiles_runtime.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/proxy.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/py.typed +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/radio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/radio_initial_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/radio_protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/radio_reconnect.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/radio_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/radio_state_snapshot.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/radios.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rig_loader.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/audit.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/circuit_breaker.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/poller.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/routing.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/state_cache.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/rigctld/utils.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_audio_recovery.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_civ_rx.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_connection_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_dual_rx_runtime.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_poller_types.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_runtime_protocols.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_scope_runtime.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_shared_state_runtime.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/_state_queries.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/cw_auto_tuner.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/ic705.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/meter_cal.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/proxy.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/radio_initial_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/radio_reconnect.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/radios.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/startup_checks.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/runtime/sync.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/scope/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/scope/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/scope/render.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/scope_render.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/startup_checks.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/sync.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/transport.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/types.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/usb_audio_resolve.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/LAYER.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/_delta_encoder.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/band_plan.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/discovery.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/dx_cluster.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/eibi.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/handlers/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/handlers/control.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/handlers/diagnostics.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/handlers/scope.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/radio_poller.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/rtc.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/runtime_helpers.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/server.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/apple-touch-icon.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/assets/ControlButtonDemo-BfIA7PVw.js +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/assets/ControlButtonDemo-Ddi7py1_.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/assets/index-BJJbl289.js +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/assets/index-DV-TVNde.css +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/lockup-dark.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/lockup-light.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/lockup-mono.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/mark-dark.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/mark-light.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/mark-mono.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/marketing/github-social-preview.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/marketing/readme-banner.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/wordmark-dark.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/wordmark-light.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/brand/wordmark-mono.svg +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicon-16.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicon-32.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicon-48.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicon.ico +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon-128.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon-16.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon-180.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon-192.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon-256.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon-32.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon-48.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon-512.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon-64.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/ink/favicon.ico +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon-128.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon-16.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon-180.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon-192.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon-256.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon-32.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon-48.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon-512.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon-64.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/paper/favicon.ico +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/transparent/favicon-128.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/transparent/favicon-16.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/transparent/favicon-180.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/transparent/favicon-192.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/transparent/favicon-256.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/transparent/favicon-32.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/transparent/favicon-48.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/transparent/favicon-512.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/favicons/transparent/favicon-64.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/index.html +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/manifest.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/og-image.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/pwa-192x192.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/pwa-512x512.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static/twitter-card.png +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/static.old/index.html +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/tls.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/web_routing.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/web_startup.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/src/rigplane/web/websocket.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/_audio_stream_fake.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/_caps.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/_command_test_helpers.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/_diagnostics_mock_server.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/_helpers.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/_perf_helpers.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/conftest.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/contracts/__init__.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/contracts/test_lazy_imports.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/e2e/package.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/e2e/v2-ui-interactive.spec.ts +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/fixtures/civ_rx_frames.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/golden/dump_state_ic7610.txt +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/golden/dump_state_yaesu.txt +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/golden/fldigi_dual_rx_session.txt +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/golden/js8call_dual_rx_session.txt +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/golden/protocol_golden.json +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/golden/wsjtx_dual_rx_session.txt +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/README.md +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/conftest.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/full_handshake.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/logging_utils.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/probe_handshake.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/probe_login.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_audio_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_audio_routing.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_connect.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_controls_extended_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_dsp_levels_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_get_freq.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_media_scope_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_memory_set_only.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_negative_auth_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_operator_toggles_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_radio_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_reliability_matrix_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_rigctld_golden_replay.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_rigctld_wsjtx.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_rit_tuner_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_scope_advanced_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_tone_tsql_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/integration/test_vfo_dual_watch_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/mock_server.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_analyzer.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_backend.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_bridge.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_bridge_stereo.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_bus.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_codec.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_codecs.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_config.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_dsp.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_fft_scope.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_fullduplex.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_recovery.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_resample.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_rx_tx_transition.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_stress.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_transcoder_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audio_watchdog.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_audit.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_auth.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_backend_contract_matrix.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_backend_factory.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_bounded_queue.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_bsr_band_switching.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_circuit_breaker.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_civ.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_civ_command_profiling.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_civ_rx_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_civ_rx_dispatch_golden.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_civ_rx_mixin_host.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cli_async.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cli_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cli_diagnose.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cli_diagnose_lazy_import.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cli_e2e.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cli_model.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cmd29_parsing.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_command_map_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_command_spec.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_commander.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_commands_extended.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cw_auto_tune_wiring.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_cw_auto_tuner.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_delta_encoder.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_bundle.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_contributor.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_contributors_batch1.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_contributors_batch2.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_contributors_batch3.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_e2e.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_logging.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_privacy_invariants.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_redaction.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_diagnostics_upload.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_discovery.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_discovery_responder.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_docs_runtime_sync.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_dsp_filter_family.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_dsp_levels_part1.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_dsp_levels_part2.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_dsp_nodes.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_dsp_nr_scipy.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_dsp_pipeline.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_dx_cluster.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_env_config.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_exports.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_frontend_e2e_config.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_ftx1_audio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_ftx1_radio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_golden_protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_handlers_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_handlers_dsp_407_408.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_handlers_protocol_gap_399.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_handlers_sys_band.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_ic705_backend.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_ic7300_backend.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_ic7610_parity_matrix.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_ic9700_backend.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_icom7610_serial_radio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_icom_lan_shim.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_icom_receiver_tier.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_issue_141_core_refactor.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_jitter_buffer.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_lifecycle_diagnostics.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_macos_audio_uid.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_main_sub_tracking.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_memory_commands.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_mock_integration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_naming_parity.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_operator_toggles.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_per_receiver_vfo_roundtrip.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_performance_regressions.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_platformdirs_migration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_poller.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_poller_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_power_unit_extension.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_profiles_routing.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_proxy.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_proxy_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_public_api_surface.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_radio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_radio_connect.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_radio_extended.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_radio_poller_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_radio_protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_radio_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_radios.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rate_limiter.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_reconnect.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rf_gain_af_level.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rig_ic7300.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rig_ic7610.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rig_loader.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rig_multi_vendor.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rig_schema.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rigctld_consistency.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rigctld_dump_state_snapshot.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rigctld_init_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rigctld_protocol.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rigctld_routable_extension.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_rigctld_utils.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_scope.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_scope_render.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_scope_render_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_scope_stress.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_security_headers.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_selected_freq_mode.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_serial_backend_smoke.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_serial_civ_link.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_serial_stub_framing.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_server_wire.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_shared_state_runtime.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_state_cache.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_state_cache_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_state_pollable_extension.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_state_queries.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_supports_command.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_swr_calibration.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_sync.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_sync_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_tap_registry.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_tls.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_token_renewal.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_tone_tsql.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_transport.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_tx_band_edge.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_usb_audio_capable_extension.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_usb_audio_resolve.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_usb_audio_stub.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_vfo_dual_watch.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_vox_tone_state.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_audio_streaming_profile.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_auth_compare_digest.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_capability_guards.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_diagnostics.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_post_body_cap.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_ptt_readonly.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_runtime_helpers.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_server.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_server_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_web_server_token_redaction.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_webrtc_signaling.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_websocket_coverage.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_yaesu_audio.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_yaesu_cat_parser.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_yaesu_cat_poller.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_yaesu_cat_transport.py +0 -0
- {rigplane-2.0.2 → rigplane-2.0.3}/tests/test_yaesu_cli_factory.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rigplane
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
4
4
|
Summary: Python library for controlling Icom transceivers over LAN (UDP) — no wfview/hamlib required
|
|
5
5
|
Project-URL: Homepage, https://rigplane.dev/
|
|
6
6
|
Project-URL: Documentation, https://rigplane.dev/
|
|
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.0.3] — 2026-05-07
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- WSJT-X LAN TX audio on direct Icom LAN: send raw PCM when conninfo negotiates `PCM_1CH_16BIT` instead of pushing Opus bytes into the radio's PCM TX stream (#1430, #1448, 999953e2). Adds explicit TX codec tracking; routes WSJT-X packet modes to DATA2/LAN only for direct Icom multi-DATA radios; keeps DATA1 user-owned (prewarm/profile-apply/state-restore no longer rewrite DATA1 MOD input). Validated on IC-7610 LAN — continuous TX audio reaches the radio.
|
|
14
|
+
|
|
15
|
+
### Other
|
|
16
|
+
- Align `tests/test_pcm_e2e.py` with the new PCM-passthrough TX path: pin `_audio_tx_codec = AudioCodec.OPUS_1CH` on the test radio so the dummy transcoder is exercised, and use a properly-sized 1920-byte synthetic frame for loopback TX (6ad40e91, #1448 follow-up).
|
|
17
|
+
|
|
10
18
|
## [2.0.2] — 2026-05-06
|
|
11
19
|
|
|
12
20
|
### Added
|
|
@@ -1223,7 +1231,8 @@ These deprecation closures were announced in v0.19 and dropped on schedule.
|
|
|
1223
1231
|
- Transport layer, authentication, CI-V commands, meters, PTT, keep-alive.
|
|
1224
1232
|
- Clean-room Icom LAN UDP protocol implementation.
|
|
1225
1233
|
|
|
1226
|
-
[Unreleased]: https://github.com/rigplane/rigplane-core/compare/v2.0.
|
|
1234
|
+
[Unreleased]: https://github.com/rigplane/rigplane-core/compare/v2.0.3...HEAD
|
|
1235
|
+
[2.0.3]: https://github.com/rigplane/rigplane-core/compare/v2.0.2...v2.0.3
|
|
1227
1236
|
[2.0.2]: https://github.com/rigplane/rigplane-core/compare/v2.0.1...v2.0.2
|
|
1228
1237
|
[2.0.1]: https://github.com/rigplane/rigplane-core/compare/v2.0.0...v2.0.1
|
|
1229
1238
|
[2.0.0]: https://github.com/rigplane/rigplane-core/compare/v1.1.0...v2.0.0
|
|
@@ -144,17 +144,18 @@ limit is undocumented but observed empirically and matches the wfview source:
|
|
|
144
144
|
// wfview: audio.data.mid(len, 1364)
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
`push_tx()`
|
|
147
|
+
`push_tx()` automatically chunks oversized payloads:
|
|
148
148
|
|
|
149
149
|
```
|
|
150
|
-
|
|
150
|
+
push_tx(pcm_frame) # 1920-byte 20ms PCM frame @ 48kHz/16-bit
|
|
151
151
|
→ chunk 0: bytes [0 : 1364] → 1364-byte UDP payload ✓
|
|
152
152
|
→ chunk 1: bytes [1364 : 1920] → 556-byte UDP payload ✓
|
|
153
153
|
```
|
|
154
154
|
|
|
155
155
|
The two chunk sizes — 1364 and 556 bytes — correspond to the fixed audio payload sizes
|
|
156
|
-
documented in wfview for the IC-7610.
|
|
157
|
-
|
|
156
|
+
documented in wfview for the IC-7610. Low-level callers do not need to pre-chunk payloads.
|
|
157
|
+
The high-level `push_audio_tx_pcm()` API still requires one complete PCM frame at the
|
|
158
|
+
configured sample rate, channel count, and frame duration.
|
|
158
159
|
|
|
159
160
|
## Usage
|
|
160
161
|
|
|
@@ -204,10 +205,15 @@ async with create_radio(config) as radio:
|
|
|
204
205
|
config = LanBackendConfig(host="192.168.1.100", username="u", password="p")
|
|
205
206
|
async with create_radio(config) as radio:
|
|
206
207
|
await radio.start_audio_tx_opus()
|
|
207
|
-
await radio.push_audio_tx_opus(
|
|
208
|
+
await radio.push_audio_tx_opus(audio_payload)
|
|
208
209
|
await radio.stop_audio_tx_opus()
|
|
209
210
|
```
|
|
210
211
|
|
|
212
|
+
The low-level method names are historical. For direct Icom LAN sessions,
|
|
213
|
+
rigplane currently negotiates TX as `PCM_1CH_16BIT`, so the TX payload sent to
|
|
214
|
+
the radio is raw PCM16LE. Opus TX payloads are only valid for endpoints that
|
|
215
|
+
negotiate an Opus TX codec, such as wfview-compatible server paths.
|
|
216
|
+
|
|
211
217
|
### TX Audio (high-level PCM)
|
|
212
218
|
|
|
213
219
|
```python
|
|
@@ -294,5 +300,6 @@ For RX PCM, migrate callback-side decoding to the built-in API:
|
|
|
294
300
|
|
|
295
301
|
For TX PCM, migrate manual Opus encoding to the built-in API:
|
|
296
302
|
|
|
297
|
-
- Before:
|
|
303
|
+
- Before: manually prepare the low-level negotiated-codec payload and call
|
|
304
|
+
`push_audio_tx_opus()`.
|
|
298
305
|
- Now: `start_audio_tx_pcm()` and `push_audio_tx_pcm()` with fixed-size PCM frames.
|
|
@@ -47,7 +47,7 @@ async with create_radio(config) as radio:
|
|
|
47
47
|
| `vfo` | `str \| None` | `None` | Select VFO: `"A"` or `"B"` |
|
|
48
48
|
| `data_mode` | `bool \| None` | `None` | `True` = enable DATA mode, `False` = disable |
|
|
49
49
|
| `data_off_mod_input` | `int \| None` | `None` | DATA-OFF modulation input source index |
|
|
50
|
-
| `data1_mod_input` | `int \| None` | `None` | DATA-1 modulation input source index |
|
|
50
|
+
| `data1_mod_input` | `int \| None` | `None` | DATA-1 modulation input source index. Captured for compatibility; apply/restore do not rewrite it because DATA1 is user-owned. |
|
|
51
51
|
| `squelch_level` | `int \| None` | `None` | Squelch level (0 = open) |
|
|
52
52
|
| `equalize_vfo` | `bool` | `False` | Copy active VFO to both VFOs |
|
|
53
53
|
| `scope_enabled` | `bool \| None` | `None` | `True` = enable spectrum scope |
|
|
@@ -97,6 +97,18 @@ When a CAT client connects for the first time:
|
|
|
97
97
|
- This eliminates a known first-TX latency when WSJT-X switches
|
|
98
98
|
from plain SSB to packet mode (PKTUSB).
|
|
99
99
|
|
|
100
|
+
When `--wsjtx-compat` is used with a direct Icom LAN radio connection on a
|
|
101
|
+
radio profile with multiple DATA sub-modes such as the IC-7610, rigplane treats
|
|
102
|
+
WSJT-X packet-mode requests as LAN audio operation:
|
|
103
|
+
|
|
104
|
+
- `PKTUSB`, `PKTLSB`, and `PKTRTTY` are mapped to DATA2 instead of DATA1.
|
|
105
|
+
- DATA2 modulation input is set to LAN.
|
|
106
|
+
- DATA1 modulation input is not changed.
|
|
107
|
+
|
|
108
|
+
For USB/serial radio connections, including cases where rigplane bridges local
|
|
109
|
+
USB audio devices for remote use, the compatibility mapping remains the legacy
|
|
110
|
+
DATA1 behavior.
|
|
111
|
+
|
|
100
112
|
### When to use it
|
|
101
113
|
|
|
102
114
|
- **Use** `--wsjtx-compat` if you run WSJT-X, JTDX, or JS8Call
|
|
@@ -106,8 +118,10 @@ When a CAT client connects for the first time:
|
|
|
106
118
|
|
|
107
119
|
### What it changes on the radio
|
|
108
120
|
|
|
109
|
-
|
|
110
|
-
|
|
121
|
+
In USB/serial CAT operation, only the DATA mode flag (CI-V `0x1A 0x06`) is
|
|
122
|
+
changed. In direct Icom LAN operation on multi-DATA radios, rigplane may also
|
|
123
|
+
set the selected LAN DATA sub-mode's modulation input to LAN. DATA1 is treated
|
|
124
|
+
as user-owned and is not rewritten by prewarm, profile apply, or state restore.
|
|
111
125
|
|
|
112
126
|
## Known Behavior
|
|
113
127
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Audio Route Resolver Design
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-05-07
|
|
4
|
+
**Status:** design
|
|
5
|
+
**Scope:** rigplane-core route contract, with rigplane-pro integration notes
|
|
6
|
+
|
|
7
|
+
## Problem
|
|
8
|
+
|
|
9
|
+
`--bridge` is an implementation mechanism, not enough information to decide how
|
|
10
|
+
CAT packet modes should be mapped on the radio.
|
|
11
|
+
|
|
12
|
+
Two valid setups both use a bridge but need different radio policies:
|
|
13
|
+
|
|
14
|
+
- Direct Icom LAN radio: TX audio is streamed to the radio over the Icom LAN
|
|
15
|
+
audio session. WSJT-X packet modes should use DATA2 with DATA2 MOD input LAN
|
|
16
|
+
on multi-DATA radios such as the IC-7610.
|
|
17
|
+
- USB/serial radio with local or remote audio bridge: TX audio reaches the radio
|
|
18
|
+
through the radio's USB audio device or another local input. WSJT-X packet
|
|
19
|
+
modes should keep the legacy DATA1 behavior, usually with DATA1 MOD input USB.
|
|
20
|
+
|
|
21
|
+
The route decision must therefore come from the actual radio transport and audio
|
|
22
|
+
capabilities, not from whether a local loopback bridge is enabled.
|
|
23
|
+
|
|
24
|
+
## Design Principle
|
|
25
|
+
|
|
26
|
+
`bridge` means "local audio loopback mechanism".
|
|
27
|
+
|
|
28
|
+
`audio route` means "source of truth for radio audio and DATA-mode policy".
|
|
29
|
+
|
|
30
|
+
DATA2/LAN is only valid when TX audio really enters the radio over direct Icom
|
|
31
|
+
LAN audio. DATA1 remains user-owned unless a future explicit USB route policy
|
|
32
|
+
chooses to manage DATA1 MOD input.
|
|
33
|
+
|
|
34
|
+
## Core Route Model
|
|
35
|
+
|
|
36
|
+
Add a small route model in core:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
@dataclass(frozen=True)
|
|
40
|
+
class AudioRoute:
|
|
41
|
+
radio_transport: Literal["lan", "serial", "remote"]
|
|
42
|
+
tx_audio_source: Literal["lan", "usb", "acc", "unavailable"]
|
|
43
|
+
rx_audio_source: Literal["lan", "usb", "acc", "unavailable"]
|
|
44
|
+
data_mode_policy: Literal["data2_lan", "data1_usb", "legacy"]
|
|
45
|
+
bridge_required: bool
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Initial policy mapping:
|
|
49
|
+
|
|
50
|
+
| Condition | Route | DATA policy |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| direct Icom LAN backend, native LAN audio, multi-DATA radio | `tx_audio_source="lan"` | `data2_lan` |
|
|
53
|
+
| direct Icom LAN backend, single-DATA radio | `tx_audio_source="lan"` | `legacy` |
|
|
54
|
+
| Icom serial/USB backend with local USB audio bridge | `tx_audio_source="usb"` | `data1_usb` or legacy DATA1 |
|
|
55
|
+
| remote/pro server | declared by server capabilities | route decided from server declaration |
|
|
56
|
+
| no usable audio route | `tx_audio_source="unavailable"` | no automatic DATA source changes |
|
|
57
|
+
|
|
58
|
+
## Core Responsibilities
|
|
59
|
+
|
|
60
|
+
Core should:
|
|
61
|
+
|
|
62
|
+
- expose backend identity and audio capabilities in a machine-readable form;
|
|
63
|
+
- resolve `AudioRoute` from the active radio/backend/profile;
|
|
64
|
+
- derive `RigctldConfig.wsjtx_data_mode` and `wsjtx_data_mod_input` from
|
|
65
|
+
`AudioRoute.data_mode_policy`;
|
|
66
|
+
- keep `push_audio_tx_pcm()` aligned with the negotiated TX codec, not method
|
|
67
|
+
names such as `push_audio_tx_opus`;
|
|
68
|
+
- avoid automatic DATA1 MOD writes in prewarm, profile apply, and state restore.
|
|
69
|
+
|
|
70
|
+
Core should not:
|
|
71
|
+
|
|
72
|
+
- treat `--bridge` as proof of LAN audio;
|
|
73
|
+
- infer USB vs LAN from a virtual audio device name;
|
|
74
|
+
- make proprietary product decisions about always-on bridge UX.
|
|
75
|
+
|
|
76
|
+
## Pro Responsibilities
|
|
77
|
+
|
|
78
|
+
Pro should start with `audio_route=auto` by default:
|
|
79
|
+
|
|
80
|
+
1. connect to the radio or remote server;
|
|
81
|
+
2. read backend/capability information;
|
|
82
|
+
3. resolve the audio route;
|
|
83
|
+
4. start the required LAN session, USB bridge, virtual device, or remote bridge;
|
|
84
|
+
5. configure embedded rigctld from the route policy;
|
|
85
|
+
6. show a user-facing route status such as:
|
|
86
|
+
- `Audio: LAN direct`
|
|
87
|
+
- `Audio: USB via local bridge`
|
|
88
|
+
- `Audio: USB via remote server`
|
|
89
|
+
- `Audio unavailable: <reason>`
|
|
90
|
+
|
|
91
|
+
Pro should preserve explicit override controls for support and debugging, but
|
|
92
|
+
the default commercial experience should not require the user to know whether to
|
|
93
|
+
pass `--bridge`.
|
|
94
|
+
|
|
95
|
+
## Testing Strategy
|
|
96
|
+
|
|
97
|
+
Core tests should cover:
|
|
98
|
+
|
|
99
|
+
- direct LAN route resolves to DATA2/LAN on multi-DATA profiles;
|
|
100
|
+
- direct LAN route falls back on single-DATA profiles;
|
|
101
|
+
- serial/USB route with bridge does not select DATA2/LAN;
|
|
102
|
+
- rigctld packet mode mapping follows route-derived config;
|
|
103
|
+
- profile apply and restore never rewrite DATA1 MOD automatically;
|
|
104
|
+
- codec contract sends PCM as raw PCM when negotiated TX codec is PCM.
|
|
105
|
+
|
|
106
|
+
Pro tests should cover:
|
|
107
|
+
|
|
108
|
+
- startup auto-routes direct LAN, serial/USB, and remote server scenarios;
|
|
109
|
+
- bridge lifecycle follows the resolved route, not user-visible flags;
|
|
110
|
+
- diagnostics and UI expose the selected route and failure reason;
|
|
111
|
+
- explicit overrides can force or disable bridge behavior for support cases.
|
|
112
|
+
|
|
113
|
+
## Migration Plan
|
|
114
|
+
|
|
115
|
+
1. Keep the current backend-based guard as a short-term safety patch.
|
|
116
|
+
2. Add `AudioRoute` and a resolver in core.
|
|
117
|
+
3. Replace direct `backend_id` checks in CLI/rigctld wiring with route-derived
|
|
118
|
+
policy.
|
|
119
|
+
4. Expose route information through diagnostics/status APIs.
|
|
120
|
+
5. Update pro to default to auto route and consume the core resolver/status.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Core Issue Draft: Build automated audio pipeline harness for WSJT-X/LAN/USB routing
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
Debugging the IC-7610 TX audio bridge required repeated manual steps across
|
|
6
|
+
machines: start rigplane, start WSJT-X, press Tune, listen locally, watch the
|
|
7
|
+
radio waterfall, inspect logs, and infer whether the failure was PortAudio,
|
|
8
|
+
bridge capture, codec negotiation, rigctld packet mode, DATA source selection,
|
|
9
|
+
or LAN audio TX payload format.
|
|
10
|
+
|
|
11
|
+
That workflow is too slow and too fragile for future audio work. We need an
|
|
12
|
+
automated harness that exercises the whole pipeline with synthetic audio and
|
|
13
|
+
observable sinks.
|
|
14
|
+
|
|
15
|
+
Related route-policy issue: rigplane/rigplane-core#1446.
|
|
16
|
+
|
|
17
|
+
## Goal
|
|
18
|
+
|
|
19
|
+
Create a layered audio pipeline test harness that can run without a human
|
|
20
|
+
pressing WSJT-X Tune, while still allowing optional hardware-assisted validation
|
|
21
|
+
against real radios.
|
|
22
|
+
|
|
23
|
+
## Proposed Test Layers
|
|
24
|
+
|
|
25
|
+
### Layer 1: Pure in-process pipeline
|
|
26
|
+
|
|
27
|
+
- Synthetic PCM source, e.g. 1 kHz tone frames.
|
|
28
|
+
- Fake bridge input/output devices.
|
|
29
|
+
- Fake radio audio sink that records pushed TX payloads.
|
|
30
|
+
- Assertions:
|
|
31
|
+
- non-zero peak/RMS reaches bridge TX capture path;
|
|
32
|
+
- expected frame count and continuity;
|
|
33
|
+
- PCM TX stays raw PCM when negotiated codec is `PCM_1CH_16BIT`;
|
|
34
|
+
- Opus encode is used only when negotiated TX codec is Opus;
|
|
35
|
+
- no silence is introduced by downmix/resampling/chunking.
|
|
36
|
+
|
|
37
|
+
### Layer 2: rigctld + bridge integration
|
|
38
|
+
|
|
39
|
+
- Run embedded rigctld against fake radio/backend.
|
|
40
|
+
- Replay WSJT-X-like rigctl commands: `M PKTUSB`, `T 1`, `T 0`.
|
|
41
|
+
- Feed synthetic audio during the TX window.
|
|
42
|
+
- Assertions:
|
|
43
|
+
- PTT transitions occur;
|
|
44
|
+
- packet mode maps to the route-derived DATA policy;
|
|
45
|
+
- DATA1 MOD is not touched automatically;
|
|
46
|
+
- TX audio payload continues for the whole TX window.
|
|
47
|
+
|
|
48
|
+
### Layer 3: OS audio backend smoke
|
|
49
|
+
|
|
50
|
+
- Use PortAudio/sounddevice with a deterministic local virtual device when
|
|
51
|
+
available, or a fake backend in CI.
|
|
52
|
+
- Feed synthetic tone into the configured TX device.
|
|
53
|
+
- Capture through the same backend path used by `AudioBridge`.
|
|
54
|
+
- Assertions:
|
|
55
|
+
- device selection uses the requested RX/TX devices;
|
|
56
|
+
- capture is non-zero under the same process/env as rigplane;
|
|
57
|
+
- no regression to all-zero capture when RX output is also open.
|
|
58
|
+
|
|
59
|
+
### Layer 4: hardware-assisted validation
|
|
60
|
+
|
|
61
|
+
- Optional test profile for real IC-7610 LAN at a configured host.
|
|
62
|
+
- No WSJT-X UI dependency: drive rigctld commands and synthetic audio directly.
|
|
63
|
+
- Capture logs and radio-side ACK/state where possible.
|
|
64
|
+
- Assertions:
|
|
65
|
+
- route policy selects DATA2/LAN for direct LAN multi-DATA radio;
|
|
66
|
+
- raw PCM TX produces continuous radio TX audio symptoms;
|
|
67
|
+
- no broad intermittent burst pattern from Opus-as-PCM mismatch.
|
|
68
|
+
|
|
69
|
+
## Requirements
|
|
70
|
+
|
|
71
|
+
- Tests must run through `uv`.
|
|
72
|
+
- CI-safe layers must not require radio hardware, microphone permissions, or
|
|
73
|
+
BlackHole/VB-Cable.
|
|
74
|
+
- Hardware/OS layers must be opt-in through environment variables and skip with
|
|
75
|
+
clear reasons.
|
|
76
|
+
- The harness must produce compact diagnostics: route, codec, frame count, RMS,
|
|
77
|
+
peak, drops, selected devices, and rigctld DATA policy.
|
|
78
|
+
- The harness must not depend on the WSJT-X GUI. WSJT-X behavior should be
|
|
79
|
+
represented by rigctl command replay and synthetic audio generation.
|
|
80
|
+
|
|
81
|
+
## Acceptance Criteria
|
|
82
|
+
|
|
83
|
+
- A developer can run one command to validate the in-process TX audio pipeline.
|
|
84
|
+
- A developer can run one command to validate rigctld packet-mode + TX audio
|
|
85
|
+
bridge behavior without a radio.
|
|
86
|
+
- Optional OS/hardware tests are documented and skipped unless explicitly
|
|
87
|
+
enabled.
|
|
88
|
+
- The previous IC-7610 failure modes would have been caught by automated tests:
|
|
89
|
+
- PCM negotiated but Opus bytes sent;
|
|
90
|
+
- DATA1 selected for direct LAN WSJT-X bridge;
|
|
91
|
+
- DATA1 MOD rewritten by profile apply/restore;
|
|
92
|
+
- PortAudio bridge TX capture reads all-zero frames.
|
|
93
|
+
|
|
94
|
+
## Notes
|
|
95
|
+
|
|
96
|
+
This is open-core scope because it validates generic audio routing, codec
|
|
97
|
+
contract, rigctld behavior, and backend-independent diagnostics. Pro can consume
|
|
98
|
+
the same harness for packaged desktop smoke tests.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Core Issue Draft: Design and implement AudioRoute resolver for WSJT-X DATA policy
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
During IC-7610 LAN TX bridge debugging we found that `--bridge` is not a reliable signal for choosing radio DATA policy. A bridge can be used both for direct Icom LAN audio workflows and for USB/serial audio workflows. Those require different packet-mode behavior:
|
|
6
|
+
|
|
7
|
+
- Direct Icom LAN TX audio: WSJT-X `PKTUSB`/`PKTLSB`/`PKTRTTY` should map to DATA2/LAN on multi-DATA radios such as IC-7610.
|
|
8
|
+
- USB/serial audio route, even with a local bridge: packet mode should remain legacy DATA1/USB behavior.
|
|
9
|
+
|
|
10
|
+
Canonical design doc: `docs/plans/2026-05-07-audio-route-resolver-design.md`.
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
- Add a core `AudioRoute` model/resolver that derives radio audio route from backend/profile/capabilities, not from `--bridge`.
|
|
15
|
+
- Route policies must distinguish at least:
|
|
16
|
+
- direct Icom LAN audio -> `data2_lan` when the profile supports multiple DATA modes;
|
|
17
|
+
- direct Icom LAN single-DATA profile -> legacy fallback;
|
|
18
|
+
- Icom serial/USB audio bridge -> DATA1/USB or legacy DATA1, never DATA2/LAN;
|
|
19
|
+
- unavailable/unknown route -> no automatic DATA source changes.
|
|
20
|
+
- Replace direct CLI/backend guard logic with route-derived `RigctldConfig` wiring.
|
|
21
|
+
- Keep DATA1 MOD user-owned by default: no automatic DATA1 MOD writes from prewarm, profile apply, or state restore.
|
|
22
|
+
- Keep TX codec behavior aligned with negotiated TX codec: direct Icom LAN PCM TX must send raw PCM, not Opus bytes.
|
|
23
|
+
|
|
24
|
+
## Acceptance Criteria
|
|
25
|
+
|
|
26
|
+
- Unit tests cover route resolution for direct LAN, serial/USB bridge, single-DATA fallback, and unavailable route.
|
|
27
|
+
- Rigctld tests prove packet-mode mapping follows route-derived policy.
|
|
28
|
+
- CLI/web startup tests prove route policy is not inferred from `--bridge` alone.
|
|
29
|
+
- Docs explain `bridge` vs `audio route` and DATA1/DATA2 ownership.
|
|
30
|
+
- Existing WSJT-X compatibility behavior is preserved for non-LAN routes.
|
|
31
|
+
|
|
32
|
+
## Notes
|
|
33
|
+
|
|
34
|
+
This is open-core scope: protocol correctness, backend capability modeling, route-derived rigctld policy, and public docs. Product auto-start behavior belongs in rigplane-pro.
|
|
@@ -593,7 +593,7 @@ class AudioStream:
|
|
|
593
593
|
self._tx_packets_sent = 0
|
|
594
594
|
logger.info("Audio TX started")
|
|
595
595
|
|
|
596
|
-
async def push_tx(self,
|
|
596
|
+
async def push_tx(self, audio_data: bytes) -> None:
|
|
597
597
|
"""Send an audio frame to the radio.
|
|
598
598
|
|
|
599
599
|
Large payloads (e.g. raw PCM) are automatically chunked to fit the
|
|
@@ -601,7 +601,7 @@ class AudioStream:
|
|
|
601
601
|
matching the wfview chunking behaviour.
|
|
602
602
|
|
|
603
603
|
Args:
|
|
604
|
-
|
|
604
|
+
audio_data: Payload encoded with the negotiated TX audio codec.
|
|
605
605
|
|
|
606
606
|
Raises:
|
|
607
607
|
RuntimeError: If not in transmitting state.
|
|
@@ -609,7 +609,7 @@ class AudioStream:
|
|
|
609
609
|
if self._state != AudioState.TRANSMITTING:
|
|
610
610
|
raise RuntimeError(f"Cannot push TX in state {self._state}")
|
|
611
611
|
|
|
612
|
-
data =
|
|
612
|
+
data = audio_data
|
|
613
613
|
offset = 0
|
|
614
614
|
while offset < len(data):
|
|
615
615
|
chunk = data[offset : offset + MAX_AUDIO_PAYLOAD]
|
|
@@ -670,17 +670,17 @@ def parse_audio_packet(data: bytes) -> AudioPacket | None:
|
|
|
670
670
|
|
|
671
671
|
|
|
672
672
|
def build_audio_packet(
|
|
673
|
-
|
|
673
|
+
audio_data: bytes,
|
|
674
674
|
*,
|
|
675
675
|
sender_id: int,
|
|
676
676
|
receiver_id: int,
|
|
677
677
|
send_seq: int,
|
|
678
678
|
ident: int = TX_IDENT,
|
|
679
679
|
) -> bytes:
|
|
680
|
-
"""Build a raw UDP audio packet from
|
|
680
|
+
"""Build a raw UDP audio packet from negotiated-codec audio data.
|
|
681
681
|
|
|
682
682
|
Args:
|
|
683
|
-
|
|
683
|
+
audio_data: Audio payload encoded with the negotiated stream codec.
|
|
684
684
|
sender_id: Our connection ID.
|
|
685
685
|
receiver_id: Radio's connection ID.
|
|
686
686
|
send_seq: Audio-level sequence number.
|
|
@@ -689,7 +689,7 @@ def build_audio_packet(
|
|
|
689
689
|
Returns:
|
|
690
690
|
Complete UDP packet bytes ready to send.
|
|
691
691
|
"""
|
|
692
|
-
total_len = AUDIO_HEADER_SIZE + len(
|
|
692
|
+
total_len = AUDIO_HEADER_SIZE + len(audio_data)
|
|
693
693
|
pkt = bytearray(total_len)
|
|
694
694
|
|
|
695
695
|
struct.pack_into("<I", pkt, 0x00, total_len) # len (LE)
|
|
@@ -700,7 +700,7 @@ def build_audio_packet(
|
|
|
700
700
|
struct.pack_into("<H", pkt, 0x10, ident) # ident (LE)
|
|
701
701
|
struct.pack_into(">H", pkt, 0x12, send_seq) # sendseq (BE)
|
|
702
702
|
# 0x14: unused (stays 0)
|
|
703
|
-
struct.pack_into(">H", pkt, 0x16, len(
|
|
703
|
+
struct.pack_into(">H", pkt, 0x16, len(audio_data)) # datalen (BE)
|
|
704
704
|
|
|
705
|
-
pkt[AUDIO_HEADER_SIZE:] =
|
|
705
|
+
pkt[AUDIO_HEADER_SIZE:] = audio_data
|
|
706
706
|
return bytes(pkt)
|
|
@@ -2499,6 +2499,11 @@ def _detect_loopback_hint() -> str | None:
|
|
|
2499
2499
|
return None
|
|
2500
2500
|
|
|
2501
2501
|
|
|
2502
|
+
def _uses_direct_lan_audio(radio: Radio) -> bool:
|
|
2503
|
+
"""Return True when the active radio backend streams TX audio over Icom LAN."""
|
|
2504
|
+
return getattr(radio, "backend_id", None) == "rigplane"
|
|
2505
|
+
|
|
2506
|
+
|
|
2502
2507
|
def _print_startup_banner(
|
|
2503
2508
|
*,
|
|
2504
2509
|
radio: Radio,
|
|
@@ -2727,10 +2732,20 @@ async def _cmd_web(radio: Radio, args: argparse.Namespace) -> int:
|
|
|
2727
2732
|
from rigplane.rigctld.server import RigctldServer
|
|
2728
2733
|
|
|
2729
2734
|
rigctld_port = getattr(args, "web_rigctld_port", 4532)
|
|
2735
|
+
wsjtx_compat = getattr(args, "wsjtx_compat", False)
|
|
2736
|
+
wsjtx_data_mode = None
|
|
2737
|
+
wsjtx_data_mod_input = None
|
|
2738
|
+
if wsjtx_compat and _uses_direct_lan_audio(radio):
|
|
2739
|
+
profile = getattr(radio, "profile", None)
|
|
2740
|
+
if getattr(profile, "data_mode_count", 1) >= 2:
|
|
2741
|
+
wsjtx_data_mode = 2
|
|
2742
|
+
wsjtx_data_mod_input = 5 # IC-7610 DATA2 MOD input: LAN
|
|
2730
2743
|
rigctld_config = RigctldConfig(
|
|
2731
2744
|
host="0.0.0.0",
|
|
2732
2745
|
port=rigctld_port,
|
|
2733
|
-
wsjtx_compat=
|
|
2746
|
+
wsjtx_compat=wsjtx_compat,
|
|
2747
|
+
wsjtx_data_mode=wsjtx_data_mode,
|
|
2748
|
+
wsjtx_data_mod_input=wsjtx_data_mod_input,
|
|
2734
2749
|
)
|
|
2735
2750
|
candidate = RigctldServer(radio, rigctld_config)
|
|
2736
2751
|
try:
|
|
@@ -180,8 +180,8 @@ def set_data1_mod_input(
|
|
|
180
180
|
from_addr: int = CONTROLLER_ADDR,
|
|
181
181
|
cmd_map: CommandMap | None = None,
|
|
182
182
|
) -> bytes:
|
|
183
|
-
if not 0 <= source <=
|
|
184
|
-
raise ValueError(f"DATA1 mod input must be 0-
|
|
183
|
+
if not 0 <= source <= 5:
|
|
184
|
+
raise ValueError(f"DATA1 mod input must be 0-5, got {source}")
|
|
185
185
|
return _build_ctl_mem_set(
|
|
186
186
|
_CTL_MEM_DATA1_MOD_INPUT,
|
|
187
187
|
source,
|
|
@@ -211,8 +211,8 @@ def set_data2_mod_input(
|
|
|
211
211
|
from_addr: int = CONTROLLER_ADDR,
|
|
212
212
|
cmd_map: CommandMap | None = None,
|
|
213
213
|
) -> bytes:
|
|
214
|
-
if not 0 <= source <=
|
|
215
|
-
raise ValueError(f"DATA2 mod input must be 0-
|
|
214
|
+
if not 0 <= source <= 5:
|
|
215
|
+
raise ValueError(f"DATA2 mod input must be 0-5, got {source}")
|
|
216
216
|
return _build_ctl_mem_set(
|
|
217
217
|
_CTL_MEM_DATA2_MOD_INPUT,
|
|
218
218
|
source,
|
|
@@ -242,8 +242,8 @@ def set_data3_mod_input(
|
|
|
242
242
|
from_addr: int = CONTROLLER_ADDR,
|
|
243
243
|
cmd_map: CommandMap | None = None,
|
|
244
244
|
) -> bytes:
|
|
245
|
-
if not 0 <= source <=
|
|
246
|
-
raise ValueError(f"DATA3 mod input must be 0-
|
|
245
|
+
if not 0 <= source <= 5:
|
|
246
|
+
raise ValueError(f"DATA3 mod input must be 0-5, got {source}")
|
|
247
247
|
return _build_ctl_mem_set(
|
|
248
248
|
_CTL_MEM_DATA3_MOD_INPUT,
|
|
249
249
|
source,
|
|
@@ -381,4 +381,6 @@ class RigctldConfig:
|
|
|
381
381
|
max_line_length: int = 1024 # max bytes per command line (OOM guard)
|
|
382
382
|
poll_interval: float = 0.2 # seconds between autonomous poll cycles
|
|
383
383
|
wsjtx_compat: bool = False # pre-warm DATA mode for WSJT-X-style CAT/PTT flow
|
|
384
|
+
wsjtx_data_mode: int | None = None # explicit DATA sub-mode for packet modes
|
|
385
|
+
wsjtx_data_mod_input: int | None = None # optional DATAx modulation source
|
|
384
386
|
command_rate_limit: float | None = None # max cmds/sec per client, None=unlimited
|
|
@@ -199,6 +199,12 @@ def _err(code: HamlibError) -> RigctldResponse:
|
|
|
199
199
|
return RigctldResponse(error=code)
|
|
200
200
|
|
|
201
201
|
|
|
202
|
+
def _profile_data_mode_count(radio: Any) -> int:
|
|
203
|
+
profile = getattr(radio, "profile", None)
|
|
204
|
+
count = getattr(profile, "data_mode_count", 1)
|
|
205
|
+
return count if isinstance(count, int) and count > 0 else 1
|
|
206
|
+
|
|
207
|
+
|
|
202
208
|
def _mode_to_hamlib_str(mode: object) -> str:
|
|
203
209
|
"""Normalize backend mode values to a hamlib-compatible string."""
|
|
204
210
|
if isinstance(mode, Mode):
|
|
@@ -354,6 +360,32 @@ class RigctldHandler:
|
|
|
354
360
|
radio, self._cache, getattr(config, "max_power_w", 100.0)
|
|
355
361
|
)
|
|
356
362
|
|
|
363
|
+
def _packet_data_mode_value(self) -> int | bool:
|
|
364
|
+
value = self._config.wsjtx_data_mode
|
|
365
|
+
if value is None:
|
|
366
|
+
return True
|
|
367
|
+
if value > _profile_data_mode_count(self._radio):
|
|
368
|
+
return True
|
|
369
|
+
return value
|
|
370
|
+
|
|
371
|
+
async def _apply_packet_data_mode(self, *, receiver: int = 0) -> int | bool:
|
|
372
|
+
data_mode = self._packet_data_mode_value()
|
|
373
|
+
source = self._config.wsjtx_data_mod_input
|
|
374
|
+
if source is not None and type(data_mode) is int:
|
|
375
|
+
setter = getattr(self._radio, f"set_data{data_mode}_mod_input", None)
|
|
376
|
+
if setter is not None:
|
|
377
|
+
await setter(source)
|
|
378
|
+
else:
|
|
379
|
+
logger.debug(
|
|
380
|
+
"rigctld: radio has no set_data%d_mod_input, skipping",
|
|
381
|
+
data_mode,
|
|
382
|
+
)
|
|
383
|
+
if receiver == 0:
|
|
384
|
+
await self._radio.set_data_mode(data_mode)
|
|
385
|
+
else:
|
|
386
|
+
await self._radio.set_data_mode(data_mode, receiver=receiver)
|
|
387
|
+
return data_mode
|
|
388
|
+
|
|
357
389
|
def _radio_state(self) -> RadioState | None:
|
|
358
390
|
state = getattr(self._radio, "radio_state", None)
|
|
359
391
|
return state if isinstance(state, RadioState) else None
|
|
@@ -621,9 +653,7 @@ class RigctldHandler:
|
|
|
621
653
|
base_mode_str, filter_width=filter_width, receiver=1
|
|
622
654
|
)
|
|
623
655
|
if requested_mode in packet_modes:
|
|
624
|
-
|
|
625
|
-
if set_data_mode is not None:
|
|
626
|
-
await set_data_mode(True, receiver=1)
|
|
656
|
+
await self._apply_packet_data_mode(receiver=1)
|
|
627
657
|
return _ok()
|
|
628
658
|
|
|
629
659
|
await self._radio.set_mode(base_mode_str, filter_width=filter_width)
|
|
@@ -631,7 +661,7 @@ class RigctldHandler:
|
|
|
631
661
|
# Only set DATA mode explicitly for packet modes.
|
|
632
662
|
# For non-packet modes, avoid hidden side-effects (do not force DATA off).
|
|
633
663
|
if requested_mode in packet_modes:
|
|
634
|
-
await self.
|
|
664
|
+
data_mode = await self._apply_packet_data_mode()
|
|
635
665
|
|
|
636
666
|
# Read-back sync: keep next get_mode deterministic for CAT clients.
|
|
637
667
|
# Some radios acknowledge set-data quickly but reflect packet mode
|
|
@@ -656,6 +686,7 @@ class RigctldHandler:
|
|
|
656
686
|
self._pending.mode = base_mode_str
|
|
657
687
|
self._pending.filter_width = filter_width
|
|
658
688
|
self._pending.data_mode = True
|
|
689
|
+
logger.debug("set_mode(%s): DATA%s selected", requested_mode, data_mode)
|
|
659
690
|
if not synced:
|
|
660
691
|
logger.debug(
|
|
661
692
|
"set_mode(%s): packet read-back not fully synced yet; cached optimistic state",
|