import qs.modules.common import QtQuick import Quickshell import Quickshell.Services.Pipewire pragma Singleton pragma ComponentBehavior: Bound /** * A nice wrapper for default Pipewire audio sink and source. */ Singleton { id: root property bool ready: Pipewire.defaultAudioSink?.ready ?? false property PwNode sink: Pipewire.defaultAudioSink property PwNode source: Pipewire.defaultAudioSource readonly property real hardMaxValue: 2.00 // People keep joking about setting volume to 5172% so... property string audioTheme: Config.options.sounds.theme signal sinkProtectionTriggered(string reason); PwObjectTracker { objects: [sink, source] } Connections { // Protection against sudden volume changes target: sink?.audio ?? null property bool lastReady: false property real lastVolume: 0 function onVolumeChanged() { if (!Config.options.audio.protection.enable) return; if (!lastReady) { lastVolume = sink.audio.volume; lastReady = true; return; } const newVolume = sink.audio.volume; const maxAllowedIncrease = Config.options.audio.protection.maxAllowedIncrease / 100; const maxAllowed = Config.options.audio.protection.maxAllowed / 100; if (newVolume - lastVolume > maxAllowedIncrease) { sink.audio.volume = lastVolume; root.sinkProtectionTriggered(Translation.tr("Illegal increment")); } else if (newVolume > maxAllowed || newVolume > root.hardMaxValue) { root.sinkProtectionTriggered(Translation.tr("Exceeded max allowed")); sink.audio.volume = Math.min(lastVolume, maxAllowed); } if (sink.ready && (isNaN(sink.audio.volume) || sink.audio.volume === undefined || sink.audio.volume === null)) { sink.audio.volume = 0; } lastVolume = sink.audio.volume; } } function playSystemSound(soundName) { const ogaPath = `/usr/share/sounds/${root.audioTheme}/stereo/${soundName}.oga`; const oggPath = `/usr/share/sounds/${root.audioTheme}/stereo/${soundName}.ogg`; // Try playing .oga first let command = [ "ffplay", "-nodisp", "-autoexit", ogaPath ]; Quickshell.execDetached(command); // Also try playing .ogg (ffplay will just fail silently if file doesn't exist) command = [ "ffplay", "-nodisp", "-autoexit", oggPath ]; Quickshell.execDetached(command); } }