mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2026-06-08 20:55:16 +00:00
AudioService: this might be it
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user