Files
LEDMatrix/src/common
ChuckandClaude Opus 5.5 c883a2fd1e feat(perf): a stall watchdog that logs what the render thread is waiting on
The recorder counts freezes; it cannot say why. hdpi showed 1-2s freezes
in both the #628 and offscreen builds, one lining up with hockey's 2s
NHL fetch on the update thread, and nothing in the logs explained it.

StallWatchdog polls every 50ms from its own thread. When a scroll's last
frame is more than 250ms old (and a scroll is still running, so the end
of a scroll is not a stall), it logs the stack of the thread that
presented that frame and the top of every other thread's, then the
stall's length when frames resume. It also measures how late its own
wake-up was: if it was held up as long as the render thread, the whole
interpreter was blocked (C code holding the GIL), not one thread on a
lock. One dump per 30s at most; LEDMATRIX_STALL_WATCHDOG=0 disables it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 10:58:27 -04:00
..

Common Utilities

This directory contains reusable utilities and helpers for LEDMatrix plugins and core modules.

Adaptive Layout & Images (src/adaptive_layout.py, src/adaptive_images.py)

The recommended way to lay out plugins that render legibly on any panel size (64x32 through 256x128+) without hand-tuned coordinates. Re-exported from src.common for convenience; canonical import paths are src.adaptive_layout / src.adaptive_images.

# Every BasePlugin already has self.layout and the draw helpers:
regs = scoreboard_regions(self.layout.bounds, ctx=self.layout)
self.draw_image(away_logo, regs.away_slot, mode="fill_height",
                crop_to_ink=True, cache_key=f"logo:{abbr}")
self.draw_fit(score_text, regs.score_area)     # largest crisp font that fits
self.draw_fit(status, regs.status_band)

Key pieces: Region (rect algebra: bands/columns/splits/offset), font ladders (LADDER_GRID, LADDER_ARCADE — discrete crisp sizes, never fractional scaling), LayoutContext (fit_text, fit_image, by_tier, px), and composite carvers scoreboard_regions() / media_row(). Full guide: docs/ADAPTIVE_LAYOUT.md.

API Helpers (api_helper.py)

Utilities for making HTTP requests and handling API responses.

Logo Helpers (logo_helper.py)

Utilities for loading and managing team logos.

Text Helpers (text_helper.py)

Utilities for text processing and formatting.

Scroll Helpers (scroll_helper.py)

Utilities for scrolling text on the display.

Permission Utilities (permission_utils.py)

Helpers for ensuring directory permissions and ownership are correct when running as a service (used by CacheManager to set up its persistent cache directory).

Best Practices

  1. Use centralized logging: Import from src.logging_config instead of creating loggers directly
  2. Reuse utilities: Check existing utilities before creating new ones
  3. Document additions: Add documentation when adding new utilities