106 lines
2.9 KiB
QML
106 lines
2.9 KiB
QML
import QtQuick
|
|
import QtQuick.Effects
|
|
import Quickshell.Services.Pipewire
|
|
import "." as M
|
|
|
|
Row {
|
|
id: root
|
|
spacing: M.Theme.moduleSpacing
|
|
|
|
// Only detect active client streams, not hardware sources/devices
|
|
readonly property bool _videoCapture: {
|
|
if (!Pipewire.nodes)
|
|
return false;
|
|
for (const node of Pipewire.nodes.values) {
|
|
if (!node.isStream)
|
|
continue;
|
|
const mc = node.properties?.["media.class"] ?? "";
|
|
if (mc === "Stream/Input/Video" || mc === "Stream/Output/Video")
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
readonly property bool _audioIn: {
|
|
if (!Pipewire.nodes)
|
|
return false;
|
|
for (const node of Pipewire.nodes.values) {
|
|
if (!node.isStream)
|
|
continue;
|
|
const mc = node.properties?.["media.class"] ?? "";
|
|
if (mc === "Stream/Input/Audio")
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
visible: root._videoCapture || root._audioIn
|
|
|
|
// Screenshare indicator
|
|
Text {
|
|
visible: root._videoCapture
|
|
text: "\uF03D"
|
|
color: M.Theme.base08
|
|
font.pixelSize: M.Theme.fontSize + 2
|
|
font.family: M.Theme.iconFontFamily
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
layer.enabled: true
|
|
layer.effect: MultiEffect {
|
|
shadowEnabled: true
|
|
shadowColor: M.Theme.base08
|
|
shadowBlur: 0.8
|
|
shadowVerticalOffset: 0
|
|
shadowHorizontalOffset: 0
|
|
}
|
|
|
|
SequentialAnimation on opacity {
|
|
running: root._videoCapture
|
|
loops: Animation.Infinite
|
|
NumberAnimation {
|
|
to: 0.4
|
|
duration: 600
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
NumberAnimation {
|
|
to: 1
|
|
duration: 600
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
}
|
|
}
|
|
|
|
// Microphone indicator
|
|
Text {
|
|
visible: root._audioIn
|
|
text: "\uF130"
|
|
color: M.Theme.base0B
|
|
font.pixelSize: M.Theme.fontSize + 2
|
|
font.family: M.Theme.iconFontFamily
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
layer.enabled: true
|
|
layer.effect: MultiEffect {
|
|
shadowEnabled: true
|
|
shadowColor: M.Theme.base0B
|
|
shadowBlur: 0.8
|
|
shadowVerticalOffset: 0
|
|
shadowHorizontalOffset: 0
|
|
}
|
|
|
|
SequentialAnimation on opacity {
|
|
running: root._audioIn
|
|
loops: Animation.Infinite
|
|
NumberAnimation {
|
|
to: 0.4
|
|
duration: 600
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
NumberAnimation {
|
|
to: 1
|
|
duration: 600
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
}
|
|
}
|
|
}
|