diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts index bfbbb26e..50a6066f 100644 --- a/ui/src/hooks/stores.ts +++ b/ui/src/hooks/stores.ts @@ -351,6 +351,12 @@ export interface SettingsState { setVideoBrightness: (value: number) => void; videoContrast: number; setVideoContrast: (value: number) => void; + + // Audio settings + audioOutputSource: string; + audioMode: string; + audioOutputEnabled: boolean; + audioInputEnabled: boolean; } export const useSettingsStore = create( @@ -396,6 +402,12 @@ export const useSettingsStore = create( setVideoBrightness: (value: number) => set({ videoBrightness: value }), videoContrast: 1.0, setVideoContrast: (value: number) => set({ videoContrast: value }), + + // Audio settings with defaults + audioOutputSource: "usb", + audioMode: "subprocess", + audioOutputEnabled: true, + audioInputEnabled: true, }), { name: "settings", diff --git a/ui/src/routes/devices.$id.settings.audio.tsx b/ui/src/routes/devices.$id.settings.audio.tsx new file mode 100644 index 00000000..13210735 --- /dev/null +++ b/ui/src/routes/devices.$id.settings.audio.tsx @@ -0,0 +1,174 @@ +import { useEffect } from "react"; + +import { SettingsItem } from "@components/SettingsItem"; +import { SettingsPageHeader } from "@components/SettingsPageheader"; +import { useSettingsStore } from "@/hooks/stores"; +import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc"; +import { SelectMenuBasic } from "@components/SelectMenuBasic"; +import Checkbox from "@components/Checkbox"; + +import notifications from "../notifications"; + +export default function SettingsAudioRoute() { + const { send } = useJsonRpc(); + const settings = useSettingsStore(); + + // Fetch current audio settings on mount + useEffect(() => { + send("getAudioOutputSource", {}, (resp: JsonRpcResponse) => { + if ("error" in resp) { + return; + } + const source = resp.result as string; + settings.audioOutputSource = source; + }); + + send("getAudioMode", {}, (resp: JsonRpcResponse) => { + if ("error" in resp) { + return; + } + const mode = resp.result as string; + settings.audioMode = mode; + }); + + send("getAudioOutputEnabled", {}, (resp: JsonRpcResponse) => { + if ("error" in resp) { + return; + } + settings.audioOutputEnabled = resp.result as boolean; + }); + + send("getAudioInputEnabled", {}, (resp: JsonRpcResponse) => { + if ("error" in resp) { + return; + } + settings.audioInputEnabled = resp.result as boolean; + }); + }, [send]); + + const handleAudioOutputSourceChange = (source: string) => { + send("setAudioOutputSource", { params: { source } }, (resp: JsonRpcResponse) => { + if ("error" in resp) { + notifications.error( + `Failed to set audio output source: ${resp.error.data || "Unknown error"}`, + ); + return; + } + settings.audioOutputSource = source; + notifications.success("Audio output source updated successfully"); + }); + }; + + const handleAudioModeChange = (mode: string) => { + send("setAudioMode", { params: { mode } }, (resp: JsonRpcResponse) => { + if ("error" in resp) { + notifications.error( + `Failed to set audio mode: ${resp.error.data || "Unknown error"}`, + ); + return; + } + settings.audioMode = mode; + notifications.success("Audio mode updated successfully. Changes will take effect on next connection."); + }); + }; + + const handleAudioOutputEnabledChange = (enabled: boolean) => { + send("setAudioOutputEnabled", { params: { enabled } }, (resp: JsonRpcResponse) => { + if ("error" in resp) { + notifications.error( + `Failed to ${enabled ? "enable" : "disable"} audio output: ${resp.error.data || "Unknown error"}`, + ); + return; + } + settings.audioOutputEnabled = enabled; + notifications.success(`Audio output ${enabled ? "enabled" : "disabled"} successfully`); + }); + }; + + const handleAudioInputEnabledChange = (enabled: boolean) => { + send("setAudioInputEnabled", { params: { enabled } }, (resp: JsonRpcResponse) => { + if ("error" in resp) { + notifications.error( + `Failed to ${enabled ? "enable" : "disable"} audio input: ${resp.error.data || "Unknown error"}`, + ); + return; + } + settings.audioInputEnabled = enabled; + notifications.success(`Audio input ${enabled ? "enabled" : "disabled"} successfully`); + }); + }; + + return ( +
+ Changing the audio mode will take effect when the next WebRTC connection is established. +
+