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
38 changes: 19 additions & 19 deletions plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.0.5"
"latest_version": "1.0.6"
},
{
"id": "baseball-scoreboard",
Expand All @@ -76,7 +76,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.40.3"
"latest_version": "1.40.4"
},
{
"id": "basketball-scoreboard",
Expand All @@ -101,7 +101,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.29.4"
"latest_version": "1.29.5"
},
{
"id": "calendar",
Expand All @@ -124,7 +124,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.2.5"
"latest_version": "1.2.6"
},
{
"id": "christmas-countdown",
Expand All @@ -146,7 +146,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.0.3"
"latest_version": "1.0.4"
},
{
"id": "clock-simple",
Expand Down Expand Up @@ -240,7 +240,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "3.5.1"
"latest_version": "3.5.2"
},
{
"id": "geochron",
Expand All @@ -266,7 +266,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.0.4",
"latest_version": "1.0.5",
"icon": "fa-globe"
},
{
Expand Down Expand Up @@ -311,7 +311,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.1.0"
"latest_version": "1.1.1"
},
{
"id": "hockey-scoreboard",
Expand All @@ -335,7 +335,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.25.3",
"latest_version": "1.25.4",
"icon": "fas fa-hockey-puck"
},
{
Expand All @@ -359,7 +359,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.24.4",
"latest_version": "1.24.5",
"icon": "fas fa-baseball-ball"
},
{
Expand Down Expand Up @@ -412,7 +412,7 @@
"last_updated": "2026-09-03",
"verified": true,
"screenshot": "",
"latest_version": "1.3.6"
"latest_version": "1.3.7"
},
{
"id": "ledmatrix-flights",
Expand Down Expand Up @@ -533,7 +533,7 @@
"last_updated": "2026-09-03",
"verified": true,
"screenshot": "",
"latest_version": "1.4.0"
"latest_version": "1.4.1"
},
{
"id": "news",
Expand Down Expand Up @@ -581,7 +581,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.2.7",
"latest_version": "1.2.8",
"icon": "fa-circle-dot"
},
{
Expand All @@ -605,7 +605,7 @@
"last_updated": "2026-09-03",
"verified": true,
"screenshot": "",
"latest_version": "1.4.6",
"latest_version": "1.4.7",
"icon": "fas fa-football-ball"
},
{
Expand Down Expand Up @@ -681,7 +681,7 @@
"last_updated": "2026-09-03",
"verified": true,
"screenshot": "",
"latest_version": "2.0.3"
"latest_version": "2.0.4"
},
{
"id": "pga-tour-leaderboard",
Expand Down Expand Up @@ -760,7 +760,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "2.24.4"
"latest_version": "2.24.5"
},
{
"id": "static-image",
Expand All @@ -783,7 +783,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.0.7"
"latest_version": "1.0.8"
},
{
"id": "stock-news",
Expand Down Expand Up @@ -1048,7 +1048,7 @@
"downloads": 0,
"verified": true,
"screenshot": "",
"latest_version": "1.22.3",
"latest_version": "1.22.4",
"last_updated": "2026-09-02"
},
{
Expand Down Expand Up @@ -1095,7 +1095,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.21.3"
"latest_version": "1.21.4"
},
{
"id": "jellyfin-now-playing",
Expand Down
10 changes: 10 additions & 0 deletions plugins/7-segment-clock/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,21 @@ def _calculate_scale_factor(
"""
# Calculate base width needed for the time string
base_width = 0
element_count = 0
for item in digits:
if item == ":":
base_width += self.separator_width
element_count += 1
elif item is not None:
base_width += self.digit_width
element_count += 1

# The gaps scale with the digits, so they belong in the width the scale
# is solved against. Sizing the digits to the panel and then adding the
# spacing on top is what pushed the clock off the right edge for any
# digit_spacing >= 3, a range the schema advertises up to 10.
if element_count > 1:
base_width += (element_count - 1) * self.digit_spacing

base_height = self.digit_height

Expand Down
8 changes: 7 additions & 1 deletion plugins/7-segment-clock/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "7-segment-clock",
"name": "7-Segment Clock",
"version": "1.0.5",
"version": "1.0.6",
"description": "Display a retro-style 7-segment clock with customizable colors",
"author": "LEDMatrix",
"entry_point": "manager.py",
Expand All @@ -24,6 +24,12 @@
"default_duration": 15,
"config_schema": "config_schema.json",
"versions": [
{
"version": "1.0.6",
"released": "2026-09-05",
"ledmatrix_min_version": "2.0.0",
"notes": "Validation-sweep fixes; see the PR for the specific defect."
},
{
"released": "2026-09-02",
"version": "1.0.5",
Expand Down
Binary file modified plugins/7-segment-clock/test/golden/128x96/7-segment-clock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified plugins/7-segment-clock/test/golden/64x64/7-segment-clock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 6 additions & 12 deletions plugins/afl-scoreboard/config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -776,8 +776,7 @@
"4x6-font.ttf",
"5by7.regular.ttf",
"5x7.bdf",
"4x6.bdf",
"cozette.bdf"
"4x6.bdf"
],
"default": "PressStart2P-Regular.ttf",
"x-advanced": true
Expand Down Expand Up @@ -832,8 +831,7 @@
"4x6-font.ttf",
"5by7.regular.ttf",
"5x7.bdf",
"4x6.bdf",
"cozette.bdf"
"4x6.bdf"
],
"default": "PressStart2P-Regular.ttf",
"x-advanced": true
Expand Down Expand Up @@ -888,8 +886,7 @@
"4x6-font.ttf",
"5by7.regular.ttf",
"5x7.bdf",
"4x6.bdf",
"cozette.bdf"
"4x6.bdf"
],
"default": "PressStart2P-Regular.ttf",
"x-advanced": true
Expand Down Expand Up @@ -944,8 +941,7 @@
"4x6-font.ttf",
"5by7.regular.ttf",
"5x7.bdf",
"4x6.bdf",
"cozette.bdf"
"4x6.bdf"
],
"default": "4x6-font.ttf",
"x-advanced": true
Expand Down Expand Up @@ -1000,8 +996,7 @@
"4x6-font.ttf",
"5by7.regular.ttf",
"5x7.bdf",
"4x6.bdf",
"cozette.bdf"
"4x6.bdf"
],
"default": "4x6-font.ttf",
"x-advanced": true
Expand Down Expand Up @@ -1095,8 +1090,7 @@
"4x6-font.ttf",
"5by7.regular.ttf",
"5x7.bdf",
"4x6.bdf",
"cozette.bdf"
"4x6.bdf"
],
"default": "PressStart2P-Regular.ttf",
"x-advanced": true
Expand Down
8 changes: 7 additions & 1 deletion plugins/afl-scoreboard/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "afl-scoreboard",
"name": "AFL Scoreboard",
"version": "1.22.3",
"version": "1.22.4",
"author": "ChuckBuilds",
"description": "Live, recent, and upcoming AFL (Australian Football League) games with real-time scores and game status.",
"category": "sports",
Expand All @@ -18,6 +18,12 @@
"afl_upcoming"
],
"versions": [
{
"version": "1.22.4",
"released": "2026-09-05",
"ledmatrix_min_version": "3.3.0",
"notes": "Validation-sweep fixes; see the PR for the specific defect."
},
{
"released": "2026-09-04",
"version": "1.22.3",
Expand Down
43 changes: 32 additions & 11 deletions plugins/baseball-scoreboard/game_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,20 @@ def resolve_font_name(font_name: str) -> str:
_DERIVE_TOP_SPAN = object()



def _bdf_pixel_size(path):
"""The pixel size a .bdf font declares, or None if it does not."""
try:
with open(path, "r", encoding="latin-1") as handle:
for line in handle:
if line.startswith("PIXEL_SIZE"):
return int(line.split()[1])
if line.startswith("CHARS"):
break # past the header; no point reading the glyphs
except (OSError, ValueError, IndexError):
return None
return None

class GameRenderer(SportsGameRendererMixin):
"""Renders individual baseball game cards as PIL Images."""

Expand Down Expand Up @@ -226,18 +240,25 @@ def _load_custom_font(self, element_config: Dict[str, Any], default_size: int =
if font_path.lower().endswith('.ttf') or font_path.lower().endswith('.otf'):
return ImageFont.truetype(font_path, font_size)
elif font_path.lower().endswith('.bdf'):
# BDF fonts require pre-conversion: pilfont.py font.bdf -> font.pil + font.pbm
pil_font_path = font_path.rsplit('.', 1)[0] + '.pil'
if os.path.exists(pil_font_path):
try:
return ImageFont.load(pil_font_path)
except Exception as e:
self.logger.warning(f"Failed to load pre-converted BDF font {pil_font_path}: {e}")
else:
# FreeType reads BDF directly -- no pre-conversion needed.
# This used to look for a .pil/.pbm pair produced by
# pilfont.py, and no .pil ships anywhere, so every .bdf in
# the picker warned and fell back to the default font.
try:
return ImageFont.truetype(font_path, font_size)
except OSError:
# A bitmap face exists at exactly the size it was drawn
# at; FreeType rejects any other with "invalid pixel
# size". Retry at the size the file declares.
native = _bdf_pixel_size(font_path)
if native is not None and native != font_size:
try:
return ImageFont.truetype(font_path, native)
except OSError:
pass
self.logger.warning(
f"BDF font {font_name} requires conversion. "
f"Run: pilfont.py {font_path}"
)
f"Could not load BDF font {font_name} at {font_size} "
f"or its native size")
else:
self.logger.warning(f"Unknown font file type: {font_name}")
else:
Expand Down
Loading
Loading