AudioPanel: display device icon in devices tab

This commit is contained in:
Lysec
2026-02-11 13:58:56 +01:00
parent 825701a57b
commit eaa5793399
3 changed files with 91 additions and 1 deletions
+1 -1
View File
@@ -1929,4 +1929,4 @@
"poor": "Poor"
}
}
}
}
+46
View File
@@ -717,6 +717,7 @@ SmartPanel {
Repeater {
model: AudioService.sinks
NRadioButton {
id: sinkButton
ButtonGroup.group: sinks
required property PwNode modelData
pointSize: Style.fontSizeS
@@ -727,6 +728,28 @@ SmartPanel {
localOutputVolume = AudioService.volume;
}
Layout.fillWidth: true
contentItem: RowLayout {
spacing: Style.marginS
anchors.left: sinkButton.indicator.right
anchors.leftMargin: Style.marginS
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
NIcon {
icon: AudioService.getDeviceIcon(modelData)
pointSize: sinkButton.pointSize
color: sinkButton.checked ? Color.mPrimary : Color.mOnSurface
}
NText {
text: sinkButton.text
pointSize: sinkButton.pointSize
Layout.fillWidth: true
color: sinkButton.checked ? Color.mPrimary : Color.mOnSurface
elide: Text.ElideRight
}
}
}
}
}
@@ -760,6 +783,7 @@ SmartPanel {
Repeater {
model: AudioService.sources
NRadioButton {
id: sourceButton
ButtonGroup.group: sources
required property PwNode modelData
pointSize: Style.fontSizeS
@@ -767,6 +791,28 @@ SmartPanel {
checked: AudioService.source?.id === modelData.id
onClicked: AudioService.setAudioSource(modelData)
Layout.fillWidth: true
contentItem: RowLayout {
spacing: Style.marginS
anchors.left: sourceButton.indicator.right
anchors.leftMargin: Style.marginS
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
NIcon {
icon: AudioService.getDeviceIcon(modelData)
pointSize: sourceButton.pointSize
color: sourceButton.checked ? Color.mPrimary : Color.mOnSurface
}
NText {
text: sourceButton.text
pointSize: sourceButton.pointSize
Layout.fillWidth: true
color: sourceButton.checked ? Color.mPrimary : Color.mOnSurface
elide: Text.ElideRight
}
}
}
}
}
+44
View File
@@ -482,4 +482,48 @@ Singleton {
}
Pipewire.preferredDefaultAudioSource = newSource;
}
function getDeviceIcon(node: PwNode): string {
if (!node || !node.properties) {
return node && !node.isSink ? "microphone" : "volume";
}
const props = node.properties;
const isSink = node.isSink;
// Properties to scan for keywords
const searchTerms = [
node.description,
node.name,
props["node.nick"],
props["alsa.card_name"],
props["alsa.id"],
props["device.form-factor"],
props["media.class"],
props["device.profile.name"]
].filter(s => s).map(s => s.toLowerCase());
const hasMatch = (keywords) => keywords.some(k => searchTerms.some(t => t.includes(k)));
if (hasMatch(["hdmi", "displayport", "digital stereo", "monitor", "tv"])) {
return "bt-device-tv";
}
if (hasMatch(["headphone", "headset", "earbud", "earphone", "cloud", "arctis", "major", "minor", "wireless"])) {
return "bt-device-headphones";
}
if (!isSink || hasMatch(["microphone", "mic"])) {
if (hasMatch(["microphone", "mic"])) return "microphone";
}
if (hasMatch(["speaker", "loudspeaker", "internal", "analog", "pci"])) {
return isSink ? "bt-device-speaker" : "microphone";
}
if (props["device.bus"] === "bluetooth") return "bluetooth";
if (props["device.bus"] === "usb") return isSink ? "bt-device-speaker" : "microphone";
return isSink ? "volume" : "microphone";
}
}