rigplane 2.7.0__tar.gz → 2.7.2__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.7.0 → rigplane-2.7.2}/PKG-INFO +1 -1
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/CHANGELOG.md +23 -1
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/__tests__/rx-player.test.ts +76 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/audio-manager.ts +4 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/rx-player.ts +81 -6
- {rigplane-2.7.0 → rigplane-2.7.2}/pyproject.toml +1 -1
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/bridge.py +30 -5
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/usb_driver.py +54 -8
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/_icom_serial_base.py +81 -5
- rigplane-2.7.2/src/rigplane/backends/icom7610/serial.py +52 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/server.py +23 -3
- rigplane-2.7.0/src/rigplane/web/static/assets/ControlButtonDemo-CbVyzA0h.js → rigplane-2.7.2/src/rigplane/web/static/assets/ControlButtonDemo-CnelvEOz.js +1 -1
- rigplane-2.7.0/src/rigplane/web/static/assets/index-BRBm4QAp.js → rigplane-2.7.2/src/rigplane/web/static/assets/index-MRf0y8eM.js +21 -21
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/index.html +1 -1
- rigplane-2.7.2/tests/hardware/test_x6200_serial_tx_smoke.py +60 -0
- rigplane-2.7.2/tests/integration/test_x6200_audio_scope_smoke.py +100 -0
- rigplane-2.7.2/tests/test_audio_scope_dispatch.py +265 -0
- rigplane-2.7.2/tests/test_serial_backend_tx_mor242.py +244 -0
- rigplane-2.7.2/tests/test_usb_audio_channel_clamp_mor238.py +267 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_x6200_rx_audio_mor236.py +17 -6
- {rigplane-2.7.0 → rigplane-2.7.2}/uv.lock +1 -1
- rigplane-2.7.0/src/rigplane/backends/icom7610/serial.py +0 -171
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/analyze-failure.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/audit-ui.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/decompose-issue.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/generate-tests.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/next.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/refactor.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/regression-check.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/scan-issues.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/solve-issue.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.claude/skills/release/SKILL.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/epic.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/feature.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/radio_report.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/ui-component.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/pull_request_template.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/scripts/check-rebrand-allowlist.sh +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/agent-review-gate.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/docs.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/full.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/publish.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/quick.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/rebrand-gate.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.gitignore +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/.importlinter +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/AGENTS.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/ARCHITECTURE.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/CHANGELOG.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/CLAUDE.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/CONTRIBUTING.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/LICENSE +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/README.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/ROADMAP.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/_config.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/arrl-hf.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/broadcast.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/iaru-r1.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/utility.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/4f4bcd28cb8d426ca58ec08b5035541e.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/AUDIO_STREAMING_PROFILE.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/CNAME +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/EXTENDED_PROTOCOL_RESEARCH.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/PERFORMANCE.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/PROJECT.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/SECURITY.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/audio.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/auth.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/backends-icom7610-drivers.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/backends-icom7610.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/backends.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/command-catalog.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/commander.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/commands.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/exceptions.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/public-api-surface.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/radio.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/radios.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/rig-loader.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/rigctld.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/scope.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/sync.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/transport.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/types.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/web.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/architecture/open-core-policy.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/assets/scope-example.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/capabilities-matrix.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/contracts/diagnostic-bundle-v1.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/contracts/diagnostic-bundle-v2.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/contracts/validation-matrix-v1.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/audio-recipes.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/cli.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/commands.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/configuration.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/connection.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/diagnostic-reports.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/hamlib-rigctld-provider.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/ic705-usb-setup.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/ic7300-usb-setup.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/ic7610-usb-setup.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/ic9700-usb-setup.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/installation.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/profiles.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/quickstart.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/radios.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/rig-profiles.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/troubleshooting.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/web-ui.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/wsjtx-setup.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/i18n/core-string-inventory.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/i18n/locale-contract.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/i18n/translating.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/index.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/architecture.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/cli-design.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/contributing.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/github-project-workflow.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/hamlib-provider-rollout.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/protocol.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/raw-civ-transactions.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/reliability-semantics.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/rfc-audio-v1-mini.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/migrate.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/operations/managed-runtime-packaging.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/opuslib-macos-fix.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/overrides/main.html +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/parity/README.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/parity/ic7610_command_matrix.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/parity/test_mapping.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-03-07-ui-architecture.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-05-desktop-companion-architecture.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-09-audio-backend-design.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-frontend-migration-plan.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-parity-matrix.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-presentation-architecture.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-rx-audio-trace.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-shared-frontend-runtime-contract.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-v2-lcd-runtime-audit.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-12-architecture-presentation.html +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-12-target-frontend-architecture.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-desktop-meters-panel.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-lcd-display-enhancements.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-mobile-ia.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-receiver-activation.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-spectrum-controls.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-ui-refinements-execution.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-19-lcd-layout-redesign-v2.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-19-lcd-layout-redesign.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-29-modularization-discovery.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-29-modularization-plan.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-29-panel-adapter-migration.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-29-ui-v1-deprecation-audit.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-03-diagnostic-data-collection-design.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-07-audio-route-resolver-design.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-08-audio-capability-probing.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-08-audio-codec-policy.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-08-audio-profile-policy-audit.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-08-usb-audio-negotiation.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-23-hamlib-provider-contract.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-28-real-radio-validation-matrix.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-28-universal-validation-matrix.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/archive/2026-03-04-dx-cluster.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/archive/2026-03-m5-m6-roadmap.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/archive/2026-04-19-lcd-twin-skins.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/build_orphan_report.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/classify_cycle_edges.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/cycles-classified.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/cycles.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/discovery_graph.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/external-usage.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/file-inventory.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/file-inventory.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/import-graph.dot +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/importlinter-config-draft.ini +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/init-snapshot.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/orphan-candidates.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/tach-config-draft.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/test-inventory.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/tooling-assessment.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/00-epic-final.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/00-epic.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/01-skeleton.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/02-core-foundationals.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/03-core-contracts.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/04-commands.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/05-profiles.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/06-scope.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/07-audio.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/08-runtime-radio.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/09-runtime-mixins.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/10-runtime-pollers.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/11-discovery-to-backends.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/12-cli.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/13-import-linter.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/14-followup-tests.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/15-followup-web-startup.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/2026-05-07-core-audio-pipeline-test-harness.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/2026-05-07-core-audio-route-resolver.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/radio-protocol.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/robots.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/screenshots/amber-lcd.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/screenshots/hero.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/screenshots/lcd-scope.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/running-validation.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/templates/ftx1.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/templates/ic7300.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/templates/tx500.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/templates/x6200.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/universal-matrix.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/.gitignore +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/README.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/eslint.config.js +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/index.html +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/package-lock.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/package.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/playwright.config.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/playwright.i18n.config.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/pnpm-lock.yaml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/apple-touch-icon.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/lockup-dark.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/lockup-light.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/lockup-mono.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/mark-dark.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/mark-light.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/mark-mono.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/marketing/github-social-preview.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/marketing/readme-banner.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/wordmark-dark.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/wordmark-light.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/wordmark-mono.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicon-16.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicon-32.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicon-48.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicon.ico +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-128.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-16.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-180.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-192.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-256.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-32.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-48.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-512.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-64.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon.ico +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-128.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-16.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-180.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-192.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-256.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-32.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-48.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-512.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-64.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon.ico +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-128.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-16.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-180.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-192.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-256.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-32.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-48.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-512.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-64.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/manifest.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/og-image.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/pwa-192x192.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/pwa-512x512.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/twitter-card.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/scripts/i18n-check.mjs +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/App.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/app.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/assets/svelte.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/shared/Toast.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/shared/__tests__/Toast.component.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/BandPlanOverlay.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/DxOverlay.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/EiBiBrowser.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/ScopeSettingsPopover.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/SpectrumCanvas.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/SpectrumPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/SpectrumToolbar.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/WaterfallCanvas.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/BandPlanOverlay.component.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/DxOverlay.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/EiBiBrowser.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/SpectrumPanel.component.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/SpectrumToolbar.component.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/band-plan-overlay.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/click-to-tune.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/passband-geometry.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/spectrum-panel-logic.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/spectrum-toolbar.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/tuning-indicator.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/band-plan-logic.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/passband-geometry.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/spectrum-logic.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/spectrum-toolbar-logic.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/AttenuatorControl.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/BandSelector.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/BottomSheet.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/CollapsiblePanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/ControlButtonDemo.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/InstallPrompt.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/LanguageSelector.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/PttFab.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/PullToRefresh.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/SegmentedButton.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/StatusBadge.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/ThemePicker.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/ValueControlLab.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/AttenuatorControl.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/BandSelector.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/BottomSheet.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/CollapsiblePanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/InstallPrompt.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/LanguageSelector.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/PullToRefresh.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/SegmentedButton.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/StatusBadge.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/broadcast-presets.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/band-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/broadcast-presets.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/button-tokens.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/control-button.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/install-prompt-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/status-badge-style.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/BipolarRenderer.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/DiscreteRenderer.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/DualParamRenderer.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/HBarRenderer.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/KnobRenderer.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/ValueControl.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/__tests__/ValueControl.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/__tests__/value-control-core.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/index.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/skin.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/skins/ProfessionalKnob.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/skins/index.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/value-control-core.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/value-control.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/dialogs/SendReportDialog.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/dialogs/__tests__/SendReportDialog.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/FrequencyDisplay.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/FrequencyDisplayInteractive.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/__tests__/FrequencyDisplay.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/__tests__/frequency-tuning.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/frequency-format.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/frequency-tuning.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/KeyboardHandler.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/LcdLayout.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/LeftSidebar.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/MobileNav.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/MobileRadioLayout.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/RadioLayout.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/RightSidebar.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/StatusBar.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/VfoHeader.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/KeyboardHandler.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/LeftSidebar.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/MobileRadioLayout.component.svelte.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/RadioLayout.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/SpectrumPanelStub.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/keyboard-map.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/mobile-layout-logic.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/mobile-nav.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/top-row-visual-regression.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/vfo-header.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/vfo-layout-tokens.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/keyboard-map.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/layout-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/mobile-chip-bar.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/mobile-layout-logic.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/mobile-nav-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/responsive.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/shortcut-hints.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/vfo-layout-tokens.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/BarGauge.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/LinearSMeter.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/NeedleGauge.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/SMeterDemo.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/__tests__/BarGauge.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/__tests__/LinearSMeter.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/__tests__/NeedleGauge.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/bar-gauge-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/needle-gauge-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/smeter-scale.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/AgcPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/AntennaPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/AudioRoutingControl.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/CwPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/DockMeterPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/DspPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/EssentialsPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/FilterPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/MemoryPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/MeterPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/MetersDockPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/ModePanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/RfFrontEnd.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/RitXitPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/RxAudioPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/ScanPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/TxPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/VoxPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/AgcPanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/AudioRoutingControl.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/CwPanel.component.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/DspPanel.component.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/DspPanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/FilterPanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/MeterPanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/MetersDockPanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/ModePanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/RfFrontEnd.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/RitXitPanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/RxAudioPanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/TxPanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/cw-panel-logic.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/dsp-panel-logic.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/filter-controls.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/agc-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-scope/AudioSpectrumCanvas.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-scope/AudioSpectrumPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-scope/__tests__/audio-spectrum-renderer.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-scope/audio-spectrum-renderer.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/cw-panel-logic.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/dsp-panel-logic.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/dsp-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/filter-controls.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/filter-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberAfScope.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberCockpit.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberFilterGhost.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberFrequency.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberIndStrip.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberLcdDisplay.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberMemoryStrip.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberScope.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberSmeter.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberSparkline.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberTelemetryStrip.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/LcdContrastControl.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/LcdDisplayModeControl.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/VfoControlPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/__tests__/lcd-components.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/__tests__/scope-frame.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/lcd-vintage.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/meter-utils.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/meter-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/rf-frontend-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/rit-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/tx-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/vfo/DualVfoDisplay.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/vfo/__tests__/DualVfoDisplay.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/fonts-digital.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/fonts.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/index.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/theme-switcher.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/amoled-black.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/ayu-dark.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/catppuccin-latte.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/catppuccin-mocha.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/crt-green.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/custom-ic7610.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/dracula.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/github-light.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/gruvbox-dark.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/gruvbox-light.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/high-contrast.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/index.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/lcd-blue.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/lcd-warm.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/nixie-tube.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/nord-light.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/nord.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/one-dark.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/solarized-dark.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/solarized-light.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/tokyo-night.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/tokens.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/vfo-themes/crt-green.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/vfo-themes/index.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/vfo-themes/lcd-blue.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/vfo-themes/nixie-tube.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/ActiveReceiverToggle.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/VfoOps.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/VfoPanel.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/__tests__/ActiveReceiverToggle.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/__tests__/VfoOps.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/__tests__/VfoPanel.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/vfo-ops-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/vfo-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/double-click.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/focus-mode-race.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/keyboard-wiring.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/state-adapter.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/vfo-wiring.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/command-bus.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/double-click.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/state-adapter.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/ControlButton.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/DotButton.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/FillButton.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/HardwareButton.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/HardwarePlainButton.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/StatusIndicator.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/__tests__/ControlButton.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/__tests__/ControlledHarness.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/index.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/roleMapping.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/types.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/SegmentedControl/index.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/__tests__/drag-reorder.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/__tests__/migrate-legacy-storage.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/actions/keyboard.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/api/__tests__/diagnostics.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/api/diagnostics.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/__tests__/audio-manager.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/__tests__/constants.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/__tests__/tx-mic.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/constants.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/tx-mic.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/data/__tests__/arrl-band-plan.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/data/arrl-band-plan.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/drag-reorder.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/gestures/gesture-recognizer.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/gestures/use-gesture.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/CONTRIBUTING.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/index.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/locale-contract.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/plural.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/pseudo-locale.smoke.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/pseudo.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/runtime.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/store.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/index.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/locale-contract.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/locales/en-US.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/locales/ja-JP.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/locales/ru-RU.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/plural.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/pseudo.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/runtime.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/store.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/types.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/LocalExtensionsHost.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/__tests__/dock-layout.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/__tests__/host-api.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/__tests__/manifest.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/dock-layout.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/host-api.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/keyboard-scope.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/manifest.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/media/__tests__/media-session.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/media/media-session.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/migrate-legacy-storage.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/radio/filter-controls.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/radio/pending-focus.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/radio/pending-focus.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/renderers/__tests__/spectrum-renderer.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/renderers/__tests__/waterfall-renderer.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/renderers/spectrum-renderer.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/renderers/waterfall-renderer.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/__tests__/frontend-runtime.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/__tests__/scope-controller.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/audio-adapter.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/capabilities-adapter.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/lcd-chrome-adapter.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/panel-adapters.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/qsy-history-adapter.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/scope-adapter.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/tx-adapter.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/vfo-adapter.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/commands/panel-commands.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/frontend-runtime.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/index.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/props/panel-props.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/scope-controller.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/system-controller.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/audio.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/capabilities.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/commands.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/connection.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/radio.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/ui.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/audio.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/capabilities.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/commands.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/connection.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/connection.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/layout.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/lcd-contrast.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/lcd-display-mode.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/qsy-history.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/radio.svelte.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/radio.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/tuning.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/ui.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/transport/__tests__/http-client.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/transport/__tests__/ws-client.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/transport/http-client.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/transport/ws-client.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/types/capabilities.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/types/protocol.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/types/state.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/__tests__/battery.test.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/battery.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/filter-width.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/haptics.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/meter-utils.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/smoothing.svelte.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/tx-permit.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/uuid.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/main.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/amber-lcd/LcdSkin.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/desktop-v2/DesktopSkin.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/lcd-cockpit/LcdCockpitSkin.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/lcd-scope/LcdScopeSkin.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/mobile/MobileSkin.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/registry.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/sdr-test/SdrTestSkin.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/sdr-test/SdrVfoScreen.svelte +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/styles/animations.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/styles/tokens.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/types/pwa.d.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/types/webcodecs.d.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/static/fonts/DSEG7Classic-Bold.woff2 +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/svelte.config.js +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/README.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/app-shell-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/app-shell-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/connection-overlay-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/connection-overlay-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/send-report-dialog-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/send-report-dialog-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/settings-modal-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/settings-modal-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/status-bar-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/status-bar-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/toast-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/toast-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/app-shell-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/app-shell-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/connection-overlay-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/connection-overlay-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/send-report-dialog-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/send-report-dialog-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/settings-modal-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/settings-modal-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/status-bar-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/status-bar-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/toast-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/toast-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/app-shell-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/app-shell-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/connection-overlay-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/connection-overlay-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/send-report-dialog-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/send-report-dialog-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/settings-modal-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/settings-modal-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/status-bar-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/status-bar-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/toast-desktop.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/toast-mobile.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/fixtures.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/i18n-visual.spec.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/v2-ui-interactive.impl.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tsconfig.app.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tsconfig.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tsconfig.node.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/frontend/vite.config.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/hooks/sitemap_noindex.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/mkdocs.yml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/_keyboard-default.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/_schema.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/_schema_v2.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/examples/ftx1.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/examples/lab599_tx500.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/examples/sdrplay_rspdx.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/examples/xiegu_x6200.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ftx1.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ic705.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ic7300.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ic7610.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ic9700.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/tx500.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/x6100.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/rigs/x6200.toml +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/icom_lan/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/icom_lan/_cli_shim.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/__main__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_audio_codecs.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_audio_recovery.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_audio_runtime_mixin.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_audio_transcoder.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_bounded_queue.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_bridge_metrics.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_bridge_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_civ_rx.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_connection_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_control_phase.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_dual_rx_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_optional_deps.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_platformdirs_migration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_poller_types.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_queue_pressure.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_runtime_protocols.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_scope_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_shared_state_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_state_cache.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_state_queries.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_bridge_metrics.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_bridge_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_codecs.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_macos_uid.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_transcoder.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_usb_resolve.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/analyzer.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/backend.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/bus.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/config.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/dsp.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/fft_scope.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/lan_stream.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/probe.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/probe_profile.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/probe_runner.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/resample.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/route.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio_analyzer.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio_bridge.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio_bus.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio_fft_scope.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/auth.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/config.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/discovery.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/factory.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/hamlib_models.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/hamlib_probe.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic705/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic705/core.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic705/serial.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic7300/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic7300/core.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic7300/serial.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic9700/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic9700/core.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic9700/serial.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/contracts.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/serial_civ_link.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/serial_session.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/serial_stub.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/usb_audio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/lan.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/rigctld_client/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/rigctld_client/radio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/rigctld_client/transport.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/parser.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/poller.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/radio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/transport.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/capabilities.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/civ.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_convert.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_diagnose.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_discover_hamlib.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_radio_validate.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_validate.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/command_map.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/command_spec.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commander.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/_builders.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/_codec.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/_frame.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/antenna.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/command_map.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/command_spec.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/commander.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/config.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/cw.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/dsp.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/freq.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/levels.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/memory.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/meters.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/mode.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/power.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/ptt.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/scope.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/speech.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/system.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/tone.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/tx_band.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/vfo.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/_bounded_queue.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/_optional_deps.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/_queue_pressure.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/_state_cache.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/auth.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/capabilities.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/civ.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/env_config.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/exceptions.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/radio_protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/radio_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/transport.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/types.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cw_auto_tuner.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_discovery.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_error_ring.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_errors.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_logging.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_manifest.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/bundle.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributor.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/audio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/config.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/dependencies.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/errors.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/invocation.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/logs.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/radio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/system.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/redaction.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/upload.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/discovery.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/exceptions.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/nodes/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/nodes/base.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/nodes/nr_scipy.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/pipeline.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/resample.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/tap_registry.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/env_config.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/exceptions.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/hamlib_bridge.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/ic705.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/meter_cal.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/profiles/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/profiles/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/profiles/rig_loader.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/profiles_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/proxy.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/py.typed +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_initial_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_reconnect.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_state_snapshot.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radios.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rig_loader.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/audit.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/circuit_breaker.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/contract.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/handler.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/poller.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/routing.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/server.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/state_cache.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/utils.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_audio_recovery.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_audio_runtime_mixin.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_civ_rx.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_connection_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_control_phase.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_dual_rx_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_poller_types.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_runtime_protocols.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_scope_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_shared_state_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_state_queries.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/cw_auto_tuner.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/ic705.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/meter_cal.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/profiles_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/proxy.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radio_initial_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radio_reconnect.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radio_state_snapshot.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radios.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/startup_checks.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/sync.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/scope/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/scope/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/scope/render.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/scope_render.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/startup_checks.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/sync.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/transport.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/types.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/usb_audio_resolve.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/comparison.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/hardware.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/overrides.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/registry.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/runner.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/schema.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/LAYER.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/_delta_encoder.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/api_contract.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/band_plan.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/discovery.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/dx_cluster.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/eibi.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/audio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/control.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/diagnostics.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/scope.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/radio_poller.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/rtc.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/runtime_helpers.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/apple-touch-icon.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/assets/ControlButtonDemo-Ddi7py1_.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/assets/index-CvOPafTi.css +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/lockup-dark.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/lockup-light.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/lockup-mono.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/mark-dark.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/mark-light.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/mark-mono.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/marketing/github-social-preview.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/marketing/readme-banner.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/wordmark-dark.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/wordmark-light.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/wordmark-mono.svg +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicon-16.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicon-32.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicon-48.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicon.ico +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-128.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-16.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-180.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-192.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-256.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-32.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-48.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-512.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-64.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon.ico +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-128.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-16.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-180.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-192.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-256.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-32.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-48.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-512.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-64.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon.ico +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-128.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-16.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-180.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-192.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-256.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-32.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-48.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-512.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-64.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/manifest.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/og-image.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/pwa-192x192.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/pwa-512x512.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/twitter-card.png +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static.old/index.html +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/tls.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/web_routing.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/web_startup.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/websocket.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/_audio_pipeline_helpers.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/_audio_stream_fake.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/_caps.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/_command_test_helpers.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/_diagnostics_mock_server.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/_helpers.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/_perf_helpers.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/conftest.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/contracts/__init__.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/contracts/test_lazy_imports.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/e2e/package.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/e2e/v2-ui-interactive.spec.ts +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/fake_rigctld.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/civ_rx_frames.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/hamlib_dump_caps_ts480.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/hamlib_rigctl_list.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/validation_artifact_mixed.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/validation_artifact_reverse_sync_fail.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/validation_template_ic7300.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/dump_state_ic7610.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/dump_state_yaesu.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/fldigi_dual_rx_session.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/js8call_dual_rx_session.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/protocol_golden.json +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/wsjtx_dual_rx_session.txt +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/hardware/test_ic7610_audio_pipeline.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/README.md +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/conftest.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/full_handshake.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/logging_utils.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/probe_handshake.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/probe_login.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_audio_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_audio_routing.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_connect.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_controls_extended_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_dsp_levels_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_get_freq.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_media_scope_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_memory_set_only.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_negative_auth_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_operator_toggles_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_radio_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_reliability_matrix_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_rigctld_audio_pipeline.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_rigctld_golden_replay.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_rigctld_wsjtx.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_rit_tuner_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_scope_advanced_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_tone_tsql_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_vfo_dual_watch_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/mock_server.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_analyzer.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_backend.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_bridge.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_bridge_stereo.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_bus.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_codec.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_codecs.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_config.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_dsp.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_fft_scope.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_fullduplex.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_pipeline_harness.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_pipeline_os_smoke.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_probe.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_probe_profile.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_probe_runner.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_recovery.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_resample.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_route.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_rx_tx_transition.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_stress.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_transcoder.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_transcoder_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_watchdog.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audit.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_auth.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_authz_registry_gated.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_backend_contract_matrix.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_backend_factory.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_bounded_queue.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_bsr_band_switching.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_circuit_breaker.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_command_profiling.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_rx_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_rx_dispatch_golden.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_rx_mixin_host.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_rx_short_frame_robustness.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_transaction_ownership.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_async.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_diagnose.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_diagnose_lazy_import.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_e2e.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_model.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cmd29_parsing.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_command_catalog_docs.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_command_map_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_command_spec.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_commander.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_commands.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_commands_extended.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_convert.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_convert_cli.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cw_auto_tune_wiring.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cw_auto_tuner.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_data_mode.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_delta_encoder.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_bundle.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_contributor.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_contributors_batch1.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_contributors_batch2.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_contributors_batch3.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_e2e.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_logging.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_privacy_invariants.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_redaction.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_upload.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_discovery.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_discovery_responder.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_docs_runtime_sync.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_filter_family.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_levels_part1.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_levels_part2.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_nodes.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_nr_scipy.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_pipeline.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dx_cluster.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_env_config.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_exports.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_fake_rigctld.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_frontend_e2e_config.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ftx1_audio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ftx1_radio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_golden_protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_bridge.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_dump_caps.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_external_rigctld_contract.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_models.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_probe.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_handlers_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_handlers_dsp_407_408.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_handlers_protocol_gap_399.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_handlers_sys_band.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic705.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic705_backend.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic7300_backend.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic7610_parity_matrix.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic9700_backend.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_icom7610_serial_radio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_icom_lan_shim.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_icom_receiver_tier.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_issue_141_core_refactor.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_jitter_buffer.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_lifecycle_diagnostics.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_macos_audio_uid.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_main_sub_tracking.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_managed_runtime_packaging_doc.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_memory_commands.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_mock_integration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_naming_parity.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_operator_toggles.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_overrides.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_pcm_e2e.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_per_receiver_vfo_roundtrip.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_performance_regressions.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_platformdirs_migration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_poller.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_poller_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_power_unit_extension.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_profiles_routing.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_profiles_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_proxy.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_proxy_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_public_api_surface.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_connect.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_extended.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_poller_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_validate.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radios.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rate_limiter.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_raw_civ_pipe.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_raw_civ_transaction.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_reconnect.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rf_gain_af_level.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_ic7300.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_ic7610.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_loader.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_multi_vendor.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_schema.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_client_backend.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_consistency.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_dump_state_snapshot.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_handler.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_init_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_protocol.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_routable_extension.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_server.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_server_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_utils.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_scope.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_scope_render.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_scope_render_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_scope_stress.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_security_headers.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_selected_freq_mode.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_serial_backend_smoke.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_serial_civ_link.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_serial_session.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_serial_stub_framing.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_server_wire.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_shared_state_runtime.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_single_rx_plain_routing.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_state_cache.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_state_cache_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_state_pollable_extension.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_state_queries.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_supports_command.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_swr_calibration.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_sync.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_sync_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_tap_registry.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_tls.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_token_renewal.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_tone_tsql.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_transport.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_tx_band_edge.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_usb_audio_capable_extension.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_usb_audio_resolve.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_usb_audio_stub.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validate_hamlib_provider.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validate_overrides.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validation_comparison.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validation_runner.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validation_schema.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validation_templates.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_vfo_dual_watch.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_vox_tone_state.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_api_contract.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_audio_streaming_profile.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_auth_compare_digest.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_capability_guards.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_command_batch_http.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_cw_http_control.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_diagnostics.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_post_body_cap.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_ptt_readonly.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_runtime_helpers.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_server.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_server_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_server_token_redaction.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_webrtc_signaling.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_websocket_coverage.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_audio.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_cat_parser.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_cat_poller.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_cat_transport.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_cli_factory.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/validation/test_generator.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/validation/test_generator_hamlib.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/validation/test_hardware.py +0 -0
- {rigplane-2.7.0 → rigplane-2.7.2}/tests/validation/test_registry.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rigplane
|
|
3
|
-
Version: 2.7.
|
|
3
|
+
Version: 2.7.2
|
|
4
4
|
Summary: Multi-vendor radio control library and Web UI with native providers and planned Hamlib-backed CAT coverage
|
|
5
5
|
Project-URL: Homepage, https://rigplane.dev/
|
|
6
6
|
Project-URL: Documentation, https://rigplane.dev/
|
|
@@ -11,6 +11,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [2.7.2] — 2026-05-30
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Desktop RX audio: resume the `AudioContext` from the LIVE user-gesture so streamed RX audio plays under WKWebView/autoplay-restricted contexts, and recover from suspended-context frame drops instead of silently dropping them (MOR-239, #1694, 921f4c88)
|
|
19
|
+
- Audio scope: dispatch audio-FFT frames to `/api/v1/audio-scope` for radios without a hardware scope (e.g. Xiegu X6200), fixing the blank AUDIO SCOPE panel; hardware-scope radios (IC-7610) are unchanged (MOR-241, #1695, 4e98ab0d)
|
|
20
|
+
- Serial USB-audio TX: arm the PCM TX path in the shared serial Icom base so bridge TX reaches the radio (IC-705/IC-7300/IC-9700/X6200) instead of raising "PCM TX not started" per frame; the audio bridge now degrades to RX-only on TX failure instead of spamming (MOR-242, #1696, 37fe3d0a)
|
|
21
|
+
|
|
22
|
+
## [2.7.1] — 2026-05-29
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- USB audio now clamps the requested channel count to the device's real
|
|
26
|
+
capability (`input_channels` for RX, `output_channels` for TX) at stream
|
|
27
|
+
open, mirroring the existing sample-rate negotiation. Any mono USB codec
|
|
28
|
+
self-heals instead of failing the global stereo default with PortAudio
|
|
29
|
+
`-9998` ("Invalid number of channels") and starving the stream; the Xiegu
|
|
30
|
+
X6200 mono RX path no longer depends on its profile `codec_preference`
|
|
31
|
+
entry (verified on hardware). The effective channel count and its source
|
|
32
|
+
are recorded on the stream contract for diagnostics (#1692).
|
|
33
|
+
|
|
14
34
|
## [2.7.0] — 2026-05-29
|
|
15
35
|
|
|
16
36
|
### Added
|
|
@@ -1523,7 +1543,9 @@ These deprecation closures were announced in v0.19 and dropped on schedule.
|
|
|
1523
1543
|
- Transport layer, authentication, CI-V commands, meters, PTT, keep-alive.
|
|
1524
1544
|
- Clean-room Icom LAN UDP protocol implementation.
|
|
1525
1545
|
|
|
1526
|
-
[Unreleased]: https://github.com/rigplane/rigplane-core/compare/v2.7.
|
|
1546
|
+
[Unreleased]: https://github.com/rigplane/rigplane-core/compare/v2.7.2...HEAD
|
|
1547
|
+
[2.7.2]: https://github.com/rigplane/rigplane-core/compare/v2.7.1...v2.7.2
|
|
1548
|
+
[2.7.1]: https://github.com/rigplane/rigplane-core/compare/v2.7.0...v2.7.1
|
|
1527
1549
|
[2.7.0]: https://github.com/rigplane/rigplane-core/compare/v2.6.0...v2.7.0
|
|
1528
1550
|
[2.6.0]: https://github.com/rigplane/rigplane-core/compare/v2.5.1...v2.6.0
|
|
1529
1551
|
[2.5.1]: https://github.com/rigplane/rigplane-core/compare/v2.5.0...v2.5.1
|
|
@@ -248,3 +248,79 @@ describe('RxPlayer jitter bounds (#1363)', () => {
|
|
|
248
248
|
p.stop();
|
|
249
249
|
});
|
|
250
250
|
});
|
|
251
|
+
|
|
252
|
+
describe('RxPlayer suspended-context recovery (MOR-239)', () => {
|
|
253
|
+
it('start() resumes a context that is created suspended (WKWebView autoplay)', () => {
|
|
254
|
+
ctx.state = 'suspended';
|
|
255
|
+
const p = new RxPlayer();
|
|
256
|
+
p.start();
|
|
257
|
+
expect(ctx.resume).toHaveBeenCalled();
|
|
258
|
+
p.stop();
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('drops the frame while suspended but re-attempts resume and warns (not silent)', () => {
|
|
262
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
263
|
+
ctx.state = 'suspended';
|
|
264
|
+
const p = new RxPlayer();
|
|
265
|
+
p.start();
|
|
266
|
+
ctx.resume.mockClear();
|
|
267
|
+
|
|
268
|
+
p.feed(pcm16(480));
|
|
269
|
+
|
|
270
|
+
// Frame can't play on a suspended ctx, but instead of a silent return
|
|
271
|
+
// we re-attempt resume() and surface a warning so it's observable.
|
|
272
|
+
expect(ctx.createBufferSource).not.toHaveBeenCalled();
|
|
273
|
+
expect(ctx.resume).toHaveBeenCalled();
|
|
274
|
+
expect(warn).toHaveBeenCalled();
|
|
275
|
+
p.stop();
|
|
276
|
+
warn.mockRestore();
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('plays frames once the context has resumed to running', () => {
|
|
280
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
281
|
+
ctx.state = 'suspended';
|
|
282
|
+
const p = new RxPlayer();
|
|
283
|
+
p.start();
|
|
284
|
+
p.feed(pcm16(480)); // dropped — suspended
|
|
285
|
+
expect(ctx._lastSrc).toBeNull();
|
|
286
|
+
|
|
287
|
+
ctx.state = 'running'; // resume() honoured by the gesture
|
|
288
|
+
p.feed(pcm16(480)); // now audible
|
|
289
|
+
expect(ctx.createBufferSource).toHaveBeenCalled();
|
|
290
|
+
expect(ctx._lastSrc.start).toHaveBeenCalled();
|
|
291
|
+
p.stop();
|
|
292
|
+
warn.mockRestore();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('re-attempts resume on focus/visibility regain (WKWebView re-suspend)', () => {
|
|
296
|
+
ctx.state = 'suspended';
|
|
297
|
+
const p = new RxPlayer();
|
|
298
|
+
p.start();
|
|
299
|
+
ctx.resume.mockClear();
|
|
300
|
+
window.dispatchEvent(new Event('focus'));
|
|
301
|
+
expect(ctx.resume).toHaveBeenCalled();
|
|
302
|
+
p.stop();
|
|
303
|
+
// After stop the listener must be gone — no further resume calls.
|
|
304
|
+
ctx.resume.mockClear();
|
|
305
|
+
window.dispatchEvent(new Event('focus'));
|
|
306
|
+
expect(ctx.resume).not.toHaveBeenCalled();
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
describe('RxPlayer mono routing (MOR-239)', () => {
|
|
311
|
+
it('routes a mono (1-ch) PCM16 buffer to the audible MAIN channel', () => {
|
|
312
|
+
const p = new RxPlayer();
|
|
313
|
+
p.start(); // default focus='both' → MAIN gain audible
|
|
314
|
+
p.feed(pcm16(480)); // header marks 1 channel
|
|
315
|
+
|
|
316
|
+
// Mono buffer allocated as 1 channel...
|
|
317
|
+
expect(ctx.createBuffer).toHaveBeenCalledWith(1, 480, SAMPLE_RATE);
|
|
318
|
+
// ...fed into preGain (→ splitter[0] → mainGain → mainPanner → destination).
|
|
319
|
+
const [preGain, mainGain] = ctx._gains;
|
|
320
|
+
expect(ctx._lastSrc.connect).toHaveBeenCalledWith(preGain);
|
|
321
|
+
// MAIN channel must carry audible gain so mono lands on an output, not
|
|
322
|
+
// only on the silenced SUB (channel 1) of the splitter.
|
|
323
|
+
expect(mainGain.gain.value).toBeGreaterThan(0);
|
|
324
|
+
p.stop();
|
|
325
|
+
});
|
|
326
|
+
});
|
|
@@ -228,6 +228,10 @@ class AudioManager {
|
|
|
228
228
|
setAudioConnected(true);
|
|
229
229
|
console.log('[audio-ws] connected');
|
|
230
230
|
if (this._rxEnabled) {
|
|
231
|
+
// Idempotent resume nudge: if the AudioContext re-entered
|
|
232
|
+
// 'suspended' while the WS was down (WKWebView backgrounding), wake
|
|
233
|
+
// it as we resubscribe so streamed frames are not dropped.
|
|
234
|
+
this.rxPlayer.start();
|
|
231
235
|
ws.send(JSON.stringify({
|
|
232
236
|
type: 'audio_start',
|
|
233
237
|
direction: 'rx',
|
|
@@ -51,6 +51,12 @@ export class RxPlayer {
|
|
|
51
51
|
private _floorSec = 0.05;
|
|
52
52
|
private _ceilingSec = 0.30;
|
|
53
53
|
|
|
54
|
+
// Count of frames dropped because the context was suspended (autoplay
|
|
55
|
+
// policy). Surfaced via console.warn so a silent no-audio state is
|
|
56
|
+
// observable instead of invisible. Reset once the context resumes.
|
|
57
|
+
private _droppedSuspendedFrames = 0;
|
|
58
|
+
private _resumeListenersAttached = false;
|
|
59
|
+
|
|
54
60
|
get volume(): number {
|
|
55
61
|
return this._volume;
|
|
56
62
|
}
|
|
@@ -104,9 +110,18 @@ export class RxPlayer {
|
|
|
104
110
|
return this.ctx !== null && this.ctx.state !== 'closed';
|
|
105
111
|
}
|
|
106
112
|
|
|
113
|
+
/** Start (or resume) playback.
|
|
114
|
+
*
|
|
115
|
+
* MUST be called synchronously from a user-gesture handler (e.g. the LIVE
|
|
116
|
+
* button click): WKWebView / mobile-Safari autoplay policy only honours
|
|
117
|
+
* ``AudioContext.resume()`` when it runs inside the gesture's call stack.
|
|
118
|
+
* Calling again on an existing context is a cheap idempotent resume — the
|
|
119
|
+
* AudioManager re-invokes start() on ``audio_start`` and reconnect to keep
|
|
120
|
+
* nudging a context that re-entered ``suspended``.
|
|
121
|
+
*/
|
|
107
122
|
start(): void {
|
|
108
123
|
if (this.ctx) {
|
|
109
|
-
|
|
124
|
+
this._resume();
|
|
110
125
|
return;
|
|
111
126
|
}
|
|
112
127
|
const Ctx = globalThis.AudioContext ?? (globalThis as any).webkitAudioContext;
|
|
@@ -129,9 +144,8 @@ export class RxPlayer {
|
|
|
129
144
|
this.subPanner.connect(this.ctx.destination);
|
|
130
145
|
this._applyGraphState();
|
|
131
146
|
this.nextPlayTime = 0;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
147
|
+
this._attachResumeListeners();
|
|
148
|
+
this._resume();
|
|
135
149
|
}
|
|
136
150
|
|
|
137
151
|
stop(): void {
|
|
@@ -139,6 +153,7 @@ export class RxPlayer {
|
|
|
139
153
|
try { this.decoder.close(); } catch { /* ok */ }
|
|
140
154
|
this.decoder = null;
|
|
141
155
|
}
|
|
156
|
+
this._detachResumeListeners();
|
|
142
157
|
if (this.ctx) {
|
|
143
158
|
this.ctx.close().catch(() => {});
|
|
144
159
|
this.ctx = null;
|
|
@@ -151,6 +166,66 @@ export class RxPlayer {
|
|
|
151
166
|
}
|
|
152
167
|
this.nextPlayTime = 0;
|
|
153
168
|
this.opusTs = 0;
|
|
169
|
+
this._droppedSuspendedFrames = 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Best-effort resume of a suspended context. Safe to call repeatedly. */
|
|
173
|
+
private _resume(): void {
|
|
174
|
+
if (this.ctx && this.ctx.state === 'suspended') {
|
|
175
|
+
this.ctx.resume().catch(() => {});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Resume-on-regain-focus handler: WKWebView re-suspends an AudioContext
|
|
180
|
+
* when the webview is backgrounded; resume it when we come back. Bound as
|
|
181
|
+
* an arrow property so add/removeEventListener see a stable reference. */
|
|
182
|
+
private _onResumeEvent = (): void => {
|
|
183
|
+
this._resume();
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
private _attachResumeListeners(): void {
|
|
187
|
+
if (this._resumeListenersAttached) return;
|
|
188
|
+
if (typeof document !== 'undefined') {
|
|
189
|
+
document.addEventListener('visibilitychange', this._onResumeEvent);
|
|
190
|
+
}
|
|
191
|
+
if (typeof window !== 'undefined') {
|
|
192
|
+
window.addEventListener('focus', this._onResumeEvent);
|
|
193
|
+
}
|
|
194
|
+
this._resumeListenersAttached = true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private _detachResumeListeners(): void {
|
|
198
|
+
if (!this._resumeListenersAttached) return;
|
|
199
|
+
if (typeof document !== 'undefined') {
|
|
200
|
+
document.removeEventListener('visibilitychange', this._onResumeEvent);
|
|
201
|
+
}
|
|
202
|
+
if (typeof window !== 'undefined') {
|
|
203
|
+
window.removeEventListener('focus', this._onResumeEvent);
|
|
204
|
+
}
|
|
205
|
+
this._resumeListenersAttached = false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** Returns true when frames can be scheduled (context running). When the
|
|
209
|
+
* context is suspended this re-attempts resume() and warns — rather than
|
|
210
|
+
* silently dropping every frame, which previously made a stuck-suspended
|
|
211
|
+
* context (no sound, blank scope) impossible to diagnose. */
|
|
212
|
+
private _ensureRunning(): boolean {
|
|
213
|
+
if (!this.ctx) return false;
|
|
214
|
+
if (this.ctx.state === 'running') {
|
|
215
|
+
this._droppedSuspendedFrames = 0;
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
if (this.ctx.state === 'suspended') {
|
|
219
|
+
this._resume();
|
|
220
|
+
this._droppedSuspendedFrames++;
|
|
221
|
+
if (this._droppedSuspendedFrames <= 3 || this._droppedSuspendedFrames % 200 === 0) {
|
|
222
|
+
console.warn(
|
|
223
|
+
`RxPlayer: AudioContext suspended — dropped ${this._droppedSuspendedFrames} ` +
|
|
224
|
+
`frame(s), retrying resume(). Audio needs a user gesture (click LIVE).`,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return false;
|
|
154
229
|
}
|
|
155
230
|
|
|
156
231
|
/** Feed a raw binary frame from WS */
|
|
@@ -174,7 +249,7 @@ export class RxPlayer {
|
|
|
174
249
|
|
|
175
250
|
private playPcm16(payload: Uint8Array, sr: number, ch: number): void {
|
|
176
251
|
if (!this.ctx || !this.preGain) return;
|
|
177
|
-
if (this.
|
|
252
|
+
if (!this._ensureRunning()) return;
|
|
178
253
|
const channels = ch === 2 ? 2 : 1;
|
|
179
254
|
const frameCount = Math.floor(payload.byteLength / (2 * channels));
|
|
180
255
|
if (frameCount <= 0) return;
|
|
@@ -194,7 +269,7 @@ export class RxPlayer {
|
|
|
194
269
|
|
|
195
270
|
private decodeOpus(payload: Uint8Array, sr: number, ch: number): void {
|
|
196
271
|
if (!this.ctx || !this.preGain) return;
|
|
197
|
-
if (this.
|
|
272
|
+
if (!this._ensureRunning()) return;
|
|
198
273
|
if (typeof AudioDecoder === 'undefined') return;
|
|
199
274
|
|
|
200
275
|
if (!this.decoder) {
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rigplane"
|
|
7
|
-
version = "2.7.
|
|
7
|
+
version = "2.7.2"
|
|
8
8
|
description = "Multi-vendor radio control library and Web UI with native providers and planned Hamlib-backed CAT coverage"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -478,11 +478,25 @@ class AudioBridge:
|
|
|
478
478
|
|
|
479
479
|
# --- TX path: virtual device input → radio ---
|
|
480
480
|
if self._tx_enabled:
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
481
|
+
try:
|
|
482
|
+
await self._radio.start_audio_tx_pcm(
|
|
483
|
+
sample_rate=self._sample_rate,
|
|
484
|
+
channels=self._channels,
|
|
485
|
+
frame_ms=self._frame_ms,
|
|
486
|
+
)
|
|
487
|
+
except (RuntimeError, NotImplementedError) as exc:
|
|
488
|
+
# The radio cannot arm a PCM TX stream (e.g. a serial backend
|
|
489
|
+
# that never set up its USB-audio TX path). Degrade to RX-only
|
|
490
|
+
# instead of spinning a _tx_loop that would reject — and log —
|
|
491
|
+
# every captured frame (MOR-242).
|
|
492
|
+
self._tx_enabled = False
|
|
493
|
+
self._tx_started = False
|
|
494
|
+
logger.warning(
|
|
495
|
+
"%s: radio rejected TX start (%s); running RX-only",
|
|
496
|
+
self._label,
|
|
497
|
+
exc,
|
|
498
|
+
)
|
|
499
|
+
return
|
|
486
500
|
self._tx_started = True
|
|
487
501
|
|
|
488
502
|
tx_dev_id = dev_id
|
|
@@ -829,6 +843,17 @@ class AudioBridge:
|
|
|
829
843
|
|
|
830
844
|
try:
|
|
831
845
|
await self._radio.push_audio_tx_pcm(pcm_bytes)
|
|
846
|
+
except (RuntimeError, NotImplementedError) as exc:
|
|
847
|
+
# The radio cannot accept PCM TX frames (TX path not armed).
|
|
848
|
+
# Degrade to RX-only and stop the loop instead of rejecting
|
|
849
|
+
# — and logging — every captured frame (MOR-242).
|
|
850
|
+
self._tx_enabled = False
|
|
851
|
+
logger.warning(
|
|
852
|
+
"%s: radio rejected TX frame (%s); switching to RX-only",
|
|
853
|
+
self._label,
|
|
854
|
+
exc,
|
|
855
|
+
)
|
|
856
|
+
return
|
|
832
857
|
except Exception:
|
|
833
858
|
if self._tx_frames <= 5:
|
|
834
859
|
logger.warning("%s: TX push error", self._label, exc_info=True)
|
|
@@ -111,6 +111,7 @@ class UsbAudioStreamContract:
|
|
|
111
111
|
channels: int
|
|
112
112
|
frame_ms: int
|
|
113
113
|
sample_rate_source: str
|
|
114
|
+
channel_source: str = "requested"
|
|
114
115
|
fallback_reason: str | None = None
|
|
115
116
|
|
|
116
117
|
def to_dict(self) -> dict[str, object]:
|
|
@@ -121,6 +122,7 @@ class UsbAudioStreamContract:
|
|
|
121
122
|
"channels": self.channels,
|
|
122
123
|
"frame_ms": self.frame_ms,
|
|
123
124
|
"sample_rate_source": self.sample_rate_source,
|
|
125
|
+
"channel_source": self.channel_source,
|
|
124
126
|
}
|
|
125
127
|
if self.fallback_reason:
|
|
126
128
|
payload["fallback_reason"] = self.fallback_reason
|
|
@@ -480,6 +482,35 @@ class UsbAudioDriver:
|
|
|
480
482
|
def _sample_rate_candidates(self, requested: int) -> tuple[int, ...]:
|
|
481
483
|
return tuple(dict.fromkeys((requested, *_DEFAULT_SAMPLE_RATE_CANDIDATES)))
|
|
482
484
|
|
|
485
|
+
def _clamp_channels(
|
|
486
|
+
self,
|
|
487
|
+
*,
|
|
488
|
+
direction: str,
|
|
489
|
+
device: UsbAudioDevice,
|
|
490
|
+
requested_channels: int,
|
|
491
|
+
) -> tuple[int, str, str | None]:
|
|
492
|
+
"""Clamp requested channels to the device's real capability (MOR-238).
|
|
493
|
+
|
|
494
|
+
A profile / codec may request stereo from a device that only exposes a
|
|
495
|
+
mono capture (or playback) endpoint. PortAudio rejects that open with
|
|
496
|
+
PaErrorCode -9998 ("Invalid number of channels"). Mirroring the
|
|
497
|
+
sample-rate negotiation, the effective channel count is clamped down to
|
|
498
|
+
what the device advertises so any mono/stereo USB codec self-heals
|
|
499
|
+
without a per-profile ``codec_preference`` entry. Downstream DSP is
|
|
500
|
+
48 kHz mono, so a 1-channel capture feeds the broadcaster cleanly.
|
|
501
|
+
"""
|
|
502
|
+
|
|
503
|
+
device_max = (
|
|
504
|
+
device.input_channels if direction == "rx" else device.output_channels
|
|
505
|
+
)
|
|
506
|
+
# A device advertising zero channels for this direction is a selection
|
|
507
|
+
# bug, not a clamp target — leave the request untouched and let the
|
|
508
|
+
# open surface the real error.
|
|
509
|
+
if device_max >= 1 and requested_channels > device_max:
|
|
510
|
+
reason = f"channels-{requested_channels}-clamped-to-device-{device_max}"
|
|
511
|
+
return device_max, "device-clamp", reason
|
|
512
|
+
return requested_channels, "requested", None
|
|
513
|
+
|
|
483
514
|
def _resolve_stream_contract(
|
|
484
515
|
self,
|
|
485
516
|
*,
|
|
@@ -491,6 +522,11 @@ class UsbAudioDriver:
|
|
|
491
522
|
allow_sample_rate_fallback: bool,
|
|
492
523
|
) -> UsbAudioStreamContract:
|
|
493
524
|
device_id = AudioDeviceId(device.index)
|
|
525
|
+
effective_channels, channel_source, channel_reason = self._clamp_channels(
|
|
526
|
+
direction=direction,
|
|
527
|
+
device=device,
|
|
528
|
+
requested_channels=channels,
|
|
529
|
+
)
|
|
494
530
|
if self._backend.check_sample_rate(
|
|
495
531
|
device_id,
|
|
496
532
|
requested_sample_rate,
|
|
@@ -501,9 +537,11 @@ class UsbAudioDriver:
|
|
|
501
537
|
direction=direction,
|
|
502
538
|
device=device,
|
|
503
539
|
sample_rate_hz=requested_sample_rate,
|
|
504
|
-
channels=
|
|
540
|
+
channels=effective_channels,
|
|
505
541
|
frame_ms=frame_ms,
|
|
506
542
|
sample_rate_source=source,
|
|
543
|
+
channel_source=channel_source,
|
|
544
|
+
fallback_reason=channel_reason,
|
|
507
545
|
)
|
|
508
546
|
|
|
509
547
|
if not allow_sample_rate_fallback:
|
|
@@ -521,16 +559,21 @@ class UsbAudioDriver:
|
|
|
521
559
|
candidate,
|
|
522
560
|
direction=direction,
|
|
523
561
|
):
|
|
562
|
+
sample_reason = f"sample-rate-{requested_sample_rate}-unsupported"
|
|
563
|
+
fallback_reason = (
|
|
564
|
+
f"{sample_reason}; {channel_reason}"
|
|
565
|
+
if channel_reason
|
|
566
|
+
else sample_reason
|
|
567
|
+
)
|
|
524
568
|
return UsbAudioStreamContract(
|
|
525
569
|
direction=direction,
|
|
526
570
|
device=device,
|
|
527
571
|
sample_rate_hz=candidate,
|
|
528
|
-
channels=
|
|
572
|
+
channels=effective_channels,
|
|
529
573
|
frame_ms=frame_ms,
|
|
530
574
|
sample_rate_source="fallback",
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
),
|
|
575
|
+
channel_source=channel_source,
|
|
576
|
+
fallback_reason=fallback_reason,
|
|
534
577
|
)
|
|
535
578
|
|
|
536
579
|
raise AudioDriverLifecycleError(
|
|
@@ -595,18 +638,21 @@ class UsbAudioDriver:
|
|
|
595
638
|
# RX frames reaching the browser.
|
|
596
639
|
logger.info(
|
|
597
640
|
"usb-audio: opening RX capture — device=[%d] %s, %d Hz, "
|
|
598
|
-
"%d ch, %d ms
|
|
641
|
+
"%d ch (requested %d, source=%s), %d ms "
|
|
642
|
+
"(device input_channels=%d)",
|
|
599
643
|
selected_rx.index,
|
|
600
644
|
selected_rx.name,
|
|
601
645
|
contract.sample_rate_hz,
|
|
646
|
+
contract.channels,
|
|
602
647
|
ch,
|
|
648
|
+
contract.channel_source,
|
|
603
649
|
fm,
|
|
604
650
|
selected_rx.input_channels,
|
|
605
651
|
)
|
|
606
652
|
self._rx_stream = self._backend.open_rx(
|
|
607
653
|
AudioDeviceId(selected_rx.index),
|
|
608
654
|
sample_rate=contract.sample_rate_hz,
|
|
609
|
-
channels=
|
|
655
|
+
channels=contract.channels,
|
|
610
656
|
frame_ms=fm,
|
|
611
657
|
)
|
|
612
658
|
await self._rx_stream.start(callback)
|
|
@@ -657,7 +703,7 @@ class UsbAudioDriver:
|
|
|
657
703
|
self._tx_stream = self._backend.open_tx(
|
|
658
704
|
AudioDeviceId(selected_tx.index),
|
|
659
705
|
sample_rate=contract.sample_rate_hz,
|
|
660
|
-
channels=
|
|
706
|
+
channels=contract.channels,
|
|
661
707
|
frame_ms=fm,
|
|
662
708
|
)
|
|
663
709
|
await self._tx_stream.start()
|
|
@@ -454,7 +454,38 @@ class _IcomSerialRadioBase(CoreRadio):
|
|
|
454
454
|
await self._serial_audio_driver.stop_rx()
|
|
455
455
|
|
|
456
456
|
# ------------------------------------------------------------------
|
|
457
|
-
# Audio TX
|
|
457
|
+
# Audio TX (Opus)
|
|
458
|
+
# ------------------------------------------------------------------
|
|
459
|
+
|
|
460
|
+
async def start_audio_tx_opus(self) -> None:
|
|
461
|
+
self._check_connected()
|
|
462
|
+
await self._serial_audio_driver.start_tx(
|
|
463
|
+
sample_rate=self.audio_sample_rate,
|
|
464
|
+
channels=self._serial_audio_channels_for_codec(),
|
|
465
|
+
frame_ms=20,
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
async def push_audio_tx_opus(self, opus_data: bytes) -> None:
|
|
469
|
+
self._check_connected()
|
|
470
|
+
if not self._serial_audio_driver.tx_running:
|
|
471
|
+
raise RuntimeError("Audio TX not started")
|
|
472
|
+
payload = bytes(opus_data)
|
|
473
|
+
if self._serial_codec_is_opus():
|
|
474
|
+
transcoder = self._get_pcm_transcoder(
|
|
475
|
+
sample_rate=self.audio_sample_rate,
|
|
476
|
+
channels=self._serial_audio_channels_for_codec(),
|
|
477
|
+
frame_ms=20,
|
|
478
|
+
)
|
|
479
|
+
payload = transcoder.opus_to_pcm(payload)
|
|
480
|
+
await self._serial_audio_driver._push_tx_pcm(payload)
|
|
481
|
+
|
|
482
|
+
async def stop_audio_tx_opus(self) -> None:
|
|
483
|
+
await self._serial_audio_driver.stop_tx()
|
|
484
|
+
self._pcm_tx_fmt = None
|
|
485
|
+
|
|
486
|
+
# ------------------------------------------------------------------
|
|
487
|
+
# Audio TX (PCM) — arms ``_pcm_tx_fmt`` so ``push_audio_tx_pcm`` works
|
|
488
|
+
# over the serial USB CODEC path (MOR-242).
|
|
458
489
|
# ------------------------------------------------------------------
|
|
459
490
|
|
|
460
491
|
async def start_audio_tx_pcm(
|
|
@@ -485,15 +516,51 @@ class _IcomSerialRadioBase(CoreRadio):
|
|
|
485
516
|
"sample_rate * frame_ms must produce an integer frame size."
|
|
486
517
|
)
|
|
487
518
|
|
|
519
|
+
# Icom USB CODEC mic input is mono-only by hardware; the LAN path
|
|
520
|
+
# enforces this by forcing txcodec to a mono value in _send_conninfo
|
|
521
|
+
# (issue #794). For the serial path we clamp channels to 1 here so
|
|
522
|
+
# that PortAudio always opens the USB CODEC as a mono output stream.
|
|
523
|
+
# Opening with channels=2 causes the radio ALC to behave erratically
|
|
524
|
+
# for the first 5-10 seconds of TX (GH#1382 regression; consistent with
|
|
525
|
+
# the MOR-238 RX clamp).
|
|
526
|
+
tx_channels = 1
|
|
527
|
+
|
|
488
528
|
self._check_connected()
|
|
489
529
|
await self._serial_audio_driver.start_tx(
|
|
490
530
|
sample_rate=sample_rate,
|
|
491
|
-
channels=
|
|
531
|
+
channels=tx_channels,
|
|
492
532
|
frame_ms=frame_ms,
|
|
493
533
|
)
|
|
534
|
+
self._pcm_tx_fmt = (sample_rate, tx_channels, frame_ms)
|
|
535
|
+
|
|
536
|
+
async def push_audio_tx_pcm(
|
|
537
|
+
self,
|
|
538
|
+
pcm_bytes: bytes | bytearray | memoryview,
|
|
539
|
+
) -> None:
|
|
540
|
+
self._check_connected()
|
|
541
|
+
if self._pcm_tx_fmt is None:
|
|
542
|
+
raise RuntimeError(
|
|
543
|
+
"PCM TX not started; call start_audio_tx_pcm() before push_audio_tx_pcm()."
|
|
544
|
+
)
|
|
545
|
+
if not isinstance(pcm_bytes, (bytes, bytearray, memoryview)):
|
|
546
|
+
raise AudioFormatError("PCM input must be bytes-like.")
|
|
547
|
+
sample_rate, channels, frame_ms = self._pcm_tx_fmt
|
|
548
|
+
if (sample_rate * frame_ms) % 1000 != 0:
|
|
549
|
+
raise AudioFormatError(
|
|
550
|
+
"sample_rate * frame_ms must produce an integer frame size."
|
|
551
|
+
)
|
|
552
|
+
frame_samples = (sample_rate * frame_ms) // 1000
|
|
553
|
+
expected = frame_samples * channels * 2
|
|
554
|
+
frame = bytes(pcm_bytes)
|
|
555
|
+
if len(frame) != expected:
|
|
556
|
+
raise AudioFormatError(
|
|
557
|
+
f"PCM frame size mismatch: expected {expected} bytes "
|
|
558
|
+
f"({frame_ms}ms at {sample_rate}Hz, {channels}ch s16le), got {len(frame)}."
|
|
559
|
+
)
|
|
560
|
+
await self._serial_audio_driver._push_tx_pcm(frame)
|
|
494
561
|
|
|
495
562
|
async def stop_audio_tx_pcm(self) -> None:
|
|
496
|
-
await self.
|
|
563
|
+
await self.stop_audio_tx_opus()
|
|
497
564
|
|
|
498
565
|
async def _push_pcm_tx(self, frame: bytes) -> None:
|
|
499
566
|
if not isinstance(frame, bytes):
|
|
@@ -613,8 +680,17 @@ class _IcomSerialRadioBase(CoreRadio):
|
|
|
613
680
|
# ------------------------------------------------------------------
|
|
614
681
|
|
|
615
682
|
async def _stop_serial_audio_driver(self) -> None:
|
|
616
|
-
|
|
617
|
-
|
|
683
|
+
self._pcm_tx_fmt = None
|
|
684
|
+
self._pcm_rx_user_callback = None
|
|
685
|
+
self._opus_rx_user_callback = None
|
|
686
|
+
try:
|
|
687
|
+
await self._serial_audio_driver.stop_tx()
|
|
688
|
+
except Exception:
|
|
689
|
+
logger.debug("serial-audio: failed to stop TX path", exc_info=True)
|
|
690
|
+
try:
|
|
691
|
+
await self._serial_audio_driver.stop_rx()
|
|
692
|
+
except Exception:
|
|
693
|
+
logger.debug("serial-audio: failed to stop RX path", exc_info=True)
|
|
618
694
|
|
|
619
695
|
def _ensure_scope_baud_guardrail(self) -> None:
|
|
620
696
|
if self._serial_baudrate >= _SERIAL_SCOPE_MIN_BAUD:
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Serial adaptation layer for the IC-7610 backend."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from ...exceptions import CommandError
|
|
8
|
+
from .._icom_serial_base import _IcomSerialRadioBase, _SERIAL_SCOPE_MIN_BAUD
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
__all__ = ["Icom7610SerialRadio"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Icom7610SerialRadio(_IcomSerialRadioBase):
|
|
16
|
+
"""IC-7610 backend wired to shared core over serial CI-V session driver.
|
|
17
|
+
|
|
18
|
+
The audio TX (Opus + PCM) path and audio-driver teardown live in
|
|
19
|
+
``_IcomSerialRadioBase`` (lifted there in MOR-242); this subclass only
|
|
20
|
+
carries the IC-7610-specific RX-PCM delegation and the scope baud
|
|
21
|
+
guardrail that raises ``CommandError``.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
_DEFAULT_MODEL = ""
|
|
25
|
+
|
|
26
|
+
# ------------------------------------------------------------------
|
|
27
|
+
# IC-7610 specific: stop_audio_rx_pcm delegates to stop_audio_rx_opus
|
|
28
|
+
# ------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
async def stop_audio_rx_pcm(self) -> None:
|
|
31
|
+
self._pcm_rx_user_callback = None
|
|
32
|
+
await self.stop_audio_rx_opus()
|
|
33
|
+
|
|
34
|
+
# ------------------------------------------------------------------
|
|
35
|
+
# IC-7610 specific: scope guardrail uses CommandError
|
|
36
|
+
# ------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
def _ensure_scope_baud_guardrail(self) -> None:
|
|
39
|
+
if self._serial_baudrate >= _SERIAL_SCOPE_MIN_BAUD:
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
msg = (
|
|
43
|
+
"Scope over serial requires baudrate >= "
|
|
44
|
+
f"{_SERIAL_SCOPE_MIN_BAUD} for stable command path; got baudrate="
|
|
45
|
+
f"{self._serial_baudrate}. Set allow_low_baud_scope=True to override."
|
|
46
|
+
)
|
|
47
|
+
if not self._allow_low_baud_scope:
|
|
48
|
+
raise CommandError(msg)
|
|
49
|
+
|
|
50
|
+
if not self._low_baud_scope_warned:
|
|
51
|
+
logger.warning("%s Running with override may increase timeout risk.", msg)
|
|
52
|
+
self._low_baud_scope_warned = True
|
|
@@ -413,10 +413,12 @@ class WebServer:
|
|
|
413
413
|
_has_scope = (CAP_SCOPE in radio.capabilities) if radio is not None else False
|
|
414
414
|
if radio is not None and _has_audio:
|
|
415
415
|
self._audio_fft_scope = AudioFftScope(fft_size=2048, fps=20, avg_count=2)
|
|
416
|
-
|
|
416
|
+
# AudioFftScope.on_frame() is a single-slot setter: register one
|
|
417
|
+
# dispatch method that fans out to BOTH broadcasters. Registering
|
|
418
|
+
# twice would clobber the first callback (MOR-241).
|
|
419
|
+
self._audio_fft_scope.on_frame(self._dispatch_audio_fft_frame)
|
|
417
420
|
if not _has_scope:
|
|
418
|
-
# No hardware scope — audio FFT also feeds /api/v1/scope
|
|
419
|
-
self._audio_fft_scope.on_frame(self._broadcast_scope)
|
|
421
|
+
# No hardware scope — audio FFT also feeds /api/v1/scope.
|
|
420
422
|
self._audio_broadcaster.set_pcm_tap(self._audio_fft_scope.feed_audio)
|
|
421
423
|
logger.info(
|
|
422
424
|
"Audio FFT scope available (has_audio=%s, has_hw_scope=%s)",
|
|
@@ -609,6 +611,24 @@ class WebServer:
|
|
|
609
611
|
if self._radio is not None:
|
|
610
612
|
self._set_scope_data_callback(self._broadcast_scope)
|
|
611
613
|
|
|
614
|
+
def _dispatch_audio_fft_frame(self, frame: Any) -> None:
|
|
615
|
+
"""Fan out an audio FFT frame to the relevant scope channels.
|
|
616
|
+
|
|
617
|
+
Single registered callback for :class:`AudioFftScope` (whose
|
|
618
|
+
``on_frame`` is a single-slot setter). Always feeds the dedicated
|
|
619
|
+
``/api/v1/audio-scope`` channel. For radios WITHOUT a hardware scope
|
|
620
|
+
the same frame also drives ``/api/v1/scope`` (the main panadapter),
|
|
621
|
+
since those radios derive their spectrum from RX audio. Hardware-scope
|
|
622
|
+
radios (e.g. IC-7610) keep ``/api/v1/scope`` sourced exclusively from
|
|
623
|
+
the real scope, so the audio FFT never touches it (MOR-241).
|
|
624
|
+
"""
|
|
625
|
+
self._broadcast_audio_scope(frame)
|
|
626
|
+
_has_scope = (
|
|
627
|
+
CAP_SCOPE in self._radio.capabilities if self._radio is not None else False
|
|
628
|
+
)
|
|
629
|
+
if not _has_scope:
|
|
630
|
+
self._broadcast_scope(frame)
|
|
631
|
+
|
|
612
632
|
def _broadcast_scope(self, frame: Any) -> None:
|
|
613
633
|
"""Broadcast scope frame to all registered handlers.
|
|
614
634
|
|