Commit Graph

790 Commits

Author SHA1 Message Date
Alex P 0be9dbcc6c Enable ALSA rate resampling for configurable audio sample rates
Changes the audio subsystem from hw: (direct hardware access) to plughw:
(plugin layer with rate conversion) to enable configurable sample rates.

Changes:
- Update ALSA build to include plug,rate,linear,copy plugins
- Change device names from hw: to plughw: in C and Go code
- Remove 48kHz hardcoding for HDMI audio output
- Keep USB at 48kHz since hardware is fixed at that rate
- Update all comments to reflect plughw usage

Technical details:
- hw: devices bypass all ALSA plugins and require exact hardware rate match
- plughw: devices enable the ALSA plugin layer for automatic rate conversion
- Hardware still receives at native rate (48kHz), resampling happens in userspace
- HDMI can now use 8k/12k/16k/24k/48kHz, USB remains at 48kHz
- NEON-optimized resampling provides good performance on Cortex-A7

Requires rebuilding ALSA library with updated plugin configuration.
2025-11-21 02:22:22 +02:00
Alex P 2040db6094 Fix USB Audio Gadget sample rate constraints
USB Audio Gadget (hw:1,0) hardware only supports 48kHz for both capture
and playback due to configfs p_srate/c_srate being hardcoded. This commit
ensures both audio paths respect this hardware limitation:

- Output path: Force 48kHz when using hw:1,0, allow configurable rates for HDMI
- Input path: Always use 48kHz regardless of UI configuration
- Calculate frame size dynamically based on actual sample rate used

Also removes redundant comments that don't add debugging or maintainability value.
2025-11-21 01:56:56 +02:00
Alex P 57baa14ee6 Fix frame size calculation for configurable sample rates
Calculate frame size dynamically based on sample rate (20ms frames):
- 48kHz: 960 samples
- 24kHz: 480 samples
- 16kHz: 320 samples
- 12kHz: 240 samples
- 8kHz: 160 samples

Previously hardcoded to 960, causing decoder init failures at non-48kHz rates
2025-11-21 01:44:03 +02:00
Alex P 1dfb4ab77f Make audio sample rate user-configurable
- Add sample rate dropdown in UI with Opus-supported rates (8k/12k/16k/24k/48kHz)
- Add sampleRate parameter to setAudioConfig RPC handler
- Validate sample rate is one of the 5 Opus-compatible values
- Configuration takes effect on next audio restart (Apply button)
2025-11-21 01:38:00 +02:00
Alex P 584b9fe3bf Fix comment inaccuracies and restore lint targets
- Clarify sample rate is configurable (8k/12k/16k/24k/48k), not fixed at 48kHz
- Expand mutex comment to include full lifecycle protection scope
- Document that ALSA playback init fails immediately with no fallback
- Add async behavior documentation to audio enable/restart functions
- Restore build_audio_deps target lost during merge
- Restore lint-fix, lint-go, lint-ui Makefile targets
- Fix variable alignment per linter
2025-11-21 01:31:33 +02:00
Alex P 4001ef651f Fix silent failures and improve documentation
- Remove silent fallback to ALSA 'default' device on playback init failure
- Return error from SetAudioOutputSource for invalid source values
- Fix misleading comment about mutex scope in C audio code
- Clarify inputSourceMutex purpose for WebRTC packet serialization
2025-11-21 00:57:31 +02:00
Alex P 5f7c90649a Simplify audio configuration and error handling
- Replace helper function in getAudioConfig with explicit validation
- Consolidate audio default application in LoadConfig
- Streamline relay retry logic with inline conditions
- Extract closeFile and openHidFile helpers in USB gadget
- Simplify setPendingInputTrack pointer handling
- Improve error handling clarity in startAudio and updateUsbRelatedConfig
- Clean up processInputPacket mutex usage
2025-11-21 00:54:32 +02:00
Alex P 3ed663b4d1 Enable ALSA software resampling for hw: devices
Use snd_pcm_hw_params_set_rate_resample(1) to enable ALSA's rate plugin,
which provides software resampling even with hw: device interface.

This fixes audio distortion when HDMI sources output non-48kHz rates
(e.g., 44.1kHz from SBCs). ALSA now automatically resamples any input
rate to the configured 48kHz that Opus expects.

The rate plugin is available because ALSA is compiled with
--with-pcm-plugins=rate in install_audio_deps.sh
2025-11-21 00:32:10 +02:00
Alex P 3cd5bdd16c Make RestartAudioOutput async to prevent RPC hanging
Consistent with other audio toggle functions, restart now happens
asynchronously to avoid blocking the RPC caller.
2025-11-21 00:15:38 +02:00
Alex P edd06e2346 Fix UI hanging when toggling audio output enable/disable
Make audio start asynchronous to prevent blocking the RPC response.
Previously, enabling audio would block until ALSA initialization completed,
which can take 30-60 seconds for HDMI audio due to TC358743 hardware.

