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
This commit is contained in:
Alex P 2025-11-21 00:57:31 +02:00
parent 5f7c90649a
commit 4001ef651f
2 changed files with 12 additions and 16 deletions

View File

@ -13,10 +13,10 @@ import (
) )
var ( var (
audioMutex sync.Mutex audioMutex sync.Mutex
inputSourceMutex sync.Mutex // Serializes Connect() and WriteMessage() calls to input source inputSourceMutex sync.Mutex // Prevents concurrent WebRTC packets from racing during lazy connect + write
outputSource atomic.Pointer[audio.AudioSource] outputSource atomic.Pointer[audio.AudioSource]
inputSource atomic.Pointer[audio.AudioSource] inputSource atomic.Pointer[audio.AudioSource]
outputRelay atomic.Pointer[audio.OutputRelay] outputRelay atomic.Pointer[audio.OutputRelay]
inputRelay atomic.Pointer[audio.InputRelay] inputRelay atomic.Pointer[audio.InputRelay]
audioInitialized bool audioInitialized bool
@ -302,7 +302,7 @@ func SetAudioInputEnabled(enabled bool) error {
// TC358743 hardware characteristics. Callers receive success before audio actually switches. // TC358743 hardware characteristics. Callers receive success before audio actually switches.
func SetAudioOutputSource(source string) error { func SetAudioOutputSource(source string) error {
if source != "hdmi" && source != "usb" { if source != "hdmi" && source != "usb" {
return nil return fmt.Errorf("invalid audio source: %s (must be 'hdmi' or 'usb')", source)
} }
ensureConfigLoaded() ensureConfigLoaded()

View File

@ -75,12 +75,11 @@ static uint32_t max_backoff_us_global = 500000;
static atomic_int capture_stop_requested = 0; static atomic_int capture_stop_requested = 0;
static atomic_int playback_stop_requested = 0; static atomic_int playback_stop_requested = 0;
// Mutexes to protect concurrent access to ALSA handles during close // Mutexes to protect concurrent access to ALSA handles and codecs
// These prevent race conditions when jetkvm_audio_*_close() is called while // These prevent race conditions when jetkvm_audio_*_close() is called while
// jetkvm_audio_read_encode() or jetkvm_audio_decode_write() are executing. // jetkvm_audio_read_encode() or jetkvm_audio_decode_write() are executing.
// The hot path functions acquire these mutexes briefly to validate handle // The mutexes are held during ALSA I/O and codec operations to ensure
// pointers, then release before slow ALSA/Opus operations to avoid holding // handles remain valid throughout the operation.
// locks during I/O. Handle comparison checks detect races after operations.
static pthread_mutex_t capture_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t capture_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t playback_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t playback_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -606,7 +605,7 @@ retry_read:
/** /**
* Initialize INPUT path (Opus decoder device speakers) * Initialize INPUT path (Opus decoder device speakers)
* Opens ALSA playback device from ALSA_PLAYBACK_DEVICE env (default: hw:1,0), falls back to "default" on error * Opens ALSA playback device from ALSA_PLAYBACK_DEVICE env (default: hw:1,0)
* and creates Opus decoder * and creates Opus decoder
* @return 0 on success, -EBUSY if initializing, -1/-2 on errors * @return 0 on success, -EBUSY if initializing, -1/-2 on errors
*/ */
@ -652,12 +651,9 @@ int jetkvm_audio_playback_init() {
fprintf(stderr, "Failed to open ALSA playback device %s: %s\n", fprintf(stderr, "Failed to open ALSA playback device %s: %s\n",
alsa_playback_device, snd_strerror(err)); alsa_playback_device, snd_strerror(err));
fflush(stderr); fflush(stderr);
err = safe_alsa_open(&pcm_playback_handle, "default", SND_PCM_STREAM_PLAYBACK); atomic_store(&playback_stop_requested, 0);
if (err < 0) { playback_initializing = 0;
atomic_store(&playback_stop_requested, 0); return -1;
playback_initializing = 0;
return -1;
}
} }
unsigned int actual_rate = 0; unsigned int actual_rate = 0;