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
30 changes: 15 additions & 15 deletions plugins.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "1.0.0",
"last_updated": "2026-02-14",
"last_updated": "2026-02-15",
"plugins": [
{
"id": "hello-world",
Expand Down Expand Up @@ -59,10 +59,10 @@
"repo": "https://github.com/ChuckBuilds/ledmatrix-plugins",
"branch": "main",
"plugin_path": "plugins/ledmatrix-weather",
"latest_version": "2.1.0",
"latest_version": "2.1.1",
"stars": 0,
"downloads": 0,
"last_updated": "2026-02-13",
"last_updated": "2026-02-15",
"verified": true,
"screenshot": ""
},
Expand Down Expand Up @@ -196,10 +196,10 @@
"plugin_path": "plugins/hockey-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-02-14",
"last_updated": "2026-02-15",
"verified": true,
"screenshot": "",
"latest_version": "1.1.0"
"latest_version": "1.1.1"
},
{
"id": "football-scoreboard",
Expand All @@ -221,10 +221,10 @@
"plugin_path": "plugins/football-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-02-14",
"last_updated": "2026-02-15",
"verified": true,
"screenshot": "",
"latest_version": "2.1.0"
"latest_version": "2.1.1"
},
{
"id": "ufc-scoreboard",
Expand All @@ -245,10 +245,10 @@
"plugin_path": "plugins/ufc-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-02-12",
"last_updated": "2026-02-15",
"verified": true,
"screenshot": "",
"latest_version": "1.0.0"
"latest_version": "1.0.1"
},
{
"id": "basketball-scoreboard",
Expand All @@ -270,10 +270,10 @@
"plugin_path": "plugins/basketball-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-02-14",
"last_updated": "2026-02-15",
"verified": true,
"screenshot": "",
"latest_version": "1.1.0"
"latest_version": "1.1.1"
},
{
"id": "baseball-scoreboard",
Expand All @@ -296,10 +296,10 @@
"plugin_path": "plugins/baseball-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-02-14",
"last_updated": "2026-02-15",
"verified": true,
"screenshot": "",
"latest_version": "2.0.0"
"latest_version": "2.0.1"
},
{
"id": "soccer-scoreboard",
Expand All @@ -325,10 +325,10 @@
"plugin_path": "plugins/soccer-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-02-14",
"last_updated": "2026-02-15",
"verified": true,
"screenshot": "",
"latest_version": "1.3.0"
"latest_version": "1.3.1"
},
{
"id": "odds-ticker",
Expand Down
12 changes: 6 additions & 6 deletions plugins/baseball-scoreboard/game_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ def _render_live_game(self, game: Dict) -> Image.Image:
center_y = self.display_height // 2

# Logos
main_img.paste(home_logo, (self.display_width - home_logo.width + 10, center_y - home_logo.height // 2), home_logo)
main_img.paste(away_logo, (-10, center_y - away_logo.height // 2), away_logo)
main_img.paste(home_logo, (self.display_width - home_logo.width, center_y - home_logo.height // 2), home_logo)
main_img.paste(away_logo, (0, center_y - away_logo.height // 2), away_logo)

# Inning indicator (top center)
inning_half = game.get('inning_half', 'top')
Expand Down Expand Up @@ -307,8 +307,8 @@ def _render_recent_game(self, game: Dict) -> Image.Image:
center_y = self.display_height // 2

# Logos (tighter fit for recent)
main_img.paste(home_logo, (self.display_width - home_logo.width + 2, center_y - home_logo.height // 2), home_logo)
main_img.paste(away_logo, (-2, center_y - away_logo.height // 2), away_logo)
main_img.paste(home_logo, (self.display_width - home_logo.width, center_y - home_logo.height // 2), home_logo)
main_img.paste(away_logo, (0, center_y - away_logo.height // 2), away_logo)

# "Final" (top center)
status_text = "Final"
Expand Down Expand Up @@ -353,8 +353,8 @@ def _render_upcoming_game(self, game: Dict) -> Image.Image:
center_y = self.display_height // 2

# Logos (tighter fit)
main_img.paste(home_logo, (self.display_width - home_logo.width + 2, center_y - home_logo.height // 2), home_logo)
main_img.paste(away_logo, (-2, center_y - away_logo.height // 2), away_logo)
main_img.paste(home_logo, (self.display_width - home_logo.width, center_y - home_logo.height // 2), home_logo)
main_img.paste(away_logo, (0, center_y - away_logo.height // 2), away_logo)

# "Next Game" (top center)
status_font = self.fonts['status'] if self.display_width <= 128 else self.fonts['time']
Expand Down
30 changes: 20 additions & 10 deletions plugins/baseball-scoreboard/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3626,20 +3626,30 @@ def get_vegas_content(self) -> Optional[Any]:
"""
Get content for Vegas-style continuous scroll mode.

Returns None to let PluginAdapter auto-detect scroll_helper.cached_image.
Triggers scroll content generation if cache is empty to ensure Vegas
has content to display.
Triggers scroll content generation if cache is empty, then returns
the cached scroll image(s) for Vegas to compose into its scroll strip.

Returns:
None - PluginAdapter will extract scroll_helper.cached_image automatically
List of PIL Images from scroll displays, or None if no content
"""
# Ensure scroll content is generated for Vegas mode
if hasattr(self, '_scroll_manager') and self._scroll_manager:
if not self._scroll_manager.has_cached_content():
self.logger.info("[Baseball Vegas] Triggering scroll content generation")
self._ensure_scroll_content_for_vegas()
if not hasattr(self, '_scroll_manager') or not self._scroll_manager:
return None

images = self._scroll_manager.get_all_vegas_content_items()

if not images:
self.logger.info("[Baseball Vegas] Triggering scroll content generation")
self._ensure_scroll_content_for_vegas()
images = self._scroll_manager.get_all_vegas_content_items()

if images:
total_width = sum(img.width for img in images)
self.logger.info(
"[Baseball Vegas] Returning %d image(s), %dpx total",
len(images), total_width
)
return images

Comment on lines +3629 to 3652
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Bump the plugin patch version for this Vegas content fix.

This change alters Vegas output behavior, so the plugin version should be incremented (e.g., 2.0.02.0.1) in version metadata such as get_info().

Suggested patch
-                "version": "2.0.0",
+                "version": "2.0.1",

As per coding guidelines, “/plugins//*.py: Bump PATCH version (1.2.x) for bug fixes, performance improvements, documentation updates, or minor tweaks”.

🤖 Prompt for AI Agents
In `@plugins/baseball-scoreboard/manager.py` around lines 3629 - 3662, The plugin
changes alter Vegas output behavior so you must bump the patch version in the
plugin metadata: update the version returned by get_info() (or equivalent
version constant/function) from the current 3-part semantic version (e.g.,
2.0.0) to the next patch (e.g., 2.0.1), and ensure any other version references
(package metadata or docs) are consistent; keep the rest of get_info()
unchanged.

# Return None - PluginAdapter will auto-detect scroll_helper.cached_image
return None

def get_vegas_content_type(self) -> str:
Expand Down
2 changes: 1 addition & 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": "2.0.0",
"version": "2.0.1",
"author": "ChuckBuilds",
"description": "Live, recent, and upcoming baseball games across MLB, MiLB, and NCAA Baseball with real-time scores and schedules",
"category": "sports",
Expand Down
13 changes: 13 additions & 0 deletions plugins/baseball-scoreboard/scroll_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ def __init__(
self._current_games: List[Dict] = []
self._current_game_type: str = ""
self._current_leagues: List[str] = []
self._vegas_content_items: List[Image.Image] = []
self._is_scrolling = False
self._scroll_start_time: Optional[float] = None
self._last_log_time: float = 0
Expand Down Expand Up @@ -381,6 +382,9 @@ def prepare_scroll_content(
self.logger.warning("No game cards rendered")
return False

# Store individual items for Vegas mode (avoids scroll_helper padding)
self._vegas_content_items = list(content_items)

# Create scrolling image using ScrollHelper
self.scroll_helper.create_scrolling_image(
content_items,
Expand Down Expand Up @@ -657,3 +661,12 @@ def has_cached_content(self) -> bool:
if scroll_display.scroll_helper.cached_image is not None:
return True
return False

def get_all_vegas_content_items(self) -> list:
"""Collect _vegas_content_items from all scroll displays."""
items = []
for sd in self._scroll_displays.values():
vegas_items = getattr(sd, '_vegas_content_items', None)
if vegas_items:
items.extend(vegas_items)
return items
6 changes: 3 additions & 3 deletions plugins/basketball-scoreboard/game_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,11 +317,11 @@ def render_game_card(
center_y = self.display_height // 2

# Draw logos
home_x = self.display_width - home_logo.width + 10
home_x = self.display_width - home_logo.width
home_y = center_y - (home_logo.height // 2)
main_img.paste(home_logo, (home_x, home_y), home_logo)
away_x = -10

away_x = 0
away_y = center_y - (away_logo.height // 2)
main_img.paste(away_logo, (away_x, away_y), away_logo)

Expand Down
33 changes: 21 additions & 12 deletions plugins/basketball-scoreboard/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3251,21 +3251,30 @@ def get_vegas_content(self) -> Optional[Any]:
"""
Get content for Vegas-style continuous scroll mode.

Returns None to let PluginAdapter auto-detect scroll_helper.cached_image.
Triggers scroll content generation if cache is empty to ensure Vegas
has content to display.
Triggers scroll content generation if cache is empty, then returns
the cached scroll image(s) for Vegas to compose into its scroll strip.

Returns:
None - PluginAdapter will extract scroll_helper.cached_image automatically
List of PIL Images from scroll displays, or None if no content
"""
# Ensure scroll content is generated for Vegas mode
if hasattr(self, '_scroll_manager') and self._scroll_manager:
# Check if any scroll display has content
if not self._scroll_manager.has_cached_content():
self.logger.info("[Basketball Vegas] Triggering scroll content generation")
self._ensure_scroll_content_for_vegas()

# Return None - PluginAdapter will auto-detect scroll_helper.cached_image
if not hasattr(self, '_scroll_manager') or not self._scroll_manager:
return None

images = self._scroll_manager.get_all_vegas_content_items()

if not images:
self.logger.info("[Basketball Vegas] Triggering scroll content generation")
self._ensure_scroll_content_for_vegas()
images = self._scroll_manager.get_all_vegas_content_items()

if images:
total_width = sum(img.width for img in images)
self.logger.info(
"[Basketball Vegas] Returning %d image(s), %dpx total",
len(images), total_width
)
return images

return None

def get_vegas_content_type(self) -> str:
Expand Down
2 changes: 1 addition & 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.1.0",
"version": "1.1.1",
"description": "Live, recent, and upcoming basketball games across NBA, NCAA Men's, NCAA Women's, and WNBA with real-time scores and schedules",
"author": "ChuckBuilds",
"category": "sports",
Expand Down
15 changes: 14 additions & 1 deletion plugins/basketball-scoreboard/scroll_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def __init__(
self._current_games: List[Dict] = []
self._current_game_type: str = ""
self._current_leagues: List[str] = []
self._vegas_content_items: List[Image.Image] = []
self._is_scrolling = False
self._scroll_start_time: Optional[float] = None
self._last_log_time: float = 0
Expand Down Expand Up @@ -396,13 +397,16 @@ def prepare_scroll_content(
self.logger.warning("No game cards rendered")
return False

# Store individual items for Vegas mode (avoids scroll_helper padding)
self._vegas_content_items = list(content_items)

# Create scrolling image using ScrollHelper
self.scroll_helper.create_scrolling_image(
content_items,
item_gap=gap_between_games,
element_gap=0 # No element gap - each item is a complete game card
)

# Log what we loaded
league_summary = ", ".join([f"{league.upper()}({count})" for league, count in league_counts.items()])
self.logger.info(
Expand Down Expand Up @@ -667,6 +671,15 @@ def has_cached_content(self) -> bool:
return True
return False

def get_all_vegas_content_items(self) -> list:
"""Collect _vegas_content_items from all scroll displays."""
items = []
for sd in self._scroll_displays.values():
vegas_items = getattr(sd, '_vegas_content_items', None)
if vegas_items:
items.extend(vegas_items)
return items

def clear_all(self) -> None:
"""Clear all scroll displays."""
for scroll_display in self._scroll_displays.values():
Expand Down
6 changes: 3 additions & 3 deletions plugins/football-scoreboard/game_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,11 @@ def render_game_card(
center_y = self.display_height // 2

# Draw logos
home_x = self.display_width - home_logo.width + 10
home_x = self.display_width - home_logo.width
home_y = center_y - (home_logo.height // 2)
main_img.paste(home_logo, (home_x, home_y), home_logo)
away_x = -10

away_x = 0
away_y = center_y - (away_logo.height // 2)
main_img.paste(away_logo, (away_x, away_y), away_logo)

Expand Down
30 changes: 20 additions & 10 deletions plugins/football-scoreboard/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3376,20 +3376,30 @@ def get_vegas_content(self) -> Optional[Any]:
"""
Get content for Vegas-style continuous scroll mode.

Returns None to let PluginAdapter auto-detect scroll_helper.cached_image.
Triggers scroll content generation if cache is empty to ensure Vegas
has content to display.
Triggers scroll content generation if cache is empty, then returns
the cached scroll image(s) for Vegas to compose into its scroll strip.

Returns:
None - PluginAdapter will extract scroll_helper.cached_image automatically
List of PIL Images from scroll displays, or None if no content
"""
# Ensure scroll content is generated for Vegas mode
if hasattr(self, '_scroll_manager') and self._scroll_manager:
if not self._scroll_manager.has_cached_content():
self.logger.info("[Football Vegas] Triggering scroll content generation")
self._ensure_scroll_content_for_vegas()
if not hasattr(self, '_scroll_manager') or not self._scroll_manager:
return None

images = self._scroll_manager.get_all_vegas_content_items()

if not images:
self.logger.info("[Football Vegas] Triggering scroll content generation")
self._ensure_scroll_content_for_vegas()
images = self._scroll_manager.get_all_vegas_content_items()

if images:
total_width = sum(img.width for img in images)
self.logger.info(
"[Football Vegas] Returning %d image(s), %dpx total",
len(images), total_width
)
return images

# Return None - PluginAdapter will auto-detect scroll_helper.cached_image
return None

def get_vegas_content_type(self) -> str:
Expand Down
2 changes: 1 addition & 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": "2.1.0",
"version": "2.1.1",
"author": "ChuckBuilds",
"class_name": "FootballScoreboardPlugin",
"description": "Standalone plugin for live, recent, and upcoming football games across NFL and NCAA Football with real-time scores, down/distance, possession, and game status. Now with organized nested config!",
Expand Down
Loading