125 lines
3.4 KiB
QML
125 lines
3.4 KiB
QML
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Services.Pipewire
|
|
import "." as M
|
|
import "../applets" as C
|
|
|
|
M.BarSection {
|
|
id: root
|
|
spacing: M.Theme.moduleSpacing
|
|
tooltip: ""
|
|
|
|
PwObjectTracker {
|
|
objects: [Pipewire.defaultAudioSink, ...root._streamList]
|
|
}
|
|
|
|
readonly property var sink: Pipewire.defaultAudioSink
|
|
readonly property real volume: sink?.audio?.volume ?? 0
|
|
readonly property bool muted: sink?.audio?.muted ?? false
|
|
readonly property string _volumeIcon: muted ? "\uF026" : (volume > 0.5 ? "\uF028" : (volume > 0 ? "\uF027" : "\uF026"))
|
|
readonly property color _volumeColor: muted ? M.Theme.base04 : root.accentColor
|
|
|
|
readonly property var _sinkList: {
|
|
const sinks = [];
|
|
if (Pipewire.nodes) {
|
|
for (const node of Pipewire.nodes.values)
|
|
if (!node.isStream && node.isSink)
|
|
sinks.push(node);
|
|
}
|
|
return sinks;
|
|
}
|
|
|
|
readonly property var _streamList: {
|
|
const streams = [];
|
|
if (Pipewire.nodes) {
|
|
for (const node of Pipewire.nodes.values)
|
|
if (node.isStream && node.audio)
|
|
streams.push(node);
|
|
}
|
|
return streams;
|
|
}
|
|
|
|
property bool _osdActive: false
|
|
property bool _volumeInit: false
|
|
property bool _mutedInit: false
|
|
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
|
|
readonly property bool _showPanel: _anyHover || _osdActive
|
|
|
|
onVolumeChanged: {
|
|
if (!_volumeInit) {
|
|
_volumeInit = true;
|
|
return;
|
|
}
|
|
_flashPanel();
|
|
}
|
|
onMutedChanged: {
|
|
if (!_mutedInit) {
|
|
_mutedInit = true;
|
|
return;
|
|
}
|
|
_flashPanel();
|
|
}
|
|
|
|
function _flashPanel() {
|
|
_osdActive = true;
|
|
_osdTimer.restart();
|
|
}
|
|
|
|
Timer {
|
|
id: _osdTimer
|
|
interval: 1500
|
|
onTriggered: root._osdActive = false
|
|
}
|
|
|
|
M.BarIcon {
|
|
icon: root._volumeIcon
|
|
minIcon: "\uF028"
|
|
color: root._volumeColor
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: if (root.sink?.audio)
|
|
root.sink.audio.muted = !root.sink.audio.muted
|
|
}
|
|
}
|
|
M.BarLabel {
|
|
label: Math.round(root.volume * 100) + "%"
|
|
minText: "100%"
|
|
color: root._volumeColor
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: if (root.sink?.audio)
|
|
root.sink.audio.muted = !root.sink.audio.muted
|
|
}
|
|
}
|
|
|
|
WheelHandler {
|
|
onWheel: event => {
|
|
if (!root.sink?.audio)
|
|
return;
|
|
root.sink.audio.volume = Math.max(0, root.sink.audio.volume + (event.angleDelta.y > 0 ? 0.05 : -0.05));
|
|
}
|
|
}
|
|
|
|
M.HoverPanel {
|
|
id: hoverPanel
|
|
showPanel: root._showPanel
|
|
screen: QsWindow.window?.screen ?? null
|
|
anchorItem: root
|
|
accentColor: root.accentColor
|
|
panelNamespace: "nova-volume"
|
|
panelTitle: "Sound"
|
|
contentWidth: 220
|
|
|
|
C.VolumeContent {
|
|
width: hoverPanel.contentWidth
|
|
sink: root.sink
|
|
sinkList: root._sinkList
|
|
streamList: root._streamList
|
|
accentColor: root.accentColor
|
|
}
|
|
}
|
|
}
|