import QtQuick import qs.config import qs.services SettingsPage { title: "Sound" lede: "Live PipeWire output, input, and device selection." SettingsCard { title: "Output" subtitle: AudioDevices.current(true)?.description ?? "No output device" SoundDeviceList { width: parent.width output: true } AudioBalance { width: parent.width node: AudioDevices.current(true) } } SettingsCard { title: "Input" subtitle: AudioDevices.current(false)?.description ?? "No input device" SoundDeviceList { width: parent.width output: false } } // Beside Input on purpose: dictation listens through whichever device that // card selects, and putting the two together is what makes that obvious. SettingsCard { title: "Dictation" subtitle: Dictation.ready ? "Hold Super+D, speak, and release. The words are typed where the cursor is." : "Speech to text, on the GPU. Two pieces have to be in place first — neither ships with Panama, because both are large and want the network." // Not a toggle: the keybind exists either way, and a switch would imply // dictation can be turned off rather than simply not set up. TextRow { label: "Speech server" detail: Dictation.imageBuilt ? (Dictation.serverReady ? "Built and running" : "Built. Starts on the first dictation and stays loaded.") : "Not built — run: panama app whisper-vulkan" value: Dictation.imageBuilt ? "Ready" : "Missing" } ActionRow { label: "Speech model" detail: Dictation.downloading ? (Dictation.downloadTotalBytes > 0 ? Math.round(Dictation.downloadFraction * 100) + "% of " + Math.round(Dictation.downloadTotalBytes / 1048576) + " MB" : "Downloading…") : (Dictation.modelInstalled ? Math.round(Dictation.modelBytes / 1048576) + " MB, in place" : "About 490 MB, downloaded once and kept") action: Dictation.downloading ? "Downloading…" : "Download" enabled: !Dictation.downloading && !Dictation.modelInstalled visible: !Dictation.modelInstalled || Dictation.downloading onTriggered: Dictation.download() } TextRow { visible: Dictation.modelInstalled && !Dictation.downloading label: "Speech model" detail: "Downloaded once and kept across rebuilds of the server." value: Math.round(Dictation.modelBytes / 1048576) + " MB" } TextRow { visible: !Dictation.typingAvailable label: "Typing" detail: "wtype is missing, so dictated text would go to the clipboard instead of being typed." value: "Missing" } TextRow { visible: Dictation.lastError !== "" label: "Problem" detail: Dictation.lastError value: "" divider: false } } SettingsCard { title: "Applications" subtitle: "Control each application currently playing through PipeWire." ApplicationMixer { width: parent.width } } SettingsCard { title: "Sound feedback" subtitle: "Use the same event preferences as GTK and GNOME applications." SettingRow { label: "Event sounds" detail: "Play alerts and interface event sounds" controlWidth: 42 SettingsToggle { anchors.fill: parent checked: SoundFeedback.eventSounds enabled: !SoundFeedback.busy onToggled: checked => SoundFeedback.setEventSounds(checked) } } SettingRow { label: "Input feedback" detail: "Play sounds for supported typing and input events" controlWidth: 42 divider: false SettingsToggle { anchors.fill: parent checked: SoundFeedback.inputFeedback enabled: !SoundFeedback.busy onToggled: checked => SoundFeedback.setInputFeedback(checked) } } } SettingsCard { title: "Advanced sound" ActionRow { label: "Device profiles" detail: "Open Fedora's complete device profile panel" divider: false action: "Open panel" onTriggered: SystemSettings.openGnomePanel("sound") } } }