fix(audio): stop volume sliders fighting service state

This commit is contained in:
Lysec
2026-03-31 14:43:03 +02:00
parent d4e7a8e967
commit 43fe1e1947
4 changed files with 44 additions and 35 deletions
+20 -18
View File
@@ -17,6 +17,9 @@ NBox {
property bool localInputVolumeChanging: false
property int lastSourceId: -1
readonly property bool outputVolumeGuard: outputVolumeSlider.sliderActive || localOutputVolumeChanging
readonly property bool inputVolumeGuard: inputVolumeSlider.sliderActive || localInputVolumeChanging
Component.onCompleted: {
var vol = AudioService.volume;
localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
@@ -89,21 +92,10 @@ NBox {
}
}
// Connections to update local volumes when AudioService changes
Connections {
target: AudioService
function onVolumeChanged() {
if (!localOutputVolumeChanging && AudioService.sink && AudioService.sink.id === lastSinkId) {
var vol = AudioService.volume;
localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
}
}
Connections {
target: AudioService.sink?.audio ? AudioService.sink?.audio : null
function onVolumeChanged() {
if (!localOutputVolumeChanging && AudioService.sink && AudioService.sink.id === lastSinkId) {
if (!outputVolumeGuard && !AudioService.isSettingOutputVolume && AudioService.sink && AudioService.sink.id === lastSinkId) {
var vol = AudioService.volume;
localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
@@ -113,7 +105,7 @@ NBox {
Connections {
target: AudioService
function onInputVolumeChanged() {
if (!localInputVolumeChanging && AudioService.source && AudioService.source.id === lastSourceId) {
if (!inputVolumeGuard && !AudioService.isSettingInputVolume && AudioService.source && AudioService.source.id === lastSourceId) {
var vol = AudioService.inputVolume;
localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
@@ -121,9 +113,19 @@ NBox {
}
Connections {
target: AudioService.source?.audio ? AudioService.source?.audio : null
function onVolumeChanged() {
if (!localInputVolumeChanging && AudioService.source && AudioService.source.id === lastSourceId) {
target: outputVolumeSlider
function onSliderActiveChanged() {
if (!outputVolumeSlider.sliderActive && AudioService.sink && AudioService.sink.id === lastSinkId) {
var vol = AudioService.volume;
localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
}
}
Connections {
target: inputVolumeSlider
function onSliderActiveChanged() {
if (!inputVolumeSlider.sliderActive && AudioService.source && AudioService.source.id === lastSourceId) {
var vol = AudioService.inputVolume;
localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
@@ -179,7 +181,7 @@ NBox {
heightRatio: 0.5
onMoved: localOutputVolume = value
onPressedChanged: localOutputVolumeChanging = pressed
tooltipText: `${Math.round(localOutputVolume * 100)}%`
tooltipText: `${Math.round((outputVolumeGuard ? localOutputVolume : AudioService.volume) * 100)}%`
tooltipDirection: "bottom"
// MouseArea to handle wheel events when hovering over the slider
@@ -247,7 +249,7 @@ NBox {
heightRatio: 0.5
onMoved: localInputVolume = value
onPressedChanged: localInputVolumeChanging = pressed
tooltipText: `${Math.round(localInputVolume * 100)}%`
tooltipText: `${Math.round((inputVolumeGuard ? localInputVolume : AudioService.inputVolume) * 100)}%`
tooltipDirection: "bottom"
// MouseArea to handle wheel events when hovering over the slider
+22 -17
View File
@@ -27,6 +27,9 @@ SmartPanel {
property bool localInputVolumeChanging: false
property int lastSourceId: -1
readonly property bool outputVolumeGuard: outputVolumeSlider.sliderActive || localOutputVolumeChanging
readonly property bool inputVolumeGuard: inputVolumeSlider.sliderActive || localInputVolumeChanging
// UI state (lazy-loaded with panelContent)
property int currentTabIndex: 0
@@ -84,17 +87,7 @@ SmartPanel {
Connections {
target: AudioService
function onVolumeChanged() {
if (!panelContent.localOutputVolumeChanging && AudioService.sink && AudioService.sink.id === panelContent.lastSinkId) {
var vol = AudioService.volume;
panelContent.localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
}
}
Connections {
target: AudioService.sink?.audio ? AudioService.sink?.audio : null
function onVolumeChanged() {
if (!panelContent.localOutputVolumeChanging && AudioService.sink && AudioService.sink.id === panelContent.lastSinkId) {
if (!panelContent.outputVolumeGuard && !AudioService.isSettingOutputVolume && AudioService.sink && AudioService.sink.id === panelContent.lastSinkId) {
var vol = AudioService.volume;
panelContent.localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
@@ -104,7 +97,7 @@ SmartPanel {
Connections {
target: AudioService
function onInputVolumeChanged() {
if (!panelContent.localInputVolumeChanging && AudioService.source && AudioService.source.id === panelContent.lastSourceId) {
if (!panelContent.inputVolumeGuard && !AudioService.isSettingInputVolume && AudioService.source && AudioService.source.id === panelContent.lastSourceId) {
var vol = AudioService.inputVolume;
panelContent.localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
@@ -112,9 +105,19 @@ SmartPanel {
}
Connections {
target: AudioService.source?.audio ? AudioService.source?.audio : null
function onVolumeChanged() {
if (!panelContent.localInputVolumeChanging && AudioService.source && AudioService.source.id === panelContent.lastSourceId) {
target: outputVolumeSlider
function onSliderActiveChanged() {
if (!outputVolumeSlider.sliderActive && AudioService.sink && AudioService.sink.id === panelContent.lastSinkId) {
var vol = AudioService.volume;
panelContent.localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
}
}
Connections {
target: inputVolumeSlider
function onSliderActiveChanged() {
if (!inputVolumeSlider.sliderActive && AudioService.source && AudioService.source.id === panelContent.lastSourceId) {
var vol = AudioService.inputVolume;
panelContent.localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
@@ -272,6 +275,7 @@ SmartPanel {
spacing: Style.marginM
NValueSlider {
id: outputVolumeSlider
Layout.fillWidth: true
from: 0
to: Settings.data.audio.volumeOverdrive ? 1.5 : 1.0
@@ -287,7 +291,7 @@ SmartPanel {
}
NText {
text: Math.round((localOutputVolumeChanging ? localOutputVolume : AudioService.volume) * 100) + "%"
text: Math.round((panelContent.outputVolumeGuard ? localOutputVolume : AudioService.volume) * 100) + "%"
pointSize: Style.fontSizeM
family: Settings.data.ui.fontFixed
color: Color.mOnSurface
@@ -347,6 +351,7 @@ SmartPanel {
spacing: Style.marginM
NValueSlider {
id: inputVolumeSlider
Layout.fillWidth: true
from: 0
to: Settings.data.audio.volumeOverdrive ? 1.5 : 1.0
@@ -362,7 +367,7 @@ SmartPanel {
}
NText {
text: Math.round((localInputVolumeChanging ? localInputVolume : AudioService.inputVolume) * 100) + "%"
text: Math.round((panelContent.inputVolumeGuard ? localInputVolume : AudioService.inputVolume) * 100) + "%"
pointSize: Style.fontSizeM
family: Settings.data.ui.fontFixed
color: Color.mOnSurface
+1
View File
@@ -7,6 +7,7 @@ import qs.Services.UI
Slider {
id: root
readonly property bool sliderActive: activeFocus || pressed
property color fillColor: Color.mPrimary
property var cutoutColor: Color.mSurface
property bool snapAlways: true
+1
View File
@@ -30,6 +30,7 @@ RowLayout {
signal moved(real value)
signal pressedChanged(bool pressed, real value)
readonly property bool sliderActive: slider.activeFocus || slider.pressed
readonly property bool isValueChanged: defaultValue !== undefined && (value !== defaultValue)
readonly property string indicatorTooltip: {
if (defaultValue === undefined)