mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 13:02:59 +00:00
* fix: check live priority during display loops to interrupt long durations (#196) _check_live_priority() was only called once per main loop iteration, before entering the display duration loop. With dynamic duration enabled, the loop could run for 60-120+ seconds without ever checking if a favorite team's live game started — so the display stayed on leaderboard, weather, etc. while the live game played. Now both the high-FPS and normal FPS display loops check for live priority every ~30 seconds (throttled to avoid overhead). When live content is detected, the loop breaks immediately and switches to the live game mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update rotation index when live priority interrupts display loop The live priority break set current_display_mode but not current_mode_index, so the post-loop rotation logic (which checks the old active_mode) would overwrite the live mode on the next advance. Now both loops also set current_mode_index to match the live mode, mirroring the existing pattern at the top of the main loop (line 1385). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use timestamp throttle for live priority and skip post-loop rotation Two issues fixed: 1. The modulo-based throttle (elapsed % 30.0 < display_interval) could miss the narrow 8ms window due to timing jitter. Replaced with an explicit timestamp check (_next_live_priority_check) that fires reliably every 30 seconds. 2. After breaking out of the display loop for live priority, the post-loop code (remaining-duration sleep and rotation advancement) would still run and overwrite the live mode. Now a continue skips directly to the next main loop iteration when current_display_mode was changed during the loop. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -79,6 +79,7 @@ class DisplayController:
|
||||
logger.info("Display modes initialized in %.3f seconds", time.time() - init_time)
|
||||
|
||||
self.force_change = False
|
||||
self._next_live_priority_check = 0.0 # timestamp for throttled live priority checks
|
||||
|
||||
# All sports and content managers now handled via plugins
|
||||
logger.info("All sports and content managers now handled via plugin system")
|
||||
@@ -1790,11 +1791,29 @@ class DisplayController:
|
||||
self._poll_on_demand_requests()
|
||||
self._check_on_demand_expiration()
|
||||
|
||||
# Check for live priority every ~30s so live
|
||||
# games can interrupt long display durations
|
||||
elapsed = time.time() - start_time
|
||||
now = time.time()
|
||||
if not self.on_demand_active and now >= self._next_live_priority_check:
|
||||
self._next_live_priority_check = now + 30.0
|
||||
live_mode = self._check_live_priority()
|
||||
if live_mode and live_mode != active_mode:
|
||||
logger.info("Live priority detected during high-FPS loop: %s", live_mode)
|
||||
self.current_display_mode = live_mode
|
||||
self.force_change = True
|
||||
try:
|
||||
self.current_mode_index = self.available_modes.index(live_mode)
|
||||
except ValueError:
|
||||
pass
|
||||
# continue the main while loop to skip
|
||||
# post-loop rotation/sleep logic
|
||||
break
|
||||
|
||||
if self.current_display_mode != active_mode:
|
||||
logger.debug("Mode changed during high-FPS loop, breaking early")
|
||||
break
|
||||
|
||||
elapsed = time.time() - start_time
|
||||
if elapsed >= target_duration:
|
||||
logger.debug(
|
||||
"Reached high-FPS target duration %.2fs for mode %s",
|
||||
@@ -1853,6 +1872,23 @@ class DisplayController:
|
||||
|
||||
self._poll_on_demand_requests()
|
||||
self._check_on_demand_expiration()
|
||||
|
||||
# Check for live priority every ~30s so live
|
||||
# games can interrupt long display durations
|
||||
now = time.time()
|
||||
if not self.on_demand_active and now >= self._next_live_priority_check:
|
||||
self._next_live_priority_check = now + 30.0
|
||||
live_mode = self._check_live_priority()
|
||||
if live_mode and live_mode != active_mode:
|
||||
logger.info("Live priority detected during display loop: %s", live_mode)
|
||||
self.current_display_mode = live_mode
|
||||
self.force_change = True
|
||||
try:
|
||||
self.current_mode_index = self.available_modes.index(live_mode)
|
||||
except ValueError:
|
||||
pass
|
||||
break
|
||||
|
||||
if self.current_display_mode != active_mode:
|
||||
logger.info("Mode changed during display loop from %s to %s, breaking early", active_mode, self.current_display_mode)
|
||||
break
|
||||
@@ -1866,6 +1902,13 @@ class DisplayController:
|
||||
loop_completed = True
|
||||
break
|
||||
|
||||
# If live priority preempted the display loop, skip
|
||||
# all post-loop logic (remaining sleep, rotation) and
|
||||
# restart the main loop so the live mode displays
|
||||
# immediately.
|
||||
if self.current_display_mode != active_mode:
|
||||
continue
|
||||
|
||||
# Ensure we honour minimum duration when not dynamic and loop ended early
|
||||
if (
|
||||
not dynamic_enabled
|
||||
|
||||
Reference in New Issue
Block a user