From 7618eafaa687174a2891769e9eec1eeaa64b62d6 Mon Sep 17 00:00:00 2001 From: Chuck <33324927+ChuckBuilds@users.noreply.github.com> Date: Mon, 15 Sep 2025 14:53:26 -0400 Subject: [PATCH] troubleshooting of the day manager --- src/music_manager.py | 53 ++++++++++++++++----------------------- src/of_the_day_manager.py | 51 ++++++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 38 deletions(-) diff --git a/src/music_manager.py b/src/music_manager.py index 4b24c269..5383efe6 100644 --- a/src/music_manager.py +++ b/src/music_manager.py @@ -27,10 +27,7 @@ except ImportError: logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) -# Define paths relative to this file's location -CONFIG_DIR = os.path.join(os.path.dirname(__file__), '..', 'config') -CONFIG_PATH = os.path.join(CONFIG_DIR, 'config.json') -# SECRETS_PATH is handled within SpotifyClient +# Note: Config is now passed in from DisplayController instead of being loaded separately class MusicSource(Enum): NONE = auto() @@ -72,37 +69,32 @@ class MusicManager: def _load_config(self): default_interval = 2 - # default_preferred_source = "auto" # Removed self.enabled = False # Assume disabled until config proves otherwise - if not os.path.exists(CONFIG_PATH): - logging.warning(f"Config file not found at {CONFIG_PATH}. Music manager disabled.") + # Use the config that was already loaded and passed to us instead of loading our own + if self.config is None: + logging.warning("No config provided to MusicManager. Music manager disabled.") return try: - with open(CONFIG_PATH, 'r') as f: - config_data = json.load(f) - music_config = config_data.get("music", {}) + music_config = self.config.get("music", {}) - self.enabled = music_config.get("enabled", False) - if not self.enabled: - logging.info("Music manager is disabled in config.json (top level 'enabled': false).") - return # Don't proceed further if disabled + self.enabled = music_config.get("enabled", False) + if not self.enabled: + logging.info("Music manager is disabled in config.json (top level 'enabled': false).") + return # Don't proceed further if disabled - self.polling_interval = music_config.get("POLLING_INTERVAL_SECONDS", default_interval) - configured_source = music_config.get("preferred_source", "spotify").lower() + self.polling_interval = music_config.get("POLLING_INTERVAL_SECONDS", default_interval) + configured_source = music_config.get("preferred_source", "spotify").lower() - if configured_source in ["spotify", "ytm"]: - self.preferred_source = configured_source - logging.info(f"Music manager enabled. Polling interval: {self.polling_interval}s. Preferred source: {self.preferred_source}") - else: - logging.warning(f"Invalid 'preferred_source' ('{configured_source}') in config.json. Must be 'spotify' or 'ytm'. Music manager disabled.") - self.enabled = False - return + if configured_source in ["spotify", "ytm"]: + self.preferred_source = configured_source + logging.info(f"Music manager enabled. Polling interval: {self.polling_interval}s. Preferred source: {self.preferred_source}") + else: + logging.warning(f"Invalid 'preferred_source' ('{configured_source}') in config.json. Must be 'spotify' or 'ytm'. Music manager disabled.") + self.enabled = False + return - except json.JSONDecodeError: - logging.error(f"Error decoding JSON from {CONFIG_PATH}. Music manager disabled.") - self.enabled = False except Exception as e: logging.error(f"Error loading music config: {e}. Music manager disabled.") self.enabled = False @@ -916,15 +908,12 @@ if __name__ == '__main__': # The MusicManager expects the overall config, not just the music part directly for its _load_config # So we simulate a config object that has a .get('music', {}) method. - # However, MusicManager's _load_config reads from CONFIG_PATH. - # For a true standalone test, we might need to mock file IO or provide a test config file. + # MusicManager now uses the passed config instead of loading from file. # Simplified test: - # manager = MusicManager(display_manager=mock_display, config=mock_config_main) # This won't work due to file reading + manager = MusicManager(display_manager=mock_display, config=mock_config_main) - # To truly test, you'd point CONFIG_PATH to a test config.json or mock open() - # For now, this __main__ block is mostly a placeholder. - logger.info("MusicManager standalone test setup is complex due to file dependencies for config.") + logger.info("MusicManager standalone test setup completed.") logger.info("To test: run the main application and observe logs from MusicManager.") # if manager.enabled: # manager.start_polling() diff --git a/src/of_the_day_manager.py b/src/of_the_day_manager.py index 6c93394b..ef5641a2 100644 --- a/src/of_the_day_manager.py +++ b/src/of_the_day_manager.py @@ -44,6 +44,7 @@ class OfTheDayManager: possible_font_dirs = [ os.path.abspath(os.path.join(script_dir, '..', 'assets', 'fonts')), # Relative to src/ os.path.abspath(os.path.join(os.getcwd(), 'assets', 'fonts')), # Relative to project root + os.path.abspath('assets/fonts'), # Simple relative path made absolute 'assets/fonts' # Simple relative path ] @@ -63,6 +64,12 @@ class OfTheDayManager: font_path = os.path.abspath(os.path.join(font_dir, filename)) if not os.path.exists(font_path): logger.debug(f"Font file not found: {font_path}") + # List available fonts for debugging + try: + available_fonts = [f for f in os.listdir(font_dir) if f.endswith('.bdf')] + logger.debug(f"Available BDF fonts in {font_dir}: {available_fonts}") + except: + pass return None logger.debug(f"Loading BDF font: {font_path}") return freetype.Face(font_path) @@ -128,6 +135,16 @@ class OfTheDayManager: logger.info(f"Loading data files for {len(self.categories)} categories") logger.info(f"Current working directory: {os.getcwd()}") logger.info(f"Script directory: {os.path.dirname(__file__)}") + + # Additional debugging for Pi environment + logger.debug(f"Absolute script directory: {os.path.abspath(os.path.dirname(__file__))}") + logger.debug(f"Absolute working directory: {os.path.abspath(os.getcwd())}") + + # Check if we're running on Pi + if os.path.exists('/home/ledpi'): + logger.debug("Detected Pi environment (/home/ledpi exists)") + else: + logger.debug("Not running on Pi environment") for category_name, category_config in self.categories.items(): logger.debug(f"Processing category: {category_name}") @@ -143,6 +160,7 @@ class OfTheDayManager: try: # Try multiple possible paths for data files script_dir = os.path.dirname(os.path.abspath(__file__)) + current_dir = os.getcwd() possible_paths = [] if os.path.isabs(data_file): @@ -152,13 +170,15 @@ class OfTheDayManager: if data_file.startswith('of_the_day/'): possible_paths.extend([ os.path.join(script_dir, '..', data_file), - os.path.join(os.getcwd(), data_file), + os.path.join(current_dir, data_file), + os.path.join('/home/ledpi/LEDMatrix', data_file), # Explicit Pi path data_file ]) else: possible_paths.extend([ os.path.join(script_dir, '..', 'of_the_day', data_file), - os.path.join(os.getcwd(), 'of_the_day', data_file), + os.path.join(current_dir, 'of_the_day', data_file), + os.path.join('/home/ledpi/LEDMatrix/of_the_day', data_file), # Explicit Pi path os.path.join('of_the_day', data_file) ]) @@ -174,6 +194,19 @@ class OfTheDayManager: # Use the first attempted path for error reporting file_path = os.path.abspath(possible_paths[0]) logger.debug(f"No data file found for {category_name}, tried: {[os.path.abspath(p) for p in possible_paths]}") + + # Additional debugging - check if parent directory exists + parent_dir = os.path.dirname(file_path) + logger.debug(f"Parent directory: {parent_dir}") + logger.debug(f"Parent directory exists: {os.path.exists(parent_dir)}") + if os.path.exists(parent_dir): + try: + parent_contents = os.listdir(parent_dir) + logger.debug(f"Parent directory contents: {parent_contents}") + except PermissionError: + logger.debug(f"Permission denied accessing parent directory: {parent_dir}") + except Exception as e: + logger.debug(f"Error listing parent directory: {e}") logger.debug(f"Attempting to load {category_name} from: {file_path}") @@ -200,11 +233,17 @@ class OfTheDayManager: else: logger.error(f"Data file not found for {category_name}: {file_path}") - if os.path.exists(os.path.dirname(file_path)): - dir_contents = os.listdir(os.path.dirname(file_path)) - logger.error(f"Directory contents: {dir_contents}") + parent_dir = os.path.dirname(file_path) + if os.path.exists(parent_dir): + try: + dir_contents = os.listdir(parent_dir) + logger.error(f"Directory contents of {parent_dir}: {dir_contents}") + except PermissionError: + logger.error(f"Permission denied accessing directory: {parent_dir}") + except Exception as e: + logger.error(f"Error listing directory {parent_dir}: {e}") else: - logger.error(f"Parent directory does not exist: {os.path.dirname(file_path)}") + logger.error(f"Parent directory does not exist: {parent_dir}") logger.error(f"Tried paths: {[os.path.abspath(p) for p in possible_paths]}") self.data_files[category_name] = {}