feat(audio): implement volume feedback sound

This commit is contained in:
kyle
2026-01-19 00:56:03 +11:00
parent c8f1cbb79e
commit 01c892df2e
7 changed files with 53 additions and 2 deletions
Binary file not shown.
+3 -1
View File
@@ -679,7 +679,9 @@
"volumes-step-size-description": "Adjust the step size for volume changes (scroll wheel, keyboard shortcuts).", "volumes-step-size-description": "Adjust the step size for volume changes (scroll wheel, keyboard shortcuts).",
"volumes-step-size-label": "Volume step size", "volumes-step-size-label": "Volume step size",
"volumes-volume-overdrive-description": "Allow raising volume above 100%. May not be supported by all hardware.", "volumes-volume-overdrive-description": "Allow raising volume above 100%. May not be supported by all hardware.",
"volumes-volume-overdrive-label": "Allow volume overdrive" "volumes-volume-overdrive-label": "Allow volume overdrive",
"volumes-volume-feedback-label": "Play volume feedback sound",
"volumes-volume-feedback-description": "Play a feedback sound when adjusting volume"
}, },
"bar": { "bar": {
"appearance-background-opacity-description": "Set the background opacity specifically for the bar.", "appearance-background-opacity-description": "Set the background opacity specifically for the bar.",
+3 -1
View File
@@ -679,7 +679,9 @@
"volumes-step-size-description": "调整音量变化的步长(滚轮、键盘快捷键)。", "volumes-step-size-description": "调整音量变化的步长(滚轮、键盘快捷键)。",
"volumes-step-size-label": "音量步长", "volumes-step-size-label": "音量步长",
"volumes-volume-overdrive-description": "允许将音量提高到100%以上。可能不被所有硬件支持。", "volumes-volume-overdrive-description": "允许将音量提高到100%以上。可能不被所有硬件支持。",
"volumes-volume-overdrive-label": "允许音量过载" "volumes-volume-overdrive-label": "允许音量过载",
"volumes-volume-feedback-label": "播放音量反馈",
"volumes-volume-feedback-description": "调整音量时播放反馈音效"
}, },
"bar": { "bar": {
"appearance-background-opacity-description": "为状态栏设置背景不透明度。", "appearance-background-opacity-description": "为状态栏设置背景不透明度。",
+1
View File
@@ -33,6 +33,7 @@ Noctalia Shell is made possible by the incredible work of many open-source proje
## Audio Assets ## Audio Assets
- **[Universfield on Pixabay](https://pixabay.com/users/universfield-28281460/)** - Notification sound effect - **[Universfield on Pixabay](https://pixabay.com/users/universfield-28281460/)** - Notification sound effect
- **[DrNI on Freesound](https://freesound.org/people/DrNI/sounds/34562/)** - Timer's alarm sound effect - **[DrNI on Freesound](https://freesound.org/people/DrNI/sounds/34562/)** - Timer's alarm sound effect
- **[Lucas McCallister on Freesound](http://www.freesound.org/samplesViewSingle.php?id=67091)** - Volume change feedback sound effect
## Special Thanks ## Special Thanks
+1
View File
@@ -586,6 +586,7 @@ Singleton {
property string visualizerType: "linear" property string visualizerType: "linear"
property list<string> mprisBlacklist: [] property list<string> mprisBlacklist: []
property string preferredPlayer: "" property string preferredPlayer: ""
property bool volumeFeedback: false
} }
// brightness // brightness
@@ -61,6 +61,21 @@ ColumnLayout {
} }
} }
// Volume Feedback sound Toggle
ColumnLayout {
spacing: Style.marginS
Layout.fillWidth: true
NToggle {
label: I18n.tr("panels.audio.volumes-volume-feedback-label")
description: I18n.tr("panels.audio.volumes-volume-feedback-description")
checked: Settings.data.audio.volumeFeedback
defaultValue: Settings.getDefaultValue("audio.volumeFeedback")
onToggled: checked => Settings.data.audio.volumeFeedback = checked
}
}
// Mute Toggle // Mute Toggle
ColumnLayout { ColumnLayout {
spacing: Style.marginS spacing: Style.marginS
+30
View File
@@ -4,10 +4,15 @@ import QtQuick
import Quickshell import Quickshell
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import qs.Commons import qs.Commons
import qs.Services.System
Singleton { Singleton {
id: root id: root
// Rate limiting for volume feedback (minimum 100ms between sounds)
property var lastVolumeFeedbackTime: 0
readonly property int minVolumeFeedbackInterval: 100
// Devices // Devices
readonly property PwNode sink: Pipewire.ready ? Pipewire.defaultAudioSink : null readonly property PwNode sink: Pipewire.ready ? Pipewire.defaultAudioSink : null
readonly property PwNode source: validatedSource readonly property PwNode source: validatedSource
@@ -230,6 +235,8 @@ Singleton {
sink.audio.muted = false; sink.audio.muted = false;
sink.audio.volume = clampedVolume; sink.audio.volume = clampedVolume;
playVolumeFeedback(clampedVolume);
// Clear flag after a short delay to allow external changes to be detected // Clear flag after a short delay to allow external changes to be detected
Qt.callLater(() => { Qt.callLater(() => {
isSettingOutputVolume = false; isSettingOutputVolume = false;
@@ -305,6 +312,29 @@ Singleton {
}); });
} }
function playVolumeFeedback(currentVolume: real) {
if (!SoundService.multimediaAvailable) {
return;
}
if (!Settings.data.audio.volumeFeedback) {
return;
}
const now = Date.now();
if (now - lastVolumeFeedbackTime < minVolumeFeedbackInterval) {
return;
}
lastVolumeFeedbackTime = now;
const feedbackVolume = currentVolume;
SoundService.playSound("volume-change.wav", {
volume: feedbackVolume,
fallback: false,
repeat: false
});
}
function setInputMuted(muted: bool) { function setInputMuted(muted: bool) {
if (!Pipewire.ready || !source?.audio) { if (!Pipewire.ready || !source?.audio) {
Logger.w("AudioService", "No source available or Pipewire not ready"); Logger.w("AudioService", "No source available or Pipewire not ready");