From 97b2546fb0c45d9221680270f9ea31834ad570d7 Mon Sep 17 00:00:00 2001 From: jim kolpack Date: Sat, 10 Oct 2026 16:51:41 -0400 Subject: [PATCH] Let a show's own theme override the configured color scheme SUB/WAVE lets a show set its own color theme, which overrides the station's default while that show is on air -- the station's own web UI already does this (controller/src/routes/public.ts resolves it server-side: activeShow?.themeId || station default). That resolved value rides on /api/state's theme.active field, not /api/now-playing, so this adds a second fetch (_fetch_show_theme) rather than reading an existing response field. Theme ids there use hyphens ("classic-light"); this app's COLOR_SCHEMES keys use underscores ("classic_light") -- otherwise the same 8 names, confirmed against SUB/WAVE's own theme registry (press-run-plates.ts), so swapping the separator is enough to look it up directly. Falls back to the user's configured color_scheme on a fetch failure, a non-200 response, or an id this app doesn't recognize -- verified a real reachable server returns a clean 404 for an unsupported path (not a hard connection error), so that fallback path is exercised by real servers, not just a theoretical case. Verified against the live test station (currently "classic-light"): renders with its light cream background/dark text/red accent instead of the hardcoded cyberpunk default, confirming the override actually takes effect. --- subwave_nowplaying.star | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/subwave_nowplaying.star b/subwave_nowplaying.star index aa16110..7986320 100644 --- a/subwave_nowplaying.star +++ b/subwave_nowplaying.star @@ -196,6 +196,14 @@ def main(config): if not now["online"]: return render.Root(child = _with_background(_message_screen([now["station"], "offline"], colors), colors)) + # A show's own theme override (if any) wins over the user's configured + # color_scheme, mirroring what SUB/WAVE's own web UI does -- see + # _fetch_show_theme. Falls back to the configured scheme on a fetch + # failure or an id this app doesn't recognize, rather than erroring. + show_theme_id = _fetch_show_theme(station_url) + if show_theme_id != None and show_theme_id in COLOR_SCHEMES: + colors = COLOR_SCHEMES[show_theme_id] + art = _fetch_cover(station_url, now["subsonic_id"]) progress = _track_progress(now["subsonic_id"], now["duration"]) @@ -958,6 +966,28 @@ def _format_time_temp(clock, weather): return " ยท ".join(parts) +def _fetch_show_theme(station_url): + # SUB/WAVE lets a show override the station's default color theme + # (controller/src/routes/public.ts resolves this server-side already: + # activeShow?.themeId || station default). That resolved value rides + # on /api/state's theme.active, not /api/now-playing -- a separate + # fetch, not a field on the response this app already pulls. + # + # Theme ids there use hyphens (e.g. "classic-light"), this app's + # COLOR_SCHEMES keys use underscores ("classic_light") -- same 8 + # names otherwise (confirmed against SUB/WAVE's own theme registry), + # so swapping the separator is enough to look it up directly rather + # than needing an explicit id-mapping table. + rep = http.get(station_url + "/api/state", ttl_seconds = NOWPLAYING_TTL) + if rep.status_code != 200: + return None + + theme_id = (rep.json().get("theme", {}) or {}).get("active", "") + if not theme_id: + return None + + return theme_id.replace("-", "_") + def _fetch_cover(station_url, subsonic_id): if not subsonic_id: return None