up su Gitea
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Modules.DesktopWidgets
|
||||
import qs.Services.Media
|
||||
|
||||
DraggableDesktopWidget {
|
||||
id: root
|
||||
|
||||
property var pluginApi: null
|
||||
|
||||
implicitWidth: Math.round(300 * widgetScale)
|
||||
implicitHeight: Math.round(300 * widgetScale)
|
||||
|
||||
showBackground: false
|
||||
|
||||
// Scaled dimensions
|
||||
readonly property int scaledRadiusL: Math.round(Style.radiusL * widgetScale)
|
||||
|
||||
// Settings from plugin
|
||||
readonly property real sensitivity: widgetData?.sensitivity ?? pluginApi?.pluginSettings?.sensitivity ?? pluginApi?.manifest?.metadata?.defaultSettings?.sensitivity
|
||||
readonly property real rotationSpeed: widgetData?.rotationSpeed ?? pluginApi?.pluginSettings?.rotationSpeed ?? pluginApi?.manifest?.metadata?.defaultSettings?.rotationSpeed
|
||||
readonly property real barWidth: widgetData?.barWidth ?? pluginApi?.pluginSettings?.barWidth ?? pluginApi?.manifest?.metadata?.defaultSettings?.barWidth
|
||||
readonly property real ringOpacity: widgetData?.ringOpacity ?? pluginApi?.pluginSettings?.ringOpacity ?? pluginApi?.manifest?.metadata?.defaultSettings?.ringOpacity
|
||||
readonly property real bloomIntensity: widgetData?.bloomIntensity ?? pluginApi.pluginSettings?.bloomIntensity ?? pluginApi?.manifest?.metadata?.defaultSettings?.bloomIntensity
|
||||
readonly property int visualizationMode: widgetData?.visualizationMode ?? pluginApi?.pluginSettings?.visualizationMode ?? pluginApi?.manifest?.metadata?.defaultSettings?.visualizationMode ?? 3
|
||||
readonly property real waveThickness: widgetData?.waveThickness ?? pluginApi?.pluginSettings?.waveThickness ?? pluginApi?.manifest?.metadata?.defaultSettings?.waveThickness ?? 1.0
|
||||
readonly property real innerDiameter: widgetData?.innerDiameter ?? pluginApi?.pluginSettings?.innerDiameter ?? pluginApi?.manifest?.metadata?.defaultSettings?.innerDiameter ?? 0.7
|
||||
readonly property bool fadeWhenIdle: widgetData?.fadeWhenIdle ?? pluginApi?.pluginSettings?.fadeWhenIdle ?? false
|
||||
readonly property bool useCustomColors: widgetData?.useCustomColors ?? pluginApi?.pluginSettings?.useCustomColors ?? false
|
||||
readonly property color customPrimaryColor: widgetData?.customPrimaryColor ?? pluginApi?.pluginSettings?.customPrimaryColor ?? "#6750A4"
|
||||
readonly property color customSecondaryColor: widgetData?.customSecondaryColor ?? pluginApi?.pluginSettings?.customSecondaryColor ?? "#625B71"
|
||||
|
||||
// Animation time for shader (0 to 3600, 1 hour cycle)
|
||||
property real shaderTime: 0
|
||||
NumberAnimation on shaderTime {
|
||||
loops: Animation.Infinite
|
||||
from: 0
|
||||
to: 3600
|
||||
duration: 3600000
|
||||
running: !SpectrumService.isIdle
|
||||
}
|
||||
|
||||
// Hidden canvas that encodes audio data as a 32x1 texture
|
||||
Canvas {
|
||||
id: audioCanvas
|
||||
width: 32
|
||||
height: 1
|
||||
visible: false
|
||||
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
var values = SpectrumService.values;
|
||||
if (!values || values.length === 0) {
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, 32, 1);
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < 32; i++) {
|
||||
var v = values[i] || 0;
|
||||
// Encode amplitude in grayscale (R=G=B=amplitude)
|
||||
var c = Math.floor(v * 255);
|
||||
ctx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
|
||||
ctx.fillRect(i, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger canvas repaint when audio data changes
|
||||
Connections {
|
||||
target: SpectrumService
|
||||
function onValuesChanged() {
|
||||
if (!SpectrumService.isIdle) {
|
||||
audioCanvas.requestPaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unique instance ID for SpectrumService registration
|
||||
// This prevents the old widget's destruction from unregistering the new widget
|
||||
readonly property string spectrumInstanceId: "plugin:fancy-audiovisualizer:" + Date.now() + Math.random()
|
||||
|
||||
// Register with SpectrumService when pluginApi becomes available
|
||||
onPluginApiChanged: {
|
||||
if (pluginApi) {
|
||||
SpectrumService.registerComponent(spectrumInstanceId);
|
||||
audioCanvas.requestPaint();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
SpectrumService.unregisterComponent(spectrumInstanceId);
|
||||
}
|
||||
|
||||
// Audio texture source (outside ShaderEffect to avoid 'source' property warning)
|
||||
ShaderEffectSource {
|
||||
id: audioTextureSource
|
||||
sourceItem: audioCanvas
|
||||
live: true
|
||||
hideSource: true
|
||||
}
|
||||
|
||||
// The shader effect visualization
|
||||
ShaderEffect {
|
||||
id: visualizer
|
||||
anchors.fill: parent
|
||||
visible: pluginApi !== null
|
||||
opacity: (root.fadeWhenIdle && SpectrumService.isIdle) ? 0 : 1
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 500; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
|
||||
// Audio texture - named 'source' to match ShaderEffectSource's property and avoid warning
|
||||
property var source: audioTextureSource
|
||||
|
||||
// Uniforms passed to shader
|
||||
property real time: root.shaderTime
|
||||
property real itemWidth: visualizer.width
|
||||
property real itemHeight: visualizer.height
|
||||
property color primaryColor: root.useCustomColors ? root.customPrimaryColor : Color.mPrimary
|
||||
property color secondaryColor: root.useCustomColors ? root.customSecondaryColor : Color.mSecondary
|
||||
property real sensitivity: root.sensitivity
|
||||
property real rotationSpeed: root.rotationSpeed
|
||||
property real barWidth: root.barWidth
|
||||
property real ringOpacity: root.ringOpacity
|
||||
property real cornerRadius: scaledRadiusL
|
||||
property real bloomIntensity: root.bloomIntensity
|
||||
property real visualizationMode: root.visualizationMode
|
||||
property real waveThickness: root.waveThickness
|
||||
property real innerDiameter: root.innerDiameter
|
||||
|
||||
fragmentShader: pluginApi ? Qt.resolvedUrl(pluginApi.pluginDir + "/shaders/visualizer.frag.qsb") : ""
|
||||
}
|
||||
|
||||
// Fallback when shader not loaded
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Color.mSurface
|
||||
radius: scaledRadiusL
|
||||
visible: !visualizer.visible || visualizer.fragmentShader === ""
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Loading..."
|
||||
color: Color.mOnSurface
|
||||
font.pointSize: Math.round(Style.fontSizeM * widgetScale)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user