Files
noctalia-shell/Modules/Bar/Widgets/AudioVisualizer.qml
T

159 lines
4.6 KiB
QML

import QtQuick
import Quickshell
import qs.Commons
import qs.Modules.AudioSpectrum
import qs.Services
import qs.Widgets
Item {
id: root
property ShellScreen screen
// Widget properties passed from Bar.qml for per-instance settings
property string widgetId: ""
property string section: ""
property int sectionWidgetIndex: -1
property int sectionWidgetsCount: 0
property string barPosition: "top" // Passed from Bar.qml
property string barDensity: "default" // Passed from Bar.qml
property bool barShowCapsule: true // Passed from Bar.qml
readonly property real barHeight: BarService.getBarHeight(barDensity, barPosition)
readonly property real capsuleHeight: BarService.getCapsuleHeight(barDensity, barPosition)
readonly property bool isVerticalBar: (barPosition === "left" || barPosition === "right")
property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId]
property var widgetSettings: {
if (screen && section && sectionWidgetIndex >= 0) {
return Settings.getWidgetSettings(screen.name, section, sectionWidgetIndex)
}
return {}
}
// Resolve settings: try user settings or defaults from BarWidgetRegistry
readonly property int visualizerWidth: widgetSettings.width !== undefined ? widgetSettings.width : widgetMetadata.width
readonly property bool hideWhenIdle: widgetSettings.hideWhenIdle !== undefined ? widgetSettings.hideWhenIdle : widgetMetadata.hideWhenIdle
readonly property string colorName: widgetSettings.colorName !== undefined ? widgetSettings.colorName : widgetMetadata.colorName
readonly property color fillColor: {
switch (colorName) {
case "primary":
return Color.mPrimary
case "secondary":
return Color.mSecondary
case "tertiary":
return Color.mTertiary
case "error":
return Color.mError
case "onSurface":
default:
return Color.mOnSurface
}
}
readonly property bool shouldShow: (currentVisualizerType !== "" && currentVisualizerType !== "none") && (!hideWhenIdle || MediaService.isPlaying)
implicitWidth: !shouldShow ? 0 : isVerticalBar ? capsuleHeight : visualizerWidth
implicitHeight: !shouldShow ? 0 : isVerticalBar ? visualizerWidth : capsuleHeight
visible: shouldShow
Behavior on implicitWidth {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.InOutCubic
}
}
Behavior on implicitHeight {
NumberAnimation {
duration: Style.animationNormal
easing.type: Easing.InOutCubic
}
}
Rectangle {
id: background
anchors.fill: parent
radius: Style.radiusS
color: barShowCapsule ? Color.mSurfaceVariant : Color.transparent
}
// Store visualizer type to force re-evaluation
readonly property string currentVisualizerType: Settings.data.audio.visualizerType
// When visualizer type or playback changes, shouldShow updates automatically
// The Loader dynamically loads the appropriate visualizer based on settings
Loader {
id: visualizerLoader
anchors.fill: parent
anchors.margins: Style.marginS
active: shouldShow
asynchronous: true
sourceComponent: {
switch (currentVisualizerType) {
case "linear":
return linearComponent
case "mirrored":
return mirroredComponent
case "wave":
return waveComponent
default:
return null
}
}
}
// Click to cycle through visualizer types
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
acceptedButtons: Qt.LeftButton
onClicked: mouse => {
const types = ["linear", "mirrored", "wave"]
const currentIndex = types.indexOf(currentVisualizerType)
const nextIndex = (currentIndex + 1) % types.length
const newType = types[nextIndex]
// Update settings directly, maybe this should be a widget setting...
Settings.data.audio.visualizerType = newType
}
}
Component {
id: linearComponent
LinearSpectrum {
anchors.fill: parent
values: CavaService.values
fillColor: root.fillColor
showMinimumSignal: true
vertical: root.isVerticalBar
}
}
Component {
id: mirroredComponent
MirroredSpectrum {
anchors.fill: parent
values: CavaService.values
fillColor: root.fillColor
showMinimumSignal: true
vertical: root.isVerticalBar
}
}
Component {
id: waveComponent
WaveSpectrum {
anchors.fill: parent
values: CavaService.values
fillColor: root.fillColor
showMinimumSignal: true
vertical: root.isVerticalBar
}
}
}