This also fixes the -1 decode errors that occurred when packets arrived
during the synchronous restart window.

Matches the existing async pattern used in SetAudioOutputSource().
2025-11-21 00:10:10 +02:00
Alex P a6cbf20f66 Fix audio capture to force Opus-compatible sample rates
ALSA now forces the configured sample rate (default 48kHz) instead of
auto-detecting the source rate. This prevents Opus encoder initialization
failures when HDMI sources output 44.1kHz audio, which Opus doesn't support.

Changes:
- Use snd_pcm_hw_params_set_rate() to force exact rate (48kHz by default)
- ALSA performs software resampling if hardware rate differs
- Update valid rates to Opus-compatible only (8k, 12k, 16k, 24k, 48k)
- Remove auto-adaptation logic that caused Opus failures with 44.1kHz

This ensures audio capture works reliably with any HDMI source rate.
2025-11-21 00:02:29 +02:00
Alex P fba4eabf3b Merge branch 'dev' into feat/audio-support
Integrated latest dev branch changes including:
- Native process refactoring with gRPC architecture
- OTA update system refactor with new component-based updates
- Updated build system and dependencies
- UI improvements and bug fixes

Post-merge fixes applied:
- Remove duplicate OTA RPC function declarations (now in ota.go)
- Fix GetDefaultEDID reference to use native.DefaultEDID constant
- Fix IsUpdatePending to use otaState.IsUpdatePending() method
- Add missing OTA RPC handler registrations for new update system

