feat(bar): add audio indicator widget

This commit is contained in:
tux
2026-08-24 15:43:43 +05:30
parent e95f62579b
commit de3c9274b5
6 changed files with 63 additions and 2 deletions

View File

@@ -32,12 +32,14 @@ shell.qml Entry point: Scope { Bar {}; Notification {} }
│ └── Notification.qml Popup notification stack window │ └── Notification.qml Popup notification stack window
├── modules/ Feature widgets, grouped by surface ├── modules/ Feature widgets, grouped by surface
│ ├── bar/ Widgets placed in the bar (Clock, Workspaces, │ ├── bar/ Widgets placed in the bar (Clock, Workspaces,
│ │ BatteryIndicator, CavaVisualizer, SystemTray, │ │ BatteryIndicator, AudioWidget, CavaVisualizer,
│ │ LauncherButton, PowerProfileWidget, GhostButton) │ │ SystemTray, LauncherButton, PowerProfileWidget,
│ │ GhostButton)
│ └── osd/ NotificationCard.qml │ └── osd/ NotificationCard.qml
├── services/ QML Singletons exposing system state ├── services/ QML Singletons exposing system state
│ ├── Time.qml SystemClock → formatted time string │ ├── Time.qml SystemClock → formatted time string
│ ├── Battery.qml UPower display device → percentage/icon │ ├── Battery.qml UPower display device → percentage/icon
│ ├── Audio.qml PipeWire default sink/source → device names/icons
│ ├── PowerProfile.qml UPower power profiles → name/icon │ ├── PowerProfile.qml UPower power profiles → name/icon
│ ├── Cava.qml Spawns `cava`, parses stdout into `values[]` │ ├── Cava.qml Spawns `cava`, parses stdout into `values[]`
│ └── Notifications.qml NotificationServer: popups, DND flag, history │ └── Notifications.qml NotificationServer: popups, DND flag, history

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 9C4.41421 9 4.75 9.33579 4.75 9.75V10.75C4.75 14.7541 7.99594 18 12 18C16.0041 18 19.25 14.7541 19.25 10.75V9.75C19.25 9.33579 19.5858 9 20 9C20.4142 9 20.75 9.33579 20.75 9.75V10.75C20.75 15.3298 17.2314 19.0879 12.75 19.4683V21.75C12.75 22.1642 12.4142 22.5 12 22.5C11.5858 22.5 11.25 22.1642 11.25 21.75V19.4683C6.7686 19.0879 3.25 15.3298 3.25 10.75V9.75C3.25 9.33579 3.58579 9 4 9Z" fill="#1C274C"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C8.82436 2 6.25 4.57436 6.25 7.75V10.75C6.25 13.9256 8.82436 16.5 12 16.5C15.1756 16.5 17.75 13.9256 17.75 10.75V7.75C17.75 4.57436 15.1756 2 12 2ZM14 11.5C14.4142 11.5 14.75 11.1642 14.75 10.75C14.75 10.3358 14.4142 10 14 10H10C9.58579 10 9.25 10.3358 9.25 10.75C9.25 11.1642 9.58579 11.5 10 11.5H14ZM13.75 7.75C13.75 8.16421 13.4142 8.5 13 8.5H11C10.5858 8.5 10.25 8.16421 10.25 7.75C10.25 7.33579 10.5858 7 11 7H13C13.4142 7 13.75 7.33579 13.75 7.75Z" fill="#1C274C"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

5
assets/icons/speaker.svg Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 10.75C10.2051 10.75 8.75 12.2051 8.75 14C8.75 15.7949 10.2051 17.25 12 17.25C13.7949 17.25 15.25 15.7949 15.25 14C15.25 12.2051 13.7949 10.75 12 10.75Z" fill="#1C274C"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 10C4 6.22876 4 4.34315 5.17157 3.17157C6.34315 2 8.22876 2 12 2C15.7712 2 17.6569 2 18.8284 3.17157C20 4.34315 20 6.22876 20 10V14C20 17.7712 20 19.6569 18.8284 20.8284C17.6569 22 15.7712 22 12 22C8.22876 22 6.34315 22 5.17157 20.8284C4 19.6569 4 17.7712 4 14V10ZM7.25 14C7.25 11.3766 9.37665 9.25 12 9.25C14.6234 9.25 16.75 11.3766 16.75 14C16.75 16.6234 14.6234 18.75 12 18.75C9.37665 18.75 7.25 16.6234 7.25 14ZM10 5.25C9.58579 5.25 9.25 5.58579 9.25 6C9.25 6.41421 9.58579 6.75 10 6.75H14C14.4142 6.75 14.75 6.41421 14.75 6C14.75 5.58579 14.4142 5.25 14 5.25H10Z" fill="#1C274C"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -24,6 +24,7 @@ Singleton {
] ]
property var right: [ property var right: [
root.widget("AudioWidget"),
root.widget("BatteryIndicator"), root.widget("BatteryIndicator"),
root.widget("SystemTrayWidget"), root.widget("SystemTrayWidget"),
root.widget("ClockWidget"), root.widget("ClockWidget"),

View File

@@ -0,0 +1,24 @@
pragma ComponentBehavior: Bound
import QtQuick.Layouts
import qs.ui
import qs.services
RowLayout {
BarButton {
hoverHighlight: false
pointerCursor: false
label: Audio.inputName
iconSource: Audio.inputIcon
}
BarButton {
hoverHighlight: false
pointerCursor: false
label: Audio.outputName
iconSource: Audio.outputIcon
}
}

24
services/Audio.qml Normal file
View File

@@ -0,0 +1,24 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Services.Pipewire
Singleton {
id: root
readonly property string outputName: root.displayName(Pipewire.defaultAudioSink)
readonly property string inputName: root.displayName(Pipewire.defaultAudioSource)
readonly property url outputIcon: `${Quickshell.shellPath("assets")}/icons/speaker.svg`
readonly property url inputIcon: `${Quickshell.shellPath("assets")}/icons/microphone.svg`
function displayName(node: PwNode): string {
if (!node)
return "none";
return node.description || node.name;
}
PwObjectTracker {
objects: [Pipewire.defaultAudioSink, Pipewire.defaultAudioSource]
}
}