// Read-only contract harness for the Sound page. It instantiates every device // row against the real PipeWire graph but exposes no mutating IPC methods. import Quickshell import Quickshell.Io import Quickshell.Services.Pipewire import QtQuick import qs.services import qs.modules.settings ShellRoot { id: root QtObject { id: fixtureAudio property real volume: 0.42 property bool muted: false } QtObject { id: fixtureNode property QtObject audio: fixtureAudio } readonly property var fixtureApplication: ({ key: "fixture.player", label: "Fixture Player", icon: "audio-x-generic-symbolic", nodes: [fixtureNode] }) SoundPage { width: 760 height: 900 } ApplicationMixer { id: populatedMixer width: 620 visible: false applications: [root.fixtureApplication] pipewireReady: true } ApplicationMixer { id: emptyMixer width: 620 visible: false applications: [] pipewireReady: true } ApplicationMixer { id: unavailableMixer width: 620 visible: false applications: [] pipewireReady: false } PwObjectTracker { objects: AudioDevices.outputs.concat(AudioDevices.inputs) } IpcHandler { target: "sound-page-test" function status(): string { return JSON.stringify({ ready: Pipewire.ready, outputs: AudioDevices.outputs.length, inputs: AudioDevices.inputs.length, applications: AudioDevices.applications.length, defaultOutput: AudioDevices.label(AudioDevices.current(true)), defaultInput: AudioDevices.label(AudioDevices.current(false)), populatedRows: populatedMixer.rowCount, populatedStatus: populatedMixer.statusText, emptyRows: emptyMixer.rowCount, emptyStatus: emptyMixer.statusText, unavailableRows: unavailableMixer.rowCount, unavailableStatus: unavailableMixer.statusText }); } } }