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.
This commit is contained in:
poprhythm committed 2026-10-10 16:51:41 -04:00
1 parent c17dbb7807
commit 97b2546fb0
1 file changed
+30
+30
View File
@@ -196,6 +196,14 @@ def main(config):
if not now["online"]: if not now["online"]:
return render.Root(child = _with_background(_message_screen([now["station"], "offline"], colors), colors)) 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"]) art = _fetch_cover(station_url, now["subsonic_id"])
progress = _track_progress(now["subsonic_id"], now["duration"]) progress = _track_progress(now["subsonic_id"], now["duration"])
@@ -958,6 +966,28 @@ def _format_time_temp(clock, weather):
return " · ".join(parts) 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): def _fetch_cover(station_url, subsonic_id):
if not subsonic_id: if not subsonic_id:
return None return None
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.