bar/popouts: add audio device switcher (#319)
* feat: basic audio switcher * feat: replace VerticalSlider with StyledSlider * fix: styling * fix: formatting * chore: make sound icons consistent, change slider styling * feat: styled slider component variants * chore: cleanup * chore: cleanup * fix: pr fixes * fix: remove redundant code * chore: remove old code * fix: controls styling * fixes * more tweaks * radiobtn: add interaction stuff Anim slider --------- Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
This commit is contained in:
parent
e4d4c457f8
commit
9ada66a78e
10 changed files with 277 additions and 154 deletions
|
|
@ -25,7 +25,7 @@ Slider {
|
||||||
implicitHeight: parent.height - y
|
implicitHeight: parent.height - y
|
||||||
|
|
||||||
color: Colours.alpha(Colours.palette.m3secondary, true)
|
color: Colours.alpha(Colours.palette.m3secondary, true)
|
||||||
radius: Appearance.rounding.full
|
radius: parent.radius
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
58
components/controls/StyledRadioButton.qml
Normal file
58
components/controls/StyledRadioButton.qml
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import qs.components
|
||||||
|
import qs.services
|
||||||
|
import qs.config
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
|
||||||
|
RadioButton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
font.pointSize: Appearance.font.size.smaller
|
||||||
|
|
||||||
|
indicator: Rectangle {
|
||||||
|
id: outerCircle
|
||||||
|
|
||||||
|
implicitWidth: 20
|
||||||
|
implicitHeight: 20
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
color: "transparent"
|
||||||
|
border.color: root.checked ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant
|
||||||
|
border.width: 2
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
anchors.margins: -Appearance.padding.smaller
|
||||||
|
color: root.checked ? Colours.palette.m3onSurface : Colours.palette.m3primary
|
||||||
|
z: -1
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
root.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
implicitWidth: 8
|
||||||
|
implicitHeight: 8
|
||||||
|
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
color: root.checked ? Colours.palette.m3primary : "transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.standard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: StyledText {
|
||||||
|
text: root.text
|
||||||
|
font.pointSize: root.font.pointSize
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: outerCircle.right
|
||||||
|
anchors.leftMargin: Appearance.spacing.smaller
|
||||||
|
}
|
||||||
|
}
|
||||||
59
components/controls/StyledSlider.qml
Normal file
59
components/controls/StyledSlider.qml
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import qs.components
|
||||||
|
import qs.config
|
||||||
|
import qs.services
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Slider {
|
||||||
|
id: slider
|
||||||
|
|
||||||
|
background: Item {
|
||||||
|
StyledRect {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.topMargin: slider.implicitHeight / 3
|
||||||
|
anchors.bottomMargin: slider.implicitHeight / 3
|
||||||
|
|
||||||
|
implicitWidth: slider.handle.x - slider.implicitHeight / 6
|
||||||
|
|
||||||
|
color: Colours.palette.m3primary
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
topRightRadius: slider.implicitHeight / 15
|
||||||
|
bottomRightRadius: slider.implicitHeight / 15
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: slider.implicitHeight / 3
|
||||||
|
anchors.bottomMargin: slider.implicitHeight / 3
|
||||||
|
|
||||||
|
implicitWidth: parent.width - slider.handle.x - slider.handle.implicitWidth - slider.implicitHeight / 6
|
||||||
|
|
||||||
|
color: Colours.palette.m3surfaceContainer
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
topLeftRadius: slider.implicitHeight / 15
|
||||||
|
bottomLeftRadius: slider.implicitHeight / 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle: StyledRect {
|
||||||
|
id: rect
|
||||||
|
|
||||||
|
x: slider.visualPosition * slider.availableWidth
|
||||||
|
|
||||||
|
implicitWidth: slider.implicitHeight / 4.5
|
||||||
|
implicitHeight: slider.implicitHeight
|
||||||
|
|
||||||
|
color: Colours.palette.m3primary
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onPressed: event => event.accepted = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -58,7 +58,7 @@ Item {
|
||||||
|
|
||||||
sourceComponent: MaterialIcon {
|
sourceComponent: MaterialIcon {
|
||||||
animate: true
|
animate: true
|
||||||
text: Audio.muted ? "volume_off" : Audio.volume >= 0.66 ? "volume_up" : Audio.volume >= 0.33 ? "volume_down" : "volume_mute"
|
text: Icons.getVolumeIcon(Audio.volume, Audio.muted)
|
||||||
color: root.colour
|
color: root.colour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,58 +1,139 @@
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import qs.components
|
import qs.components
|
||||||
import qs.components.controls
|
import qs.components.controls
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.config
|
import qs.config
|
||||||
import QtQuick.Layouts
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Services.Pipewire
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls
|
||||||
|
|
||||||
ColumnLayout {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property var wrapper
|
required property var wrapper
|
||||||
|
|
||||||
spacing: Appearance.spacing.normal
|
implicitWidth: layout.implicitWidth + Appearance.padding.normal * 2
|
||||||
|
implicitHeight: layout.implicitHeight + Appearance.padding.normal * 2
|
||||||
|
|
||||||
VerticalSlider {
|
ButtonGroup {
|
||||||
id: volumeSlider
|
id: sinks
|
||||||
|
|
||||||
icon: {
|
|
||||||
if (Audio.muted)
|
|
||||||
return "no_sound";
|
|
||||||
if (value >= 0.5)
|
|
||||||
return "volume_up";
|
|
||||||
if (value > 0)
|
|
||||||
return "volume_down";
|
|
||||||
return "volume_mute";
|
|
||||||
}
|
|
||||||
|
|
||||||
value: Audio.volume
|
|
||||||
onMoved: Audio.setVolume(value)
|
|
||||||
|
|
||||||
implicitWidth: Config.osd.sizes.sliderWidth
|
|
||||||
implicitHeight: Config.osd.sizes.sliderHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledRect {
|
ButtonGroup {
|
||||||
id: pavuButton
|
id: sources
|
||||||
|
}
|
||||||
|
|
||||||
implicitWidth: implicitHeight
|
ColumnLayout {
|
||||||
implicitHeight: icon.implicitHeight + Appearance.padding.small * 2
|
id: layout
|
||||||
|
|
||||||
radius: Appearance.rounding.normal
|
anchors.left: parent.left
|
||||||
color: Colours.palette.m3surfaceContainer
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
StateLayer {
|
StyledText {
|
||||||
function onClicked(): void {
|
Layout.bottomMargin: Appearance.spacing.small / 2
|
||||||
root.wrapper.hasCurrent = false;
|
text: qsTr("Output")
|
||||||
Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.audio]);
|
font.weight: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: Audio.sinks
|
||||||
|
|
||||||
|
StyledRadioButton {
|
||||||
|
id: control
|
||||||
|
|
||||||
|
required property PwNode modelData
|
||||||
|
|
||||||
|
ButtonGroup.group: sinks
|
||||||
|
checked: Audio.sink?.id === modelData.id
|
||||||
|
onClicked: Audio.setAudioSink(modelData)
|
||||||
|
text: modelData.description
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
StyledText {
|
||||||
id: icon
|
Layout.topMargin: Appearance.spacing.small
|
||||||
|
Layout.bottomMargin: Appearance.spacing.small / 2
|
||||||
|
text: qsTr("Input")
|
||||||
|
font.weight: 500
|
||||||
|
}
|
||||||
|
|
||||||
anchors.centerIn: parent
|
Repeater {
|
||||||
text: "settings"
|
model: Audio.sources
|
||||||
|
|
||||||
|
StyledRadioButton {
|
||||||
|
required property PwNode modelData
|
||||||
|
|
||||||
|
ButtonGroup.group: sources
|
||||||
|
checked: Audio.source?.id === modelData.id
|
||||||
|
onClicked: Audio.setAudioSource(modelData)
|
||||||
|
text: modelData.description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.topMargin: Appearance.spacing.small
|
||||||
|
Layout.bottomMargin: Appearance.spacing.small / 2
|
||||||
|
text: qsTr("Volume")
|
||||||
|
font.weight: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledSlider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: Appearance.padding.normal * 3
|
||||||
|
|
||||||
|
value: Audio.volume
|
||||||
|
onMoved: Audio.setVolume(value)
|
||||||
|
|
||||||
|
Behavior on value {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.standard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
Layout.topMargin: Appearance.spacing.normal
|
||||||
|
visible: Config.general.apps.audio.length > 0
|
||||||
|
|
||||||
|
implicitWidth: expandBtn.implicitWidth + Appearance.padding.normal * 2
|
||||||
|
implicitHeight: expandBtn.implicitHeight + Appearance.padding.small
|
||||||
|
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
color: Colours.palette.m3primaryContainer
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
color: Colours.palette.m3onPrimaryContainer
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
root.wrapper.hasCurrent = false;
|
||||||
|
Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.audio]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: expandBtn
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Appearance.spacing.small
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.leftMargin: Appearance.padding.smaller
|
||||||
|
text: qsTr("Open settings")
|
||||||
|
color: Colours.palette.m3onPrimaryContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
text: "chevron_right"
|
||||||
|
color: Colours.palette.m3onPrimaryContainer
|
||||||
|
font.pointSize: Appearance.font.size.large
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
|
||||||
import qs.components
|
import qs.components
|
||||||
import qs.components.effects
|
import qs.components.effects
|
||||||
import qs.components.misc
|
import qs.components.misc
|
||||||
|
import qs.components.controls
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.utils
|
import qs.utils
|
||||||
import qs.config
|
import qs.config
|
||||||
|
|
@ -279,9 +280,10 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Slider {
|
StyledSlider {
|
||||||
id: slider
|
id: slider
|
||||||
|
|
||||||
|
enabled: !!Players.active
|
||||||
implicitWidth: controls.implicitWidth * 1.5
|
implicitWidth: controls.implicitWidth * 1.5
|
||||||
implicitHeight: Appearance.padding.normal * 3
|
implicitHeight: Appearance.padding.normal * 3
|
||||||
|
|
||||||
|
|
@ -291,56 +293,6 @@ Item {
|
||||||
if (active?.canSeek && active?.positionSupported)
|
if (active?.canSeek && active?.positionSupported)
|
||||||
active.position = value * active.length;
|
active.position = value * active.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
background: Item {
|
|
||||||
StyledRect {
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.topMargin: slider.implicitHeight / 3
|
|
||||||
anchors.bottomMargin: slider.implicitHeight / 3
|
|
||||||
|
|
||||||
implicitWidth: slider.handle.x - slider.implicitHeight / 6
|
|
||||||
|
|
||||||
color: Colours.palette.m3primary
|
|
||||||
radius: Appearance.rounding.full
|
|
||||||
topRightRadius: slider.implicitHeight / 15
|
|
||||||
bottomRightRadius: slider.implicitHeight / 15
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledRect {
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: slider.implicitHeight / 3
|
|
||||||
anchors.bottomMargin: slider.implicitHeight / 3
|
|
||||||
|
|
||||||
implicitWidth: parent.width - slider.handle.x - slider.handle.implicitWidth - slider.implicitHeight / 6
|
|
||||||
|
|
||||||
color: Colours.palette.m3surfaceContainer
|
|
||||||
radius: Appearance.rounding.full
|
|
||||||
topLeftRadius: slider.implicitHeight / 15
|
|
||||||
bottomLeftRadius: slider.implicitHeight / 15
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handle: StyledRect {
|
|
||||||
id: rect
|
|
||||||
|
|
||||||
x: slider.visualPosition * slider.availableWidth
|
|
||||||
|
|
||||||
implicitWidth: slider.implicitHeight / 4.5
|
|
||||||
implicitHeight: slider.implicitHeight
|
|
||||||
|
|
||||||
color: Colours.palette.m3primary
|
|
||||||
radius: Appearance.rounding.full
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: event => event.accepted = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import qs.components
|
import qs.components
|
||||||
|
import qs.components.controls
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.config
|
import qs.config
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
|
|
@ -164,7 +165,7 @@ RowLayout {
|
||||||
|
|
||||||
spacing: Appearance.spacing.small
|
spacing: Appearance.spacing.small
|
||||||
|
|
||||||
Slider {
|
StyledSlider {
|
||||||
id: slider
|
id: slider
|
||||||
|
|
||||||
Layout.rightMargin: root.isLarge ? Appearance.spacing.small : 0
|
Layout.rightMargin: root.isLarge ? Appearance.spacing.small : 0
|
||||||
|
|
@ -177,56 +178,6 @@ RowLayout {
|
||||||
if (active?.canSeek && active?.positionSupported)
|
if (active?.canSeek && active?.positionSupported)
|
||||||
active.position = value * active.length;
|
active.position = value * active.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
background: Item {
|
|
||||||
StyledRect {
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.topMargin: slider.implicitHeight / 3
|
|
||||||
anchors.bottomMargin: slider.implicitHeight / 3
|
|
||||||
|
|
||||||
implicitWidth: slider.handle.x - slider.implicitHeight / 6
|
|
||||||
|
|
||||||
color: Colours.palette.m3primary
|
|
||||||
radius: Appearance.rounding.full
|
|
||||||
topRightRadius: slider.implicitHeight / 15
|
|
||||||
bottomRightRadius: slider.implicitHeight / 15
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledRect {
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: slider.implicitHeight / 3
|
|
||||||
anchors.bottomMargin: slider.implicitHeight / 3
|
|
||||||
|
|
||||||
implicitWidth: parent.width - slider.handle.x - slider.handle.implicitWidth - slider.implicitHeight / 6
|
|
||||||
|
|
||||||
color: Colours.palette.m3surfaceContainer
|
|
||||||
radius: Appearance.rounding.full
|
|
||||||
topLeftRadius: slider.implicitHeight / 15
|
|
||||||
bottomLeftRadius: slider.implicitHeight / 15
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handle: StyledRect {
|
|
||||||
id: rect
|
|
||||||
|
|
||||||
x: slider.visualPosition * slider.availableWidth
|
|
||||||
|
|
||||||
implicitWidth: slider.implicitHeight / 4.5
|
|
||||||
implicitHeight: slider.implicitHeight
|
|
||||||
|
|
||||||
color: Colours.palette.m3primary
|
|
||||||
radius: Appearance.rounding.full
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: event => event.accepted = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Control {
|
Control {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import qs.components.controls
|
import qs.components.controls
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.config
|
import qs.config
|
||||||
|
import qs.utils
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
|
@ -26,18 +27,10 @@ Column {
|
||||||
Audio.setVolume(Audio.volume - 0.1);
|
Audio.setVolume(Audio.volume - 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
VerticalSlider {
|
FilledSlider {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
icon: {
|
icon: Icons.getVolumeIcon(value, Audio.muted)
|
||||||
if (Audio.muted)
|
|
||||||
return "no_sound";
|
|
||||||
if (value >= 0.5)
|
|
||||||
return "volume_up";
|
|
||||||
if (value > 0)
|
|
||||||
return "volume_down";
|
|
||||||
return "volume_mute";
|
|
||||||
}
|
|
||||||
value: Audio.volume
|
value: Audio.volume
|
||||||
onMoved: Audio.setVolume(value)
|
onMoved: Audio.setVolume(value)
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +50,7 @@ Column {
|
||||||
monitor.setBrightness(monitor.brightness - 0.1);
|
monitor.setBrightness(monitor.brightness - 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
VerticalSlider {
|
FilledSlider {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
icon: `brightness_${(Math.round(value * 6) + 1)}`
|
icon: `brightness_${(Math.round(value * 6) + 1)}`
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,39 @@ import Quickshell.Services.Pipewire
|
||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
readonly property var nodes: Pipewire.nodes.values.reduce((acc, node) => {
|
||||||
|
if (!node.isStream) {
|
||||||
|
if (node.isSink) acc.sinks.push(node)
|
||||||
|
else if (node.audio) acc.sources.push(node)
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}, { sources: [], sinks: [] })
|
||||||
|
|
||||||
|
readonly property list<PwNode> sinks: nodes.sinks
|
||||||
|
readonly property list<PwNode> sources: nodes.sources
|
||||||
|
|
||||||
readonly property PwNode sink: Pipewire.defaultAudioSink
|
readonly property PwNode sink: Pipewire.defaultAudioSink
|
||||||
readonly property PwNode source: Pipewire.defaultAudioSource
|
readonly property PwNode source: Pipewire.defaultAudioSource
|
||||||
|
|
||||||
readonly property bool muted: sink?.audio?.muted ?? false
|
readonly property bool muted: !!sink?.audio?.muted
|
||||||
readonly property real volume: sink?.audio?.volume ?? 0
|
readonly property real volume: sink?.audio?.volume ?? 0
|
||||||
|
|
||||||
function setVolume(volume: real): void {
|
function setVolume(newVolume: real): void {
|
||||||
if (sink?.ready && sink?.audio) {
|
if (sink?.ready && sink?.audio) {
|
||||||
sink.audio.muted = false;
|
sink.audio.muted = false;
|
||||||
sink.audio.volume = volume;
|
sink.audio.volume = newVolume;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setAudioSink(newSink: PwNode): void {
|
||||||
|
Pipewire.preferredDefaultAudioSink = newSink
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAudioSource(newSource: PwNode): void {
|
||||||
|
Pipewire.preferredDefaultAudioSource = newSource
|
||||||
|
}
|
||||||
|
|
||||||
PwObjectTracker {
|
PwObjectTracker {
|
||||||
objects: [Pipewire.defaultAudioSink, Pipewire.defaultAudioSource]
|
objects: [...root.sinks, ...root.sources]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,16 @@ Singleton {
|
||||||
return "chat";
|
return "chat";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getVolumeIcon(volume: real, isMuted: bool): string {
|
||||||
|
if (isMuted)
|
||||||
|
return "no_sound";
|
||||||
|
if (volume >= 0.5)
|
||||||
|
return "volume_up";
|
||||||
|
if (volume > 0)
|
||||||
|
return "volume_down";
|
||||||
|
return "volume_mute";
|
||||||
|
}
|
||||||
|
|
||||||
FileView {
|
FileView {
|
||||||
path: "/etc/os-release"
|
path: "/etc/os-release"
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue