refactor(audio): remove unused context from audio input manager

Simplify AudioInputIPCManager by removing unused context and cancellation logic. The context was not providing any meaningful functionality.

fix(ui): handle audio device changes with proper sync

Add delayed microphone state synchronization when audio devices change to prevent race conditions during USB audio reconfiguration.
This commit is contained in:
Alex P 2025-08-25 13:53:29 +00:00
parent 6f02870c90
commit c89d678963
2 changed files with 18 additions and 17 deletions

View File

@ -1,7 +1,6 @@
package audio
import (
"context"
"sync/atomic"
"time"
@ -16,18 +15,13 @@ type AudioInputIPCManager struct {
supervisor *AudioInputSupervisor
logger zerolog.Logger
running int32
ctx context.Context
cancel context.CancelFunc
}
// NewAudioInputIPCManager creates a new IPC-based audio input manager
func NewAudioInputIPCManager() *AudioInputIPCManager {
ctx, cancel := context.WithCancel(context.Background())
return &AudioInputIPCManager{
supervisor: NewAudioInputSupervisor(),
logger: logging.GetDefaultLogger().With().Str("component", "audio-input-ipc").Logger(),
ctx: ctx,
cancel: cancel,
}
}
@ -52,14 +46,8 @@ func (aim *AudioInputIPCManager) Start() error {
FrameSize: 960,
}
// Wait with timeout for subprocess readiness
select {
case <-time.After(200 * time.Millisecond):
case <-aim.ctx.Done():
aim.supervisor.Stop()
atomic.StoreInt32(&aim.running, 0)
return aim.ctx.Err()
}
// Wait for subprocess readiness
time.Sleep(200 * time.Millisecond)
err = aim.supervisor.SendConfig(config)
if err != nil {
@ -77,7 +65,6 @@ func (aim *AudioInputIPCManager) Stop() {
}
aim.logger.Info().Msg("Stopping IPC-based audio input system")
aim.cancel()
aim.supervisor.Stop()
aim.logger.Info().Msg("IPC-based audio input system stopped")
}

View File

@ -146,6 +146,8 @@ export default function KvmIdRoute() {
// Microphone hook - moved here to prevent unmounting when popover closes
const microphoneHook = useMicrophone();
// Extract syncMicrophoneState to avoid dependency issues
const { syncMicrophoneState } = microphoneHook;
const isLegacySignalingEnabled = useRef(false);
@ -656,8 +658,20 @@ export default function KvmIdRoute() {
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
const { send } = useJsonRpc(onJsonRpcRequest);
// Use audio events hook without device change handler to avoid subscription loops
useAudioEvents();
// Handle audio device changes to sync microphone state
const handleAudioDeviceChanged = useCallback((data: { enabled: boolean; reason: string }) => {
console.log('[AudioDeviceChanged] Audio device changed:', data);
// Sync microphone state when audio device configuration changes
// This ensures the microphone state is properly synchronized after USB audio reconfiguration
if (syncMicrophoneState) {
setTimeout(() => {
syncMicrophoneState();
}, 500); // Small delay to ensure backend state is settled
}
}, [syncMicrophoneState]);
// Use audio events hook with device change handler
useAudioEvents(handleAudioDeviceChanged);
useEffect(() => {
if (rpcDataChannel?.readyState !== "open") return;