mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-29 12:03:00 +00:00
change how font is loaded via systemctl - added direct paths
This commit is contained in:
@@ -46,35 +46,11 @@ class CacheManager:
|
|||||||
self.logger.warning("ConfigManager not available, using default cache intervals")
|
self.logger.warning("ConfigManager not available, using default cache intervals")
|
||||||
|
|
||||||
def _get_writable_cache_dir(self) -> Optional[str]:
|
def _get_writable_cache_dir(self) -> Optional[str]:
|
||||||
"""Tries to find or create a writable cache directory in a few common locations."""
|
"""Tries to find or create a writable cache directory, preferring a system path when available."""
|
||||||
# Attempt 1: User's home directory (handling sudo)
|
# Attempt 1: System-wide persistent cache directory (preferred for services)
|
||||||
try:
|
try:
|
||||||
real_user = os.environ.get('SUDO_USER') or os.environ.get('USER', 'default')
|
|
||||||
if real_user and real_user != 'root':
|
|
||||||
home_dir = os.path.expanduser(f"~{real_user}")
|
|
||||||
else:
|
|
||||||
home_dir = os.path.expanduser('~')
|
|
||||||
|
|
||||||
user_cache_dir = os.path.join(home_dir, '.ledmatrix_cache')
|
|
||||||
os.makedirs(user_cache_dir, exist_ok=True)
|
|
||||||
|
|
||||||
# Test writability
|
|
||||||
test_file = os.path.join(user_cache_dir, '.writetest')
|
|
||||||
with open(test_file, 'w') as f:
|
|
||||||
f.write('test')
|
|
||||||
os.remove(test_file)
|
|
||||||
return user_cache_dir
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.warning(f"Could not use user-specific cache directory: {e}")
|
|
||||||
|
|
||||||
# Attempt 2: System-wide persistent cache directory (for sudo scenarios)
|
|
||||||
try:
|
|
||||||
# Try /var/cache/ledmatrix first (most standard)
|
|
||||||
system_cache_dir = '/var/cache/ledmatrix'
|
system_cache_dir = '/var/cache/ledmatrix'
|
||||||
|
|
||||||
# Check if directory exists and we can write to it
|
|
||||||
if os.path.exists(system_cache_dir):
|
if os.path.exists(system_cache_dir):
|
||||||
# Test if we can write to the existing directory
|
|
||||||
test_file = os.path.join(system_cache_dir, '.writetest')
|
test_file = os.path.join(system_cache_dir, '.writetest')
|
||||||
try:
|
try:
|
||||||
with open(test_file, 'w') as f:
|
with open(test_file, 'w') as f:
|
||||||
@@ -84,13 +60,30 @@ class CacheManager:
|
|||||||
except (IOError, OSError):
|
except (IOError, OSError):
|
||||||
self.logger.warning(f"Directory exists but is not writable: {system_cache_dir}")
|
self.logger.warning(f"Directory exists but is not writable: {system_cache_dir}")
|
||||||
else:
|
else:
|
||||||
# Try to create the directory
|
|
||||||
os.makedirs(system_cache_dir, exist_ok=True)
|
os.makedirs(system_cache_dir, exist_ok=True)
|
||||||
if os.access(system_cache_dir, os.W_OK):
|
if os.access(system_cache_dir, os.W_OK):
|
||||||
return system_cache_dir
|
return system_cache_dir
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not use /var/cache/ledmatrix: {e}")
|
self.logger.warning(f"Could not use /var/cache/ledmatrix: {e}")
|
||||||
|
|
||||||
|
# Attempt 2: User's home directory (handling sudo), but avoid /root preference
|
||||||
|
try:
|
||||||
|
real_user = os.environ.get('SUDO_USER') or os.environ.get('USER', 'default')
|
||||||
|
if real_user and real_user != 'root':
|
||||||
|
home_dir = os.path.expanduser(f"~{real_user}")
|
||||||
|
else:
|
||||||
|
# When running as root and /var/cache/ledmatrix failed, still allow fallback to /root
|
||||||
|
home_dir = os.path.expanduser('~')
|
||||||
|
user_cache_dir = os.path.join(home_dir, '.ledmatrix_cache')
|
||||||
|
os.makedirs(user_cache_dir, exist_ok=True)
|
||||||
|
test_file = os.path.join(user_cache_dir, '.writetest')
|
||||||
|
with open(test_file, 'w') as f:
|
||||||
|
f.write('test')
|
||||||
|
os.remove(test_file)
|
||||||
|
return user_cache_dir
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f"Could not use user-specific cache directory: {e}")
|
||||||
|
|
||||||
# Attempt 3: /opt/ledmatrix/cache (alternative persistent location)
|
# Attempt 3: /opt/ledmatrix/cache (alternative persistent location)
|
||||||
try:
|
try:
|
||||||
opt_cache_dir = '/opt/ledmatrix/cache'
|
opt_cache_dir = '/opt/ledmatrix/cache'
|
||||||
@@ -240,6 +233,16 @@ class CacheManager:
|
|||||||
pass
|
pass
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Atomic write failed for key '{key}': {e}")
|
self.logger.error(f"Atomic write failed for key '{key}': {e}")
|
||||||
|
# Attempt one-time fallback write directly into /var/cache/ledmatrix if available
|
||||||
|
try:
|
||||||
|
fallback_dir = '/var/cache/ledmatrix'
|
||||||
|
if os.path.isdir(fallback_dir) and os.access(fallback_dir, os.W_OK):
|
||||||
|
fallback_path = os.path.join(fallback_dir, os.path.basename(cache_path))
|
||||||
|
with open(fallback_path, 'w') as tmp_file:
|
||||||
|
json.dump(data, tmp_file, indent=4, cls=DateTimeEncoder)
|
||||||
|
self.logger.warning(f"Cache wrote to fallback location: {fallback_path}")
|
||||||
|
except Exception as e2:
|
||||||
|
self.logger.error(f"Fallback cache write also failed: {e2}")
|
||||||
|
|
||||||
except (IOError, OSError) as e:
|
except (IOError, OSError) as e:
|
||||||
self.logger.error(f"Failed to save cache for key '{key}': {e}")
|
self.logger.error(f"Failed to save cache for key '{key}': {e}")
|
||||||
|
|||||||
@@ -98,9 +98,11 @@ class DisplayManager:
|
|||||||
self.draw = ImageDraw.Draw(self.image)
|
self.draw = ImageDraw.Draw(self.image)
|
||||||
logger.info(f"Image canvas created with dimensions: {self.matrix.width}x{self.matrix.height}")
|
logger.info(f"Image canvas created with dimensions: {self.matrix.width}x{self.matrix.height}")
|
||||||
|
|
||||||
# Initialize font with Press Start 2P
|
# Initialize font with Press Start 2P using an absolute path so services don't fall back
|
||||||
try:
|
try:
|
||||||
self.font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
ps2p_path = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
|
self.font = ImageFont.truetype(ps2p_path, 8)
|
||||||
logger.info("Initial Press Start 2P font loaded successfully")
|
logger.info("Initial Press Start 2P font loaded successfully")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to load initial font: {e}")
|
logger.error(f"Failed to load initial font: {e}")
|
||||||
@@ -290,12 +292,14 @@ class DisplayManager:
|
|||||||
def _load_fonts(self):
|
def _load_fonts(self):
|
||||||
"""Load fonts with proper error handling."""
|
"""Load fonts with proper error handling."""
|
||||||
try:
|
try:
|
||||||
# Load Press Start 2P font
|
# Load Press Start 2P font using absolute path to avoid fallback when run under systemd
|
||||||
self.regular_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
ps2p_path = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
|
self.regular_font = ImageFont.truetype(ps2p_path, 8)
|
||||||
logger.info("Press Start 2P font loaded successfully")
|
logger.info("Press Start 2P font loaded successfully")
|
||||||
|
|
||||||
# Use the same font for small text, just at a smaller size
|
# Use the same font for small text (currently same size; adjust size here if needed)
|
||||||
self.small_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
self.small_font = ImageFont.truetype(ps2p_path, 8)
|
||||||
logger.info("Press Start 2P small font loaded successfully")
|
logger.info("Press Start 2P small font loaded successfully")
|
||||||
|
|
||||||
# Load 5x7 BDF font for calendar events
|
# Load 5x7 BDF font for calendar events
|
||||||
|
|||||||
@@ -336,8 +336,10 @@ class BaseMiLBManager:
|
|||||||
date_font = getattr(self.display_manager, 'small_font', None)
|
date_font = getattr(self.display_manager, 'small_font', None)
|
||||||
time_font = getattr(self.display_manager, 'small_font', None)
|
time_font = getattr(self.display_manager, 'small_font', None)
|
||||||
if date_font is None or time_font is None:
|
if date_font is None or time_font is None:
|
||||||
date_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
time_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
|
date_font = ImageFont.truetype(ps2p, 8)
|
||||||
|
time_font = ImageFont.truetype(ps2p, 8)
|
||||||
self.logger.debug(f"[MiLB] Fonts prepared successfully")
|
self.logger.debug(f"[MiLB] Fonts prepared successfully")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"[MiLB] Failed to prepare fonts: {e}")
|
self.logger.error(f"[MiLB] Failed to prepare fonts: {e}")
|
||||||
@@ -403,7 +405,9 @@ class BaseMiLBManager:
|
|||||||
away_score = str(game_data['away_score'])
|
away_score = str(game_data['away_score'])
|
||||||
home_score = str(game_data['home_score'])
|
home_score = str(game_data['home_score'])
|
||||||
score_text = f"{away_score}-{home_score}"
|
score_text = f"{away_score}-{home_score}"
|
||||||
score_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
|
score_font = ImageFont.truetype(ps2p, 12)
|
||||||
|
|
||||||
# Calculate position for the score text
|
# Calculate position for the score text
|
||||||
score_width = draw.textlength(score_text, font=score_font)
|
score_width = draw.textlength(score_text, font=score_font)
|
||||||
@@ -415,7 +419,10 @@ class BaseMiLBManager:
|
|||||||
# Draw records for upcoming and recent games
|
# Draw records for upcoming and recent games
|
||||||
if self.show_records and game_data['status'] in ['status_scheduled', 'status_final', 'final', 'completed']:
|
if self.show_records and game_data['status'] in ['status_scheduled', 'status_final', 'final', 'completed']:
|
||||||
try:
|
try:
|
||||||
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
# Resolve 4x6 font via absolute path
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||||
|
record_font = ImageFont.truetype(font_4x6, 6)
|
||||||
except IOError:
|
except IOError:
|
||||||
record_font = ImageFont.load_default()
|
record_font = ImageFont.load_default()
|
||||||
|
|
||||||
|
|||||||
@@ -264,8 +264,10 @@ class BaseMLBManager:
|
|||||||
game_time_str = self._format_game_time(game_data['start_time'])
|
game_time_str = self._format_game_time(game_data['start_time'])
|
||||||
|
|
||||||
# Draw date and time using NHL-style fonts
|
# Draw date and time using NHL-style fonts
|
||||||
date_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
time_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
|
date_font = ImageFont.truetype(ps2p, 8)
|
||||||
|
time_font = ImageFont.truetype(ps2p, 8)
|
||||||
|
|
||||||
# Draw date in center
|
# Draw date in center
|
||||||
date_width = draw.textlength(game_date, font=date_font)
|
date_width = draw.textlength(game_date, font=date_font)
|
||||||
@@ -302,7 +304,7 @@ class BaseMLBManager:
|
|||||||
away_score = str(game_data['away_score'])
|
away_score = str(game_data['away_score'])
|
||||||
home_score = str(game_data['home_score'])
|
home_score = str(game_data['home_score'])
|
||||||
display_text = f"{away_score}-{home_score}"
|
display_text = f"{away_score}-{home_score}"
|
||||||
font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
font = ImageFont.truetype(ps2p, 12)
|
||||||
display_width = draw.textlength(display_text, font=font)
|
display_width = draw.textlength(display_text, font=font)
|
||||||
display_x = (width - display_width) // 2
|
display_x = (width - display_width) // 2
|
||||||
display_y = (height - font.size) // 2
|
display_y = (height - font.size) // 2
|
||||||
@@ -330,7 +332,7 @@ class BaseMLBManager:
|
|||||||
away_score = str(game_data['away_score'])
|
away_score = str(game_data['away_score'])
|
||||||
home_score = str(game_data['home_score'])
|
home_score = str(game_data['home_score'])
|
||||||
score_text = f"{away_score}-{home_score}"
|
score_text = f"{away_score}-{home_score}"
|
||||||
score_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
score_font = ImageFont.truetype(ps2p, 12)
|
||||||
|
|
||||||
# Calculate position for the score text
|
# Calculate position for the score text
|
||||||
score_width = draw.textlength(score_text, font=score_font)
|
score_width = draw.textlength(score_text, font=score_font)
|
||||||
|
|||||||
@@ -193,11 +193,14 @@ class BaseNBAManager:
|
|||||||
"""Load fonts used by the scoreboard."""
|
"""Load fonts used by the scoreboard."""
|
||||||
fonts = {}
|
fonts = {}
|
||||||
try:
|
try:
|
||||||
# Try to load the Press Start 2P font first
|
# Try to load the Press Start 2P font first using absolute paths
|
||||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
fonts['score'] = ImageFont.truetype(ps2p, 10)
|
||||||
|
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['status'] = ImageFont.truetype(font_4x6, 6)
|
||||||
logging.info("[NBA] Successfully loaded Press Start 2P font for all text elements")
|
logging.info("[NBA] Successfully loaded Press Start 2P font for all text elements")
|
||||||
except IOError:
|
except IOError:
|
||||||
logging.warning("[NBA] Press Start 2P font not found, trying 4x6 font.")
|
logging.warning("[NBA] Press Start 2P font not found, trying 4x6 font.")
|
||||||
|
|||||||
@@ -240,7 +240,9 @@ class BaseNCAABaseballManager:
|
|||||||
status_x = (width - status_width) // 2
|
status_x = (width - status_width) // 2
|
||||||
status_y = 2
|
status_y = 2
|
||||||
self.display_manager.draw = draw
|
self.display_manager.draw = draw
|
||||||
status_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using a default small font
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||||
|
status_font = ImageFont.truetype(font_4x6, 6) # Using a default small font
|
||||||
self._draw_text_with_outline(draw, status_text, (status_x, status_y), status_font)
|
self._draw_text_with_outline(draw, status_text, (status_x, status_y), status_font)
|
||||||
|
|
||||||
game_time = datetime.fromisoformat(game_data['start_time'].replace('Z', '+00:00'))
|
game_time = datetime.fromisoformat(game_data['start_time'].replace('Z', '+00:00'))
|
||||||
@@ -263,8 +265,9 @@ class BaseNCAABaseballManager:
|
|||||||
|
|
||||||
game_time_str = self._format_game_time(game_data['start_time'])
|
game_time_str = self._format_game_time(game_data['start_time'])
|
||||||
|
|
||||||
date_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
time_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
date_font = ImageFont.truetype(ps2p, 8)
|
||||||
|
time_font = ImageFont.truetype(ps2p, 8)
|
||||||
|
|
||||||
date_width = draw.textlength(game_date, font=date_font)
|
date_width = draw.textlength(game_date, font=date_font)
|
||||||
date_x = (width - date_width) // 2
|
date_x = (width - date_width) // 2
|
||||||
@@ -279,7 +282,7 @@ class BaseNCAABaseballManager:
|
|||||||
# For recent/final games, show scores and status
|
# For recent/final games, show scores and status
|
||||||
elif game_data['status'] in ['status_final', 'final', 'completed']:
|
elif game_data['status'] in ['status_final', 'final', 'completed']:
|
||||||
status_text = "Final"
|
status_text = "Final"
|
||||||
status_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using a default small font
|
status_font = ImageFont.truetype(font_4x6, 6) # Using a default small font
|
||||||
status_width = draw.textlength(status_text, font=status_font)
|
status_width = draw.textlength(status_text, font=status_font)
|
||||||
status_x = (width - status_width) // 2
|
status_x = (width - status_width) // 2
|
||||||
status_y = 2
|
status_y = 2
|
||||||
@@ -289,7 +292,7 @@ class BaseNCAABaseballManager:
|
|||||||
away_score = str(game_data['away_score'])
|
away_score = str(game_data['away_score'])
|
||||||
home_score = str(game_data['home_score'])
|
home_score = str(game_data['home_score'])
|
||||||
score_text = f"{away_score}-{home_score}"
|
score_text = f"{away_score}-{home_score}"
|
||||||
score_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
score_font = ImageFont.truetype(ps2p, 12)
|
||||||
|
|
||||||
score_width = draw.textlength(score_text, font=score_font)
|
score_width = draw.textlength(score_text, font=score_font)
|
||||||
score_x = (width - score_width) // 2
|
score_x = (width - score_width) // 2
|
||||||
@@ -298,7 +301,7 @@ class BaseNCAABaseballManager:
|
|||||||
|
|
||||||
if self.show_records and game_data['status'] in ['status_scheduled', 'status_final', 'final', 'completed']:
|
if self.show_records and game_data['status'] in ['status_scheduled', 'status_final', 'final', 'completed']:
|
||||||
try:
|
try:
|
||||||
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
record_font = ImageFont.truetype(font_4x6, 6)
|
||||||
except IOError:
|
except IOError:
|
||||||
record_font = ImageFont.load_default()
|
record_font = ImageFont.load_default()
|
||||||
|
|
||||||
@@ -339,7 +342,7 @@ class BaseNCAABaseballManager:
|
|||||||
# Define colors for odds text
|
# Define colors for odds text
|
||||||
# Use a small readable font for odds; fall back to default if not available
|
# Use a small readable font for odds; fall back to default if not available
|
||||||
try:
|
try:
|
||||||
odds_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
odds_font = ImageFont.truetype(font_4x6, 6)
|
||||||
except IOError:
|
except IOError:
|
||||||
odds_font = ImageFont.load_default()
|
odds_font = ImageFont.load_default()
|
||||||
odds_color = (255, 0, 0) # Red text
|
odds_color = (255, 0, 0) # Red text
|
||||||
|
|||||||
@@ -211,11 +211,14 @@ class BaseNCAAFBManager: # Renamed class
|
|||||||
"""Load fonts used by the scoreboard."""
|
"""Load fonts used by the scoreboard."""
|
||||||
fonts = {}
|
fonts = {}
|
||||||
try:
|
try:
|
||||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using 4x6 for status
|
fonts['score'] = ImageFont.truetype(ps2p, 10)
|
||||||
fonts['detail'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Added detail font
|
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['status'] = ImageFont.truetype(font_4x6, 6) # Using 4x6 for status
|
||||||
|
fonts['detail'] = ImageFont.truetype(font_4x6, 6) # Added detail font
|
||||||
logging.info("[NCAAFB] Successfully loaded fonts") # Changed log prefix
|
logging.info("[NCAAFB] Successfully loaded fonts") # Changed log prefix
|
||||||
except IOError:
|
except IOError:
|
||||||
logging.warning("[NCAAFB] Fonts not found, using default PIL font.") # Changed log prefix
|
logging.warning("[NCAAFB] Fonts not found, using default PIL font.") # Changed log prefix
|
||||||
|
|||||||
@@ -213,11 +213,13 @@ class BaseNCAAMBasketballManager:
|
|||||||
"""Load fonts used by the scoreboard."""
|
"""Load fonts used by the scoreboard."""
|
||||||
fonts = {}
|
fonts = {}
|
||||||
try:
|
try:
|
||||||
# Try to load the Press Start 2P font first
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
fonts['score'] = ImageFont.truetype(ps2p, 10)
|
||||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['status'] = ImageFont.truetype(font_4x6, 6)
|
||||||
logging.info("[NCAAMBasketball] Successfully loaded Press Start 2P font for all text elements")
|
logging.info("[NCAAMBasketball] Successfully loaded Press Start 2P font for all text elements")
|
||||||
except IOError:
|
except IOError:
|
||||||
logging.warning("[NCAAMBasketball] Press Start 2P font not found, trying 4x6 font.")
|
logging.warning("[NCAAMBasketball] Press Start 2P font not found, trying 4x6 font.")
|
||||||
|
|||||||
@@ -182,11 +182,14 @@ class BaseNFLManager: # Renamed class
|
|||||||
"""Load fonts used by the scoreboard."""
|
"""Load fonts used by the scoreboard."""
|
||||||
fonts = {}
|
fonts = {}
|
||||||
try:
|
try:
|
||||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using 4x6 for status
|
fonts['score'] = ImageFont.truetype(ps2p, 10)
|
||||||
fonts['detail'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Added detail font
|
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['status'] = ImageFont.truetype(font_4x6, 6) # Using 4x6 for status
|
||||||
|
fonts['detail'] = ImageFont.truetype(font_4x6, 6) # Added detail font
|
||||||
logging.info("[NFL] Successfully loaded fonts")
|
logging.info("[NFL] Successfully loaded fonts")
|
||||||
except IOError:
|
except IOError:
|
||||||
logging.warning("[NFL] Fonts not found, using default PIL font.")
|
logging.warning("[NFL] Fonts not found, using default PIL font.")
|
||||||
|
|||||||
@@ -162,11 +162,13 @@ class BaseNHLManager:
|
|||||||
"""Load fonts used by the scoreboard."""
|
"""Load fonts used by the scoreboard."""
|
||||||
fonts = {}
|
fonts = {}
|
||||||
try:
|
try:
|
||||||
# Try to load the Press Start 2P font first
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
fonts['score'] = ImageFont.truetype(ps2p, 12)
|
||||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['status'] = ImageFont.truetype(font_4x6, 6)
|
||||||
logging.info("[NHL] Successfully loaded Press Start 2P font for all text elements")
|
logging.info("[NHL] Successfully loaded Press Start 2P font for all text elements")
|
||||||
except IOError:
|
except IOError:
|
||||||
logging.warning("[NHL] Press Start 2P font not found, trying 4x6 font.")
|
logging.warning("[NHL] Press Start 2P font not found, trying 4x6 font.")
|
||||||
|
|||||||
@@ -185,10 +185,12 @@ class OddsTickerManager:
|
|||||||
def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]:
|
def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]:
|
||||||
"""Load fonts for the ticker display."""
|
"""Load fonts for the ticker display."""
|
||||||
try:
|
try:
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
return {
|
return {
|
||||||
'small': ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 6),
|
'small': ImageFont.truetype(ps2p, 6),
|
||||||
'medium': ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8),
|
'medium': ImageFont.truetype(ps2p, 8),
|
||||||
'large': ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
'large': ImageFont.truetype(ps2p, 10)
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error loading fonts: {e}")
|
logger.error(f"Error loading fonts: {e}")
|
||||||
|
|||||||
@@ -312,10 +312,13 @@ class BaseSoccerManager:
|
|||||||
"""Load fonts used by the scoreboard."""
|
"""Load fonts used by the scoreboard."""
|
||||||
fonts = {}
|
fonts = {}
|
||||||
try:
|
try:
|
||||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10) # Slightly larger score
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
fonts['team'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Keep team abbr small
|
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Keep status small
|
fonts['score'] = ImageFont.truetype(ps2p, 10) # Slightly larger score
|
||||||
|
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||||
|
fonts['team'] = ImageFont.truetype(font_4x6, 6) # Keep team abbr small
|
||||||
|
fonts['status'] = ImageFont.truetype(font_4x6, 6) # Keep status small
|
||||||
logging.info("[Soccer] Successfully loaded custom fonts")
|
logging.info("[Soccer] Successfully loaded custom fonts")
|
||||||
except IOError:
|
except IOError:
|
||||||
logging.warning("[Soccer] Custom fonts not found, using default PIL font.")
|
logging.warning("[Soccer] Custom fonts not found, using default PIL font.")
|
||||||
@@ -410,7 +413,8 @@ class BaseSoccerManager:
|
|||||||
draw = ImageDraw.Draw(logo)
|
draw = ImageDraw.Draw(logo)
|
||||||
# Optionally add text to placeholder
|
# Optionally add text to placeholder
|
||||||
try:
|
try:
|
||||||
placeholder_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 12)
|
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||||
|
placeholder_font = ImageFont.truetype(font_4x6, 12)
|
||||||
text_width = draw.textlength(team_abbrev, font=placeholder_font)
|
text_width = draw.textlength(team_abbrev, font=placeholder_font)
|
||||||
text_x = (36 - text_width) // 2
|
text_x = (36 - text_width) // 2
|
||||||
text_y = 10
|
text_y = 10
|
||||||
|
|||||||
@@ -428,7 +428,10 @@ class StockManager:
|
|||||||
fallback = Image.new('RGBA', (32, 32), (0, 0, 0, 0))
|
fallback = Image.new('RGBA', (32, 32), (0, 0, 0, 0))
|
||||||
draw = ImageDraw.Draw(fallback)
|
draw = ImageDraw.Draw(fallback)
|
||||||
try:
|
try:
|
||||||
font = ImageFont.truetype("assets/fonts/OpenSans-Regular.ttf", 16)
|
# Resolve font path absolutely to avoid fallback under systemd
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
font_path = os.path.abspath(os.path.join(script_dir, "../assets/fonts/OpenSans-Regular.ttf"))
|
||||||
|
font = ImageFont.truetype(font_path, 16)
|
||||||
except:
|
except:
|
||||||
font = ImageFont.load_default()
|
font = ImageFont.load_default()
|
||||||
|
|
||||||
|
|||||||
@@ -96,12 +96,10 @@ class TextDisplay:
|
|||||||
def _load_font(self):
|
def _load_font(self):
|
||||||
"""Load the specified font file (TTF or BDF)."""
|
"""Load the specified font file (TTF or BDF)."""
|
||||||
font_path = self.font_path
|
font_path = self.font_path
|
||||||
if not os.path.isabs(font_path) and not font_path.startswith('assets/'):
|
# Resolve relative paths against project root based on this file location
|
||||||
base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
if not os.path.isabs(font_path):
|
||||||
font_path = os.path.join(base_path, font_path)
|
base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
elif not os.path.isabs(font_path) and font_path.startswith('assets/'):
|
font_path = os.path.join(base_path, font_path)
|
||||||
base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
|
||||||
font_path = os.path.join(base_path, font_path)
|
|
||||||
|
|
||||||
logger.info(f"Attempting to load font: {font_path} at size {self.font_size}")
|
logger.info(f"Attempting to load font: {font_path} at size {self.font_size}")
|
||||||
|
|
||||||
|
|||||||
@@ -337,7 +337,8 @@ class WeatherManager:
|
|||||||
# --- Right Side (Below Condition): Current Temp ---
|
# --- Right Side (Below Condition): Current Temp ---
|
||||||
temp = round(weather_data['main']['temp'])
|
temp = round(weather_data['main']['temp'])
|
||||||
temp_text = f"{temp}°"
|
temp_text = f"{temp}°"
|
||||||
temp_font = self.display_manager.small_font # Using small font
|
# Ensure we use the intended PS2P font managed by DisplayManager
|
||||||
|
temp_font = getattr(self.display_manager, 'regular_font', self.display_manager.small_font)
|
||||||
temp_text_width = draw.textlength(temp_text, font=temp_font)
|
temp_text_width = draw.textlength(temp_text, font=temp_font)
|
||||||
temp_x = self.display_manager.matrix.width - temp_text_width - 1 # Align right
|
temp_x = self.display_manager.matrix.width - temp_text_width - 1 # Align right
|
||||||
temp_y = condition_y + 8 # Position below condition text (adjust 8 based on font size)
|
temp_y = condition_y + 8 # Position below condition text (adjust 8 based on font size)
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ class YouTubeDisplay:
|
|||||||
|
|
||||||
def _initialize_display(self):
|
def _initialize_display(self):
|
||||||
"""Initialize display components."""
|
"""Initialize display components."""
|
||||||
self.font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||||
|
self.font = ImageFont.truetype(ps2p, 8)
|
||||||
try:
|
try:
|
||||||
self.youtube_logo = Image.open("assets/youtube_logo.png")
|
self.youtube_logo = Image.open("assets/youtube_logo.png")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user