Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/assets/ledmatrix-leaderboard/shots.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"sport": "football",
"league": "nfl",
"logo_dir": "assets/sports/nfl_logos",
"league_logo": "assets/sports/nfl_logos/nfl.png",
"league_logo": "assets/sports/nfl_logos/NFL.png",
"top_teams": 6,
"level": 1,
"show_ranking": false
Expand Down
28 changes: 12 additions & 16 deletions plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,11 @@
"plugin_path": "plugins/baseball-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-02",
"last_updated": "2026-10-03",
"verified": true,
"screenshot": "",
"latest_version": "1.57.0",
"ledmatrix_min_version": "3.8.0",
"commit": "886d2038d22a35c962beac0ea261543339cffec9"
"latest_version": "1.57.1",
"ledmatrix_min_version": "3.8.0"
},
{
"id": "basketball-scoreboard",
Expand All @@ -104,12 +103,11 @@
"plugin_path": "plugins/basketball-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-02",
"last_updated": "2026-10-03",
"verified": true,
"screenshot": "",
"latest_version": "1.42.0",
"ledmatrix_min_version": "3.8.0",
"commit": "886d2038d22a35c962beac0ea261543339cffec9"
"latest_version": "1.42.1",
"ledmatrix_min_version": "3.8.0"
},
{
"id": "calendar",
Expand Down Expand Up @@ -382,13 +380,12 @@
"plugin_path": "plugins/hockey-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-02",
"last_updated": "2026-10-03",
"verified": true,
"screenshot": "",
"latest_version": "1.42.2",
"latest_version": "1.42.3",
"icon": "fas fa-hockey-puck",
"ledmatrix_min_version": "3.8.0",
"commit": "886d2038d22a35c962beac0ea261543339cffec9"
"ledmatrix_min_version": "3.8.0"
},
{
"id": "lacrosse-scoreboard",
Expand Down Expand Up @@ -465,15 +462,14 @@
"plugin_path": "plugins/ledmatrix-leaderboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-02",
"last_updated": "2026-10-03",
"verified": true,
"screenshot": "",
"latest_version": "1.5.5",
"latest_version": "1.5.6",
"ledmatrix_min_version": "3.4.0",
"aliases": [
"ledmatrix-leaderboard"
],
"commit": "886d2038d22a35c962beac0ea261543339cffec9"
]
},
{
"id": "ledmatrix-flights",
Expand Down
2 changes: 1 addition & 1 deletion plugins/baseball-scoreboard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ three league blocks, and all are **Advanced**.
| `<league>.scroll_settings.scroll_speed` | `50.0` | Pixels per second. Higher scrolls faster. |
| `<league>.scroll_settings.scroll_delay` | `0.01` | **Hidden.** Ignored; kept declared so saved configs still load. Scrolling is paced to the panel refresh; `scroll_speed` sets the speed. |
| `<league>.scroll_settings.gap_between_games` | `48` | Pixels between game cards. |
| `<league>.scroll_settings.show_league_separators` | `true` | Draw a league icon between leagues in a mixed ticker. |
| `<league>.scroll_settings.show_league_separators` | `true` | Draw a league icon between leagues in a mixed ticker. Only MLB has one: the core ships no MiLB or NCAA baseball icon, so those leagues scroll without one unless you add `assets/sports/milb_logos/MiLB.png` or `assets/sports/ncaa_logos/ncaa_baseball.png` to the LEDMatrix install. |
| `<league>.scroll_settings.dynamic_duration` | `true` | Size the mode's duration from how long the scroll actually takes, so a long slate is not cut off mid-scroll. |
| `<league>.scroll_settings.game_card_width` | `128` | Width of each card. Lower it on a multi-panel chain to fit more games on screen at once. |

Expand Down
8 changes: 7 additions & 1 deletion plugins/baseball-scoreboard/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "baseball-scoreboard",
"name": "Baseball Scoreboard",
"version": "1.57.0",
"version": "1.57.1",
"update_interval": 60,
"author": "ChuckBuilds",
"description": "Live, recent, and upcoming baseball games across MLB, MiLB, and NCAA Baseball with real-time scores and schedules",
Expand Down Expand Up @@ -31,6 +31,12 @@
"branch": "main",
"plugin_path": "plugins/baseball-scoreboard",
"versions": [
{
"version": "1.57.1",
"released": "2026-10-03",
"ledmatrix_min_version": "3.8.0",
"notes": "The MiLB and NCAA baseball separator icons are skipped quietly (debug) instead of warning on every scroll display load: the core ships neither (MiLB.png, ncaa_baseball.png), and its NCAA badges show a basketball or hockey player. MLB keeps its separator. Adding either file to the LEDMatrix install still turns its separator on."
},
{
"version": "1.57.0",
"released": "2026-10-02",
Expand Down
9 changes: 7 additions & 2 deletions plugins/baseball-scoreboard/scroll_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ class ScrollDisplay(_ScrollDisplayBase):
# The ladder the legacy _get_scroll_settings walked, same order.
SCROLL_LEAGUE_KEYS = ("mlb", "milb", "ncaa_baseball")

# Paths to league separator icons
# Paths to league separator icons. The core ships MLB.png only: it has no
# MiLB or NCAA baseball league logo (its NCAA badges show a basketball or
# hockey player), so those two leagues scroll without a separator unless
# a file is added at these paths. A missing icon is skipped quietly.
MLB_SEPARATOR_ICON = "assets/sports/mlb_logos/MLB.png"
MILB_SEPARATOR_ICON = "assets/sports/milb_logos/MiLB.png"
NCAA_BASEBALL_SEPARATOR_ICON = "assets/sports/ncaa_logos/ncaa_baseball.png"
Expand Down Expand Up @@ -163,7 +166,9 @@ def _load_separator_icon(self, icon_path: str, league_key: str, target_height: i
target_height: Target height for the resized icon
"""
if not os.path.exists(icon_path):
self.logger.warning(f"{league_key.upper()} separator icon not found at {icon_path}")
# Debug, not warning: the core ships no MiLB or NCAA baseball
# icon, so every install logged these on every load.
self.logger.debug(f"{league_key.upper()} separator icon not found at {icon_path} (will skip separator)")
return

try:
Expand Down
102 changes: 102 additions & 0 deletions plugins/baseball-scoreboard/test_separator_icons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env python3
"""Separator icons: the ones the core ships load, the rest are skipped quietly.

The core ships MLB.png but no MiLB or NCAA baseball league logo, so
those two separators can never load. Each logged a warning on every
load of the scroll display, on every install.

Builds the real ScrollDisplay with the working directory at a core checkout
(the icon paths are relative to it) and records what it logs. Needs a core
with src.common.sports_scroll (LEDMATRIX_CORE, the working directory, or
../LEDMatrix next to this repo); exits 2 without one.

Run: <core-venv>/bin/python plugins/baseball-scoreboard/test_separator_icons.py
"""

import logging
import os
import sys
from pathlib import Path

PLUGIN_DIR = Path(__file__).resolve().parent

#: League keys that must get a separator: the core ships their icon.
LOADED = {"mlb"}
#: League keys whose icon the core does not ship: no separator, no warning.
SKIPPED = {"milb", "ncaa_baseball"}


def core_checkout():
for candidate in (os.environ.get("LEDMATRIX_CORE", ""), os.getcwd(),
str(PLUGIN_DIR.parents[2] / "LEDMatrix")):
if candidate and (Path(candidate) / "src" / "common" / "sports_scroll.py").is_file():
return Path(candidate)
return None


class _Records(logging.Handler):
def __init__(self):
super().__init__(logging.DEBUG)
self.records = []

def emit(self, record):
self.records.append(record)


def main():
core = core_checkout()
if core is None:
print("SKIP: no LEDMatrix core checkout with src.common.sports_scroll")
return 2
sys.path.insert(0, str(PLUGIN_DIR))
sys.path.insert(1, str(core))
os.chdir(core)

import test_core_scroll as helpers # the constructor stubs live there

logger = logging.getLogger("test_separator_icons")
logger.setLevel(logging.DEBUG)
logger.propagate = False
handler = _Records()
logger.addHandler(handler)

mod = helpers._fresh_scroll_display()
kwargs = helpers._args_for(mod.ScrollDisplay)
for name in ("custom_logger", "logger"):
if name in kwargs:
kwargs[name] = logger
display = mod.ScrollDisplay(**kwargs)
icons = display._separator_icons
height = display.display_height - 4

failures = []

def check(name, cond, detail=""):
print((" PASS " if cond else " FAIL ") + name
+ ("" if cond or not detail else ": " + detail))
if not cond:
failures.append(name)

print("separator icons against %s" % core)
for key in sorted(LOADED):
icon = icons.get(key)
check("%s separator loads" % key, icon is not None,
"not in %s" % sorted(icons))
if icon is not None:
check("%s separator is %dpx tall" % (key, height), icon.height == height,
"got %d" % icon.height)
for key in sorted(SKIPPED):
check("%s has no separator" % key, key not in icons)
warned = [r.getMessage() for r in handler.records
if r.levelno >= logging.WARNING and "separator" in r.getMessage().lower()]
check("nothing about separators is logged above debug", not warned, repr(warned))

if failures:
print("\n%d failure(s)" % len(failures))
return 1
print("\nall passed")
return 0


if __name__ == "__main__":
sys.exit(main())
2 changes: 1 addition & 1 deletion plugins/basketball-scoreboard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ All **Advanced**, and per league.
| `<league>.scroll_settings.scroll_speed` | 1.0–200.0 px/s | `50.0` | Higher scrolls faster. |
| `<league>.scroll_settings.scroll_delay` | 0.001–0.1 s | `0.01` | Ignored; kept so saved configs still load. Scrolling is paced to the panel refresh; `scroll_speed` sets the speed. **Hidden from the config form since 1.35.0 (still declared).** |
| `<league>.scroll_settings.gap_between_games` | 8–128 px | `48` | Gap between game cards. |
| `<league>.scroll_settings.show_league_separators` | boolean | `true` | Draw league icons between leagues. |
| `<league>.scroll_settings.show_league_separators` | boolean | `true` | Draw league icons between leagues: the NBA logo, the NCAA basketball badge for men's and women's college games (March Madness during the tournament). The core ships no WNBA icon, so the WNBA scrolls without one unless you add `assets/sports/wnba_logos/WNBA.png` to the LEDMatrix install. |
| `<league>.scroll_settings.dynamic_duration` | boolean | `true` | Size the scroll duration from the content width. |
| `<league>.scroll_settings.game_card_width` | 32–512 px | `128` | Card width. Lower it on a multi-panel chain to fit more games on screen at once. |

Expand Down
8 changes: 7 additions & 1 deletion plugins/basketball-scoreboard/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "basketball-scoreboard",
"name": "Basketball Scoreboard",
"version": "1.42.0",
"version": "1.42.1",
"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",
Expand All @@ -19,6 +19,12 @@
"branch": "main",
"plugin_path": "plugins/basketball-scoreboard",
"versions": [
{
"version": "1.42.1",
"released": "2026-10-03",
"ledmatrix_min_version": "3.8.0",
"notes": "NCAA men's and women's slates get a league separator again: it named an NCAA.png the core has never shipped, and now uses the core's NCAA basketball badge (ncaam.png). The core ships no WNBA icon, so that separator is skipped at debug instead of warning on every scroll display load."
},
{
"version": "1.42.0",
"released": "2026-10-02",
Expand Down
16 changes: 12 additions & 4 deletions plugins/basketball-scoreboard/scroll_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,15 @@ class ScrollDisplay(_ScrollDisplayBase):
# and reads them off self, and the core base calls it from __init__ --
# so a missing constant is not a degraded icon, it is an AttributeError
# that stops the scroll display being constructed at all.
#
# Spelled exactly as the core ships them: the Pi's filesystem is
# case-sensitive. The core has no generic NCAA.png; ncaam.png is its NCAA
# basketball badge, so the men's and women's slates share it. It has no
# WNBA icon either, so the WNBA scrolls without a separator unless one is
# added at this path.
NBA_SEPARATOR_ICON = "assets/sports/nba_logos/NBA.png"
WNBA_SEPARATOR_ICON = "assets/sports/wnba_logos/WNBA.png"
NCAA_SEPARATOR_ICON = "assets/sports/ncaa_logos/NCAA.png" # Generic NCAA logo, or use league-specific if available
NCAA_SEPARATOR_ICON = "assets/sports/ncaa_logos/ncaam.png"
MARCH_MADNESS_SEPARATOR_ICON = "assets/sports/ncaa_logos/MARCH_MADNESS.png"


Expand Down Expand Up @@ -153,7 +159,9 @@ def _load_separator_icon(
display_name: Name for logging purposes
"""
if not os.path.exists(icon_path):
self.logger.warning(f"{display_name} separator icon not found at {icon_path}")
# Debug, not warning: the core ships no WNBA icon, so every
# install logged this on every load.
self.logger.debug(f"{display_name} separator icon not found at {icon_path} (will skip separator)")
return

try:
Expand Down Expand Up @@ -252,8 +260,8 @@ def build_vegas_elements(self, games: List[Dict], leagues: List[str],
def vegas_separator(self, league: str) -> Optional[Image.Image]:
"""Core's league separator, or the March Madness one ahead of tournament games.

Built as prepare_scroll_content builds it. The core ships no NCAA.png,
so without this a tournament slate would lose its separator altogether.
Built as prepare_scroll_content builds it. Without this a tournament
slate would show the regular NCAA badge rather than March Madness.
"""
icon = self._separator_icons.get(f"{league}_tournament")
if icon is None or league not in getattr(self, "_vegas_tournament_leagues", ()):
Expand Down
Loading
Loading