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
16 changes: 8 additions & 8 deletions plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.40.0"
"latest_version": "1.40.1"
},
{
"id": "basketball-scoreboard",
Expand All @@ -101,7 +101,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.29.0"
"latest_version": "1.29.1"
},
{
"id": "calendar",
Expand Down Expand Up @@ -240,7 +240,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "3.4.0"
"latest_version": "3.4.1"
},
{
"id": "geochron",
Expand Down Expand Up @@ -335,7 +335,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.25.0",
"latest_version": "1.25.1",
"icon": "fas fa-hockey-puck"
},
{
Expand All @@ -359,7 +359,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.24.0",
"latest_version": "1.24.1",
"icon": "fas fa-baseball-ball"
},
{
Expand Down Expand Up @@ -760,7 +760,7 @@
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "2.24.0"
"latest_version": "2.24.1"
},
{
"id": "static-image",
Expand Down Expand Up @@ -1048,7 +1048,7 @@
"downloads": 0,
"verified": true,
"screenshot": "",
"latest_version": "1.22.0",
"latest_version": "1.22.1",
"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.0"
"latest_version": "1.21.1"
},
{
"id": "jellyfin-now-playing",
Expand Down
9 changes: 8 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.0",
"version": "1.22.1",
"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,13 @@
"afl_upcoming"
],
"versions": [
{
"version": "1.22.1",
"released": "2026-09-02",
"ledmatrix_min_version": "3.3.0",
"notes": "Fix every grid-snapped font rendering a pixel narrow. The shared code reads this plugin's config_schema.json to tell a default font size from one the user chose; a default gets snapped to the font's pixel grid, a choice is left alone. It located the schema by inspecting loaded modules, which fails under the real plugin loader -- the loader renames a plugin's modules and removes their original names, so nothing was left to inspect. The lookup returned nothing, every size then looked user-chosen, and the snap was skipped: 4x6-font.ttf drew at 6 instead of 7, which is 3-pixel-wide glyphs instead of 4. On a 256x64 panel the betting odds, team records and the date row were hard to read. The plugin now tells the shared code where it lives instead of leaving it to guess.",
"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.0",
"released": "2026-09-02",
Expand Down
7 changes: 7 additions & 0 deletions plugins/afl-scoreboard/sports.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ def _logo_needs_refresh(logo_file) -> bool:


class SportsCore(SportsCoreSharedMixin, ABC):
#: Absolute path of this plugin, handed to the shared mixin. It cannot
#: deduce it: __file__ there is src/common/, and inferring the directory
#: from the MRO returns None under the real plugin loader, which silently
#: disabled the schema lookup and shrank every grid-snapped font by a
#: pixel. See SportsCoreSharedMixin._plugin_dir.
_PLUGIN_DIR: ClassVar[str] = os.path.dirname(os.path.abspath(__file__))

def __init__(
self,
config: Dict[str, Any],
Expand Down
9 changes: 8 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.40.0",
"version": "1.40.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,13 @@
"branch": "main",
"plugin_path": "plugins/baseball-scoreboard",
"versions": [
{
"version": "1.40.1",
"released": "2026-09-02",
"ledmatrix_min_version": "3.3.0",
"notes": "Fix every grid-snapped font rendering a pixel narrow. The shared code reads this plugin's config_schema.json to tell a default font size from one the user chose; a default gets snapped to the font's pixel grid, a choice is left alone. It located the schema by inspecting loaded modules, which fails under the real plugin loader -- the loader renames a plugin's modules and removes their original names, so nothing was left to inspect. The lookup returned nothing, every size then looked user-chosen, and the snap was skipped: 4x6-font.ttf drew at 6 instead of 7, which is 3-pixel-wide glyphs instead of 4. On a 256x64 panel the betting odds, team records and the date row were hard to read. The plugin now tells the shared code where it lives instead of leaving it to guess.",
"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.40.0",
"released": "2026-09-02",
Expand Down
7 changes: 7 additions & 0 deletions plugins/baseball-scoreboard/sports.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ def _logo_needs_refresh(logo_file) -> bool:


class SportsCore(SportsCoreSharedMixin, ABC):
#: Absolute path of this plugin, handed to the shared mixin. It cannot
#: deduce it: __file__ there is src/common/, and inferring the directory
#: from the MRO returns None under the real plugin loader, which silently
#: disabled the schema lookup and shrank every grid-snapped font by a
#: pixel. See SportsCoreSharedMixin._plugin_dir.
_PLUGIN_DIR: ClassVar[str] = os.path.dirname(os.path.abspath(__file__))

def __init__(
self,
config: Dict[str, Any],
Expand Down
9 changes: 8 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.29.0",
"version": "1.29.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,13 @@
"branch": "main",
"plugin_path": "plugins/basketball-scoreboard",
"versions": [
{
"version": "1.29.1",
"released": "2026-09-02",
"ledmatrix_min_version": "3.3.0",
"notes": "Fix every grid-snapped font rendering a pixel narrow. The shared code reads this plugin's config_schema.json to tell a default font size from one the user chose; a default gets snapped to the font's pixel grid, a choice is left alone. It located the schema by inspecting loaded modules, which fails under the real plugin loader -- the loader renames a plugin's modules and removes their original names, so nothing was left to inspect. The lookup returned nothing, every size then looked user-chosen, and the snap was skipped: 4x6-font.ttf drew at 6 instead of 7, which is 3-pixel-wide glyphs instead of 4. On a 256x64 panel the betting odds, team records and the date row were hard to read. The plugin now tells the shared code where it lives instead of leaving it to guess.",
"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.0",
"released": "2026-09-02",
Expand Down
7 changes: 7 additions & 0 deletions plugins/basketball-scoreboard/sports.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@ def _logo_needs_refresh(logo_file) -> bool:


class SportsCore(SportsCoreSharedMixin, ABC):
#: Absolute path of this plugin, handed to the shared mixin. It cannot
#: deduce it: __file__ there is src/common/, and inferring the directory
#: from the MRO returns None under the real plugin loader, which silently
#: disabled the schema lookup and shrank every grid-snapped font by a
#: pixel. See SportsCoreSharedMixin._plugin_dir.
_PLUGIN_DIR: ClassVar[str] = os.path.dirname(os.path.abspath(__file__))

TOURNAMENT_ROUND_ORDER: ClassVar[Dict[str, int]] = {"NCG": 0, "F4": 1, "E8": 2, "S16": 3, "R32": 4, "R64": 5, "": 6}

def __init__(
Expand Down
9 changes: 8 additions & 1 deletion plugins/football-scoreboard/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "football-scoreboard",
"name": "Football Scoreboard",
"version": "3.4.0",
"version": "3.4.1",
"update_interval": 60,
"author": "ChuckBuilds",
"class_name": "FootballScoreboardPlugin",
Expand All @@ -25,6 +25,13 @@
"ncaa_fb_live"
],
"versions": [
{
"version": "3.4.1",
"released": "2026-09-02",
"ledmatrix_min_version": "3.3.0",
"notes": "Fix every grid-snapped font rendering a pixel narrow. The shared code reads this plugin's config_schema.json to tell a default font size from one the user chose; a default gets snapped to the font's pixel grid, a choice is left alone. It located the schema by inspecting loaded modules, which fails under the real plugin loader -- the loader renames a plugin's modules and removes their original names, so nothing was left to inspect. The lookup returned nothing, every size then looked user-chosen, and the snap was skipped: 4x6-font.ttf drew at 6 instead of 7, which is 3-pixel-wide glyphs instead of 4. On a 256x64 panel the betting odds, team records and the date row were hard to read. The plugin now tells the shared code where it lives instead of leaving it to guess.",
"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.0",
"released": "2026-09-02",
Expand Down
7 changes: 7 additions & 0 deletions plugins/football-scoreboard/sports.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ def _fetch(cls, key, sport_key, team_id, abbr, logo_path, logo_url, logger):


class SportsCore(SportsCoreSharedMixin, ABC):
#: Absolute path of this plugin, handed to the shared mixin. It cannot
#: deduce it: __file__ there is src/common/, and inferring the directory
#: from the MRO returns None under the real plugin loader, which silently
#: disabled the schema lookup and shrank every grid-snapped font by a
#: pixel. See SportsCoreSharedMixin._plugin_dir.
_PLUGIN_DIR: ClassVar[str] = os.path.dirname(os.path.abspath(__file__))

def __init__(
self,
config: Dict[str, Any],
Expand Down
9 changes: 8 additions & 1 deletion plugins/hockey-scoreboard/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "hockey-scoreboard",
"name": "Hockey Scoreboard",
"version": "1.25.0",
"version": "1.25.1",
"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",
Expand Down Expand Up @@ -54,6 +54,13 @@
}
],
"versions": [
{
"version": "1.25.1",
"released": "2026-09-02",
"ledmatrix_min_version": "3.3.0",
"notes": "Fix every grid-snapped font rendering a pixel narrow. The shared code reads this plugin's config_schema.json to tell a default font size from one the user chose; a default gets snapped to the font's pixel grid, a choice is left alone. It located the schema by inspecting loaded modules, which fails under the real plugin loader -- the loader renames a plugin's modules and removes their original names, so nothing was left to inspect. The lookup returned nothing, every size then looked user-chosen, and the snap was skipped: 4x6-font.ttf drew at 6 instead of 7, which is 3-pixel-wide glyphs instead of 4. On a 256x64 panel the betting odds, team records and the date row were hard to read. The plugin now tells the shared code where it lives instead of leaving it to guess.",
"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.0",
"released": "2026-09-02",
Expand Down
7 changes: 7 additions & 0 deletions plugins/hockey-scoreboard/sports.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ def _logo_needs_refresh(logo_file) -> bool:


class SportsCore(SportsCoreSharedMixin, ABC):
#: Absolute path of this plugin, handed to the shared mixin. It cannot
#: deduce it: __file__ there is src/common/, and inferring the directory
#: from the MRO returns None under the real plugin loader, which silently
#: disabled the schema lookup and shrank every grid-snapped font by a
#: pixel. See SportsCoreSharedMixin._plugin_dir.
_PLUGIN_DIR: ClassVar[str] = os.path.dirname(os.path.abspath(__file__))

def __init__(
self,
config: Dict[str, Any],
Expand Down
9 changes: 8 additions & 1 deletion plugins/lacrosse-scoreboard/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "lacrosse-scoreboard",
"name": "Lacrosse Scoreboard",
"version": "1.24.0",
"version": "1.24.1",
"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",
Expand Down Expand Up @@ -50,6 +50,13 @@
}
],
"versions": [
{
"version": "1.24.1",
"released": "2026-09-02",
"ledmatrix_min_version": "3.3.0",
"notes": "Fix every grid-snapped font rendering a pixel narrow. The shared code reads this plugin's config_schema.json to tell a default font size from one the user chose; a default gets snapped to the font's pixel grid, a choice is left alone. It located the schema by inspecting loaded modules, which fails under the real plugin loader -- the loader renames a plugin's modules and removes their original names, so nothing was left to inspect. The lookup returned nothing, every size then looked user-chosen, and the snap was skipped: 4x6-font.ttf drew at 6 instead of 7, which is 3-pixel-wide glyphs instead of 4. On a 256x64 panel the betting odds, team records and the date row were hard to read. The plugin now tells the shared code where it lives instead of leaving it to guess.",
"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.0",
"released": "2026-09-02",
Expand Down
7 changes: 7 additions & 0 deletions plugins/lacrosse-scoreboard/sports.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ def _logo_needs_refresh(logo_file) -> bool:


class SportsCore(SportsCoreSharedMixin, ABC):
#: Absolute path of this plugin, handed to the shared mixin. It cannot
#: deduce it: __file__ there is src/common/, and inferring the directory
#: from the MRO returns None under the real plugin loader, which silently
#: disabled the schema lookup and shrank every grid-snapped font by a
#: pixel. See SportsCoreSharedMixin._plugin_dir.
_PLUGIN_DIR: ClassVar[str] = os.path.dirname(os.path.abspath(__file__))

def __init__(
self,
config: Dict[str, Any],
Expand Down
Loading
Loading