feat: added widgets capture, music visualiser, bluetooth, notes
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Services.Pipewire
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import "../components"
|
||||
|
||||
DankFlickable {
|
||||
id: mixer
|
||||
|
||||
readonly property var streams: Pipewire.nodes.values.filter(node => node.audio && node.isSink && node.isStream)
|
||||
readonly property int streamCount: streams.length
|
||||
|
||||
function appName(node) {
|
||||
if (!node)
|
||||
return "";
|
||||
|
||||
const props = node.properties || {};
|
||||
return props["application.name"] || AudioService.displayName(node) || "Unknown";
|
||||
}
|
||||
|
||||
function mediaName(node) {
|
||||
const props = (node && node.properties) ? node.properties : {};
|
||||
return props["media.name"] || "";
|
||||
}
|
||||
|
||||
function appIconValue(node) {
|
||||
const props = (node && node.properties) ? node.properties : {};
|
||||
const candidates = [props["application.icon-name"], props["application.process.binary"], props["application.name"]];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (!candidate)
|
||||
continue;
|
||||
|
||||
const entry = DesktopEntries.heuristicLookup(String(candidate));
|
||||
if (entry && entry.icon)
|
||||
return entry.icon;
|
||||
}
|
||||
|
||||
return "material:graphic_eq";
|
||||
}
|
||||
|
||||
clip: true
|
||||
contentHeight: streamColumn.height
|
||||
contentWidth: width
|
||||
|
||||
Column {
|
||||
id: streamColumn
|
||||
|
||||
width: mixer.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: mixer.streams
|
||||
}
|
||||
|
||||
delegate: Rectangle {
|
||||
id: streamItem
|
||||
|
||||
required property var modelData
|
||||
|
||||
width: streamColumn.width
|
||||
height: 86
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceLight, Theme.popupTransparency)
|
||||
border.color: Theme.outlineLight
|
||||
border.width: Theme.layerOutlineWidth
|
||||
|
||||
AppIconRenderer {
|
||||
id: streamIcon
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Theme.spacingM
|
||||
width: Theme.iconSize
|
||||
height: Theme.iconSize
|
||||
iconValue: mixer.appIconValue(streamItem.modelData)
|
||||
iconSize: Theme.iconSize
|
||||
fallbackText: mixer.appName(streamItem.modelData).charAt(0).toUpperCase()
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.left: streamIcon.right
|
||||
anchors.leftMargin: Theme.spacingS
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Theme.spacingM
|
||||
spacing: 1
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: mixer.appName(streamItem.modelData)
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: mixer.mediaName(streamItem.modelData)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
elide: Text.ElideRight
|
||||
visible: text !== ""
|
||||
}
|
||||
}
|
||||
|
||||
VolumeRow {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.leftMargin: Theme.spacingS
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
anchors.bottomMargin: Theme.spacingXS
|
||||
node: streamItem.modelData
|
||||
maxPercent: 100
|
||||
activeIcon: "volume_up"
|
||||
mutedIcon: "volume_off"
|
||||
}
|
||||
|
||||
PwObjectTracker {
|
||||
objects: [streamItem.modelData]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: streamColumn.width
|
||||
height: 120
|
||||
visible: mixer.streamCount === 0
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingS
|
||||
|
||||
DankIcon {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
name: "music_off"
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "No apps are playing audio"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user