From 0e67c4d6cb1464da767f1eec0f29496b7268254d Mon Sep 17 00:00:00 2001 From: Zacharias-Brohn Date: Thu, 26 Feb 2026 14:26:20 +0100 Subject: [PATCH] cava test --- Daemons/Audio.qml | 6 ++ Modules/Dashboard/Dash/Media.qml | 98 ++++++++++++------------ Plugins/ZShell/Services/cavaprovider.cpp | 44 +++++------ 3 files changed, 78 insertions(+), 70 deletions(-) diff --git a/Daemons/Audio.qml b/Daemons/Audio.qml index 624b849..fddb283 100644 --- a/Daemons/Audio.qml +++ b/Daemons/Audio.qml @@ -10,6 +10,7 @@ import qs.Config Singleton { id: root + readonly property alias beatTracker: beatTracker readonly property alias cava: cava readonly property bool muted: !!sink?.audio?.muted readonly property var nodes: Pipewire.nodes.values.reduce((acc, node) => { @@ -138,6 +139,11 @@ Singleton { bars: Config.services.visualizerBars } + BeatTracker { + id: beatTracker + + } + PwObjectTracker { objects: [...root.sinks, ...root.sources, ...root.streams] } diff --git a/Modules/Dashboard/Dash/Media.qml b/Modules/Dashboard/Dash/Media.qml index 1eb32f2..11774c1 100644 --- a/Modules/Dashboard/Dash/Media.qml +++ b/Modules/Dashboard/Dash/Media.qml @@ -4,6 +4,7 @@ import Quickshell import QtQuick import QtQuick.Layouts import QtQuick.Shapes +import ZShell.Services import qs.Daemons import qs.Components import qs.Config @@ -37,54 +38,55 @@ Item { onTriggered: Players.active?.positionChanged() } - // Shape { - // id: visualizer - // - // readonly property real centerX: width / 2 - // readonly property real centerY: height / 2 - // property color colour: DynamicColors.palette.m3primary - // readonly property real innerX: cover.implicitWidth / 2 + Appearance.spacing.small - // readonly property real innerY: cover.implicitHeight / 2 + Appearance.spacing.small - // - // anchors.fill: cover - // anchors.margins: -Config.dashboard.sizes.mediaVisualiserSize - // asynchronous: true - // data: visualizerBars.instances - // preferredRendererType: Shape.CurveRenderer - // } - // - // Variants { - // id: visualizerBars - // - // model: Array.from({ - // length: Config.services.visualizerBars - // }, (_, i) => i) - // - // ShapePath { - // id: visualizerBar - // - // readonly property real angle: modelData * 2 * Math.PI / Config.services.visualizerBars - // readonly property real cos: Math.cos(angle) - // readonly property real magnitude: value * Config.dashboard.sizes.mediaVisualiserSize - // required property int modelData - // readonly property real sin: Math.sin(angle) - // readonly property real value: Math.max(1e-3, Math.min(1, Audio.cava.values[modelData])) - // - // capStyle: Appearance.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap - // startX: visualizer.centerX + (visualizer.innerX + strokeWidth / 2) * cos - // strokeColor: DynamicColors.palette.m3primary - // strokeWidth: 360 / Config.services.visualizerBars - Appearance.spacing.small / 4 - // - // startY: PathLine { - // x: visualizer.centerX + (visualizer.innerX + visualizerBar.strokeWidth / 2 + visualizerBar.magnitude) * visualizerBar.cos - // y: visualizer.centerY + (visualizer.innerY + visualizerBar.strokeWidth / 2 + visualizerBar.magnitude) * visualizerBar.sin - // } - // Behavior on strokeColor { - // CAnim { - // } - // } - // } - // } + ServiceRef { + service: Audio.cava + } + + Shape { + id: visualizer + + readonly property real barW: Math.max(0, (width - gap * (bars - 1)) / bars) + readonly property int bars: Config.services.visualizerBars + property color color: DynamicColors.palette.m3primary + readonly property real gap: Appearance.spacing.small + + anchors.fill: layout + asynchronous: true + data: visualizerBars.instances + preferredRendererType: Shape.CurveRenderer + } + + Variants { + id: visualizerBars + + model: Array.from({ + length: Config.services.visualizerBars + }, (_, i) => i) + + ShapePath { + id: visualizerBar + + readonly property real magnitude: value * Config.dashboard.sizes.mediaVisualiserSize + required property int modelData + readonly property real value: Math.max(1e-3, Audio.cava.values[modelData]) + + capStyle: Appearance.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap + startX: (visualizer.barW / 2) + modelData * (visualizer.barW + visualizer.gap) + startY: layout.y + layout.height + strokeColor: visualizer.color + strokeWidth: visualizer.barW + + Behavior on strokeColor { + CAnim { + } + } + + PathLine { + relativeX: 0 + relativeY: -visualizerBar.magnitude + } + } + } Shape { preferredRendererType: Shape.CurveRenderer diff --git a/Plugins/ZShell/Services/cavaprovider.cpp b/Plugins/ZShell/Services/cavaprovider.cpp index fdff3b3..1ae2d27 100644 --- a/Plugins/ZShell/Services/cavaprovider.cpp +++ b/Plugins/ZShell/Services/cavaprovider.cpp @@ -32,28 +32,28 @@ void CavaProcessor::process() { cava_execute(m_in, count, m_out, m_plan); // Apply monstercat filter - QVector values(m_bars); - - // Left to right pass - const double inv = 1.0 / 1.5; - double carry = 0.0; - for (int i = 0; i < m_bars; ++i) { - carry = std::max(m_out[i], carry * inv); - values[i] = carry; - } - - // Right to left pass and combine - carry = 0.0; - for (int i = m_bars - 1; i >= 0; --i) { - carry = std::max(m_out[i], carry * inv); - values[i] = std::max(values[i], carry); - } - - // Update values - if (values != m_values) { - m_values = std::move(values); - emit valuesChanged(m_values); - } + // QVector values(m_bars); + // + // // Left to right pass + // const double inv = 1.0 / 1.5; + // double carry = 0.0; + // for (int i = 0; i < m_bars; ++i) { + // carry = std::max(m_out[i], carry * inv); + // values[i] = carry; + // } + // + // // Right to left pass and combine + // carry = 0.0; + // for (int i = m_bars - 1; i >= 0; --i) { + // carry = std::max(m_out[i], carry * inv); + // values[i] = std::max(values[i], carry); + // } + // + // // Update values + // if (values != m_values) { + // m_values = std::move(values); + // emit valuesChanged(m_values); + // } } void CavaProcessor::setBars(int bars) {