AudioService: this might be it

This commit is contained in:
Ly-sec
2025-11-26 21:10:26 +01:00
parent e2854f2079
commit 8419549183
4 changed files with 151 additions and 144 deletions
+19
View File
@@ -216,6 +216,25 @@ Variants {
if (AudioService.hasInput)
showOSD(OSD.Type.InputVolume);
}
// Refresh OSD when device changes to ensure correct volume is displayed
function onSinkChanged() {
// If volume OSD is currently showing, refresh it to show new device's volume
if (root.currentOSDType === OSD.Type.Volume) {
Qt.callLater(() => {
showOSD(OSD.Type.Volume);
});
}
}
function onSourceChanged() {
// If input volume OSD is currently showing, refresh it to show new device's volume
if (root.currentOSDType === OSD.Type.InputVolume) {
Qt.callLater(() => {
showOSD(OSD.Type.InputVolume);
});
}
}
}
// Brightness monitoring
+68 -6
View File
@@ -13,43 +13,105 @@ SmartPanel {
property real localOutputVolume: AudioService.volume || 0
property bool localOutputVolumeChanging: false
property int lastSinkId: -1
property real localInputVolume: AudioService.inputVolume || 0
property bool localInputVolumeChanging: false
property int lastSourceId: -1
preferredWidth: Math.round(340 * Style.uiScaleRatio)
preferredHeight: Math.round(420 * Style.uiScaleRatio)
// Reset local volume when device changes - use current device's volume
Connections {
target: AudioService
function onSinkChanged() {
if (AudioService.sink) {
const newSinkId = AudioService.sink.id;
if (newSinkId !== lastSinkId) {
lastSinkId = newSinkId;
// Immediately set local volume to current device's volume
localOutputVolume = AudioService.volume;
}
} else {
lastSinkId = -1;
localOutputVolume = 0;
}
}
}
Connections {
target: AudioService
function onSourceChanged() {
if (AudioService.source) {
const newSourceId = AudioService.source.id;
if (newSourceId !== lastSourceId) {
lastSourceId = newSourceId;
// Immediately set local volume to current device's volume
localInputVolume = AudioService.inputVolume;
}
} else {
lastSourceId = -1;
localInputVolume = 0;
}
}
}
// Connections to update local volumes when AudioService changes
Connections {
target: AudioService
function onVolumeChanged() {
if (!localOutputVolumeChanging && AudioService.sink && AudioService.sink.id === lastSinkId) {
localOutputVolume = AudioService.volume;
}
}
}
Connections {
target: AudioService.sink?.audio ? AudioService.sink?.audio : null
function onVolumeChanged() {
if (!localOutputVolumeChanging) {
if (!localOutputVolumeChanging && AudioService.sink && AudioService.sink.id === lastSinkId) {
localOutputVolume = AudioService.volume;
}
}
}
Connections {
target: AudioService
function onInputVolumeChanged() {
if (!localInputVolumeChanging && AudioService.source && AudioService.source.id === lastSourceId) {
localInputVolume = AudioService.inputVolume;
}
}
}
Connections {
target: AudioService.source?.audio ? AudioService.source?.audio : null
function onVolumeChanged() {
if (!localInputVolumeChanging) {
if (!localInputVolumeChanging && AudioService.source && AudioService.source.id === lastSourceId) {
localInputVolume = AudioService.inputVolume;
}
}
}
// Timer to debounce volume changes
// Only sync if the device hasn't changed (check by comparing IDs)
Timer {
interval: 100
running: true
repeat: true
onTriggered: {
if (Math.abs(localOutputVolume - AudioService.volume) >= 0.01) {
AudioService.setVolume(localOutputVolume);
// Only sync if sink hasn't changed
if (AudioService.sink && AudioService.sink.id === lastSinkId) {
if (Math.abs(localOutputVolume - AudioService.volume) >= 0.01) {
AudioService.setVolume(localOutputVolume);
}
}
if (Math.abs(localInputVolume - AudioService.inputVolume) >= 0.01) {
AudioService.setInputVolume(localInputVolume);
// Only sync if source hasn't changed
if (AudioService.source && AudioService.source.id === lastSourceId) {
if (Math.abs(localInputVolume - AudioService.inputVolume) >= 0.01) {
AudioService.setInputVolume(localInputVolume);
}
}
}
}
@@ -11,28 +11,80 @@ NBox {
property real localOutputVolume: 0
property bool localOutputVolumeChanging: false
property int lastSinkId: -1
property real localInputVolume: 0
property bool localInputVolumeChanging: false
property int lastSourceId: -1
Component.onCompleted: {
var vol = AudioService.volume;
localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
var inputVol = AudioService.inputVolume;
localInputVolume = (inputVol !== undefined && !isNaN(inputVol)) ? inputVol : 0;
if (AudioService.sink) {
lastSinkId = AudioService.sink.id;
}
if (AudioService.source) {
lastSourceId = AudioService.source.id;
}
}
// Reset local volume when device changes - use current device's volume
Connections {
target: AudioService
function onSinkChanged() {
if (AudioService.sink) {
const newSinkId = AudioService.sink.id;
if (newSinkId !== lastSinkId) {
lastSinkId = newSinkId;
// Immediately set local volume to current device's volume
var vol = AudioService.volume;
localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
} else {
lastSinkId = -1;
localOutputVolume = 0;
}
}
}
Connections {
target: AudioService
function onSourceChanged() {
if (AudioService.source) {
const newSourceId = AudioService.source.id;
if (newSourceId !== lastSourceId) {
lastSourceId = newSourceId;
// Immediately set local volume to current device's volume
var vol = AudioService.inputVolume;
localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
} else {
lastSourceId = -1;
localInputVolume = 0;
}
}
}
// Timer to debounce volume changes
// Only sync if the device hasn't changed (check by comparing IDs)
Timer {
interval: 100
running: true
repeat: true
onTriggered: {
if (Math.abs(localOutputVolume - AudioService.volume) >= 0.01) {
AudioService.setVolume(localOutputVolume);
// Only sync if sink hasn't changed
if (AudioService.sink && AudioService.sink.id === lastSinkId) {
if (Math.abs(localOutputVolume - AudioService.volume) >= 0.01) {
AudioService.setVolume(localOutputVolume);
}
}
if (Math.abs(localInputVolume - AudioService.inputVolume) >= 0.01) {
AudioService.setInputVolume(localInputVolume);
// Only sync if source hasn't changed
if (AudioService.source && AudioService.source.id === lastSourceId) {
if (Math.abs(localInputVolume - AudioService.inputVolume) >= 0.01) {
AudioService.setInputVolume(localInputVolume);
}
}
}
}
@@ -41,7 +93,7 @@ NBox {
Connections {
target: AudioService
function onVolumeChanged() {
if (!localOutputVolumeChanging) {
if (!localOutputVolumeChanging && AudioService.sink && AudioService.sink.id === lastSinkId) {
var vol = AudioService.volume;
localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
@@ -51,7 +103,7 @@ NBox {
Connections {
target: AudioService.sink?.audio ? AudioService.sink?.audio : null
function onVolumeChanged() {
if (!localOutputVolumeChanging) {
if (!localOutputVolumeChanging && AudioService.sink && AudioService.sink.id === lastSinkId) {
var vol = AudioService.volume;
localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
@@ -61,7 +113,7 @@ NBox {
Connections {
target: AudioService
function onInputVolumeChanged() {
if (!localInputVolumeChanging) {
if (!localInputVolumeChanging && AudioService.source && AudioService.source.id === lastSourceId) {
var vol = AudioService.inputVolume;
localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
@@ -71,7 +123,7 @@ NBox {
Connections {
target: AudioService.source?.audio ? AudioService.source?.audio : null
function onVolumeChanged() {
if (!localInputVolumeChanging) {
if (!localInputVolumeChanging && AudioService.source && AudioService.source.id === lastSourceId) {
var vol = AudioService.inputVolume;
localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0;
}
+4 -130
View File
@@ -18,8 +18,7 @@ Singleton {
readonly property list<PwNode> sources: deviceNodes.sources
// Output Volume - read directly from device (like friend's version)
// Make it a regular property that updates when sink or volume changes
property real volume: {
readonly property real volume: {
if (!sink?.audio) return 0;
const vol = sink.audio.volume;
if (vol === undefined || isNaN(vol)) return 0;
@@ -29,8 +28,7 @@ Singleton {
readonly property bool muted: sink?.audio?.muted ?? true
// Input Volume - read directly from device (like friend's version)
// Make it a regular property that updates when source or volume changes
property real inputVolume: {
readonly property real inputVolume: {
if (!source?.audio) return 0;
const vol = source.audio.volume;
if (vol === undefined || isNaN(vol)) return 0;
@@ -71,28 +69,6 @@ Singleton {
// Internal state for feedback loop prevention
property bool isSettingOutputVolume: false
property bool isSettingInputVolume: false
// Track device changes to prevent old volume from being applied
property int currentSinkId: -1
property int currentSourceId: -1
property bool blockOutputVolumeChanges: false
property bool blockInputVolumeChanges: false
Timer {
id: unblockOutputTimer
interval: 1500
onTriggered: {
blockOutputVolumeChanges = false;
}
}
Timer {
id: unblockInputTimer
interval: 1500
onTriggered: {
blockInputVolumeChanges = false;
}
}
// Bind default sink and source to ensure their properties are available
PwObjectTracker {
@@ -110,36 +86,8 @@ Singleton {
objects: [...root.sinks, ...root.sources]
}
// Track sink changes and force volume property to update
onSinkChanged: {
if (sink) {
const newSinkId = sink.id;
if (newSinkId !== currentSinkId) {
currentSinkId = newSinkId;
// Block volume changes for 1.5 seconds after device change
blockOutputVolumeChanges = true;
unblockOutputTimer.restart();
// Force volume property to update by reading new device's volume
Qt.callLater(() => {
if (root.sink?.audio) {
const vol = root.sink.audio.volume;
if (vol !== undefined && !isNaN(vol)) {
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const clampedVol = Math.max(0, Math.min(maxVolume, vol));
root.volume = clampedVol; // This will trigger volumeChanged signal
}
}
});
}
} else {
currentSinkId = -1;
blockOutputVolumeChanges = true;
unblockOutputTimer.restart();
root.volume = 0; // This will trigger volumeChanged signal
}
}
// Watch output device changes for clamping and updating volume property
// Watch output device changes for clamping
Connections {
target: sink?.audio ?? null
@@ -159,12 +107,6 @@ Singleton {
}
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const clampedVol = Math.max(0, Math.min(maxVolume, vol));
// Update volume property to trigger change signal
if (Math.abs(root.volume - clampedVol) > 0.001) {
root.volume = clampedVol;
}
// If volume exceeds max, clamp it (but only if we didn't just set it)
if (vol > maxVolume) {
@@ -179,36 +121,8 @@ Singleton {
}
}
// Track source changes and force volume property to update
onSourceChanged: {
if (source) {
const newSourceId = source.id;
if (newSourceId !== currentSourceId) {
currentSourceId = newSourceId;
// Block volume changes for 1.5 seconds after device change
blockInputVolumeChanges = true;
unblockInputTimer.restart();
// Force volume property to update by reading new device's volume
Qt.callLater(() => {
if (root.source?.audio) {
const vol = root.source.audio.volume;
if (vol !== undefined && !isNaN(vol)) {
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const clampedVol = Math.max(0, Math.min(maxVolume, vol));
root.inputVolume = clampedVol; // This will trigger inputVolumeChanged signal
}
}
});
}
} else {
currentSourceId = -1;
blockInputVolumeChanges = true;
unblockInputTimer.restart();
root.inputVolume = 0; // This will trigger inputVolumeChanged signal
}
}
// Watch input device changes for clamping and updating volume property
// Watch input device changes for clamping
Connections {
target: source?.audio ?? null
@@ -228,12 +142,6 @@ Singleton {
}
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const clampedVol = Math.max(0, Math.min(maxVolume, vol));
// Update inputVolume property to trigger change signal
if (Math.abs(root.inputVolume - clampedVol) > 0.001) {
root.inputVolume = clampedVol;
}
// If volume exceeds max, clamp it (but only if we didn't just set it)
if (vol > maxVolume) {
@@ -277,23 +185,6 @@ Singleton {
return;
}
// Block volume changes for 1.5 seconds after device change to prevent old values
if (blockOutputVolumeChanges) {
const currentVol = sink.audio.volume;
if (currentVol !== undefined && !isNaN(currentVol)) {
const diff = Math.abs(newVolume - currentVol);
// Only block if difference is significant (>5%) - allow small adjustments
if (diff > 0.05) {
Logger.w("AudioService", "Ignoring setVolume - device changed recently, volume difference:", diff, "requested:", newVolume, "current:", currentVol);
return;
}
} else {
// If we can't read current volume yet, block all changes
Logger.w("AudioService", "Ignoring setVolume - device changed recently and volume not ready yet");
return;
}
}
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const clampedVolume = Math.max(0, Math.min(maxVolume, newVolume));
@@ -358,23 +249,6 @@ Singleton {
return;
}
// Block volume changes for 1.5 seconds after device change to prevent old values
if (blockInputVolumeChanges) {
const currentVol = source.audio.volume;
if (currentVol !== undefined && !isNaN(currentVol)) {
const diff = Math.abs(newVolume - currentVol);
// Only block if difference is significant (>5%) - allow small adjustments
if (diff > 0.05) {
Logger.w("AudioService", "Ignoring setInputVolume - device changed recently, volume difference:", diff, "requested:", newVolume, "current:", currentVol);
return;
}
} else {
// If we can't read current volume yet, block all changes
Logger.w("AudioService", "Ignoring setInputVolume - device changed recently and volume not ready yet");
return;
}
}
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const clampedVolume = Math.max(0, Math.min(maxVolume, newVolume));