Mute both channels from the audio hero, one from each slider
The hero switch is the panel's on/off, so it now carries output and input together rather than output alone. It reads as on while anything is still audible, which keeps muting a single channel from flipping the master switch. Right-clicking a volume bar mutes just that channel -- output, input, or one app's stream -- matching what the `m` key already does for the focused row. Only channels that exist get a vote: a machine with no default source would otherwise report its input unmuted forever, leaving the switch able to mute but never to unmute. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4a8091cd41
commit
cf8102af92
@@ -165,7 +165,13 @@ Panel {
|
|||||||
// "header" is a virtual section for the hero output mute toggle; it sits
|
// "header" is a virtual section for the hero output mute toggle; it sits
|
||||||
// above the output section so the speaker can be muted from the keyboard.
|
// above the output section so the speaker can be muted from the keyboard.
|
||||||
readonly property bool headerHasCursor: cursorActive && focusSection === "header"
|
readonly property bool headerHasCursor: cursorActive && focusSection === "header"
|
||||||
readonly property string toggleHint: root.outputMuted ? "Unmute output" : "Mute output"
|
// Only channels that actually exist get a vote. A box with no default source
|
||||||
|
// would otherwise report "input unmuted" forever, leaving the hero switch
|
||||||
|
// able to mute but never to unmute.
|
||||||
|
readonly property bool hasOutput: !!(volumeSink && volumeSink.audio)
|
||||||
|
readonly property bool hasInput: !!(source && source.audio)
|
||||||
|
readonly property bool anyAudible: (hasOutput && !outputMuted) || (hasInput && !inputMuted)
|
||||||
|
readonly property string toggleHint: anyAudible ? "Mute" : "Unmute"
|
||||||
|
|
||||||
readonly property color hoverFill: bar
|
readonly property color hoverFill: bar
|
||||||
? Style.hoverFillFor(bar.foreground, Color.accent)
|
? Style.hoverFillFor(bar.foreground, Color.accent)
|
||||||
@@ -279,7 +285,7 @@ Panel {
|
|||||||
|
|
||||||
// Enter/Space: activate whatever the cursor is on.
|
// Enter/Space: activate whatever the cursor is on.
|
||||||
function activateCursor() {
|
function activateCursor() {
|
||||||
if (focusSection === "header") { toggleOutputMute(); return }
|
if (focusSection === "header") { toggleAllMuted(); return }
|
||||||
if (focusSection === "output") {
|
if (focusSection === "output") {
|
||||||
if (selectedIndex === -1) { toggleOutputMute(); return }
|
if (selectedIndex === -1) { toggleOutputMute(); return }
|
||||||
var sink = displayAudioSinks[selectedIndex]
|
var sink = displayAudioSinks[selectedIndex]
|
||||||
@@ -432,6 +438,15 @@ Panel {
|
|||||||
if (source && source.audio) source.audio.muted = !source.audio.muted
|
if (source && source.audio) source.audio.muted = !source.audio.muted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The hero switch is the whole panel's on/off, so it carries both channels
|
||||||
|
// at once. It reads as on while anything is still audible, which keeps
|
||||||
|
// muting a single channel from the row below flipping the master switch.
|
||||||
|
function toggleAllMuted() {
|
||||||
|
var mute = anyAudible
|
||||||
|
if (hasOutput) volumeSink.audio.muted = mute
|
||||||
|
if (hasInput) source.audio.muted = mute
|
||||||
|
}
|
||||||
|
|
||||||
function setDefaultSink(node) {
|
function setDefaultSink(node) {
|
||||||
if (!node) return
|
if (!node) return
|
||||||
Pipewire.preferredDefaultAudioSink = node
|
Pipewire.preferredDefaultAudioSink = node
|
||||||
@@ -689,17 +704,17 @@ Panel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compact on/off switch on the trailing edge of the hero, and the
|
// Compact on/off switch on the trailing edge of the hero, and the
|
||||||
// header's only cursor target. Checked means audible, so muting
|
// header's only cursor target. Checked means something is still
|
||||||
// reads as switching the output off.
|
// audible, so muting everything reads as switching audio off.
|
||||||
ToggleSwitch {
|
ToggleSwitch {
|
||||||
id: powerSwitch
|
id: powerSwitch
|
||||||
checked: !root.outputMuted
|
checked: root.anyAudible
|
||||||
hasCursor: root.headerHasCursor
|
hasCursor: root.headerHasCursor
|
||||||
foreground: root.bar.foreground
|
foreground: root.bar.foreground
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
onHovered: function(on) { if (on) root.setHeaderCursor() }
|
onHovered: function(on) { if (on) root.setHeaderCursor() }
|
||||||
onToggled: root.toggleOutputMute()
|
onToggled: root.toggleAllMuted()
|
||||||
|
|
||||||
PanelToolTip {
|
PanelToolTip {
|
||||||
visible: powerSwitch.containsMouse
|
visible: powerSwitch.containsMouse
|
||||||
@@ -803,6 +818,7 @@ Panel {
|
|||||||
enabled: !!root.sink
|
enabled: !!root.sink
|
||||||
|
|
||||||
onMoved: function(v) { root.setOutputVolume(v) }
|
onMoved: function(v) { root.setOutputVolume(v) }
|
||||||
|
onRightClicked: root.toggleOutputMute()
|
||||||
}
|
}
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
@@ -894,6 +910,7 @@ Panel {
|
|||||||
enabled: !!root.source
|
enabled: !!root.source
|
||||||
|
|
||||||
onMoved: function(v) { root.setInputVolume(v) }
|
onMoved: function(v) { root.setInputVolume(v) }
|
||||||
|
onRightClicked: root.toggleInputMute()
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -1181,6 +1198,10 @@ Panel {
|
|||||||
onMoved: function(v) {
|
onMoved: function(v) {
|
||||||
if (streamRow.node && streamRow.node.audio) streamRow.node.audio.volume = v
|
if (streamRow.node && streamRow.node.audio) streamRow.node.audio.volume = v
|
||||||
}
|
}
|
||||||
|
onRightClicked: {
|
||||||
|
if (streamRow.node && streamRow.node.audio)
|
||||||
|
streamRow.node.audio.muted = !streamRow.node.audio.muted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user