208 lines
6.6 KiB
QML
208 lines
6.6 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import qs.config
|
|
import qs.custom
|
|
import qs.services
|
|
import qs.util
|
|
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import Quickshell
|
|
import Quickshell.Widgets
|
|
import Quickshell.Services.Pipewire
|
|
|
|
Item {
|
|
id: root
|
|
|
|
required property PersistentProperties uiState
|
|
required property int index
|
|
readonly property list<PwNode> nodes: Pipewire.nodes.values.filter(node => node.isSink && node.isStream)
|
|
|
|
width: Config.dashboard.mixerWidth
|
|
height: Config.dashboard.mixerHeight
|
|
|
|
PwObjectTracker {
|
|
objects: root.nodes
|
|
}
|
|
|
|
Binding {
|
|
target: root.uiState
|
|
when: root.uiState.dashboardTab === root.index
|
|
property: "osdVolumeReact"
|
|
value: false
|
|
}
|
|
|
|
ColumnLayout {
|
|
id: layout
|
|
|
|
anchors.fill: parent
|
|
spacing: 7
|
|
|
|
CustomText {
|
|
Layout.topMargin: 6
|
|
text: qsTr("Master Volume")
|
|
color: Config.colors.secondary
|
|
}
|
|
|
|
CustomMouseArea {
|
|
Layout.fillWidth: true
|
|
implicitHeight: Config.osd.sliderWidth
|
|
|
|
function onWheel(event: WheelEvent) {
|
|
if (event.angleDelta.y > 0)
|
|
Audio.increaseVolume();
|
|
else if (event.angleDelta.y < 0)
|
|
Audio.decreaseVolume();
|
|
}
|
|
|
|
acceptedButtons: Qt.RightButton
|
|
onClicked: Audio.sink.audio.muted = !Audio.muted
|
|
|
|
CustomFilledSlider {
|
|
anchors.fill: parent
|
|
|
|
orientation: Qt.Horizontal
|
|
color: Audio.muted ? Config.colors.error : Config.colors.volume
|
|
icon: Icons.getVolumeIcon(value, Audio.muted)
|
|
value: Audio.volume
|
|
onMoved: Audio.setVolume(value)
|
|
|
|
Behavior on color {
|
|
CAnim {
|
|
duration: Config.anim.durations.small
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CustomRect {
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: 5
|
|
Layout.bottomMargin: 5
|
|
height: 1
|
|
color: Config.colors.inactive
|
|
}
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
|
|
CustomListView {
|
|
id: list
|
|
|
|
anchors.fill: parent
|
|
spacing: 12
|
|
|
|
model: ScriptModel {
|
|
values: [...root.nodes]
|
|
objectProp: "id"
|
|
}
|
|
|
|
CustomScrollBar.vertical: CustomScrollBar {
|
|
flickable: list
|
|
}
|
|
|
|
delegate: RowLayout {
|
|
id: entry
|
|
|
|
required property PwNode modelData
|
|
spacing: 6
|
|
|
|
width: root.width
|
|
|
|
IconImage {
|
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
|
visible: source != ""
|
|
implicitSize: slider.height * 1.4
|
|
source: {
|
|
const icon = entry.modelData.properties["application.icon-name"];
|
|
if (icon)
|
|
return Icons.getAppIcon(icon, "image-missing");
|
|
Icons.getAppIcon(entry.modelData.name, "image-missing")
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 6
|
|
|
|
CustomText {
|
|
Layout.fillWidth: true
|
|
elide: Text.ElideRight
|
|
text: {
|
|
// application.name -> description -> name
|
|
const app = entry.modelData.properties["application.name"]
|
|
?? (entry.modelData.description != "" ? entry.modelData.description : entry.modelData.name);
|
|
const media = entry.modelData.properties["media.name"];
|
|
return media != undefined ? `${app} 🞄 ${media}` : app;
|
|
}
|
|
color: Config.colors.secondary
|
|
}
|
|
|
|
CustomMouseArea {
|
|
id: slider
|
|
Layout.fillWidth: true
|
|
implicitHeight: Config.osd.sliderWidth
|
|
|
|
acceptedButtons: Qt.RightButton
|
|
onClicked: entry.modelData.audio.muted = !entry.modelData.audio.muted
|
|
|
|
CustomFilledSlider {
|
|
|
|
anchors.fill: parent
|
|
|
|
orientation: Qt.Horizontal
|
|
color: entry.modelData.audio.muted ? Config.colors.error : Config.colors.volume
|
|
icon: Icons.getVolumeIcon(value, entry.modelData.audio.muted)
|
|
value: entry.modelData.audio.volume
|
|
onMoved: {
|
|
if (entry.modelData.ready)
|
|
entry.modelData.audio.volume = Math.max(0, Math.min(1, value));
|
|
}
|
|
|
|
|
|
Behavior on color {
|
|
CAnim {
|
|
duration: Config.anim.durations.small
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CustomText {
|
|
anchors.centerIn: parent
|
|
|
|
opacity: list.count === 0 ? 1 : 0
|
|
visible: opacity > 0
|
|
|
|
text: qsTr("No audio sources")
|
|
color: Config.colors.tertiary
|
|
font.pointSize: Config.font.size.normal
|
|
|
|
Behavior on opacity {
|
|
Anim {}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* RowLayout { */
|
|
/* id: deviceSelectorRowLayout */
|
|
/* Layout.fillWidth: true */
|
|
/* uniformCellSizes: true */
|
|
|
|
/* AudioDeviceSelectorButton { */
|
|
/* Layout.fillWidth: true */
|
|
/* input: false */
|
|
/* onClicked: root.showDeviceSelectorDialog(input) */
|
|
/* } */
|
|
/* AudioDeviceSelectorButton { */
|
|
/* Layout.fillWidth: true */
|
|
/* input: true */
|
|
/* onClicked: root.showDeviceSelectorDialog(input) */
|
|
/* } */
|
|
/* } */
|
|
}
|
|
}
|