import { useDevices } from '@/components/devices-provider/hooks/use-devices'; import { Button } from '@/components/ui/button'; import { Group } from '@/components/ui/group'; import { LoadingCard } from '@/components/ui/loading-card'; import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Slider } from '@/components/ui/slider'; import { Switch } from '@/components/ui/switch'; import { closeServerScreens } from '@/features/server-screens/actions'; import { useCurrentVoiceChannelId } from '@/features/server/channels/hooks'; import { useVoice } from '@/features/server/voice/hooks'; import { useForm } from '@/hooks/use-form'; import { Resolution } from '@/types'; import { Download, Trash2, CheckCircle, XCircle, Loader2 } from 'lucide-react'; import { memo, useCallback, useEffect, useState } from 'react'; import { toast } from 'sonner'; import { useAvailableDevices } from './hooks/use-available-devices'; import ResolutionFpsControl from './resolution-fps-control'; const DEFAULT_NAME = 'default'; type TMicProcessingSnapshot = { active: boolean; chain: string; note: string; updatedAt?: number; }; const MIC_STATUS_STORAGE_KEY = 'pulse.micProcessingStatus'; const loadStoredMicStatus = (): TMicProcessingSnapshot | null => { try { const raw = localStorage.getItem(MIC_STATUS_STORAGE_KEY); if (!raw) return null; const parsed = JSON.parse(raw) as TMicProcessingSnapshot; if ( typeof parsed?.active !== 'boolean' || typeof parsed?.chain !== 'string' || typeof parsed?.note !== 'string' ) { return null; } return parsed; } catch { return null; } }; const getConfiguredMicChain = (values: { noiseSuppressionDeepFilterNet?: boolean; noiseSuppressionRnnoise?: boolean; keyboardSuppression?: boolean; noiseSuppressionEnhanced?: boolean; echoCancellation?: boolean; noiseSuppression?: boolean; autoGainControl?: boolean; }) => { const chain: string[] = []; if (values.noiseSuppressionDeepFilterNet) chain.push('DeepFilterNet'); if (values.noiseSuppressionRnnoise) chain.push('RNNoise'); if (values.keyboardSuppression) chain.push('Keyboard Gate'); if (values.noiseSuppressionEnhanced) chain.push('Enhanced (browser)'); if ( !chain.length && (values.echoCancellation || values.noiseSuppression || values.autoGainControl) ) { chain.push('Browser DSP'); } return chain.length ? chain.join(' + ') : 'none'; }; const Devices = memo(() => { const currentVoiceChannelId = useCurrentVoiceChannelId(); const { inputDevices, videoDevices, loading: availableDevicesLoading } = useAvailableDevices(); const { micProcessingStatus } = useVoice(); const { devices, saveDevices, loading: devicesLoading } = useDevices(); const { values, onChange } = useForm(devices); const [storedMicStatus, setStoredMicStatus] = useState(null); useEffect(() => { setStoredMicStatus(loadStoredMicStatus()); const onStatus = (event: Event) => { const custom = event as CustomEvent; if (!custom.detail) return; setStoredMicStatus(custom.detail); }; window.addEventListener('pulse:mic-processing-status', onStatus as EventListener); return () => { window.removeEventListener( 'pulse:mic-processing-status', onStatus as EventListener ); }; }, []); const configuredChain = getConfiguredMicChain(values); const runtimeUnavailable = !micProcessingStatus.active && micProcessingStatus.chain === 'none' && micProcessingStatus.note === 'Runtime status unavailable on this screen'; const effectiveStatus = runtimeUnavailable && storedMicStatus ? storedMicStatus : micProcessingStatus; const handleEnhancedToggle = useCallback( (checked: boolean) => { onChange('noiseSuppressionEnhanced', checked); if (checked) { onChange('noiseSuppressionRnnoise', false); onChange('noiseSuppressionDeepFilterNet', false); } }, [onChange] ); const handleRnnoiseToggle = useCallback( (checked: boolean) => { onChange('noiseSuppressionRnnoise', checked); if (checked) { onChange('noiseSuppressionEnhanced', false); onChange('noiseSuppressionDeepFilterNet', false); onChange('echoCancellation', false); onChange('autoGainControl', false); onChange('noiseSuppression', false); } }, [onChange] ); const handleDeepFilterToggle = useCallback( (checked: boolean) => { onChange('noiseSuppressionDeepFilterNet', checked); if (checked) { onChange('noiseSuppressionEnhanced', false); onChange('noiseSuppressionRnnoise', false); onChange('echoCancellation', false); onChange('autoGainControl', false); onChange('noiseSuppression', false); } }, [onChange] ); const handleEchoCancellationToggle = useCallback( (checked: boolean) => { onChange('echoCancellation', checked); if (checked) { onChange('noiseSuppressionRnnoise', false); onChange('noiseSuppressionDeepFilterNet', false); } }, [onChange] ); const handleNoiseSuppressionToggle = useCallback( (checked: boolean) => { onChange('noiseSuppression', checked); if (checked) { onChange('noiseSuppressionRnnoise', false); onChange('noiseSuppressionDeepFilterNet', false); } }, [onChange] ); const handleAutoGainControlToggle = useCallback( (checked: boolean) => { onChange('autoGainControl', checked); if (checked) { onChange('noiseSuppressionRnnoise', false); onChange('noiseSuppressionDeepFilterNet', false); } }, [onChange] ); const hasWasmSuppression = !!values.noiseSuppressionRnnoise || !!values.noiseSuppressionDeepFilterNet; const saveDeviceSettings = useCallback(() => { saveDevices(values); toast.success('Device settings saved'); }, [saveDevices, values]); if (availableDevicesLoading || devicesLoading) { return ; } return (
{hasWasmSuppression ? (
Browser echo/noise/AGC are disabled while RNNoise or DeepFilterNet is active.
) : null} onChange('keyboardSuppression', checked) } /> onChange('voiceSensitivity', sensitivity) } rightSlot={ {Math.round(values.voiceSensitivity ?? 70)} } />
Configured: {configuredChain}
Runtime chain: {effectiveStatus.chain}
Active: {effectiveStatus.active ? 'yes' : 'no'}
Note: {runtimeUnavailable && !storedMicStatus ? 'Open this panel while connected to voice to read live processing status.' : effectiveStatus.note}
onChange('webcamFramerate', value)} onResolutionChange={(value) => onChange('webcamResolution', value as Resolution) } /> onChange('screenFramerate', value)} onResolutionChange={(value) => onChange('screenResolution', value as Resolution) } />
{/* macOS Audio Driver — only shown in Electron on macOS */}
); }); /** macOS system audio capture driver management section */ const MacOSAudioDriverSection = memo(() => { const isMacElectron = window.pulseDesktop?.platform === 'darwin'; const [driverStatus, setDriverStatus] = useState<{ supported: boolean; fileInstalled: boolean; active: boolean; } | null>(null); const [loading, setLoading] = useState(false); const refreshStatus = useCallback(async () => { if (!window.pulseDesktop?.audioDriver) return; try { const status = await window.pulseDesktop.audioDriver.getStatus(); setDriverStatus(status); } catch { setDriverStatus(null); } }, []); useEffect(() => { if (isMacElectron) refreshStatus(); }, [isMacElectron, refreshStatus]); if (!isMacElectron || !driverStatus?.supported) return null; const handleInstall = async () => { setLoading(true); try { const result = await window.pulseDesktop!.audioDriver.install(); if (result.success) { toast.success('Audio driver installed — "Pulse Audio" device is now available'); } else if (result.error) { toast.error(result.error); } } catch { toast.error('Failed to install audio driver'); } finally { setLoading(false); refreshStatus(); } }; const handleUninstall = async () => { setLoading(true); try { const result = await window.pulseDesktop!.audioDriver.uninstall(); if (result.success) { toast.success('Audio driver uninstalled'); } else if (result.error) { toast.error(result.error); } } catch { toast.error('Failed to uninstall audio driver'); } finally { setLoading(false); refreshStatus(); } }; return (

Share system audio during screen sharing. Requires a virtual audio driver installed to /Library/Audio/Plug-Ins/HAL/.

{driverStatus.active ? ( <> Driver installed and active ) : driverStatus.fileInstalled ? ( <> Driver installed but not active (restart coreaudiod) ) : ( <> Driver not installed )}
{!driverStatus.active && ( )} {(driverStatus.fileInstalled || driverStatus.active) && ( )}
); }); export { Devices };