Add application volume mixer
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import Quickshell.Services.Pipewire
|
||||
import QtQuick
|
||||
|
||||
import qs.config
|
||||
import qs.services
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
property var applications: AudioDevices.applications
|
||||
property bool pipewireReady: Pipewire.ready
|
||||
|
||||
readonly property int rowCount: applicationRepeater.count
|
||||
readonly property string statusText: {
|
||||
if (!root.pipewireReady)
|
||||
return "PipeWire is unavailable";
|
||||
if (root.applications.length === 0)
|
||||
return "Applications playing sound will appear here";
|
||||
return "";
|
||||
}
|
||||
|
||||
width: parent ? parent.width : 620
|
||||
spacing: 8
|
||||
|
||||
Repeater {
|
||||
id: applicationRepeater
|
||||
model: root.applications
|
||||
|
||||
ApplicationVolumeRow {
|
||||
required property var modelData
|
||||
|
||||
width: root.width
|
||||
application: modelData
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
visible: root.statusText !== ""
|
||||
text: root.statusText
|
||||
color: Theme.fgDim
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSize
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
topPadding: 18
|
||||
bottomPadding: 18
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import Quickshell.Services.Pipewire
|
||||
import QtQuick
|
||||
|
||||
import qs.config
|
||||
import qs.modules.quicksettings
|
||||
import qs.services
|
||||
import qs.widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
required property var application
|
||||
|
||||
readonly property real volume: AudioDevices.applicationVolume(root.application)
|
||||
readonly property bool muted: AudioDevices.applicationMuted(root.application)
|
||||
|
||||
width: parent ? parent.width : 620
|
||||
implicitHeight: 78
|
||||
radius: Theme.cardRadius
|
||||
color: Theme.alpha(Theme.fg, 0.025)
|
||||
border.width: 1
|
||||
border.color: Theme.alpha(Theme.fg, 0.07)
|
||||
|
||||
PwObjectTracker {
|
||||
objects: root.application?.nodes ?? []
|
||||
}
|
||||
|
||||
ThemedIcon {
|
||||
id: applicationIcon
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 11
|
||||
size: 20
|
||||
icon: root.application?.icon ?? "audio-x-generic-symbolic"
|
||||
iconFallback: "audio-x-generic-symbolic"
|
||||
tint: Theme.fg
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.left: applicationIcon.right
|
||||
anchors.leftMargin: 10
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
anchors.verticalCenter: applicationIcon.verticalCenter
|
||||
spacing: 1
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
text: root.application?.label ?? "Unknown application"
|
||||
color: Theme.fg
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSize
|
||||
font.weight: Font.Medium
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
visible: (root.application?.nodes?.length ?? 0) > 1
|
||||
text: `${root.application?.nodes?.length ?? 0} audio streams`
|
||||
color: Theme.fgDim
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: muteButton
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 6
|
||||
size: 30
|
||||
iconSize: 17
|
||||
icon: root.muted || root.volume <= 0.001
|
||||
? "audio-volume-muted-symbolic"
|
||||
: "audio-volume-high-symbolic"
|
||||
iconFallback: "audio-volume-high-symbolic"
|
||||
onClicked: AudioDevices.setApplicationMuted(root.application, !root.muted)
|
||||
}
|
||||
|
||||
ValueSlider {
|
||||
anchors.left: muteButton.right
|
||||
anchors.leftMargin: 7
|
||||
anchors.right: volumeText.left
|
||||
anchors.rightMargin: 10
|
||||
anchors.verticalCenter: muteButton.verticalCenter
|
||||
value: root.muted ? 0 : root.volume
|
||||
onMoved: value => AudioDevices.setApplicationVolume(root.application, value)
|
||||
}
|
||||
|
||||
Text {
|
||||
id: volumeText
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
anchors.verticalCenter: muteButton.verticalCenter
|
||||
width: 38
|
||||
text: Math.round(root.volume * 100) + "%"
|
||||
color: Theme.fgDim
|
||||
font.family: Theme.fontMono
|
||||
font.features: Theme.tabularFigures
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
horizontalAlignment: Text.AlignRight
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ SettingRow {
|
||||
|
||||
readonly property int leftIndex: root.channelIndex(PwAudioChannel.FrontLeft)
|
||||
readonly property int rightIndex: root.channelIndex(PwAudioChannel.FrontRight)
|
||||
readonly property bool available: root.node?.audio
|
||||
readonly property bool available: !!root.node?.audio
|
||||
&& root.leftIndex >= 0 && root.rightIndex >= 0
|
||||
&& root.node.audio.volumes.length > Math.max(root.leftIndex, root.rightIndex)
|
||||
|
||||
|
||||
@@ -31,6 +31,15 @@ SettingsPage {
|
||||
}
|
||||
}
|
||||
|
||||
SettingsCard {
|
||||
title: "Applications"
|
||||
subtitle: "Control each application currently playing through PipeWire."
|
||||
|
||||
ApplicationMixer {
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
SettingsCard {
|
||||
title: "Sound feedback"
|
||||
subtitle: "Use the same event preferences as GTK and GNOME applications."
|
||||
@@ -67,8 +76,8 @@ SettingsPage {
|
||||
title: "Advanced sound"
|
||||
|
||||
ActionRow {
|
||||
label: "Application volumes and profiles"
|
||||
detail: "Open Fedora's complete sound panel"
|
||||
label: "Device profiles"
|
||||
detail: "Open Fedora's complete device profile panel"
|
||||
divider: false
|
||||
action: "Open panel"
|
||||
onTriggered: SystemSettings.openGnomePanel("sound")
|
||||
|
||||
@@ -46,6 +46,8 @@ PasswordField 1.0 PasswordField.qml
|
||||
AudioBalance 1.0 AudioBalance.qml
|
||||
SoundDeviceList 1.0 SoundDeviceList.qml
|
||||
SoundDeviceRow 1.0 SoundDeviceRow.qml
|
||||
ApplicationMixer 1.0 ApplicationMixer.qml
|
||||
ApplicationVolumeRow 1.0 ApplicationVolumeRow.qml
|
||||
TimeOfDayRow 1.0 TimeOfDayRow.qml
|
||||
LocationPicker 1.0 LocationPicker.qml
|
||||
FontPicker 1.0 FontPicker.qml
|
||||
|
||||
Reference in New Issue
Block a user