All audio functionality from feat/audio-support preserved.
All dev branch functionality preserved.
2025-11-20 23:47:44 +02:00
Siyuan 9c4a9e144f chore: bump version to 0.5.0-dev 2025-11-20 17:38:04 +00:00
Adam Shiervani 3652c4ceea
fix: enhance reboot state management with health check and redirect options (#994) 2025-11-20 18:25:21 +01:00
Adam Shiervani ba8a169ef2
refactor: remove unused state for log download in FailSafeModeOverlay (#993) 2025-11-20 17:48:56 +01:00
Adam Shiervani 661110cdb5
fix: update downgrade navigation parameter (#992) 2025-11-20 17:33:34 +01:00
Aveline d34d01c4b3
feat: add failsafe reason for video max restart attempts reached (#991) 2025-11-20 17:32:54 +01:00
Aveline 641b03199e
chore: make udhcpc the default DHCP client (#990) 2025-11-20 16:48:07 +01:00
Adam Shiervani 0a09d9e8bf
feat: add hostname change detection and reboot requirement in network settings (#989) 2025-11-20 16:36:02 +01:00
Adam Shiervani 0952c6abf2
chore: use en by default (#988) 2025-11-20 16:34:02 +01:00
Adam Shiervani 85eb4babdf
feat: handle grpc events (#986)
Co-authored-by: Siyuan <siyuan@buildjet.com>
2025-11-20 16:07:50 +01:00
Adam Shiervani 07935add15
refactor: remove redundant initialization of native and display components in Main function (#987) 2025-11-20 14:56:17 +01:00
Nitish Agarwal 78cef12c97
fix: mobile viewport cropping on video element (#985) 2025-11-20 13:55:24 +01:00
Alex P fe4fb33561 Fix misleading comment and incorrect Go terminology
- config.go: Clarify that package-level defaults are for efficiency, not temporary
- jsonrpc.go: Correct "thread" to "goroutine" (Go uses goroutines, not threads)

After thorough review of all reported issues:
- processInputPacket early nil check is correct double-checked locking (not a race)
- Async audio source switching is intentional design for 30-60s HDMI init time
- TypeScript JSON.parse is safe (backend controls data, React catches errors)

Only actual terminology issues needed fixing.
2025-11-19 17:28:31 +02:00
Alex P 41604626cf Remove inaccurate and redundant comments
Fix comment inaccuracies:
- NEON: Change from "required" to "optimizations" (scalar fallback exists)
- capture_channels: Remove "always stereo" claim (configurable via API)

Remove redundant comments that duplicate code:
- "Apply boolean flags directly" (line duplicates what code does)
- Mutex comments in setAudioTrack (visible from code structure)

Also remove accidentally committed review artifacts (PR_REVIEW.md, jetkvm_default_edid.bin).
2025-11-19 17:19:46 +02:00
Alex P 3897a61729 Fix critical comment inaccuracies in audio code
- Fix validateAndApply comment to clarify it returns values, doesn't apply them
- Correct capture_channels comment about hardware capabilities
- Fix opus_packet_loss_perc default value from 0 to 20 (matches backend default)
- Fix handle_alsa_error return value documentation (return 0 also unlocks mutex)
2025-11-19 17:19:46 +02:00
Alex P 1d570a8cbf Fix critical audio race conditions and improve reliability
- Replace volatile with C11 atomics for proper ARM memory barriers
- Fix race condition in audio source swapping (swap to nil before cleanup)
- Prevent double-close of ALSA handles via atomic ownership claim
- Add exponential backoff with 10-retry circuit breaker to prevent infinite loops
- Improve error propagation to report dual failures
- Add defensive null checks for concurrent access safety
- Simplify UI error handling with helper functions
- Fix TypeScript compilation error in packet loss dropdown
2025-11-19 17:19:46 +02:00
Aveline 3fcd5e7def
feat: move native to a separate process, again (#964) 2025-11-19 16:02:37 +01:00
Aveline 752fb55799
refactor: OTA (#912)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Adam Shiervani <adam.shiervani@gmail.com>
2025-11-19 15:20:59 +01:00
Alex P 8d69780061 Update audio source switch notification to indicate 30-60s delay
The HDMI audio device can take 30-60 seconds to initialize due to
TC358743 hardware characteristics. Updated success notification in
all languages to inform users that audio will start shortly.
2025-11-19 14:23:26 +02:00
Alex P 7fc90b86a8 Make audio source switching instant with async initialization
When switching audio output source between HDMI and USB, the HDMI
audio device (hw:0,0) can take 18-31 seconds to initialize due to
hardware characteristics of the TC358743 chip. This caused the UI
to freeze during source changes.

Changes:
- Move startAudio() to background goroutine in SetAudioOutputSource
- Move SaveConfig() to background goroutine to avoid blocking on disk I/O
- Return immediately after updating in-memory config
- Audio will initialize in background while UI remains responsive

The in-memory config is updated synchronously so subsequent calls
see the new source immediately. Both async operations are protected
by their respective mutexes (audioMutex, configLock).
2025-11-19 14:12:12 +02:00
Alex P ee23e3bf22 Refactor audio subsystem for improved maintainability
Changes:
- Consolidate duplicate stop logic into helper functions
- Fix RPC getAudioConfig to return actual runtime values instead of
  inconsistent defaults (bitrate was returning 128 vs actual 192)
- Improve setAudioTrack mutex handling to eliminate nested locking
- Simplify ALSA error retry logic by reorganizing conditional branches
- Split CGO Connect() into separate input/output methods for clarity
- Use map lookup for sample rate validation instead of long if-chain
- Add inline comments documenting validation steps

All changes preserve existing functionality while reducing code
duplication and improving readability. Tested with both HDMI and
USB audio sources.
2025-11-19 13:42:51 +02:00
Alex P 0dbf2dfda9 Update default EDID for improved compatibility
Changes:
- Switch manufacturer ID from DEL to LNX for better open-source alignment
- Add dual audio sample rate support (44.1kHz + 48kHz) to eliminate
  resampling quality loss on MacBooks and other devices
- Declare 640×480p60 in established timings and CEA video block (VIC-1)
- Use 1920×1200p60 as secondary timing to meet validator requirements
- Fix white point coordinates to D65 standard (0.313, 0.329)

This EDID now passes edidtool.com validation and provides universal
compatibility across macOS, Linux, and Windows systems.
2025-11-19 12:31:48 +02:00
Alex P 0168fcbdbd Make config.EdidString the single source of truth for EDID
- Set DefaultEDID in config defaults instead of empty string
- Pass config EDID to Native.Start() to fix initialization race condition
- Update DefaultEDID to MacBook-compatible value (2ch, 48kHz, 16/20/24-bit)
- Add getDefaultEDID RPC endpoint for UI to fetch backend constant
- Update UI to dynamically fetch default EDID instead of hardcoding
- Remove all EDID fallback logic now that config always has a value
- Simplify rpcGetEDID to return config value directly

This ensures the configured EDID is used from startup and eliminates
sync issues between backend constant, config, and UI.
2025-11-19 11:08:32 +02:00
Alex P c88b98c1f0 Fix critical audio race conditions and align configuration defaults
Critical Fixes:
- Fix race condition in handleInputTrackForSession by reloading source inside mutex
- Fix ALSA handle cleanup atomicity (nullify before close to prevent use-after-free)
- Bounds check for opus buffer already present (verified)

Configuration Alignment:
- Align audio bitrate default to 192 kbps across all layers (C, Go defaults, config)
- Align audio complexity default to 8 across all layers
- Align DTX default to enabled (true/1) across all layers for bandwidth efficiency

Documentation Improvements:
- Update C header comment to reflect accurate 192 kbps default
- Clarify NEON requirement (not just "always available")
- Fix ALSA device mapping comments to reflect environment variable usage
- Document fallback behavior in playback init

Code Quality:
- Add validation logging for out-of-range audio configuration values
- Improve error visibility for configuration issues

All changes thoroughly analyzed before implementation.
2025-11-18 16:37:44 +02:00
Alex P da4c6c70d2 Use efficient uint8_t for recovery attempt counters
Change recovery_attempts from int to uint8_t for better efficiency:
- Reduces memory footprint (1 byte vs 4 bytes)
- Better cache utilization on ARM
- Matches max_attempts type (uint8_t)
- Values never exceed 3, fits perfectly in uint8_t range

Updated function signature and all call sites for consistency.
2025-11-18 15:32:55 +02:00
Alex P befdfc7ce6 Fix type mismatch in ALSA error handler
Change recovery_attempts from uint8_t to int to match
handle_alsa_error signature and eliminate compiler warnings.
2025-11-18 14:38:12 +02:00
Alex P 0e299aac38 Deduplicate ALSA error handling and cleanup code
Extract shared error recovery logic:
- Create handle_alsa_error() for EPIPE, EAGAIN, ESTRPIPE, EIO errors
- Consolidates ~180 lines of duplicate error handling code
- Used by both capture and playback paths

Extract shared close logic:
- Create close_audio_stream() for safe shutdown sequence
- Handles CAS synchronization, delay, mutex protection
- Used by both jetkvm_audio_capture_close and jetkvm_audio_playback_close

Remove all TRACE_LOG dead code:
- TRACE_LOG was compiled to ((void)0) with zero runtime value
- Eliminates ~30 statements cluttering the codebase

Result: 87 lines removed (9% reduction), improved maintainability
2025-11-18 14:34:21 +02:00
Alex P 478302144f Fix USB audio channels and remove redundant synchronization
USB audio configuration:
- Set playback to mono (microphone input from remote PC)
- Set capture to stereo (audio output to remote PC)
- Fixes audio input initialization failures and stereo output

Audio management optimizations:
- Remove redundant mutex in stopInputAudio (C layer provides synchronization)
- Remove unnecessary 100ms delay when switching audio sources
- Simplify error handling (Disconnect is idempotent)
- Remove time import (no longer needed)
2025-11-18 14:25:33 +02:00
Alex P 0022599b03 Fix audio channel separation and improve quality defaults
- Separate capture_channels (stereo HDMI) from playback_channels (mono mic)
  to prevent initialization conflicts that were breaking stereo output
- Optimize defaults for LAN use: 192kbps bitrate, complexity 8, 0% packet
  loss compensation, DTX disabled (eliminates static and improves clarity)
- Add comprehensive race condition protection in C audio layer with handle
  validity checks and mutex-protected cleanup operations
- Enable USB audio volume control and configure microphone as mono
- Add centralized AUDIO_DEFAULTS constant in UI with localized labels
- Add missing time import to fix compilation

This resolves audio quality issues and crash scenarios when switching
between HDMI and USB audio sources.
2025-11-18 13:38:06 +02:00
Alex P 2f622df28d Fix input audio source swap bug
startInputAudioUnderMutex was incorrectly swapping outputSource
instead of inputSource, breaking microphone functionality.
2025-11-18 10:03:42 +02:00
Alex bc2a5f88e1
Merge pull request #1 from IDisposable/small-tweaks
Some cleanup to eliminate duplicate code ensure we don't carry around multiple copies of state
2025-11-18 09:49:10 +02:00
Marc Brooks 1ec9941103
Simplify audio management
Moved all start/stop of sources into audio (out of jsonrpc)
Clean up duplicated code, made direction a bool, more logging, made all source/relay atomics.
Eliminate SetConfig since we always set it during start.
Eliminate the extra initialized flag.
Properly detect when USB audio was previously active.
Relay has the pointer to the source, not a copy.
CgoSource (and stub) expose the AudioSource interface.
2025-11-17 22:21:47 -06:00
Marc Brooks 8c7764a663
Ensure the stopAudio() always runs 2025-11-17 20:12:34 -06:00
Marc Brooks 9b2500b2df
Extract alsaDevice configuration to helper 2025-11-17 20:12:12 -06:00
Marc Brooks 7f930e01b3
Add missing translations for new connection stats 2025-11-17 20:11:33 -06:00
Marc Brooks cbba7f255a
Removed unused translations. 2025-11-17 20:11:33 -06:00
Marc Brooks ba831dc682
Ran npm run i18n to sort the message strings. 2025-11-17 20:11:32 -06:00
Alex P a1a2b9d1c0 Remove unnecessary assignment when USB devices unchanged
Addresses PR #718 review comment - no need to assign config.UsbDevices
when we've already verified the devices are equal.
2025-11-18 02:11:29 +02:00
Alex P 2e84354d78 Fix shutdown log level and order per PR review
- Change logger.Info() to logger.Log() for shutdown message to ensure it always logs
- Move stopAudio() before logging to stop audio first, then log shutdown

Addresses PR #718 review comment
2025-11-18 02:08:40 +02:00