aboutsummaryrefslogtreecommitdiffstats
path: root/deckit/server.py
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-09 19:08:51 +0100
committerDanilo M. <danix@danix.xyz>2026-11-09 19:08:51 +0100
commit15e384bc1d97c84df0545555bf4c298702c9eacb (patch)
treef386400b398ebf55f9c3f2d060642e9b01255a95 /deckit/server.py
parent4632e6183d38bfd239f066d7e9698f3d118a3f77 (diff)
downloaddeck-it-15e384bc1d97c84df0545555bf4c298702c9eacb.tar.gz
deck-it-15e384bc1d97c84df0545555bf4c298702c9eacb.zip
feat: card headers, music art/seek, clearer build card
Diffstat (limited to 'deckit/server.py')
-rw-r--r--deckit/server.py25
1 files changed, 24 insertions, 1 deletions
diff --git a/deckit/server.py b/deckit/server.py
index bddbb00..638322f 100644
--- a/deckit/server.py
+++ b/deckit/server.py
@@ -11,11 +11,12 @@ import mimetypes
import os
import secrets
import socketserver
+import subprocess
import threading
from http.cookies import CookieError, SimpleCookie
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
-from urllib.parse import parse_qs, urlsplit
+from urllib.parse import parse_qs, unquote, urlparse, urlsplit
from . import config, module, theme
@@ -39,6 +40,25 @@ def token_path() -> Path:
return config.user_config_path().parent / "token"
+def _run(cmd, timeout=2):
+ try:
+ return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout).stdout.strip()
+ except (OSError, subprocess.TimeoutExpired):
+ return ""
+
+
+def art():
+ """The current track's cover art, if the player exposes a local file."""
+ url = _run(["playerctl", "metadata", "mpris:artUrl"])
+ if not url.startswith("file://"):
+ return None
+ path = Path(unquote(urlparse(url).path))
+ try:
+ return path.read_bytes(), mimetypes.guess_type(path)[0] or "image/png"
+ except OSError:
+ return None
+
+
def load_token() -> str:
"""A per-machine secret the tablet's browser holds as a cookie."""
path = token_path()
@@ -98,6 +118,9 @@ class Handler(BaseHTTPRequestHandler):
if not self._authed():
return self._send(401)
parts = path.strip("/").split("/")
+ if len(parts) == 2 and parts[1] == "art":
+ image = art()
+ return self._send(200, image[0], image[1], cache=True) if image else self._send(404)
if len(parts) == 2 and parts[1] == "modules":
return self._json(REGISTRY.names())
if len(parts) == 2: