forked from Shinonome/dots-hyprland
media controls: visualizer
This commit is contained in:
@@ -25,6 +25,8 @@ Item { // Player instance
|
||||
property string artFilePath: `${artDownloadLocation}/${artFileName}`
|
||||
property color artDominantColor: colorQuantizer?.colors[0] || Appearance.m3colors.m3secondaryContainer
|
||||
property bool downloaded: false
|
||||
property list<real> visualizerPoints: []
|
||||
property real maxVisualizerValue: 1000 // Max value in the data points
|
||||
|
||||
implicitWidth: widgetWidth
|
||||
implicitHeight: widgetHeight
|
||||
@@ -150,6 +152,69 @@ Item { // Player instance
|
||||
}
|
||||
}
|
||||
|
||||
Canvas { // Visualizer
|
||||
id: visualizerCanvas
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
var points = playerController.visualizerPoints;
|
||||
var maxVal = playerController.maxVisualizerValue || 1;
|
||||
var h = height;
|
||||
var w = width;
|
||||
var n = points.length;
|
||||
if (n < 2) return;
|
||||
|
||||
// Smoothing: simple moving average (optional)
|
||||
var smoothPoints = [];
|
||||
var smoothWindow = 3; // adjust for more/less smoothing
|
||||
for (var i = 0; i < n; ++i) {
|
||||
var sum = 0, count = 0;
|
||||
for (var j = -smoothWindow; j <= smoothWindow; ++j) {
|
||||
var idx = Math.max(0, Math.min(n - 1, i + j));
|
||||
sum += points[idx];
|
||||
count++;
|
||||
}
|
||||
smoothPoints.push(sum / count);
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, h);
|
||||
for (var i = 0; i < n; ++i) {
|
||||
var x = i * w / (n - 1);
|
||||
var y = h - (smoothPoints[i] / maxVal) * h;
|
||||
ctx.lineTo(x, y);
|
||||
}
|
||||
ctx.lineTo(w, h);
|
||||
ctx.closePath();
|
||||
|
||||
ctx.fillStyle = Qt.rgba(
|
||||
blendedColors.colPrimary.r,
|
||||
blendedColors.colPrimary.g,
|
||||
blendedColors.colPrimary.b,
|
||||
0.25
|
||||
);
|
||||
ctx.fill();
|
||||
}
|
||||
Connections {
|
||||
target: playerController
|
||||
function onVisualizerPointsChanged() {
|
||||
visualizerCanvas.requestPaint()
|
||||
}
|
||||
}
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect { // Blur a tiny bit to obscure away the points
|
||||
source: visualizerCanvas
|
||||
saturation: 0.2
|
||||
blurEnabled: true
|
||||
blurMax: 6
|
||||
blur: 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.contentPadding
|
||||
@@ -160,7 +225,7 @@ Item { // Player instance
|
||||
Layout.fillHeight: true
|
||||
implicitWidth: height
|
||||
radius: root.artRounding
|
||||
color: blendedColors.colLayer1
|
||||
color: ColorUtils.transparentize(blendedColors.colLayer1, 0.5)
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
@@ -235,12 +300,18 @@ Item { // Player instance
|
||||
iconName: "skip_previous"
|
||||
onClicked: playerController.player?.previous()
|
||||
}
|
||||
StyledProgressBar {
|
||||
id: slider
|
||||
Item {
|
||||
id: progressBarContainer
|
||||
Layout.fillWidth: true
|
||||
highlightColor: blendedColors.colPrimary
|
||||
trackColor: blendedColors.colSecondaryContainer
|
||||
value: playerController.player?.position / playerController.player?.length
|
||||
implicitHeight: progressBar.implicitHeight
|
||||
|
||||
StyledProgressBar {
|
||||
id: progressBar
|
||||
anchors.fill: parent
|
||||
highlightColor: blendedColors.colPrimary
|
||||
trackColor: blendedColors.colSecondaryContainer
|
||||
value: playerController.player?.position / playerController.player?.length
|
||||
}
|
||||
}
|
||||
TrackChangeButton {
|
||||
iconName: "skip_next"
|
||||
|
||||
Reference in New Issue
Block a user