From 5a0dce9984ff585f7728630bbb243d90c01b723c Mon Sep 17 00:00:00 2001 From: Alex P Date: Sat, 6 Sep 2025 06:11:29 +0000 Subject: [PATCH] Fix: Microphone & audio on page load, PID field parsing in audio input supervisor --- audio_handlers.go | 10 ++++++++++ internal/audio/core_handlers.go | 7 +++++++ internal/audio/input_supervisor.go | 4 ++-- ui/src/hooks/useAudioEvents.ts | 18 ++++++++++++++++++ web.go | 1 + 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/audio_handlers.go b/audio_handlers.go index f430b2df..44b6ddbe 100644 --- a/audio_handlers.go +++ b/audio_handlers.go @@ -103,11 +103,21 @@ func handleUnsubscribeAudioEvents(connectionID string, l *zerolog.Logger) { audioControlService.UnsubscribeFromAudioEvents(connectionID, l) } +// handleAudioStatus handles GET requests for audio status +func handleAudioStatus(c *gin.Context) { + initAudioControlService() + + status := audioControlService.GetAudioStatus() + c.JSON(200, status) +} + // handleAudioQuality handles GET requests for audio quality presets func handleAudioQuality(c *gin.Context) { initAudioControlService() + presets := audioControlService.GetAudioQualityPresets() current := audioControlService.GetCurrentAudioQuality() + c.JSON(200, gin.H{ "presets": presets, "current": current, diff --git a/internal/audio/core_handlers.go b/internal/audio/core_handlers.go index 8f7aa940..e94d4db3 100644 --- a/internal/audio/core_handlers.go +++ b/internal/audio/core_handlers.go @@ -97,6 +97,13 @@ func (s *AudioControlService) ResetMicrophone() error { return nil } +// GetAudioStatus returns the current audio output status +func (s *AudioControlService) GetAudioStatus() map[string]interface{} { + return map[string]interface{}{ + "muted": IsAudioMuted(), + } +} + // GetMicrophoneStatus returns the current microphone status func (s *AudioControlService) GetMicrophoneStatus() map[string]interface{} { if s.sessionProvider == nil { diff --git a/internal/audio/input_supervisor.go b/internal/audio/input_supervisor.go index 889b124c..0d5f6b42 100644 --- a/internal/audio/input_supervisor.go +++ b/internal/audio/input_supervisor.go @@ -347,8 +347,8 @@ func (ais *AudioInputSupervisor) findExistingAudioInputProcess() (int, error) { // Extract PID from ps output (second column) fields := strings.Fields(line) if len(fields) >= 2 { - if pid, err := strconv.Atoi(fields[1]); err == nil { - // Verify the process is still running and accessible + // PID is the first field + if pid, err := strconv.Atoi(fields[0]); err == nil { if ais.isProcessRunning(pid) { return pid, nil } diff --git a/ui/src/hooks/useAudioEvents.ts b/ui/src/hooks/useAudioEvents.ts index 0a1672ee..aa3dd436 100644 --- a/ui/src/hooks/useAudioEvents.ts +++ b/ui/src/hooks/useAudioEvents.ts @@ -63,6 +63,19 @@ export function useAudioEvents(onAudioDeviceChanged?: (data: AudioDeviceChangedD const [audioMuted, setAudioMuted] = useState(null); const [microphoneState, setMicrophoneState] = useState(null); + // Fetch initial audio status + const fetchInitialAudioStatus = useCallback(async () => { + try { + const response = await fetch('/audio/status'); + if (response.ok) { + const data = await response.json(); + setAudioMuted(data.muted); + } + } catch (error) { + devError('Failed to fetch initial audio status:', error); + } + }, []); + // Local subscription state const [isLocallySubscribed, setIsLocallySubscribed] = useState(false); const subscriptionTimeoutRef = useRef(null); @@ -240,6 +253,11 @@ export function useAudioEvents(onAudioDeviceChanged?: (data: AudioDeviceChangedD } }, [readyState]); + // Fetch initial audio status on component mount + useEffect(() => { + fetchInitialAudioStatus(); + }, [fetchInitialAudioStatus]); + // Cleanup on component unmount useEffect(() => { return () => { diff --git a/web.go b/web.go index 1a3d7c21..05f74782 100644 --- a/web.go +++ b/web.go @@ -156,6 +156,7 @@ func setupRouter() *gin.Engine { protected.POST("/storage/upload", handleUploadHttp) // Audio handlers + protected.GET("/audio/status", handleAudioStatus) protected.POST("/audio/mute", handleAudioMute) protected.GET("/audio/quality", handleAudioQuality) protected.POST("/audio/quality", handleSetAudioQuality)