diff --git a/plugins.json b/plugins.json index f818927f..35c36949 100644 --- a/plugins.json +++ b/plugins.json @@ -101,7 +101,7 @@ "last_updated": "2026-09-02", "verified": true, "screenshot": "", - "latest_version": "1.29.1" + "latest_version": "1.29.2" }, { "id": "calendar", @@ -240,7 +240,7 @@ "last_updated": "2026-09-02", "verified": true, "screenshot": "", - "latest_version": "3.4.1" + "latest_version": "3.4.2" }, { "id": "geochron", @@ -335,7 +335,7 @@ "last_updated": "2026-09-02", "verified": true, "screenshot": "", - "latest_version": "1.25.1", + "latest_version": "1.25.2", "icon": "fas fa-hockey-puck" }, { @@ -359,7 +359,7 @@ "last_updated": "2026-09-02", "verified": true, "screenshot": "", - "latest_version": "1.24.1", + "latest_version": "1.24.2", "icon": "fas fa-baseball-ball" }, { @@ -760,7 +760,7 @@ "last_updated": "2026-09-02", "verified": true, "screenshot": "", - "latest_version": "2.24.1" + "latest_version": "2.24.2" }, { "id": "static-image", @@ -1048,7 +1048,7 @@ "downloads": 0, "verified": true, "screenshot": "", - "latest_version": "1.22.1", + "latest_version": "1.22.2", "last_updated": "2026-09-02" }, { @@ -1095,7 +1095,7 @@ "last_updated": "2026-09-02", "verified": true, "screenshot": "", - "latest_version": "1.21.1" + "latest_version": "1.21.2" }, { "id": "jellyfin-now-playing", diff --git a/plugins/afl-scoreboard/game_renderer.py b/plugins/afl-scoreboard/game_renderer.py index f2b1228d..ac08bdf8 100644 --- a/plugins/afl-scoreboard/game_renderer.py +++ b/plugins/afl-scoreboard/game_renderer.py @@ -146,7 +146,7 @@ def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]: fonts["score"] = self._load_custom_font(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font(detail_config, default_size=6, default_font='4x6-font.ttf', element_key='detail_text') fonts["odds"] = self._load_custom_font(odds_config, default_size=6, default_font='4x6-font.ttf', element_key='odds_text') fonts["rank"] = self._load_custom_font(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/afl-scoreboard/manifest.json b/plugins/afl-scoreboard/manifest.json index 63636dcb..47ffc0ea 100644 --- a/plugins/afl-scoreboard/manifest.json +++ b/plugins/afl-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "afl-scoreboard", "name": "AFL Scoreboard", - "version": "1.22.1", + "version": "1.22.2", "author": "ChuckBuilds", "description": "Live, recent, and upcoming AFL (Australian Football League) games with real-time scores and game status.", "category": "sports", @@ -18,6 +18,13 @@ "afl_upcoming" ], "versions": [ + { + "version": "1.22.2", + "released": "2026-09-02", + "ledmatrix_min_version": "3.3.0", + "notes": "Render the font the settings page advertises. Each text element's schema names a default font, but several elements never passed it to the loader, so the loader used its own fallback instead: the status text -- and on hockey the detail and odds text too -- advertised the 4x6 font while actually drawing in PressStart2P. Choosing the font the picker already showed as active therefore changed the display, which looked like the picker was broken. Each element now renders what its schema declares. This affects panels 128 pixels wide and narrower, on upcoming screens only; wider panels draw that header in the time font and are unchanged. It also fixes a knock-on problem: \"Next Game\" needed 72px in the wrong font and had to shorten to \"Next\" on a 64px panel, where it now fits whole at 41px.", + "changelog": "Documentation only, no behaviour change. Rewrites the README around real rendered screenshots of the 2026 finals series and documents every configuration option. Writes down the game-selection logic in full: the three selection paths, and that upcoming_games_to_show/recent_games_to_show mean a per-team budget under show_favorite_teams_only but a total otherwise. Records four verified dead ends so they stop costing people time: show_odds is a no-op for AFL because ESPN publishes no odds block for the league (though it still issues one odds request per selected game), show_ranking has no poll to draw, dynamic_duration.min_duration_seconds is never read, and background_service.max_workers is ignored in favour of a single worker. Also corrects README defaults that had drifted from the schema (show_favorite_teams_only, display_duration, show_odds)." + }, { "version": "1.22.1", "released": "2026-09-02", diff --git a/plugins/afl-scoreboard/sports.py b/plugins/afl-scoreboard/sports.py index bfa934e0..1cc15915 100644 --- a/plugins/afl-scoreboard/sports.py +++ b/plugins/afl-scoreboard/sports.py @@ -867,7 +867,7 @@ def _load_fonts(self): fonts["score"] = self._load_custom_font_from_element_config(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font_from_element_config(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font_from_element_config(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font_from_element_config(detail_config, default_size=6, element_key='detail_text', default_font='4x6-font.ttf') fonts["odds"] = self._load_custom_font_from_element_config(odds_config, default_size=6, element_key='odds_text', default_font='4x6-font.ttf') fonts["rank"] = self._load_custom_font_from_element_config(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/baseball-scoreboard/game_renderer.py b/plugins/baseball-scoreboard/game_renderer.py index 2720aa56..f56a1e39 100644 --- a/plugins/baseball-scoreboard/game_renderer.py +++ b/plugins/baseball-scoreboard/game_renderer.py @@ -153,7 +153,7 @@ def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]: fonts["score"] = self._load_custom_font(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text', default_font='PressStart2P-Regular.ttf') fonts["detail"] = self._load_custom_font(detail_config, default_size=6, default_font='4x6-font.ttf', element_key='detail_text') fonts["odds"] = self._load_custom_font(odds_config, default_size=6, default_font='4x6-font.ttf', element_key='odds_text') fonts["rank"] = self._load_custom_font(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/baseball-scoreboard/sports.py b/plugins/baseball-scoreboard/sports.py index d68528b7..c2ff8bf6 100644 --- a/plugins/baseball-scoreboard/sports.py +++ b/plugins/baseball-scoreboard/sports.py @@ -809,7 +809,7 @@ def _load_fonts(self): fonts["score"] = self._load_custom_font_from_element_config(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font_from_element_config(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font_from_element_config(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text', default_font='PressStart2P-Regular.ttf') fonts["detail"] = self._load_custom_font_from_element_config(detail_config, default_size=6, element_key='detail_text', default_font='4x6-font.ttf') fonts["odds"] = self._load_custom_font_from_element_config(odds_config, default_size=6, element_key='odds_text', default_font='4x6-font.ttf') fonts["rank"] = self._load_custom_font_from_element_config(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/basketball-scoreboard/game_renderer.py b/plugins/basketball-scoreboard/game_renderer.py index 8dc0dbef..ae9d6d11 100644 --- a/plugins/basketball-scoreboard/game_renderer.py +++ b/plugins/basketball-scoreboard/game_renderer.py @@ -174,7 +174,7 @@ def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]: fonts["score"] = self._load_custom_font(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font(detail_config, default_size=6, default_font='4x6-font.ttf', element_key='detail_text') fonts["odds"] = self._load_custom_font(odds_config, default_size=6, default_font='4x6-font.ttf', element_key='odds_text') fonts["rank"] = self._load_custom_font(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/basketball-scoreboard/manifest.json b/plugins/basketball-scoreboard/manifest.json index 151dec6d..fa6a6f4e 100644 --- a/plugins/basketball-scoreboard/manifest.json +++ b/plugins/basketball-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "basketball-scoreboard", "name": "Basketball Scoreboard", - "version": "1.29.1", + "version": "1.29.2", "update_interval": 60, "description": "Live, recent, and upcoming basketball games across NBA, NCAA Men's, NCAA Women's, and WNBA with real-time scores, schedules, and March Madness tournament support", "author": "ChuckBuilds", @@ -19,6 +19,13 @@ "branch": "main", "plugin_path": "plugins/basketball-scoreboard", "versions": [ + { + "version": "1.29.2", + "released": "2026-09-02", + "ledmatrix_min_version": "3.3.0", + "notes": "Render the font the settings page advertises. Each text element's schema names a default font, but several elements never passed it to the loader, so the loader used its own fallback instead: the status text -- and on hockey the detail and odds text too -- advertised the 4x6 font while actually drawing in PressStart2P. Choosing the font the picker already showed as active therefore changed the display, which looked like the picker was broken. Each element now renders what its schema declares. This affects panels 128 pixels wide and narrower, on upcoming screens only; wider panels draw that header in the time font and are unchanged. It also fixes a knock-on problem: \"Next Game\" needed 72px in the wrong font and had to shorten to \"Next\" on a 64px panel, where it now fits whole at 41px.", + "changelog": "Retry a team logo whose previous download failed, instead of showing a grey box forever. A failed download is cached by the core as a placeholder wearing the real logo's filename; the logo loader scans filename variations, found that stub, and so never called the downloader again. The loader now skips a placeholder that is stale enough to be worth retrying and lets the download run, which also picks up stubs already on disk. The retry is rate-limited by the core (6h), so this does not trade a permanent grey box for a request every frame. Needs a core carrying src.logo_downloader.is_placeholder_logo; against an older core the check is skipped and behaviour is unchanged. Ported byte-identically across every sports lineage." + }, { "version": "1.29.1", "released": "2026-09-02", diff --git a/plugins/basketball-scoreboard/sports.py b/plugins/basketball-scoreboard/sports.py index e6c18873..f404b87e 100644 --- a/plugins/basketball-scoreboard/sports.py +++ b/plugins/basketball-scoreboard/sports.py @@ -670,7 +670,7 @@ def _load_fonts(self): fonts["score"] = self._load_custom_font_from_element_config(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font_from_element_config(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font_from_element_config(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font_from_element_config(detail_config, default_size=6, default_font='4x6-font.ttf', element_key='detail_text') fonts["odds"] = self._load_custom_font_from_element_config(odds_config, default_size=6, default_font='4x6-font.ttf', element_key='odds_text') fonts["rank"] = self._load_custom_font_from_element_config(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/football-scoreboard/game_renderer.py b/plugins/football-scoreboard/game_renderer.py index 3dbd343b..705b701e 100644 --- a/plugins/football-scoreboard/game_renderer.py +++ b/plugins/football-scoreboard/game_renderer.py @@ -474,7 +474,7 @@ def _load_fonts(self) -> Dict[str, Union[ImageFont.FreeTypeFont, Any]]: fonts["team"] = self._load_custom_font( team_config, default_size=team_size, element_key='team_name') fonts["status"] = self._load_custom_font( - status_config, default_size=status_size, element_key='status_text') + status_config, default_size=status_size, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font( detail_config, default_size=self._detail_font_size(), element_key='detail_text', @@ -900,7 +900,7 @@ def render_game_card( 'score': ('PressStart2P-Regular.ttf', 10), 'time': ('PressStart2P-Regular.ttf', 8), 'team': ('PressStart2P-Regular.ttf', 8), - 'status': ('PressStart2P-Regular.ttf', 6), + 'status': ('4x6-font.ttf', 6), 'detail': ('4x6-font.ttf', 6), # Same default as detail: odds rendered with the detail font until # this setting existed, and the default must not change that. diff --git a/plugins/football-scoreboard/manifest.json b/plugins/football-scoreboard/manifest.json index 2d928979..fda414f0 100644 --- a/plugins/football-scoreboard/manifest.json +++ b/plugins/football-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "football-scoreboard", "name": "Football Scoreboard", - "version": "3.4.1", + "version": "3.4.2", "update_interval": 60, "author": "ChuckBuilds", "class_name": "FootballScoreboardPlugin", @@ -25,6 +25,13 @@ "ncaa_fb_live" ], "versions": [ + { + "version": "3.4.2", + "released": "2026-09-02", + "ledmatrix_min_version": "3.3.0", + "notes": "Render the font the settings page advertises. Each text element's schema names a default font, but several elements never passed it to the loader, so the loader used its own fallback instead: the status text -- and on hockey the detail and odds text too -- advertised the 4x6 font while actually drawing in PressStart2P. Choosing the font the picker already showed as active therefore changed the display, which looked like the picker was broken. Each element now renders what its schema declares. This affects panels 128 pixels wide and narrower, on upcoming screens only; wider panels draw that header in the time font and are unchanged. It also fixes a knock-on problem: \"Next Game\" needed 72px in the wrong font and had to shorten to \"Next\" on a 64px panel, where it now fits whole at 41px.", + "changelog": "Retry a team logo whose previous download failed, instead of showing a grey box forever. A failed download is cached by the core as a placeholder wearing the real logo's filename; the logo loader scans filename variations, found that stub, and so never called the downloader again. The loader now skips a placeholder that is stale enough to be worth retrying and lets the download run, which also picks up stubs already on disk. The retry is rate-limited by the core (6h), so this does not trade a permanent grey box for a request every frame. Needs a core carrying src.logo_downloader.is_placeholder_logo; against an older core the check is skipped and behaviour is unchanged. Ported byte-identically across every sports lineage." + }, { "version": "3.4.1", "released": "2026-09-02", diff --git a/plugins/football-scoreboard/sports.py b/plugins/football-scoreboard/sports.py index 7cbcac10..b9d66d95 100644 --- a/plugins/football-scoreboard/sports.py +++ b/plugins/football-scoreboard/sports.py @@ -821,7 +821,7 @@ def _load_fonts(self): fonts["score"] = self._load_custom_font_from_element_config(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font_from_element_config(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font_from_element_config(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font_from_element_config(detail_config, default_size=6, element_key='detail_text', default_font='4x6-font.ttf') fonts["odds"] = self._load_custom_font_from_element_config(odds_config, default_size=6, element_key='odds_text', default_font='4x6-font.ttf') fonts["rank"] = self._load_custom_font_from_element_config(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/football-scoreboard/test_fonts_render_crisply.py b/plugins/football-scoreboard/test_fonts_render_crisply.py index 78d117f5..5e2be83c 100644 --- a/plugins/football-scoreboard/test_fonts_render_crisply.py +++ b/plugins/football-scoreboard/test_fonts_render_crisply.py @@ -123,13 +123,22 @@ def main(): # Loading "without raising" proves nothing on its own: _load_fonts wraps # the whole block in try/except and drops to hardcoded emergency defaults, # which are crisp as well -- so a broken call in the config path is - # invisible unless the two paths can be told apart. They can: the config - # path gives status PressStart2P (the loader's own default face), while - # the emergency fallback hardcodes 4x6-font for it. - status_face = os.path.basename(str(getattr(local.get("status"), "path", ""))) + # invisible unless the two paths can be told apart. + # + # The status FACE used to be that discriminator: the config path gave + # PressStart2P (the loader's own fallback face) while the emergency block + # hardcodes 4x6-font. That stopped discriminating when the config path was + # corrected to pass the font its schema declares, which is 4x6-font -- both + # paths now agree on status, so the old check could not tell them apart. + # + # The odds slot replaces it: only the config path builds one. The emergency + # block predates the setting and never gained it, which is safe at runtime + # (_draw_dynamic_odds falls back to fonts["detail"]) and is exactly the + # asymmetry this check needs. If the emergency block ever gains an odds + # entry, pick another: rank is 10px on the config path and 8px here. check("the no-resolver path used the config loader, not the emergency " - "fallback (status face %s)" % (status_face or "none"), - status_face == "PressStart2P-Regular.ttf") + "fallback (odds slot %s)" % ("present" if "odds" in local else "absent"), + "odds" in local) for key, font in sorted(local.items()): size = getattr(font, "size", None) if size: diff --git a/plugins/hockey-scoreboard/game_renderer.py b/plugins/hockey-scoreboard/game_renderer.py index ca633665..3bb28460 100644 --- a/plugins/hockey-scoreboard/game_renderer.py +++ b/plugins/hockey-scoreboard/game_renderer.py @@ -150,9 +150,9 @@ def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]: fonts["score"] = self._load_custom_font(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text') - fonts["detail"] = self._load_custom_font(detail_config, default_size=6, element_key='detail_text') - fonts["odds"] = self._load_custom_font(odds_config, default_size=6, element_key='odds_text') + fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') + fonts["detail"] = self._load_custom_font(detail_config, default_size=6, element_key='detail_text', default_font='4x6-font.ttf') + fonts["odds"] = self._load_custom_font(odds_config, default_size=6, element_key='odds_text', default_font='4x6-font.ttf') fonts["rank"] = self._load_custom_font(rank_config, default_size=10, element_key='rank_text') self.logger.debug("Successfully loaded fonts from config") except Exception: @@ -204,9 +204,9 @@ def _resolve_font_size(self, element_config, element_key, default_size, font_nam default_size, font_name, self._FONT_NAME_ALIASES, self._FONT_PIXEL_GRID) - def _load_custom_font(self, element_config: Dict[str, Any], default_size: int = 8, element_key=None) -> ImageFont.FreeTypeFont: + def _load_custom_font(self, element_config: Dict[str, Any], default_size: int = 8, default_font: str = 'PressStart2P-Regular.ttf', element_key=None) -> ImageFont.FreeTypeFont: """Load a custom font from an element configuration dictionary.""" - font_name = element_config.get('font', 'PressStart2P-Regular.ttf') + font_name = element_config.get('font', default_font) # Resolve a family alias to its filename BEFORE the path is built. # The grid table understands aliases, so a configured # "four_by_six" was sized on the 4x6 grid (7px) while the path diff --git a/plugins/hockey-scoreboard/manifest.json b/plugins/hockey-scoreboard/manifest.json index a3f6894a..c99184d3 100644 --- a/plugins/hockey-scoreboard/manifest.json +++ b/plugins/hockey-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "hockey-scoreboard", "name": "Hockey Scoreboard", - "version": "1.25.1", + "version": "1.25.2", "author": "ChuckBuilds", "description": "Live, recent, and upcoming hockey games across NHL, NCAA Men's, and NCAA Women's hockey with real-time scores and schedules", "homepage": "https://github.com/ChuckBuilds/ledmatrix-plugins/tree/main/plugins/hockey-scoreboard", @@ -54,6 +54,13 @@ } ], "versions": [ + { + "version": "1.25.2", + "released": "2026-09-02", + "ledmatrix_min_version": "3.3.0", + "notes": "Render the font the settings page advertises. Each text element's schema names a default font, but several elements never passed it to the loader, so the loader used its own fallback instead: the status text -- and on hockey the detail and odds text too -- advertised the 4x6 font while actually drawing in PressStart2P. Choosing the font the picker already showed as active therefore changed the display, which looked like the picker was broken. Each element now renders what its schema declares. This affects panels 128 pixels wide and narrower, on upcoming screens only; wider panels draw that header in the time font and are unchanged. It also fixes a knock-on problem: \"Next Game\" needed 72px in the wrong font and had to shorten to \"Next\" on a 64px panel, where it now fits whole at 41px.", + "changelog": "Retry a team logo whose previous download failed, instead of showing a grey box forever. A failed download is cached by the core as a placeholder wearing the real logo's filename; the logo loader scans filename variations, found that stub, and so never called the downloader again. The loader now skips a placeholder that is stale enough to be worth retrying and lets the download run, which also picks up stubs already on disk. The retry is rate-limited by the core (6h), so this does not trade a permanent grey box for a request every frame. Needs a core carrying src.logo_downloader.is_placeholder_logo; against an older core the check is skipped and behaviour is unchanged. Ported byte-identically across every sports lineage." + }, { "version": "1.25.1", "released": "2026-09-02", diff --git a/plugins/hockey-scoreboard/sports.py b/plugins/hockey-scoreboard/sports.py index 60577dcf..10b05e99 100644 --- a/plugins/hockey-scoreboard/sports.py +++ b/plugins/hockey-scoreboard/sports.py @@ -742,7 +742,7 @@ def _load_fonts(self): fonts["score"] = self._load_custom_font_from_element_config(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font_from_element_config(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font_from_element_config(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font_from_element_config( detail_config, default_size=6, default_font="4x6-font.ttf" , element_key='detail_text') diff --git a/plugins/lacrosse-scoreboard/game_renderer.py b/plugins/lacrosse-scoreboard/game_renderer.py index 454de92c..b5dad5bd 100644 --- a/plugins/lacrosse-scoreboard/game_renderer.py +++ b/plugins/lacrosse-scoreboard/game_renderer.py @@ -148,7 +148,7 @@ def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]: fonts["score"] = self._load_custom_font(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font(detail_config, default_size=6, default_font='4x6-font.ttf', element_key='detail_text') fonts["odds"] = self._load_custom_font(odds_config, default_size=6, default_font='4x6-font.ttf', element_key='odds_text') fonts["rank"] = self._load_custom_font(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/lacrosse-scoreboard/manifest.json b/plugins/lacrosse-scoreboard/manifest.json index a115a0de..9b29b352 100644 --- a/plugins/lacrosse-scoreboard/manifest.json +++ b/plugins/lacrosse-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "lacrosse-scoreboard", "name": "Lacrosse Scoreboard", - "version": "1.24.1", + "version": "1.24.2", "author": "ChuckBuilds", "description": "Live, recent, and upcoming NCAA men's and women's lacrosse games with real-time scores and schedules", "homepage": "https://github.com/ChuckBuilds/ledmatrix-plugins/tree/main/plugins/lacrosse-scoreboard", @@ -50,6 +50,13 @@ } ], "versions": [ + { + "version": "1.24.2", + "released": "2026-09-02", + "ledmatrix_min_version": "3.3.0", + "notes": "Render the font the settings page advertises. Each text element's schema names a default font, but several elements never passed it to the loader, so the loader used its own fallback instead: the status text -- and on hockey the detail and odds text too -- advertised the 4x6 font while actually drawing in PressStart2P. Choosing the font the picker already showed as active therefore changed the display, which looked like the picker was broken. Each element now renders what its schema declares. This affects panels 128 pixels wide and narrower, on upcoming screens only; wider panels draw that header in the time font and are unchanged. It also fixes a knock-on problem: \"Next Game\" needed 72px in the wrong font and had to shorten to \"Next\" on a 64px panel, where it now fits whole at 41px.", + "changelog": "Retry a team logo whose previous download failed, instead of showing a grey box forever. A failed download is cached by the core as a placeholder wearing the real logo's filename; the logo loader scans filename variations, found that stub, and so never called the downloader again. The loader now skips a placeholder that is stale enough to be worth retrying and lets the download run, which also picks up stubs already on disk. The retry is rate-limited by the core (6h), so this does not trade a permanent grey box for a request every frame. Needs a core carrying src.logo_downloader.is_placeholder_logo; against an older core the check is skipped and behaviour is unchanged. Ported byte-identically across every sports lineage." + }, { "version": "1.24.1", "released": "2026-09-02", diff --git a/plugins/lacrosse-scoreboard/sports.py b/plugins/lacrosse-scoreboard/sports.py index 14ff178e..e5018304 100644 --- a/plugins/lacrosse-scoreboard/sports.py +++ b/plugins/lacrosse-scoreboard/sports.py @@ -743,7 +743,7 @@ def _load_fonts(self): fonts["score"] = self._load_custom_font_from_element_config(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font_from_element_config(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font_from_element_config(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font_from_element_config( detail_config, default_size=6, default_font="4x6-font.ttf" , element_key='detail_text') diff --git a/plugins/nrl-scoreboard/game_renderer.py b/plugins/nrl-scoreboard/game_renderer.py index 087ef3ec..ab3fa5b7 100644 --- a/plugins/nrl-scoreboard/game_renderer.py +++ b/plugins/nrl-scoreboard/game_renderer.py @@ -138,7 +138,7 @@ def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]: fonts["score"] = self._load_custom_font(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font(detail_config, default_size=6, default_font='4x6-font.ttf', element_key='detail_text') fonts["odds"] = self._load_custom_font(odds_config, default_size=6, default_font='4x6-font.ttf', element_key='odds_text') fonts["rank"] = self._load_custom_font(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/nrl-scoreboard/manifest.json b/plugins/nrl-scoreboard/manifest.json index a2b2a297..5e1cfd55 100644 --- a/plugins/nrl-scoreboard/manifest.json +++ b/plugins/nrl-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "nrl-scoreboard", "name": "NRL Scoreboard", - "version": "1.21.1", + "version": "1.21.2", "author": "ChuckBuilds", "description": "Live, recent, and upcoming NRL (National Rugby League) games with real-time scores and game status.", "category": "sports", @@ -18,6 +18,13 @@ "nrl_upcoming" ], "versions": [ + { + "version": "1.21.2", + "released": "2026-09-02", + "ledmatrix_min_version": "3.3.0", + "notes": "Render the font the settings page advertises. Each text element's schema names a default font, but several elements never passed it to the loader, so the loader used its own fallback instead: the status text -- and on hockey the detail and odds text too -- advertised the 4x6 font while actually drawing in PressStart2P. Choosing the font the picker already showed as active therefore changed the display, which looked like the picker was broken. Each element now renders what its schema declares. This affects panels 128 pixels wide and narrower, on upcoming screens only; wider panels draw that header in the time font and are unchanged. It also fixes a knock-on problem: \"Next Game\" needed 72px in the wrong font and had to shorten to \"Next\" on a 64px panel, where it now fits whole at 41px.", + "changelog": "Retry a team logo whose previous download failed, instead of showing a grey box forever. A failed download is cached by the core as a placeholder wearing the real logo's filename; the logo loader scans filename variations, found that stub, and so never called the downloader again. The loader now skips a placeholder that is stale enough to be worth retrying and lets the download run, which also picks up stubs already on disk. The retry is rate-limited by the core (6h), so this does not trade a permanent grey box for a request every frame. Needs a core carrying src.logo_downloader.is_placeholder_logo; against an older core the check is skipped and behaviour is unchanged. Ported byte-identically across every sports lineage." + }, { "version": "1.21.1", "released": "2026-09-02", diff --git a/plugins/nrl-scoreboard/sports.py b/plugins/nrl-scoreboard/sports.py index a4e9bc18..2a3bb456 100644 --- a/plugins/nrl-scoreboard/sports.py +++ b/plugins/nrl-scoreboard/sports.py @@ -887,7 +887,7 @@ def _load_fonts(self): fonts["score"] = self._load_custom_font_from_element_config(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font_from_element_config(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font_from_element_config(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font_from_element_config(detail_config, default_size=6, element_key='detail_text', default_font='4x6-font.ttf') fonts["odds"] = self._load_custom_font_from_element_config(odds_config, default_size=6, element_key='odds_text', default_font='4x6-font.ttf') fonts["rank"] = self._load_custom_font_from_element_config(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/soccer-scoreboard/game_renderer.py b/plugins/soccer-scoreboard/game_renderer.py index b9e17205..da663cb4 100644 --- a/plugins/soccer-scoreboard/game_renderer.py +++ b/plugins/soccer-scoreboard/game_renderer.py @@ -138,7 +138,7 @@ def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]: fonts["score"] = self._load_custom_font(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font(detail_config, default_size=6, default_font='4x6-font.ttf', element_key='detail_text') fonts["odds"] = self._load_custom_font(odds_config, default_size=6, default_font='4x6-font.ttf', element_key='odds_text') fonts["rank"] = self._load_custom_font(rank_config, default_size=10, element_key='rank_text') diff --git a/plugins/soccer-scoreboard/manifest.json b/plugins/soccer-scoreboard/manifest.json index 6977cc39..224fadd0 100644 --- a/plugins/soccer-scoreboard/manifest.json +++ b/plugins/soccer-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "soccer-scoreboard", "name": "Soccer Scoreboard", - "version": "2.24.1", + "version": "2.24.2", "author": "ChuckBuilds", "description": "Live, recent, and upcoming soccer games across multiple leagues including Premier League, La Liga, Bundesliga, Serie A, Ligue 1, MLS, Liga Portugal, Champions League, Europa League, and FIFA World Cup", "category": "sports", @@ -26,6 +26,13 @@ "soccer_upcoming" ], "versions": [ + { + "version": "2.24.2", + "released": "2026-09-02", + "ledmatrix_min_version": "3.3.0", + "notes": "Render the font the settings page advertises. Each text element's schema names a default font, but several elements never passed it to the loader, so the loader used its own fallback instead: the status text -- and on hockey the detail and odds text too -- advertised the 4x6 font while actually drawing in PressStart2P. Choosing the font the picker already showed as active therefore changed the display, which looked like the picker was broken. Each element now renders what its schema declares. This affects panels 128 pixels wide and narrower, on upcoming screens only; wider panels draw that header in the time font and are unchanged. It also fixes a knock-on problem: \"Next Game\" needed 72px in the wrong font and had to shorten to \"Next\" on a 64px panel, where it now fits whole at 41px.", + "changelog": "Retry a team logo whose previous download failed, instead of showing a grey box forever. A failed download is cached by the core as a placeholder wearing the real logo's filename; the logo loader scans filename variations, found that stub, and so never called the downloader again. The loader now skips a placeholder that is stale enough to be worth retrying and lets the download run, which also picks up stubs already on disk. The retry is rate-limited by the core (6h), so this does not trade a permanent grey box for a request every frame. Needs a core carrying src.logo_downloader.is_placeholder_logo; against an older core the check is skipped and behaviour is unchanged. Ported byte-identically across every sports lineage." + }, { "version": "2.24.1", "released": "2026-09-02", diff --git a/plugins/soccer-scoreboard/sports.py b/plugins/soccer-scoreboard/sports.py index 00e5643a..16c69a65 100644 --- a/plugins/soccer-scoreboard/sports.py +++ b/plugins/soccer-scoreboard/sports.py @@ -874,7 +874,7 @@ def _load_fonts(self): fonts["score"] = self._load_custom_font_from_element_config(score_config, default_size=10, element_key='score_text') fonts["time"] = self._load_custom_font_from_element_config(period_config, default_size=8, element_key='period_text') fonts["team"] = self._load_custom_font_from_element_config(team_config, default_size=8, element_key='team_name') - fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text') + fonts["status"] = self._load_custom_font_from_element_config(status_config, default_size=6, element_key='status_text', default_font='4x6-font.ttf') fonts["detail"] = self._load_custom_font_from_element_config(detail_config, default_size=6, element_key='detail_text', default_font='4x6-font.ttf') fonts["odds"] = self._load_custom_font_from_element_config(odds_config, default_size=6, element_key='odds_text', default_font='4x6-font.ttf') fonts["rank"] = self._load_custom_font_from_element_config(rank_config, default_size=10, element_key='rank_text')