Files
Panama/config/dot/quickshell/modules/settings/SoundPage.qml
T
Gabriel Brown 14fc4fc8a3 Make the dictation setup button call a command that exists
The Download button on Sound → Dictation ran `panama-dictate download`. There
is no such command: the helper answered {"ok": false, "error":
"unknown-command"} and the button did nothing, every time, for anyone who
tried it. The real command is `setup`, which pulls the speech server image
and downloads the ~490 MB model together -- one trip, by design. And the card
told you the server needed `panama app whisper-vulkan`, an app that exists in
no package or setup/apps entry; the server is a prebuilt image the helper
pulls with podman.

So the card described three things and got all three wrong. It now shows the
real state of both pieces and offers one action -- "Set up dictation" -- wired
to the command that actually fetches them, with progress that names which half
is running (server image, then model). Verified end to end: `panama-dictate
setup` emits the pulling/downloading JSON the service parses.

Claude-Session: https://claude.ai/code/session_01Epx9ZC1gwm81K3jm9x9CKh
2026-08-23 13:59:42 -04:00

153 lines
5.2 KiB
QML

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. Hold Super+D once it is set up. The one-time setup below fetches a speech server and a ~490 MB model — neither ships with Panama, because both are large and want the network."
// Status of the two pieces, read from the machine rather than guessed.
TextRow {
label: "Speech server"
detail: Dictation.serverReady
? "Running"
: (Dictation.imageBuilt ? "Ready — starts on the first dictation" : "Not set up yet")
value: Dictation.imageBuilt ? "Ready" : "Missing"
}
TextRow {
label: "Speech model"
detail: Dictation.modelInstalled
? "Kept across rebuilds of the server"
: "About 490 MB, downloaded once"
value: Dictation.modelInstalled ? Math.round(Dictation.modelBytes / 1048576) + " MB" : "Missing"
}
// ONE action that actually works: panama-dictate setup pulls the
// server image and downloads the model together. This card used to
// offer a Download button wired to a command the helper does not have,
// and told you to build a "panama app whisper-vulkan" that does not
// exist -- so nothing here did anything. It does now.
ActionRow {
visible: !Dictation.ready || Dictation.downloading
label: "Set up dictation"
detail: {
if (!Dictation.downloading)
return "Fetches the speech server and the model. Runs once, keeps both.";
if (Dictation.phase === "pulling")
return "Fetching the speech server…";
if (Dictation.downloadTotalBytes > 0)
return "Downloading model — " + Math.round(Dictation.downloadFraction * 100)
+ "% of " + Math.round(Dictation.downloadTotalBytes / 1048576) + " MB";
return "Setting up…";
}
action: Dictation.downloading ? "Working…" : "Set up"
enabled: !Dictation.downloading
onTriggered: Dictation.setup()
divider: !Dictation.typingAvailable || Dictation.lastError !== ""
}
TextRow {
visible: !Dictation.typingAvailable
label: "Typing"
detail: "wtype is missing, so dictated text would go to the clipboard instead of being typed."
value: "Missing"
divider: Dictation.lastError !== ""
}
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")
}
}
}