""" Applet: SUB/WAVE Now Playing Summary: Shows what's playing on a SUB/WAVE station Description: Configure with your SUB/WAVE (github.com/perminder-klair/subwave) station's base URL to display the current track, artist, and album art. Author: poprhythm """ load("render.star", "render") load("schema.star", "schema") load("http.star", "http") DEFAULT_STATION_URL = "" NOWPLAYING_TTL = 20 COVER_TTL = 300 def main(config): station_url = config.get("station_url", DEFAULT_STATION_URL) if station_url: station_url = station_url.rstrip("/") if not station_url: return render.Root(child = _message_screen(["Set station URL", "in app settings"])) now = _fetch_now_playing(station_url) if now == None: return render.Root(child = _message_screen(["Can't reach", "station"])) if not now["online"]: return render.Root(child = _message_screen([now["station"], "offline"])) art = _fetch_cover(station_url, now["subsonic_id"]) text_column = render.Column( children = [ render.Marquee(width = 32, child = render.Text(now["title"])), render.Marquee(width = 32, child = render.Text(now["artist"], color = "#aaaaaa")), render.Marquee(width = 32, child = render.Text(now["station"], font = "tom-thumb", color = "#666666")), ], ) if art: content = render.Row(children = [render.Image(src = art, width = 32, height = 32), text_column]) else: content = render.Column( main_align = "center", cross_align = "center", expanded = True, children = [ render.Marquee(width = 64, child = render.Text(now["title"])), render.Marquee(width = 64, child = render.Text(now["artist"], color = "#aaaaaa")), ], ) return render.Root(child = content) def _message_screen(lines): return render.Column( main_align = "center", cross_align = "center", expanded = True, children = [render.Text(line, font = "tom-thumb") for line in lines], ) def _fetch_now_playing(station_url): rep = http.get(station_url + "/api/now-playing", ttl_seconds = NOWPLAYING_TTL) if rep.status_code != 200: return None data = rep.json() np = data.get("nowPlaying", {}) dj = data.get("dj", {}) return { "title": np.get("title", "Unknown title"), "artist": np.get("artist", "Unknown artist"), "subsonic_id": np.get("subsonic_id", ""), "station": dj.get("station", "SUB/WAVE"), "online": bool(data.get("streamOnline", False)), } def _fetch_cover(station_url, subsonic_id): if not subsonic_id: return None rep = http.get(station_url + "/api/cover/" + subsonic_id, ttl_seconds = COVER_TTL) if rep.status_code != 200: return None return rep.body() def get_schema(): return schema.Schema( version = "1", fields = [ schema.Text( id = "station_url", name = "Station URL", desc = "Base URL of your SUB/WAVE station, e.g. https://radio.example.com", icon = "server", default = DEFAULT_STATION_URL, ), ], )