progress maybe, maybe not

This commit is contained in:
kossLAN 2025-07-04 02:16:35 -04:00
parent ce6c1f410c
commit 83a0ac8899
Signed by: kossLAN
SSH key fingerprint: SHA256:bdV0x+wdQHGJ6LgmstH3KV8OpWY+OOFmJcPcB0wQPV8
21 changed files with 1412 additions and 49 deletions

View file

@ -0,0 +1,70 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import Quickshell.Services.Pipewire
import "../../widgets/" as Widgets
import "../.."
ColumnLayout {
id: root
Loader {
id: sinkLoader
active: sink
property PwNode sink: Pipewire.defaultAudioSink
sourceComponent: WrapperItem {
PwNodeLinkTracker {
id: linkTracker
node: sinkLoader.sink
}
ColumnLayout {
Repeater {
model: linkTracker.linkGroups
delegate: Loader {
id: nodeLoader
active: modelData.source !== null
Layout.preferredWidth: 350
Layout.preferredHeight: 45
required property PwLinkGroup modelData
sourceComponent: VolumeCard {
id: nodeCard
node: nodeLoader.modelData.source
text: node.properties["media.name"] ?? ""
// if icon-name is undefined, just gonna fallback on the application name
icon: IconImage {
source: {
if (nodeCard.node.properties["application.icon-name"] !== undefined)
return `image://icon/${nodeCard.node.properties["application.icon-name"]}`;
let applicationName = nodeCard.node.properties["application.name"];
return `image://icon/${applicationName?.toLowerCase() ?? "image-missing"}`;
}
}
button: Widgets.FontIconButton {
hoverEnabled: false
iconName: nodeCard.node.audio.muted ? "volume_off" : "volume_up"
checked: !nodeCard.node.audio.muted
inactiveColor: ShellSettings.colors["surface_container_highest"]
onClicked: {
nodeCard.node.audio.muted = !nodeCard.node.audio.muted;
}
}
anchors.fill: parent
}
}
}
}
}
}
}

View file

@ -0,0 +1,64 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Services.Pipewire
import "../../widgets/" as Widgets
import "../.."
ColumnLayout {
id: root
// headphones
// don't load until the node is not null
Loader {
id: sinkLoader
active: sink !== null
Layout.preferredWidth: 350
Layout.preferredHeight: 45
property PwNode sink: Pipewire.defaultAudioSink
sourceComponent: VolumeCard {
id: sinkCard
node: sinkLoader.sink
button: Widgets.FontIconButton {
hoverEnabled: false
iconName: sinkCard.node.audio.muted ? "volume_off" : "volume_up"
checked: !sinkCard.node.audio.muted
inactiveColor: ShellSettings.colors["surface_container_highest"]
onClicked: {
sinkCard.node.audio.muted = !sinkCard.node.audio.muted;
}
}
anchors.fill: parent
}
}
// microphone, same as above
Loader {
id: sourceLoader
active: source !== null
Layout.preferredWidth: 350
Layout.preferredHeight: 45
property PwNode source: Pipewire.defaultAudioSource
sourceComponent: VolumeCard {
id: sourceCard
node: sourceLoader.source
button: Widgets.FontIconButton {
hoverEnabled: false
iconName: sourceCard.node.audio.muted ? "mic_off" : "mic"
checked: !sourceCard.node.audio.muted
inactiveColor: ShellSettings.colors["surface_container_highest"]
onClicked: {
sourceCard.node.audio.muted = !sourceCard.node.audio.muted;
}
}
anchors.fill: parent
}
}
}

View file

@ -0,0 +1,50 @@
import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import Quickshell.Services.Pipewire
import "../../widgets/" as Widgets
import "../.."
WrapperRectangle {
id: root
color: ShellSettings.colors["surface_container"]
radius: width / 2
margin: 6
required property PwNode node
property string text
property Component button
property Component icon
PwObjectTracker {
id: tracker
objects: [root.node]
}
RowLayout {
Widgets.MaterialSlider {
value: root.node.audio.volume ?? 0
text: root.text
icon: root.icon
onValueChanged: {
// only allow changes when the node is ready other wise you will combust
if (!root.node.ready)
return;
root.node.audio.volume = value;
}
Layout.fillWidth: true
Layout.fillHeight: true
}
Loader {
id: buttonLoader
sourceComponent: root.button
Layout.preferredWidth: this.height
Layout.fillHeight: true
}
}
}

View file

@ -0,0 +1,34 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import "../../widgets/" as Widgets
WrapperItem {
id: root
visible: false
ColumnLayout {
spacing: 10
Widgets.TabBar {
id: tabBar
model: ["headphones", "tune"]
Layout.fillWidth: true
Layout.preferredHeight: 35
}
StackLayout {
id: page
currentIndex: tabBar.currentIndex
Layout.fillWidth: true
Layout.preferredHeight: currentItem ? currentItem.implicitHeight : 0
readonly property Item currentItem: children[currentIndex]
DeviceMixer {}
ApplicationMixer {}
}
}
}

View file

@ -0,0 +1,27 @@
import QtQuick
import "../../widgets/" as Widgets
Item {
id: root
required property var popup
Widgets.FontIconButton {
id: button
iconName: "volume_up"
anchors.fill: parent
onClicked: {
if (root.popup.content == volumeMenu) {
root.popup.hide();
return;
}
root.popup.set(this, volumeMenu);
root.popup.show();
}
}
VolumeControl {
id: volumeMenu
}
}