mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 21:03:01 +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)
|
logger.info("Display modes initialized in %.3f seconds", time.time() - init_time)
|
||||||
|
|
||||||
self.force_change = False
|
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
|
# All sports and content managers now handled via plugins
|
||||||
logger.info("All sports and content managers now handled via plugin system")
|
logger.info("All sports and content managers now handled via plugin system")
|
||||||
@@ -1790,11 +1791,29 @@ class DisplayController:
|
|||||||
self._poll_on_demand_requests()
|
self._poll_on_demand_requests()
|
||||||
self._check_on_demand_expiration()
|
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:
|
if self.current_display_mode != active_mode:
|
||||||
logger.debug("Mode changed during high-FPS loop, breaking early")
|
logger.debug("Mode changed during high-FPS loop, breaking early")
|
||||||
break
|
break
|
||||||
|
|
||||||
elapsed = time.time() - start_time
|
|
||||||
if elapsed >= target_duration:
|
if elapsed >= target_duration:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Reached high-FPS target duration %.2fs for mode %s",
|
"Reached high-FPS target duration %.2fs for mode %s",
|
||||||
@@ -1853,6 +1872,23 @@ class DisplayController:
|
|||||||
|
|
||||||
self._poll_on_demand_requests()
|
self._poll_on_demand_requests()
|
||||||
self._check_on_demand_expiration()
|
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:
|
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)
|
logger.info("Mode changed during display loop from %s to %s, breaking early", active_mode, self.current_display_mode)
|
||||||
break
|
break
|
||||||
@@ -1866,6 +1902,13 @@ class DisplayController:
|
|||||||
loop_completed = True
|
loop_completed = True
|
||||||
break
|
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
|
# Ensure we honour minimum duration when not dynamic and loop ended early
|
||||||
if (
|
if (
|
||||||
not dynamic_enabled
|
not dynamic_enabled
|
||||||
|
|||||||
Reference in New Issue
Block a user