Replace QML CAVA polling with SSE server for smooth bars
DataSource fork+exec was limited to ~1fps. Now cava pipes into a Python SSE server (port 5555) and the HTML connects directly via EventSource, getting updates at up to 60fps without QML overhead. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5876701a64
commit
39e7c07309
4 changed files with 59 additions and 22 deletions
45
plugin/contents/ui/cava-server.py
Normal file
45
plugin/contents/ui/cava-server.py
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Reads CAVA ASCII output from stdin and streams it to the wallpaper
|
||||||
|
via Server-Sent Events on http://127.0.0.1:5555.
|
||||||
|
Run as: cava -p cava.conf | python3 cava-server.py
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||||
|
|
||||||
|
latest = ""
|
||||||
|
lock = threading.Lock()
|
||||||
|
|
||||||
|
class Handler(BaseHTTPRequestHandler):
|
||||||
|
def do_GET(self):
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-Type", "text/event-stream")
|
||||||
|
self.send_header("Cache-Control", "no-cache")
|
||||||
|
self.send_header("Access-Control-Allow-Origin", "*")
|
||||||
|
self.end_headers()
|
||||||
|
last = None
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
with lock:
|
||||||
|
cur = latest
|
||||||
|
if cur and cur != last:
|
||||||
|
self.wfile.write(f"data: {cur}\n\n".encode())
|
||||||
|
self.wfile.flush()
|
||||||
|
last = cur
|
||||||
|
time.sleep(0.016) # cap at ~60fps
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def log_message(self, *args):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def serve():
|
||||||
|
HTTPServer(("127.0.0.1", 5555), Handler).serve_forever()
|
||||||
|
|
||||||
|
threading.Thread(target=serve, daemon=True).start()
|
||||||
|
|
||||||
|
for line in sys.stdin:
|
||||||
|
with lock:
|
||||||
|
latest = line.strip()
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Kill any previous instance tied to this config
|
|
||||||
pkill -f "cava -p.*skeledance" 2>/dev/null
|
pkill -f "cava -p.*skeledance" 2>/dev/null
|
||||||
|
pkill -f "cava-server.py" 2>/dev/null
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
|
|
||||||
CONF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/cava.conf"
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
cava -p "$CONF" | while IFS= read -r line; do
|
cava -p "$DIR/cava.conf" | python3 "$DIR/cava-server.py"
|
||||||
printf '%s\n' "$line" > /tmp/skeledance_bars
|
|
||||||
done
|
|
||||||
|
|
|
||||||
|
|
@ -886,7 +886,7 @@ for (let i = 0; i < VU_COUNT; i++) {
|
||||||
vuBars.push(bar);
|
vuBars.push(bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by QML with semicolon-separated CAVA values (0–100 per bar)
|
// Called with semicolon-separated CAVA values (0–100 per bar)
|
||||||
function updateBars(raw) {
|
function updateBars(raw) {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying) return;
|
||||||
const vals = raw.split(';');
|
const vals = raw.split(';');
|
||||||
|
|
@ -898,6 +898,13 @@ function updateBars(raw) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Connect to CAVA SSE server (started by cava-start.sh via QML)
|
||||||
|
(function connectCava() {
|
||||||
|
const sse = new EventSource('http://127.0.0.1:5555');
|
||||||
|
sse.onmessage = e => { if (e.data) updateBars(e.data); };
|
||||||
|
sse.onerror = () => { sse.close(); setTimeout(connectCava, 3000); };
|
||||||
|
})();
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
FLOATING MUSIC NOTES
|
FLOATING MUSIC NOTES
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ WallpaperItem {
|
||||||
settings {
|
settings {
|
||||||
javascriptEnabled: true
|
javascriptEnabled: true
|
||||||
localContentCanAccessFileUrls: true
|
localContentCanAccessFileUrls: true
|
||||||
|
localContentCanAccessRemoteUrls: true
|
||||||
localStorageEnabled: false
|
localStorageEnabled: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,18 +52,4 @@ WallpaperItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Polls CAVA bars at ~60fps
|
|
||||||
Plasma5Support.DataSource {
|
|
||||||
id: cavaSource
|
|
||||||
engine: "executable"
|
|
||||||
connectedSources: ["cat /tmp/skeledance_bars 2>/dev/null || echo ''"]
|
|
||||||
interval: 80
|
|
||||||
|
|
||||||
onNewData: function(sourceName, data) {
|
|
||||||
var raw = data["stdout"].trim()
|
|
||||||
if (raw !== "") {
|
|
||||||
webView.runJavaScript("updateBars(" + JSON.stringify(raw) + ")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue