diff options
Diffstat (limited to 'desktop/island')
| -rw-r--r-- | desktop/island/SoundPanel.qml | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/desktop/island/SoundPanel.qml b/desktop/island/SoundPanel.qml new file mode 100644 index 0000000..115fd75 --- /dev/null +++ b/desktop/island/SoundPanel.qml @@ -0,0 +1,113 @@ +// Copyright (C) 2026 Danilo M. <danix@danix.xyz> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +import Quickshell +import Quickshell.Widgets +import QtQuick +import ".." +import "Logic.js" as Logic + +// Output and input level with mute, and the way into the drawer's sound +// page. Device pickers and per-app volume stay on that page. +Column { + id: panel + + // The sound module's Service: sink, source, tracked by PwObjectTracker. + required property QtObject sound + signal openDrawer() + + spacing: 12 + + Repeater { + model: [{ label: "Output", input: false }, { label: "Input", input: true }] + + delegate: Row { + id: row + required property var modelData + readonly property var audio: + (modelData.input ? panel.sound.source : panel.sound.sink)?.audio ?? null + + width: panel.width + spacing: 10 + + IconImage { + id: muteIcon + anchors.verticalCenter: parent.verticalCenter + implicitSize: 18 + source: Quickshell.iconPath(row.modelData.input + ? (row.audio?.muted ? "microphone-sensitivity-muted" : "audio-input-microphone") + : Logic.volumeIcon(row.audio?.volume ?? 0, row.audio?.muted ?? false), true) + + MouseArea { + anchors.fill: parent + enabled: row.audio !== null + cursorShape: Qt.PointingHandCursor + onClicked: row.audio.muted = !row.audio.muted + } + } + + Rectangle { + id: track + anchors.verticalCenter: parent.verticalCenter + width: row.width - muteIcon.width - pct.width - row.spacing * 2 + height: 8 + radius: 4 + color: Theme.surface + + Rectangle { + height: parent.height + radius: parent.radius + width: parent.width * Math.min(1, row.audio?.volume ?? 0) + color: row.audio?.muted ? Theme.red : Theme.accent + opacity: row.audio?.muted ? 0.5 : 1 + } + + MouseArea { + anchors.fill: parent + enabled: row.audio !== null + preventStealing: true + cursorShape: Qt.PointingHandCursor + onPressed: mouse => set(mouse.x) + onPositionChanged: mouse => { if (pressed) set(mouse.x); } + function set(x) { + row.audio.volume = Math.max(0, Math.min(1, x / width)); + } + } + } + + Text { + id: pct + anchors.verticalCenter: parent.verticalCenter + width: 44 + horizontalAlignment: Text.AlignRight + text: !row.audio ? "—" : row.audio.muted ? "muted" + : Math.round(row.audio.volume * 100) + "%" + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } + color: row.audio?.muted ? Theme.red : Theme.subtext + } + } + } + + Text { + anchors.right: parent.right + text: "Sound settings ›" + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } + color: drawerLink.containsMouse ? Theme.accent : Theme.subtext + + MouseArea { + id: drawerLink + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: panel.openDrawer() + } + } +} |
