diff --git a/subwave_nowplaying.star b/subwave_nowplaying.star index 7abdbe1..651c1a2 100644 --- a/subwave_nowplaying.star +++ b/subwave_nowplaying.star @@ -91,11 +91,21 @@ COLOR_SCHEMES = { } DEFAULT_COLOR_SCHEME = "cyberpunk" # matches the station's own site theme -# How many seconds into a track's start, or before its end, the "static" -# overlay shows over the album art (a bundled animated GIF of sparse noise -# specks over a transparent background -- images/static.gif). Only used -# when the "Static overlay" schema field is enabled. -STATIC_OVERLAY_SECONDS = 5 +# How many seconds into a track's start, or before its reported end, the +# glitch overlay shows over the album art. Only used when the "Static +# overlay" schema field is enabled. +# +# These aren't symmetric on purpose: SUB/WAVE's reported `duration` is a +# track's full metadata length, but in practice the station appears to +# cut/crossfade to the next track a bit before that duration actually +# elapses (observed via the progress bar consistently stalling a few +# segments short of full, never reaching the end) -- so `remaining` was +# rarely if ever dropping below a short end-window before the subsonic_id +# changed out from under it. Widening the end window compensates for that +# observed early cutoff; the start window doesn't have the same problem +# (elapsed genuinely starts at 0) so it stays short. +STATIC_OVERLAY_START_SECONDS = 5 +STATIC_OVERLAY_END_SECONDS = 22 DEFAULT_STATIC_OVERLAY = "on" # How far in the album art zoom goes, relative to its fully-zoomed-out rest @@ -180,7 +190,7 @@ def main(config): show_static = ( static_overlay_enabled and progress != None and - (progress["elapsed"] < STATIC_OVERLAY_SECONDS or progress["remaining"] < STATIC_OVERLAY_SECONDS) + (progress["elapsed"] < STATIC_OVERLAY_START_SECONDS or progress["remaining"] < STATIC_OVERLAY_END_SECONDS) ) # The show/host and time/temp rows always render, even when empty, so @@ -384,14 +394,24 @@ GLITCH_STATE_POOL = [ ] # render.Sequence doesn't loop on its own (see _glitch_scanlines below), so -# to repeat the burst-then-pause pattern for the whole show_static window, -# the repeats have to be spelled out as one long children list up front -# rather than relying on any runtime looping. Rounds up so the window is -# always fully covered, even if that runs a little past -# STATIC_OVERLAY_SECONDS -- better than the jitter cutting out early. +# to repeat the burst-then-pause pattern, the repeats have to be spelled +# out as one long children list up front rather than relying on any +# runtime looping. +# +# Deliberately *not* sized against the full show_static window (which can +# now be up to STATIC_OVERLAY_END_SECONDS = 22s): each repeat adds several +# more uniquely-tinted/shifted frames for WebP to encode, and scaling that +# up to cover 22s of jitter pushed a real render past the 460KB device +# limit (measured 481KB). Scanlines and corner ticks (see _glitch_effect) +# are cheap, constant per-pixel layers that can cover the full window for +# free, but the hue-shifted bands don't need to keep jittering the whole +# time to read as "something's happening" -- GLITCH_ACTIVE_SECONDS caps +# how much of the window actually gets jitter, independent of how long +# the window itself is. +GLITCH_ACTIVE_SECONDS = 6 _GLITCH_CYCLE_TICKS = GLITCH_STATES_PER_CYCLE * GLITCH_HOLD_TICKS + GLITCH_PAUSE_TICKS _GLITCH_TICKS_PER_SECOND = 20 # 1000ms / 50ms-per-tick -GLITCH_REPEATS = int(STATIC_OVERLAY_SECONDS * _GLITCH_TICKS_PER_SECOND / _GLITCH_CYCLE_TICKS) + 1 +GLITCH_REPEATS = int(GLITCH_ACTIVE_SECONDS * _GLITCH_TICKS_PER_SECOND / _GLITCH_CYCLE_TICKS) + 1 def _glitch_states_for_cycle(cycle_index): # Rotate through GLITCH_STATE_POOL instead of slicing (which doesn't