shift-shell/components/mobileshell/qml/dataproviders/AudioInfo.qml
2023-10-21 11:32:41 +02:00

131 lines
4.3 KiB
QML

// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
pragma Singleton
import QtQuick
import org.kde.plasma.private.volume
QtObject {
id: root
property var config: GlobalConfig {}
property SinkModel paSinkModel: SinkModel {}
// whether the audio icon should be visible in the status bar
readonly property bool isVisible: paSinkModel.preferredSink
// the icon that should be displayed in the status bar
readonly property string icon: paSinkModel.preferredSink && !isDummyOutput(paSinkModel.preferredSink)
? iconName(paSinkModel.preferredSink.volume, paSinkModel.preferredSink.muted)
: iconName(0, true)
// the name of the audio device when it isn't valid
readonly property string dummyOutputName: "auto_null"
// the maximum volume amount (percentage)
readonly property int maxVolumePercent: config.raiseMaximumVolume ? 150 : 100
// the maximum volume amount
readonly property int maxVolumeValue: maxVolumePercent * PulseAudio.NormalVolume / 100
// step that increments when adjusting the volume
readonly property int volumeStep: Math.round(5 * PulseAudio.NormalVolume / 100.0)
// The current audio volume (updated by connecting to sinks)
property int volumeValue
function isDummyOutput(output) {
return output && output.name === dummyOutputName;
}
function boundVolume(volume) {
return Math.max(PulseAudio.MinimalVolume, Math.min(volume, maxVolumeValue));
}
function volumePercent(volume, max){
if (!max) {
max = PulseAudio.NormalVolume;
}
return Math.round(volume / max * maxVolumePercent);
}
function increaseVolume() {
if (!paSinkModel.preferredSink || isDummyOutput(paSinkModel.preferredSink)) {
return;
}
var volume = boundVolume(paSinkModel.preferredSink.volume + volumeStep);
var percent = volumePercent(volume, maxVolumeValue);
paSinkModel.preferredSink.muted = percent == 0;
paSinkModel.preferredSink.volume = volume;
}
function decreaseVolume() {
if (!paSinkModel.preferredSink || isDummyOutput(paSinkModel.preferredSink)) {
return;
}
var volume = boundVolume(paSinkModel.preferredSink.volume - volumeStep);
var percent = volumePercent(volume, maxVolumeValue);
paSinkModel.preferredSink.muted = percent == 0;
paSinkModel.preferredSink.volume = volume;
}
function muteVolume() {
if (!paSinkModel.preferredSink || isDummyOutput(paSinkModel.preferredSink)) {
return;
}
paSinkModel.preferredSink.muted = !paSinkModel.preferredSink.muted;
}
function iconName(volume, muted, prefix) {
if (!prefix) {
prefix = "audio-volume";
}
var icon = null;
var percent = volume / maxVolumeValue;
if (percent <= 0.0 || muted) {
icon = prefix + "-muted";
} else if (percent <= 0.25) {
icon = prefix + "-low";
} else if (percent <= 0.75) {
icon = prefix + "-medium";
} else {
icon = prefix + "-high";
}
return icon;
}
// emitted when the volume changed, but not due to sink switching
signal volumeChanged()
property var updateVolume: Connections {
target: root.paSinkModel ? (root.paSinkModel.preferredSink ? root.paSinkModel.preferredSink : null) : null
enabled: target !== null
function onVolumeChanged() {
root.volumeValue = root.volumePercent(root.paSinkModel.preferredSink.volume, root.maxVolumeValue);
root.volumeChanged();
}
function onMutedChanged() {
root.volumeValue = root.paSinkModel.preferredSink.muted ? 0 : root.volumePercent(root.paSinkModel.preferredSink.volume, root.maxVolumeValue);
root.volumeChanged();
}
}
property var updateVolumeOnSinkChange: Connections {
target: root.paSinkModel ? root.paSinkModel : null
enabled: target !== null
function onPreferredSinkChanged() {
if (root.paSinkModel.preferredSink) {
root.volumeValue = root.volumePercent(root.paSinkModel.preferredSink.volume, root.maxVolumeValue);
}
}
}
}