From bda92b4a6279de4675db6ad4e03c9c87336bb27e Mon Sep 17 00:00:00 2001 From: Alex P Date: Tue, 9 Sep 2025 08:42:43 +0000 Subject: [PATCH] [Milestone] Fix: in-flight audio input quality updates --- internal/audio/goroutine_pool.go | 4 ++-- internal/audio/input_supervisor.go | 4 ++-- internal/audio/quality_presets.go | 33 ++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/internal/audio/goroutine_pool.go b/internal/audio/goroutine_pool.go index 23115a1d..4f954d19 100644 --- a/internal/audio/goroutine_pool.go +++ b/internal/audio/goroutine_pool.go @@ -196,7 +196,7 @@ func (p *GoroutinePool) supervisor() { tasks := atomic.LoadInt64(&p.taskCount) queueLen := len(p.taskQueue) - p.logger.Info(). + p.logger.Debug(). Int64("workers", workers). Int64("tasks_processed", tasks). Int("queue_length", queueLen). @@ -215,7 +215,7 @@ func (p *GoroutinePool) Shutdown(wait bool) { if wait { // Wait for all tasks to be processed if len(p.taskQueue) > 0 { - p.logger.Info().Int("remaining_tasks", len(p.taskQueue)).Msg("Waiting for tasks to complete") + p.logger.Debug().Int("remaining_tasks", len(p.taskQueue)).Msg("Waiting for tasks to complete") } // Close the task queue to signal no more tasks diff --git a/internal/audio/input_supervisor.go b/internal/audio/input_supervisor.go index 3e7f499c..94d1e370 100644 --- a/internal/audio/input_supervisor.go +++ b/internal/audio/input_supervisor.go @@ -136,8 +136,8 @@ func (ais *AudioInputSupervisor) startProcess() error { // Add process to monitoring - // Connect client to the server - go ais.connectClient() + // Connect client to the server synchronously to avoid race condition + ais.connectClient() return nil } diff --git a/internal/audio/quality_presets.go b/internal/audio/quality_presets.go index b41bad56..0d50bc8d 100644 --- a/internal/audio/quality_presets.go +++ b/internal/audio/quality_presets.go @@ -311,14 +311,26 @@ func SetMicrophoneQuality(quality AudioQuality) { } // Update audio input subprocess configuration dynamically without restart - if supervisor := GetAudioInputSupervisor(); supervisor != nil { - logger := logging.GetDefaultLogger().With().Str("component", "audio").Logger() - logger.Info().Int("quality", int(quality)).Msg("updating audio input subprocess quality settings dynamically") + logger := logging.GetDefaultLogger().With().Str("component", "audio").Logger() + logger.Info().Int("quality", int(quality)).Msg("updating audio input quality settings dynamically") - // Set new OPUS configuration for future restarts + // Set new OPUS configuration for future restarts + if supervisor := GetAudioInputSupervisor(); supervisor != nil { supervisor.SetOpusConfig(config.Bitrate*1000, complexity, vbr, signalType, bandwidth, dtx) - // Send dynamic configuration update to running subprocess + // Check if microphone is active but IPC control is broken + inputManager := getAudioInputManager() + if inputManager.IsRunning() && !supervisor.IsConnected() { + logger.Info().Msg("microphone active but IPC disconnected, attempting to reconnect control channel") + // Reconnect the IPC control channel + supervisor.Stop() + time.Sleep(50 * time.Millisecond) + if err := supervisor.Start(); err != nil { + logger.Warn().Err(err).Msg("failed to reconnect IPC control channel") + } + } + + // Send dynamic configuration update to running subprocess via IPC if supervisor.IsConnected() { // Convert AudioConfig to InputIPCOpusConfig with complete Opus parameters opusConfig := InputIPCOpusConfig{ @@ -335,17 +347,16 @@ func SetMicrophoneQuality(quality AudioQuality) { logger.Info().Interface("opusConfig", opusConfig).Msg("sending Opus configuration to audio input subprocess") if err := supervisor.SendOpusConfig(opusConfig); err != nil { - logger.Warn().Err(err).Msg("failed to send dynamic Opus config update, subprocess may need restart") - // Fallback to restart if dynamic update fails + logger.Warn().Err(err).Msg("failed to send dynamic Opus config update via IPC, falling back to subprocess restart") + // Fallback to subprocess restart if IPC update fails supervisor.Stop() if err := supervisor.Start(); err != nil { - logger.Error().Err(err).Msg("failed to restart audio input subprocess after config update failure") + logger.Error().Err(err).Msg("failed to restart audio input subprocess after IPC update failure") } } else { - logger.Info().Msg("audio input quality updated dynamically with complete Opus configuration") + logger.Info().Msg("audio input quality updated dynamically via IPC") - // Reset audio input server stats after config update - // Allow adaptive buffer manager to naturally adjust buffer sizes + // Reset audio input stats after config update go func() { time.Sleep(Config.QualityChangeSettleDelay) // Wait for quality change to settle // Reset audio input server stats to clear persistent warnings