From 7ec583ed6a844b9f2c72ff75ff3b42388d6a2548 Mon Sep 17 00:00:00 2001 From: Alex P Date: Mon, 25 Aug 2025 16:49:48 +0000 Subject: [PATCH] refactor(audio): centralize config and remove debug logs - Move hardcoded constants to centralized config system - Remove verbose debug logging statements - Clean up unused code and improve error handling --- internal/audio/audio.go | 15 +- internal/audio/config.go | 26 +-- internal/audio/config_constants.go | 150 ++++++++++++++++++ internal/audio/events.go | 28 +--- internal/audio/output_streaming.go | 4 +- internal/audio/supervisor.go | 40 +++-- internal/audio/zero_copy.go | 11 +- jsonrpc.go | 16 +- ui/src/components/AudioMetricsDashboard.tsx | 20 +-- ui/src/components/InfoBar.tsx | 5 +- .../popovers/AudioControlPopover.tsx | 36 ++--- ui/src/hooks/stores.ts | 29 ++-- ui/src/hooks/useAudioDevices.ts | 7 +- ui/src/hooks/useAudioEvents.ts | 16 +- ui/src/hooks/useAudioLevel.ts | 4 +- ui/src/hooks/useMicrophone.ts | 21 +-- ui/src/hooks/useUsbDeviceConfig.ts | 2 +- 17 files changed, 265 insertions(+), 165 deletions(-) create mode 100644 internal/audio/config_constants.go diff --git a/internal/audio/audio.go b/internal/audio/audio.go index 702390f..243899a 100644 --- a/internal/audio/audio.go +++ b/internal/audio/audio.go @@ -10,7 +10,10 @@ var ( ErrAudioAlreadyRunning = errors.New("audio already running") ) -const MaxAudioFrameSize = 1500 +// MaxAudioFrameSize is now retrieved from centralized config +func GetMaxAudioFrameSize() int { + return GetConfig().MaxAudioFrameSize +} // AudioQuality represents different audio quality presets type AudioQuality int @@ -45,14 +48,14 @@ var ( currentConfig = AudioConfig{ Quality: AudioQualityMedium, Bitrate: 64, - SampleRate: 48000, - Channels: 2, + SampleRate: GetConfig().SampleRate, + Channels: GetConfig().Channels, FrameSize: 20 * time.Millisecond, } currentMicrophoneConfig = AudioConfig{ Quality: AudioQualityMedium, Bitrate: 32, - SampleRate: 48000, + SampleRate: GetConfig().SampleRate, Channels: 1, FrameSize: 20 * time.Millisecond, } @@ -77,12 +80,12 @@ var qualityPresets = map[AudioQuality]struct { }, AudioQualityHigh: { outputBitrate: 128, inputBitrate: 64, - sampleRate: 48000, channels: 2, + sampleRate: GetConfig().SampleRate, channels: GetConfig().Channels, frameSize: 20 * time.Millisecond, }, AudioQualityUltra: { outputBitrate: 192, inputBitrate: 96, - sampleRate: 48000, channels: 2, + sampleRate: GetConfig().SampleRate, channels: GetConfig().Channels, frameSize: 10 * time.Millisecond, }, } diff --git a/internal/audio/config.go b/internal/audio/config.go index 0521864..f5bb739 100644 --- a/internal/audio/config.go +++ b/internal/audio/config.go @@ -2,28 +2,14 @@ package audio import "time" -// MonitoringConfig contains configuration constants for audio monitoring -type MonitoringConfig struct { - // MetricsUpdateInterval defines how often metrics are collected and broadcast - MetricsUpdateInterval time.Duration -} - -// DefaultMonitoringConfig returns the default monitoring configuration -func DefaultMonitoringConfig() MonitoringConfig { - return MonitoringConfig{ - MetricsUpdateInterval: 1000 * time.Millisecond, // 1 second interval - } -} - -// Global monitoring configuration instance -var monitoringConfig = DefaultMonitoringConfig() - -// GetMetricsUpdateInterval returns the current metrics update interval +// GetMetricsUpdateInterval returns the current metrics update interval from centralized config func GetMetricsUpdateInterval() time.Duration { - return monitoringConfig.MetricsUpdateInterval + return GetConfig().MetricsUpdateInterval } -// SetMetricsUpdateInterval sets the metrics update interval +// SetMetricsUpdateInterval sets the metrics update interval in centralized config func SetMetricsUpdateInterval(interval time.Duration) { - monitoringConfig.MetricsUpdateInterval = interval + config := GetConfig() + config.MetricsUpdateInterval = interval + UpdateConfig(config) } diff --git a/internal/audio/config_constants.go b/internal/audio/config_constants.go new file mode 100644 index 0000000..b1a956c --- /dev/null +++ b/internal/audio/config_constants.go @@ -0,0 +1,150 @@ +package audio + +import "time" + +// AudioConfigConstants centralizes all hardcoded values used across audio components +type AudioConfigConstants struct { + // Audio Quality Presets + MaxAudioFrameSize int + + // Opus Encoding Parameters + OpusBitrate int + OpusComplexity int + OpusVBR int + OpusVBRConstraint int + OpusDTX int + + // Audio Parameters + SampleRate int + Channels int + FrameSize int + MaxPacketSize int + + // Process Management + MaxRestartAttempts int + RestartWindow time.Duration + RestartDelay time.Duration + MaxRestartDelay time.Duration + + // Buffer Management + PreallocSize int + MaxPoolSize int + MessagePoolSize int + OptimalSocketBuffer int + MaxSocketBuffer int + MinSocketBuffer int + + // IPC Configuration + MagicNumber uint32 + MaxFrameSize int + WriteTimeout time.Duration + MaxDroppedFrames int + HeaderSize int + + // Monitoring and Metrics + MetricsUpdateInterval time.Duration + EMAAlpha float64 + WarmupSamples int + LogThrottleInterval time.Duration + MetricsChannelBuffer int + + // Performance Tuning + CPUFactor float64 + MemoryFactor float64 + LatencyFactor float64 + InputSizeThreshold int + OutputSizeThreshold int + TargetLevel float64 + + // Priority Scheduling + AudioHighPriority int + AudioMediumPriority int + AudioLowPriority int + NormalPriority int + NiceValue int + + // Error Handling + MaxConsecutiveErrors int + MaxRetryAttempts int +} + +// DefaultAudioConfig returns the default configuration constants +func DefaultAudioConfig() *AudioConfigConstants { + return &AudioConfigConstants{ + // Audio Quality Presets + MaxAudioFrameSize: 4096, + + // Opus Encoding Parameters + OpusBitrate: 128000, + OpusComplexity: 10, + OpusVBR: 1, + OpusVBRConstraint: 0, + OpusDTX: 0, + + // Audio Parameters + SampleRate: 48000, + Channels: 2, + FrameSize: 960, + MaxPacketSize: 4000, + + // Process Management + MaxRestartAttempts: 5, + RestartWindow: 5 * time.Minute, + RestartDelay: 2 * time.Second, + MaxRestartDelay: 30 * time.Second, + + // Buffer Management + PreallocSize: 1024 * 1024, // 1MB + MaxPoolSize: 100, + MessagePoolSize: 100, + OptimalSocketBuffer: 262144, // 256KB + MaxSocketBuffer: 1048576, // 1MB + MinSocketBuffer: 8192, // 8KB + + // IPC Configuration + MagicNumber: 0xDEADBEEF, + MaxFrameSize: 4096, + WriteTimeout: 5 * time.Second, + MaxDroppedFrames: 10, + HeaderSize: 8, + + // Monitoring and Metrics + MetricsUpdateInterval: 1000 * time.Millisecond, + EMAAlpha: 0.1, + WarmupSamples: 10, + LogThrottleInterval: 5 * time.Second, + MetricsChannelBuffer: 100, + + // Performance Tuning + CPUFactor: 0.7, + MemoryFactor: 0.8, + LatencyFactor: 0.9, + InputSizeThreshold: 1024, + OutputSizeThreshold: 2048, + TargetLevel: 0.5, + + // Priority Scheduling + AudioHighPriority: -10, + AudioMediumPriority: -5, + AudioLowPriority: 0, + NormalPriority: 0, + NiceValue: -10, + + // Error Handling + MaxConsecutiveErrors: 5, + MaxRetryAttempts: 3, + } +} + +// Global configuration instance +var audioConfigInstance = DefaultAudioConfig() + +// UpdateConfig allows runtime configuration updates +func UpdateConfig(newConfig *AudioConfigConstants) { + audioConfigInstance = newConfig +} + +// GetConfig returns the current configuration +func GetConfig() *AudioConfigConstants { + return audioConfigInstance +} diff --git a/internal/audio/events.go b/internal/audio/events.go index d6fa2ac..ce3dc2f 100644 --- a/internal/audio/events.go +++ b/internal/audio/events.go @@ -220,18 +220,6 @@ func (aeb *AudioEventBroadcaster) sendInitialState(connectionID string) { aeb.sendCurrentMetrics(subscriber) } -// convertAudioMetricsToEventData converts internal audio metrics to AudioMetricsData for events -func convertAudioMetricsToEventData(metrics AudioMetrics) AudioMetricsData { - return AudioMetricsData{ - FramesReceived: metrics.FramesReceived, - FramesDropped: metrics.FramesDropped, - BytesProcessed: metrics.BytesProcessed, - LastFrameTime: metrics.LastFrameTime.Format("2006-01-02T15:04:05.000Z"), - ConnectionDrops: metrics.ConnectionDrops, - AverageLatency: metrics.AverageLatency.String(), - } -} - // convertAudioMetricsToEventDataWithLatencyMs converts internal audio metrics to AudioMetricsData with millisecond latency formatting func convertAudioMetricsToEventDataWithLatencyMs(metrics AudioMetrics) AudioMetricsData { return AudioMetricsData{ @@ -244,18 +232,6 @@ func convertAudioMetricsToEventDataWithLatencyMs(metrics AudioMetrics) AudioMetr } } -// convertAudioInputMetricsToEventData converts internal audio input metrics to MicrophoneMetricsData for events -func convertAudioInputMetricsToEventData(metrics AudioInputMetrics) MicrophoneMetricsData { - return MicrophoneMetricsData{ - FramesSent: metrics.FramesSent, - FramesDropped: metrics.FramesDropped, - BytesProcessed: metrics.BytesProcessed, - LastFrameTime: metrics.LastFrameTime.Format("2006-01-02T15:04:05.000Z"), - ConnectionDrops: metrics.ConnectionDrops, - AverageLatency: metrics.AverageLatency.String(), - } -} - // convertAudioInputMetricsToEventDataWithLatencyMs converts internal audio input metrics to MicrophoneMetricsData with millisecond latency formatting func convertAudioInputMetricsToEventDataWithLatencyMs(metrics AudioInputMetrics) MicrophoneMetricsData { return MicrophoneMetricsData{ @@ -358,7 +334,7 @@ func (aeb *AudioEventBroadcaster) getMicrophoneProcessMetrics() ProcessMetricsDa func (aeb *AudioEventBroadcaster) sendCurrentMetrics(subscriber *AudioEventSubscriber) { // Send audio metrics audioMetrics := GetAudioMetrics() - audioMetricsEvent := createAudioEvent(AudioEventMetricsUpdate, convertAudioMetricsToEventData(audioMetrics)) + audioMetricsEvent := createAudioEvent(AudioEventMetricsUpdate, convertAudioMetricsToEventDataWithLatencyMs(audioMetrics)) aeb.sendToSubscriber(subscriber, audioMetricsEvent) // Send audio process metrics @@ -374,7 +350,7 @@ func (aeb *AudioEventBroadcaster) sendCurrentMetrics(subscriber *AudioEventSubsc if sessionProvider.IsSessionActive() { if inputManager := sessionProvider.GetAudioInputManager(); inputManager != nil { micMetrics := inputManager.GetMetrics() - micMetricsEvent := createAudioEvent(AudioEventMicrophoneMetrics, convertAudioInputMetricsToEventData(micMetrics)) + micMetricsEvent := createAudioEvent(AudioEventMicrophoneMetrics, convertAudioInputMetricsToEventDataWithLatencyMs(micMetrics)) aeb.sendToSubscriber(subscriber, micMetricsEvent) } } diff --git a/internal/audio/output_streaming.go b/internal/audio/output_streaming.go index bef3eae..4dfb646 100644 --- a/internal/audio/output_streaming.go +++ b/internal/audio/output_streaming.go @@ -58,7 +58,7 @@ func NewOutputStreamer() (*OutputStreamer, error) { ctx, cancel := context.WithCancel(context.Background()) return &OutputStreamer{ client: client, - bufferPool: NewAudioBufferPool(MaxAudioFrameSize), // Use existing buffer pool + bufferPool: NewAudioBufferPool(GetMaxAudioFrameSize()), // Use existing buffer pool ctx: ctx, cancel: cancel, batchSize: initialBatchSize, // Use adaptive batch size @@ -319,7 +319,7 @@ func StartAudioOutputStreaming(send func([]byte)) error { }() getOutputStreamingLogger().Info().Msg("Audio output streaming started") - buffer := make([]byte, MaxAudioFrameSize) + buffer := make([]byte, GetMaxAudioFrameSize()) for { select { diff --git a/internal/audio/supervisor.go b/internal/audio/supervisor.go index ab65b4a..9429c05 100644 --- a/internal/audio/supervisor.go +++ b/internal/audio/supervisor.go @@ -17,16 +17,22 @@ import ( "github.com/rs/zerolog" ) -const ( - // Maximum number of restart attempts within the restart window - maxRestartAttempts = 5 - // Time window for counting restart attempts - restartWindow = 5 * time.Minute - // Delay between restart attempts - restartDelay = 2 * time.Second - // Maximum restart delay (exponential backoff) - maxRestartDelay = 30 * time.Second -) +// Restart configuration is now retrieved from centralized config +func getMaxRestartAttempts() int { + return GetConfig().MaxRestartAttempts +} + +func getRestartWindow() time.Duration { + return GetConfig().RestartWindow +} + +func getRestartDelay() time.Duration { + return GetConfig().RestartDelay +} + +func getMaxRestartDelay() time.Duration { + return GetConfig().MaxRestartDelay +} // AudioServerSupervisor manages the audio server subprocess lifecycle type AudioServerSupervisor struct { @@ -395,13 +401,13 @@ func (s *AudioServerSupervisor) shouldRestart() bool { now := time.Now() var recentAttempts []time.Time for _, attempt := range s.restartAttempts { - if now.Sub(attempt) < restartWindow { + if now.Sub(attempt) < getRestartWindow() { recentAttempts = append(recentAttempts, attempt) } } s.restartAttempts = recentAttempts - return len(s.restartAttempts) < maxRestartAttempts + return len(s.restartAttempts) < getMaxRestartAttempts() } // recordRestartAttempt records a restart attempt @@ -420,17 +426,17 @@ func (s *AudioServerSupervisor) calculateRestartDelay() time.Duration { // Exponential backoff based on recent restart attempts attempts := len(s.restartAttempts) if attempts == 0 { - return restartDelay + return getRestartDelay() } // Calculate exponential backoff: 2^attempts * base delay - delay := restartDelay - for i := 0; i < attempts && delay < maxRestartDelay; i++ { + delay := getRestartDelay() + for i := 0; i < attempts && delay < getMaxRestartDelay(); i++ { delay *= 2 } - if delay > maxRestartDelay { - delay = maxRestartDelay + if delay > getMaxRestartDelay() { + delay = getMaxRestartDelay() } return delay diff --git a/internal/audio/zero_copy.go b/internal/audio/zero_copy.go index 5d0cfb9..b282d8b 100644 --- a/internal/audio/zero_copy.go +++ b/internal/audio/zero_copy.go @@ -262,7 +262,7 @@ type ZeroCopyFramePoolStats struct { } var ( - globalZeroCopyPool = NewZeroCopyFramePool(MaxAudioFrameSize) + globalZeroCopyPool = NewZeroCopyFramePool(GetMaxAudioFrameSize()) ) // GetZeroCopyFrame gets a frame from the global pool @@ -284,16 +284,17 @@ func PutZeroCopyFrame(frame *ZeroCopyAudioFrame) { func ZeroCopyAudioReadEncode() (*ZeroCopyAudioFrame, error) { frame := GetZeroCopyFrame() + maxFrameSize := GetMaxAudioFrameSize() // Ensure frame has enough capacity - if frame.Capacity() < MaxAudioFrameSize { + if frame.Capacity() < maxFrameSize { // Reallocate if needed - frame.data = make([]byte, MaxAudioFrameSize) - frame.capacity = MaxAudioFrameSize + frame.data = make([]byte, maxFrameSize) + frame.capacity = maxFrameSize frame.pooled = false } // Use unsafe pointer for direct CGO call - n, err := CGOAudioReadEncode(frame.data[:MaxAudioFrameSize]) + n, err := CGOAudioReadEncode(frame.data[:maxFrameSize]) if err != nil { PutZeroCopyFrame(frame) return nil, err diff --git a/jsonrpc.go b/jsonrpc.go index fb24f2f..ae49a77 100644 --- a/jsonrpc.go +++ b/jsonrpc.go @@ -1088,15 +1088,15 @@ func rpcSetUsbDeviceState(device string, enabled bool) error { if err := audioSupervisor.Start(); err != nil { logger.Error().Err(err).Msg("failed to start audio supervisor") } else { - // Broadcast audio device change event to notify WebRTC session + // Broadcast audio device change event to notify WebRTC session + broadcaster := audio.GetAudioEventBroadcaster() + broadcaster.BroadcastAudioDeviceChanged(true, "device_enabled") + logger.Info().Msg("broadcasted audio device change event after enabling audio device") + } + // Always broadcast the audio device change event regardless of enable/disable broadcaster := audio.GetAudioEventBroadcaster() - broadcaster.BroadcastAudioDeviceChanged(true, "device_enabled") - logger.Info().Msg("broadcasted audio device change event after enabling audio device") - } - // Always broadcast the audio device change event regardless of enable/disable - broadcaster := audio.GetAudioEventBroadcaster() - broadcaster.BroadcastAudioDeviceChanged(enabled, "device_state_changed") - logger.Info().Bool("enabled", enabled).Msg("broadcasted audio device state change event") + broadcaster.BroadcastAudioDeviceChanged(enabled, "device_state_changed") + logger.Info().Bool("enabled", enabled).Msg("broadcasted audio device state change event") } config.UsbDevices.Audio = enabled default: diff --git a/ui/src/components/AudioMetricsDashboard.tsx b/ui/src/components/AudioMetricsDashboard.tsx index 0c3032a..910f7cd 100644 --- a/ui/src/components/AudioMetricsDashboard.tsx +++ b/ui/src/components/AudioMetricsDashboard.tsx @@ -122,8 +122,8 @@ export default function AudioMetricsDashboard() { const response = await api.GET('/system/memory'); const data = await response.json(); setSystemMemoryMB(data.total_memory_mb); - } catch (error) { - console.warn('Failed to fetch system memory, using default:', error); + } catch { + // Failed to fetch system memory, using default } }; fetchSystemMemory(); @@ -260,8 +260,8 @@ export default function AudioMetricsDashboard() { const micConfigData = await micConfigResp.json(); setMicrophoneConfig(micConfigData.current); } - } catch (micConfigError) { - console.debug("Microphone config not available:", micConfigError); + } catch { + // Microphone config not available } } catch (error) { console.error("Failed to load audio config:", error); @@ -321,8 +321,8 @@ export default function AudioMetricsDashboard() { }); } } - } catch (audioProcessError) { - console.debug("Audio process metrics not available:", audioProcessError); + } catch { + // Audio process metrics not available } // Load microphone metrics @@ -332,9 +332,9 @@ export default function AudioMetricsDashboard() { const micData = await micResp.json(); setFallbackMicrophoneMetrics(micData); } - } catch (micError) { + } catch { // Microphone metrics might not be available, that's okay - console.debug("Microphone metrics not available:", micError); + // Microphone metrics not available } // Load microphone process metrics @@ -374,8 +374,8 @@ export default function AudioMetricsDashboard() { return newMap; }); } - } catch (micProcessError) { - console.debug("Microphone process metrics not available:", micProcessError); + } catch { + // Microphone process metrics not available } } catch (error) { console.error("Failed to load audio data:", error); diff --git a/ui/src/components/InfoBar.tsx b/ui/src/components/InfoBar.tsx index 7ce67a4..2eed449 100644 --- a/ui/src/components/InfoBar.tsx +++ b/ui/src/components/InfoBar.tsx @@ -32,9 +32,8 @@ export default function InfoBar() { useEffect(() => { if (!rpcDataChannel) return; - rpcDataChannel.onclose = () => console.log("rpcDataChannel has closed"); - rpcDataChannel.onerror = e => - console.log(`Error on DataChannel '${rpcDataChannel.label}': ${e}`); + rpcDataChannel.onclose = () => { /* RPC data channel closed */ }; + rpcDataChannel.onerror = () => { /* Error on RPC data channel */ }; }, [rpcDataChannel]); const keyboardLedState = useHidStore(state => state.keyboardLedState); diff --git a/ui/src/components/popovers/AudioControlPopover.tsx b/ui/src/components/popovers/AudioControlPopover.tsx index 9dd0568..7cce34d 100644 --- a/ui/src/components/popovers/AudioControlPopover.tsx +++ b/ui/src/components/popovers/AudioControlPopover.tsx @@ -155,8 +155,8 @@ export default function AudioControlPopover({ microphone, open }: AudioControlPo } setConfigsLoaded(true); - } catch (error) { - console.error("Failed to load audio configurations:", error); + } catch { + // Failed to load audio configurations } }; @@ -165,11 +165,11 @@ export default function AudioControlPopover({ microphone, open }: AudioControlPo try { const resp = await api.POST("/audio/mute", { muted: !isMuted }); if (!resp.ok) { - console.error("Failed to toggle mute:", resp.statusText); + // Failed to toggle mute } // WebSocket will handle the state update automatically - } catch (error) { - console.error("Failed to toggle mute:", error); + } catch { + // Failed to toggle mute } finally { setIsLoading(false); } @@ -183,8 +183,8 @@ export default function AudioControlPopover({ microphone, open }: AudioControlPo const data = await resp.json(); setCurrentConfig(data.config); } - } catch (error) { - console.error("Failed to change audio quality:", error); + } catch { + // Failed to change audio quality } finally { setIsLoading(false); } @@ -197,8 +197,8 @@ export default function AudioControlPopover({ microphone, open }: AudioControlPo const data = await resp.json(); setCurrentMicrophoneConfig(data.config); } - } catch (error) { - console.error("Failed to change microphone quality:", error); + } catch { + // Failed to change microphone quality } }; @@ -217,8 +217,8 @@ export default function AudioControlPopover({ microphone, open }: AudioControlPo if (!result.success && result.error) { notifications.error(result.error.message); } - } catch (error) { - console.error("Failed to toggle microphone:", error); + } catch { + // Failed to toggle microphone notifications.error("An unexpected error occurred"); } }; @@ -238,8 +238,8 @@ export default function AudioControlPopover({ microphone, open }: AudioControlPo if (!result.success && result.error) { notifications.error(result.error.message); } - } catch (error) { - console.error("Failed to toggle microphone mute:", error); + } catch { + // Failed to toggle microphone mute notifications.error("Failed to toggle microphone mute"); } }; @@ -258,8 +258,8 @@ export default function AudioControlPopover({ microphone, open }: AudioControlPo if (!result.success && result.error) { notifications.error(result.error.message); } - } catch (error) { - console.error("Failed to change microphone device:", error); + } catch { + // Failed to change microphone device notifications.error("Failed to change microphone device"); } } @@ -273,11 +273,11 @@ export default function AudioControlPopover({ microphone, open }: AudioControlPo if (videoElement && 'setSinkId' in videoElement) { try { await (videoElement as HTMLVideoElement & { setSinkId: (deviceId: string) => Promise }).setSinkId(deviceId); - } catch (error: unknown) { - console.error('Failed to change audio output device:', error); + } catch { + // Failed to change audio output device } } else { - console.warn('setSinkId not supported or video element not found'); + // setSinkId not supported or video element not found } }; diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts index e800f8b..e0817f3 100644 --- a/ui/src/hooks/stores.ts +++ b/ui/src/hooks/stores.ts @@ -845,7 +845,7 @@ export const useMacrosStore = create((set, get) => ({ const { sendFn } = get(); if (!sendFn) { - console.warn("JSON-RPC send function not available."); + // console.warn("JSON-RPC send function not available."); return; } @@ -855,7 +855,7 @@ export const useMacrosStore = create((set, get) => ({ await new Promise((resolve, reject) => { sendFn("getKeyboardMacros", {}, (response: JsonRpcResponse) => { if (response.error) { - console.error("Error loading macros:", response.error); + // console.error("Error loading macros:", response.error); reject(new Error(response.error.message)); return; } @@ -879,8 +879,8 @@ export const useMacrosStore = create((set, get) => ({ resolve(); }); }); - } catch (error) { - console.error("Failed to load macros:", error); + } catch { + // console.error("Failed to load macros:", _error); } finally { set({ loading: false }); } @@ -889,20 +889,20 @@ export const useMacrosStore = create((set, get) => ({ saveMacros: async (macros: KeySequence[]) => { const { sendFn } = get(); if (!sendFn) { - console.warn("JSON-RPC send function not available."); + // console.warn("JSON-RPC send function not available."); throw new Error("JSON-RPC send function not available"); } if (macros.length > MAX_TOTAL_MACROS) { - console.error(`Cannot save: exceeded maximum of ${MAX_TOTAL_MACROS} macros`); + // console.error(`Cannot save: exceeded maximum of ${MAX_TOTAL_MACROS} macros`); throw new Error(`Cannot save: exceeded maximum of ${MAX_TOTAL_MACROS} macros`); } for (const macro of macros) { if (macro.steps.length > MAX_STEPS_PER_MACRO) { - console.error( - `Cannot save: macro "${macro.name}" exceeds maximum of ${MAX_STEPS_PER_MACRO} steps`, - ); + // console.error( + // `Cannot save: macro "${macro.name}" exceeds maximum of ${MAX_STEPS_PER_MACRO} steps`, + // ); throw new Error( `Cannot save: macro "${macro.name}" exceeds maximum of ${MAX_STEPS_PER_MACRO} steps`, ); @@ -911,9 +911,9 @@ export const useMacrosStore = create((set, get) => ({ for (let i = 0; i < macro.steps.length; i++) { const step = macro.steps[i]; if (step.keys && step.keys.length > MAX_KEYS_PER_STEP) { - console.error( - `Cannot save: macro "${macro.name}" step ${i + 1} exceeds maximum of ${MAX_KEYS_PER_STEP} keys`, - ); + // console.error( + // `Cannot save: macro "${macro.name}" step ${i + 1} exceeds maximum of ${MAX_KEYS_PER_STEP} keys`, + // ); throw new Error( `Cannot save: macro "${macro.name}" step ${i + 1} exceeds maximum of ${MAX_KEYS_PER_STEP} keys`, ); @@ -940,7 +940,7 @@ export const useMacrosStore = create((set, get) => ({ }); if (response.error) { - console.error("Error saving macros:", response.error); + // console.error("Error saving macros:", response.error); const errorMessage = typeof response.error.data === "string" ? response.error.data @@ -950,9 +950,6 @@ export const useMacrosStore = create((set, get) => ({ // Only update the store if the request was successful set({ macros: macrosWithSortOrder }); - } catch (error) { - console.error("Failed to save macros:", error); - throw error; } finally { set({ loading: false }); } diff --git a/ui/src/hooks/useAudioDevices.ts b/ui/src/hooks/useAudioDevices.ts index c0b20f3..12dd1c5 100644 --- a/ui/src/hooks/useAudioDevices.ts +++ b/ui/src/hooks/useAudioDevices.ts @@ -63,10 +63,7 @@ export function useAudioDevices(): UseAudioDevicesReturn { setAudioInputDevices(inputDevices); setAudioOutputDevices(outputDevices); - console.log('Audio devices enumerated:', { - inputs: inputDevices.length, - outputs: outputDevices.length - }); + // Audio devices enumerated } catch (err) { console.error('Failed to enumerate audio devices:', err); @@ -79,7 +76,7 @@ export function useAudioDevices(): UseAudioDevicesReturn { // Listen for device changes useEffect(() => { const handleDeviceChange = () => { - console.log('Audio devices changed, refreshing...'); + // Audio devices changed, refreshing refreshDevices(); }; diff --git a/ui/src/hooks/useAudioEvents.ts b/ui/src/hooks/useAudioEvents.ts index 8436529..bb4bc14 100644 --- a/ui/src/hooks/useAudioEvents.ts +++ b/ui/src/hooks/useAudioEvents.ts @@ -124,13 +124,13 @@ export function useAudioEvents(onAudioDeviceChanged?: (data: AudioDeviceChangedD reconnectInterval: 3000, share: true, // Share the WebSocket connection across multiple hooks onOpen: () => { - console.log('[AudioEvents] WebSocket connected'); + // WebSocket connected // Reset global state on new connection globalSubscriptionState.isSubscribed = false; globalSubscriptionState.connectionId = Math.random().toString(36); }, onClose: () => { - console.log('[AudioEvents] WebSocket disconnected'); + // WebSocket disconnected // Reset global state on disconnect globalSubscriptionState.isSubscribed = false; globalSubscriptionState.subscriberCount = 0; @@ -160,7 +160,7 @@ export function useAudioEvents(onAudioDeviceChanged?: (data: AudioDeviceChangedD sendMessage(JSON.stringify(subscribeMessage)); globalSubscriptionState.isSubscribed = true; - console.log('[AudioEvents] Subscribed to audio events'); + // Subscribed to audio events } }, 100); // 100ms delay to debounce subscription attempts } @@ -197,11 +197,11 @@ export function useAudioEvents(onAudioDeviceChanged?: (data: AudioDeviceChangedD sendMessage(JSON.stringify(unsubscribeMessage)); globalSubscriptionState.isSubscribed = false; globalSubscriptionState.subscriberCount = 0; - console.log('[AudioEvents] Sent unsubscribe message to backend'); + // Sent unsubscribe message to backend } } - console.log('[AudioEvents] Component unsubscribed from audio events'); + // Component unsubscribed from audio events }, [readyState, isLocallySubscribed, sendMessage]); // Handle incoming messages @@ -218,7 +218,7 @@ export function useAudioEvents(onAudioDeviceChanged?: (data: AudioDeviceChangedD case 'audio-mute-changed': { const muteData = audioEvent.data as AudioMuteData; setAudioMuted(muteData.muted); - console.log('[AudioEvents] Audio mute changed:', muteData.muted); + // Audio mute changed break; } @@ -231,7 +231,7 @@ export function useAudioEvents(onAudioDeviceChanged?: (data: AudioDeviceChangedD case 'microphone-state-changed': { const micStateData = audioEvent.data as MicrophoneStateData; setMicrophoneState(micStateData); - console.log('[AudioEvents] Microphone state changed:', micStateData); + // Microphone state changed break; } @@ -255,7 +255,7 @@ export function useAudioEvents(onAudioDeviceChanged?: (data: AudioDeviceChangedD case 'audio-device-changed': { const deviceChangedData = audioEvent.data as AudioDeviceChangedData; - console.log('[AudioEvents] Audio device changed:', deviceChangedData); + // Audio device changed if (onAudioDeviceChanged) { onAudioDeviceChanged(deviceChangedData); } diff --git a/ui/src/hooks/useAudioLevel.ts b/ui/src/hooks/useAudioLevel.ts index 091f963..769c167 100644 --- a/ui/src/hooks/useAudioLevel.ts +++ b/ui/src/hooks/useAudioLevel.ts @@ -104,8 +104,8 @@ export const useAudioLevel = ( // Use setInterval instead of requestAnimationFrame for more predictable timing intervalRef.current = window.setInterval(updateLevel, updateInterval); - } catch (error) { - console.error('Failed to create audio level analyzer:', error); + } catch { + // Audio level analyzer creation failed - silently handle setIsAnalyzing(false); setAudioLevel(0); } diff --git a/ui/src/hooks/useMicrophone.ts b/ui/src/hooks/useMicrophone.ts index 5cd5cb1..87bc078 100644 --- a/ui/src/hooks/useMicrophone.ts +++ b/ui/src/hooks/useMicrophone.ts @@ -57,19 +57,14 @@ export function useMicrophone() { // Cleanup function to stop microphone stream const stopMicrophoneStream = useCallback(async () => { - console.log("stopMicrophoneStream called - cleaning up stream"); - console.trace("stopMicrophoneStream call stack"); + // Cleaning up microphone stream if (microphoneStreamRef.current) { - console.log("Stopping microphone stream:", microphoneStreamRef.current.id); microphoneStreamRef.current.getTracks().forEach(track => { track.stop(); }); microphoneStreamRef.current = null; setMicrophoneStream(null); - console.log("Microphone stream cleared from ref and store"); - } else { - console.log("No microphone stream to stop"); } if (microphoneSender && peerConnection) { @@ -217,17 +212,7 @@ export function useMicrophone() { audio: audioConstraints }); - console.log("Microphone stream created successfully:", { - streamId: stream.id, - audioTracks: stream.getAudioTracks().length, - videoTracks: stream.getVideoTracks().length, - audioTrackDetails: stream.getAudioTracks().map(track => ({ - id: track.id, - label: track.label, - enabled: track.enabled, - readyState: track.readyState - })) - }); + // Microphone stream created successfully // Store the stream in both ref and store microphoneStreamRef.current = stream; @@ -471,7 +456,7 @@ export function useMicrophone() { setIsStarting(false); return { success: true }; } catch (error) { - console.error("Failed to start microphone:", error); + // Failed to start microphone let micError: MicrophoneError; if (error instanceof Error) { diff --git a/ui/src/hooks/useUsbDeviceConfig.ts b/ui/src/hooks/useUsbDeviceConfig.ts index 5dba723..9ee427a 100644 --- a/ui/src/hooks/useUsbDeviceConfig.ts +++ b/ui/src/hooks/useUsbDeviceConfig.ts @@ -38,7 +38,7 @@ export function useUsbDeviceConfig() { // Listen for audio device changes to update USB config in real-time const handleAudioDeviceChanged = useCallback(() => { - console.log('[useUsbDeviceConfig] Audio device changed, refetching USB config'); + // Audio device changed, refetching USB config fetchUsbDeviceConfig(); }, [fetchUsbDeviceConfig]);