Files
omarchy/shell/plugins/bar/widgets/Microphone.qml
T
ZacharyZhang-NY a9b39710a2 Add Simplified Chinese as a system language
The installer asks for the language before the keyboard, and
Setup > Language (omarchy language en|zh) switches it later. Under
zh_CN the menu reads its labels from omarchy-menu.zh-cn.jsonc, the
shell from I18nZh.js through I18n.tr, and notifications are worded
by their sender through omarchy-text, which reads the same table.
User text is never translated.
2026-10-12 02:56:40 -04:00

77 lines
2.7 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Services.Pipewire
import qs.Commons
import qs.Ui
import qs.Commons
BarWidget {
id: root
moduleName: "omarchy.microphone"
readonly property var source: Pipewire.defaultAudioSource
// A virtual source is untyped in Quickshell, so it has no PwNode.audio; its
// volume and mute go through wpctl (UntypedInput).
readonly property bool viaWpctl: UntypedInput.active
readonly property bool muted: viaWpctl ? (!UntypedInput.known || UntypedInput.muted) : (source && source.audio ? source.audio.muted : true)
readonly property real volume: viaWpctl ? UntypedInput.volume : (source && source.audio ? source.audio.volume : 0)
readonly property var nodes: Pipewire.nodes ? Pipewire.nodes.values : []
readonly property var nodeNames: {
var names = []
for (var i = 0; i < nodes.length; i++)
if (nodes[i] && nodes[i].name) names.push(String(nodes[i].name))
return names
}
readonly property var activeStreams: {
var list = []
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i]
if (!node || !node.isStream || node.isSink !== false || node.audio?.muted) continue
// The shell's own level meters, and a platform's audio processing that
// records all the time, are not an app using the microphone.
if (AudioNodes.isShellLevelMeter(node.name) || AudioNodes.platformHides(node.name, nodeNames)) continue
list.push(node)
}
return list
}
readonly property bool inUse: activeStreams.length > 0 && !muted
visible: source !== null
implicitWidth: button.implicitWidth
implicitHeight: button.implicitHeight
function toggleMute() {
if (viaWpctl) {
if (UntypedInput.known) UntypedInput.setMuted(!UntypedInput.muted)
}
else if (source && source.audio) source.audio.muted = !source.audio.muted
}
PwObjectTracker { objects: root.source ? [root.source] : [] }
BarIconButton {
id: button
anchors.fill: parent
bar: root.bar
text: root.muted ? "󰍭" : "󰍬"
active: root.inUse
tooltipText: root.muted ? I18n.tr("Microphone muted") : (root.inUse ? I18n.tr("Microphone in use") : I18n.tr("Microphone live"))
onPressed: function(b) {
if (b === Qt.MiddleButton) root.bar.run("omarchy-shell shell toggle omarchy.audio")
else root.toggleMute()
}
onWheelMoved: function(delta) {
var step = 0.05
if (root.viaWpctl) {
if (UntypedInput.known) UntypedInput.setVolume(root.volume + (delta > 0 ? step : -step))
return
}
if (!root.source || !root.source.audio) return
root.source.audio.volume = Math.max(0, Math.min(1, root.volume + (delta > 0 ? step : -step)))
}
}
}