177 lines
6.2 KiB
QML
177 lines
6.2 KiB
QML
import Quickshell
|
|
import Quickshell.Io
|
|
import Quickshell.Services.Pipewire
|
|
import QtQuick
|
|
|
|
import "services/AudioStreams.js" as AudioStreams
|
|
import qs.services
|
|
|
|
ShellRoot {
|
|
readonly property int audioOutStreamFlag: 4
|
|
|
|
property var fixtureNodes: [
|
|
{
|
|
id: 10,
|
|
ready: true,
|
|
type: audioOutStreamFlag,
|
|
properties: {
|
|
"application.id": "org.chromium.Chromium",
|
|
"application.name": "Chromium",
|
|
"application.icon_name": "chromium"
|
|
},
|
|
description: "Chromium audio",
|
|
audio: { volume: 0.4, muted: false }
|
|
},
|
|
{
|
|
id: 11,
|
|
ready: true,
|
|
type: audioOutStreamFlag,
|
|
properties: {
|
|
"application.id": "org.chromium.Chromium",
|
|
"application.name": "Chromium",
|
|
"application.icon_name": "chromium"
|
|
},
|
|
description: "Chromium audio",
|
|
audio: { volume: 0.8, muted: true }
|
|
},
|
|
{
|
|
id: 20,
|
|
ready: true,
|
|
type: audioOutStreamFlag,
|
|
properties: {
|
|
"application.process.binary": "spotify",
|
|
"application.name": "Spotify"
|
|
},
|
|
description: "Spotify",
|
|
audio: { volume: 0.25, muted: false }
|
|
},
|
|
{
|
|
id: 30,
|
|
ready: true,
|
|
type: 2,
|
|
properties: { "application.name": "Microphone capture" },
|
|
description: "Input stream",
|
|
audio: { volume: 0.5, muted: false }
|
|
},
|
|
{
|
|
id: 40,
|
|
ready: false,
|
|
type: audioOutStreamFlag,
|
|
properties: { "application.name": "Not ready" },
|
|
description: "Unready stream",
|
|
audio: { volume: 0.5, muted: false }
|
|
},
|
|
{
|
|
id: 99,
|
|
ready: true,
|
|
type: audioOutStreamFlag,
|
|
properties: {},
|
|
description: "",
|
|
audio: { volume: 1, muted: false }
|
|
}
|
|
]
|
|
|
|
function groups(): var {
|
|
return AudioStreams.group(fixtureNodes, audioOutStreamFlag);
|
|
}
|
|
|
|
// A throwaway two-stream group for the clamp cases. The shared fixture
|
|
// above is mutated by the volume and mute tests, and a clamp assertion that
|
|
// depended on which of those ran first would be worthless.
|
|
function clampFixture(): var {
|
|
return {
|
|
key: "clamp",
|
|
label: "Clamp",
|
|
icon: "audio-x-generic-symbolic",
|
|
nodes: [
|
|
{ audio: { volume: 0.1, muted: true } },
|
|
{ audio: { volume: 0.1, muted: true } }
|
|
]
|
|
};
|
|
}
|
|
|
|
IpcHandler {
|
|
target: "application-volume-test"
|
|
|
|
function summary(): string {
|
|
const applications = groups();
|
|
const chromium = applications.find(application =>
|
|
application.key === "org.chromium.Chromium");
|
|
return JSON.stringify({
|
|
groups: applications.map(application => ({
|
|
key: application.key,
|
|
label: application.label,
|
|
icon: application.icon,
|
|
count: application.nodes.length
|
|
})),
|
|
chromiumVolume: AudioStreams.volume(chromium),
|
|
chromiumMuted: AudioStreams.muted(chromium)
|
|
});
|
|
}
|
|
|
|
function mutateVolume(): string {
|
|
const chromium = groups().find(application =>
|
|
application.key === "org.chromium.Chromium");
|
|
const changed = AudioStreams.setVolume(chromium, 0.7);
|
|
return JSON.stringify({
|
|
changed,
|
|
volumes: chromium.nodes.map(node => node.audio.volume),
|
|
muted: chromium.nodes.map(node => node.audio.muted)
|
|
});
|
|
}
|
|
|
|
function mutateMute(): string {
|
|
const chromium = groups().find(application =>
|
|
application.key === "org.chromium.Chromium");
|
|
const changed = AudioStreams.setMuted(chromium, true);
|
|
return JSON.stringify({
|
|
changed,
|
|
muted: chromium.nodes.map(node => node.audio.muted)
|
|
});
|
|
}
|
|
|
|
// Over-amplification is a preference, so the ceiling is an argument
|
|
// rather than a constant -- this file stays Settings-free on purpose.
|
|
function clampVolume(): string {
|
|
const overAmp = clampFixture();
|
|
const overAmpChanged = AudioStreams.setVolume(overAmp, 1.4, 1.5);
|
|
const ceiling = clampFixture();
|
|
AudioStreams.setVolume(ceiling, 2.5, 1.5);
|
|
const defaultMax = clampFixture();
|
|
AudioStreams.setVolume(defaultMax, 1.4);
|
|
const floor = clampFixture();
|
|
AudioStreams.setVolume(floor, -0.5, 1.5);
|
|
const nonNumeric = clampFixture();
|
|
const nonNumericChanged = AudioStreams.setVolume(nonNumeric, "loud", 1.5);
|
|
return JSON.stringify({
|
|
overAmpChanged,
|
|
overAmp: overAmp.nodes.map(node => node.audio.volume),
|
|
overAmpMuted: overAmp.nodes.map(node => node.audio.muted),
|
|
ceiling: ceiling.nodes.map(node => node.audio.volume),
|
|
defaultMax: defaultMax.nodes.map(node => node.audio.volume),
|
|
floor: floor.nodes.map(node => node.audio.volume),
|
|
nonNumericChanged,
|
|
nonNumeric: nonNumeric.nodes.map(node => node.audio.volume)
|
|
});
|
|
}
|
|
|
|
function serviceSummary(): string {
|
|
const applications = AudioDevices.applications;
|
|
return JSON.stringify({
|
|
count: applications.length,
|
|
validTypes: applications.every(application =>
|
|
application.nodes.every(node =>
|
|
(node.type & PwNodeType.AudioOutStream)
|
|
=== PwNodeType.AudioOutStream))
|
|
});
|
|
}
|
|
|
|
function invalidMutations(): string {
|
|
return JSON.stringify({
|
|
nullVolume: AudioDevices.setApplicationVolume(null, 0.5),
|
|
emptyMute: AudioDevices.setApplicationMuted({ nodes: [] }, true)
|
|
});
|
|
}
|
|
}
|
|
}
|