Give Sound the whole story, and keep the buttons inside the card

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-24 11:39:16 -04:00
parent 9bc68ba358
commit b58371bb35
38 changed files with 3884 additions and 213 deletions
@@ -27,6 +27,16 @@ Singleton {
readonly property var applications: AudioStreams.group(
root.playbackStreams, PwNodeType.AudioOutStream)
// The capture side of the same story: which applications currently hold the
// microphone open. Same grouping rules as playback, so an application that
// records on three streams reads as one entry with one mute.
readonly property var captureStreams: Pipewire.nodes.values.filter(node =>
node.ready && node.audio
&& (node.type & PwNodeType.AudioInStream) === PwNodeType.AudioInStream)
readonly property var captureApplications: AudioStreams.group(
root.captureStreams, PwNodeType.AudioInStream)
function nodes(output: bool): var {
return output ? root.outputs : root.inputs;
}
@@ -58,8 +68,11 @@ Singleton {
return AudioStreams.muted(application);
}
function setApplicationVolume(application: var, value: real): bool {
return AudioStreams.setVolume(application, value);
// `max` is the clamp ceiling; omitting it means 1, and anything that is not
// a positive number is treated as omitted. Callers that honor the
// over-amplification setting pass 1.5.
function setApplicationVolume(application: var, value: real, max: real): bool {
return AudioStreams.setVolume(application, value, max);
}
function setApplicationMuted(application: var, muted: bool): bool {