diff --git a/run_app.sh b/run_app.sh index 98a9320..7726135 100755 --- a/run_app.sh +++ b/run_app.sh @@ -3,7 +3,7 @@ # filepath: /home/pi/Desktop/signage-player/run_app.sh # Navigate to the application directory -cd /home/pi/signage-player/src || exit +cd /home/pi/Desktop/signage-player/src || exit # Check for the --verbose flag if [[ "$1" == "--verbose" ]]; then diff --git a/src/Resurse/app_config.txt b/src/Resurse/app_config.txt index b36229d..c9a19bb 100644 --- a/src/Resurse/app_config.txt +++ b/src/Resurse/app_config.txt @@ -1 +1 @@ -{"screen_orientation": "Landscape", "screen_name": "tv-terasa", "quickconnect_key": "8887779", "server_ip": "digi-signage.moto-adv.com", "port": "80", "screen_w": "1920", "screen_h": "1080"} \ No newline at end of file +{"screen_orientation": "Landscape", "screen_name": "rpi-tv11", "quickconnect_key": "8887779", "server_ip": "192.168.1.74", "port": "5000", "screen_w": "1920", "screen_h": "1080"} \ No newline at end of file diff --git a/src/Resurse/log.txt b/src/Resurse/log.txt index b42c430..efc93c4 100644 --- a/src/Resurse/log.txt +++ b/src/Resurse/log.txt @@ -1,15 +1,2 @@ -2025-06-19 16:03:02 - STARTED: IMG-20250526-WA0003.jpg -2025-06-19 16:03:03 - STARTED: IMG-20250602-WA0011.jpg -2025-06-19 16:03:23 - STARTED: IMG_20250601_192845.jpg -2025-06-19 16:03:43 - STARTED: IMG_20250601_185017.jpg -2025-06-19 16:04:03 - STARTED: IMG_20250601_185019.jpg -2025-06-19 16:04:23 - STARTED: IMG_20250601_180727.jpg -2025-06-19 16:04:43 - STARTED: IMG_20250601_174724.jpg -2025-06-19 16:05:03 - STARTED: IMG-20250531-WA0070.jpg -2025-06-19 16:05:23 - STARTED: IMG-20250604-WA0006.jpg -2025-06-19 16:05:43 - STARTED: IMG-20250526-WA0003.jpg -2025-06-19 16:06:03 - STARTED: IMG-20250602-WA0011.jpg -2025-06-19 16:06:23 - STARTED: IMG_20250601_192845.jpg -2025-06-19 16:06:43 - STARTED: IMG_20250601_185017.jpg -2025-06-19 16:39:23 - STARTED: IMG-20250526-WA0003.jpg -2025-06-19 16:39:23 - STARTED: IMG-20250602-WA0011.jpg +2025-06-20 16:32:40 - STARTED: edit_pencil.png +2025-06-20 16:33:00 - STARTED: delete.png diff --git a/src/__pycache__/python_functions.cpython-311.pyc b/src/__pycache__/python_functions.cpython-311.pyc index 5056009..b22c0c9 100644 Binary files a/src/__pycache__/python_functions.cpython-311.pyc and b/src/__pycache__/python_functions.cpython-311.pyc differ diff --git a/src/__pycache__/python_functions2.cpython-311.pyc b/src/__pycache__/python_functions2.cpython-311.pyc new file mode 100644 index 0000000..d77abfc Binary files /dev/null and b/src/__pycache__/python_functions2.cpython-311.pyc differ diff --git a/src/media_player.py b/src/media_player.py index eec21fd..33ff255 100644 --- a/src/media_player.py +++ b/src/media_player.py @@ -23,7 +23,7 @@ import datetime # Import datetime for timestamping logs import subprocess # Import functions from python_functions.py -from python_functions import load_playlist, download_media_files, clean_unused_files +from python_functions import load_local_playlist, download_media_files, clean_unused_files, fetch_server_playlist # Load the KV file for UI layout Builder.load_file('kv/media_player.kv') @@ -102,10 +102,36 @@ class MediaPlayer(Screen): def on_enter(self): """Called when the screen is entered.""" - self.playlist = load_playlist() # Load the playlist (local or server) - if self.playlist: # Only proceed if the playlist is not empty - download_media_files(self.playlist) # Download media files if the playlist has changed - clean_unused_files(self.playlist) # Remove unused files from the resource folder + Logger.info("MediaPlayer: Entering screen...") + + # Attempt to load the local playlist + self.playlist = load_local_playlist() + Logger.info(f"MediaPlayer: Loaded local playlist: {self.playlist}") + + if not self.playlist: # If no local playlist exists + Logger.warning("MediaPlayer: No local playlist found. Fetching from server...") + + # Fetch the server playlist + server_playlist_data = fetch_server_playlist() + server_playlist = server_playlist_data.get('playlist', []) + server_version = server_playlist_data.get('version', 0) + + if server_playlist: # If server playlist is valid + Logger.info("MediaPlayer: Server playlist fetched successfully.") + + # Download media files and save the playlist locally + download_media_files(server_playlist, server_version) + self.playlist = load_local_playlist() # Reload the updated local playlist + + if self.playlist: + Logger.info("MediaPlayer: Local playlist updated successfully.") + else: + Logger.error("MediaPlayer: Failed to update local playlist.") + else: + Logger.error("MediaPlayer: Failed to fetch server playlist. No media to play.") + return + + if self.playlist: # If the playlist is loaded successfully self.play_media() # Start playing media self.show_buttons() # Ensure buttons are visible when the screen is entered else: @@ -159,7 +185,7 @@ class MediaPlayer(Screen): Logger.error(f"Failed to clean up old logs: {e}") def play_media(self): - # Play the current media in the playlist. + """Play the current media in the playlist.""" if self.playlist: media = self.playlist[self.current_index] # Get the current media file_name = media.get('file_name', '') # Get the file name @@ -214,11 +240,11 @@ class MediaPlayer(Screen): Logger.warning("Video duration is unknown. Using default duration") def show_image(self, file_path, duration): - # Display an image with a fade-in effect. + """Display an image with a fade-in effect.""" Logger.info(f"Showing image: {file_path}") if not os.path.exists(file_path): Logger.error(f"Image file not found: {file_path}") - #return # Ensure this return is properly indented within the method + return # Set the image source self.image_display.source = file_path @@ -320,14 +346,28 @@ class MediaPlayer(Screen): self.ids.play_pause_button.background_normal = './Resurse/play.png' def check_playlist_updates(self, dt): - #Check for updates to the playlist.""" - new_playlist = load_playlist() # Load the new playlist - if new_playlist != self.playlist: # Compare the new playlist with the current one - Logger.info("Playlist updated. Changes detected.") - self.updated_playlist = new_playlist # Store the updated playlist - self.is_playlist_update_pending = True # Mark the update as pending + """Check for updates to the playlist.""" + Logger.info("Checking for playlist updates...") + + # Fetch the server playlist + server_playlist_data = fetch_server_playlist() # Fetch the playlist from the server + server_playlist = server_playlist_data.get('playlist', []) + server_version = server_playlist_data.get('version', 0) + + # Load the local playlist + local_playlist_data = load_local_playlist() # Load the local playlist + local_version = local_playlist_data.get('version', 0) if local_playlist_data else 0 + + # Compare versions + if server_version != local_version: # If versions differ + Logger.info(f"Playlist version mismatch detected. Local version: {local_version}, Server version: {server_version}") + + # Update the local playlist and download new media files + download_media_files(server_playlist) # Download media files from the server + self.playlist = load_local_playlist() # Reload the updated local playlist + Logger.info("Playlist updated successfully.") else: - Logger.info("Playlist update skipped. No changes detected.") + Logger.info("Playlist versions match. No update needed.") class SettingsScreen(Screen): """Settings screen for configuring the app.""" diff --git a/src/python_functions.py b/src/python_functions.py index 88e5a10..f2cb39f 100644 --- a/src/python_functions.py +++ b/src/python_functions.py @@ -2,9 +2,12 @@ import os import json import requests from kivy.logger import Logger +import bcrypt +import time CONFIG_FILE = './Resurse/app_config.txt' LOCAL_PLAYLIST_FILE = './static/local_playlist.json' # Path to the local playlist file + def load_config(): """Load configuration from app_config.txt.""" if os.path.exists(CONFIG_FILE): @@ -14,49 +17,55 @@ def load_config(): return json.load(file) except json.JSONDecodeError as e: Logger.error(f"python_functions: Failed to parse configuration file. Error: {e}") - return { - "screen_orientation": "Landscape", - "screen_name": "", - "quickconnect_key": "", - "server_ip": "", - "port": "" - } + return {} else: Logger.error(f"python_functions: Configuration file {CONFIG_FILE} not found.") - return { - "screen_orientation": "Landscape", - "screen_name": "", - "quickconnect_key": "", - "server_ip": "", - "port": "" - } + return {} # Load configuration and initialize variables config_data = load_config() server = config_data.get("server_ip", "") host = config_data.get("screen_name", "") quick = config_data.get("quickconnect_key", "") -port = config_data.get("port", "") -# Determine the configuration status -if server and host and quick and port: - config_status = "ok" -else: - config_status = "not_ok" +port = config_data.get("port", "") Logger.info(f"python_functions: Configuration loaded: server={server}, host={host}, quick={quick}, port={port}") -Logger.info(f"python_functions: Configuration status: {config_status}") +def load_local_playlist(): + """Load the playlist from local storage.""" + if os.path.exists(LOCAL_PLAYLIST_FILE): + try: + with open(LOCAL_PLAYLIST_FILE, 'r') as local_file: + local_playlist = json.load(local_file) + Logger.info(f"python_functions: Local playlist loaded: {local_playlist}") + if isinstance(local_playlist, dict) and 'playlist' in local_playlist and 'version' in local_playlist: + return local_playlist.get('playlist', []) + else: + Logger.error("python_functions: Invalid local playlist structure.") + return [] + except json.JSONDecodeError as e: + Logger.error(f"python_functions: Failed to parse local playlist file. Error: {e}") + return [] + else: + Logger.warning("python_functions: Local playlist file not found.") + return [] -def load_playlist(): - """Load playlist from the server or local storage.""" - # Check if the local playlist exists and is valid - local_playlist = load_local_playlist() - if local_playlist: - Logger.info("python_functions: Using local playlist.") - return local_playlist # Skip server download if local playlist is valid +def save_local_playlist(playlist): + """Save the updated playlist locally.""" + if not playlist or 'playlist' not in playlist: + Logger.error("python_functions: Invalid playlist data. Cannot save local playlist.") + return try: - Logger.info("python_functions: Attempting to load playlist from server...") + with open(LOCAL_PLAYLIST_FILE, 'w') as local_file: + json.dump(playlist, local_file) + Logger.info("python_functions: Updated local playlist with server data.") + except IOError as e: + Logger.error(f"python_functions: Failed to save local playlist: {e}") + +def fetch_server_playlist(): + """Fetch the updated playlist from the server.""" + try: server_ip = f'{server}:{port}' # Construct the server IP with port url = f'http://{server_ip}/api/playlists' params = { @@ -65,104 +74,83 @@ def load_playlist(): } response = requests.get(url, params=params) - # Print the raw response content and status code for debugging - Logger.debug(f"python_functions: Status Code: {response.status_code}") - Logger.debug(f"python_functions: Response Content: {response.text}") - - # Check if the request was successful if response.status_code == 200: - try: - # Parse the JSON response - server_data = response.json() - playlist = server_data.get('playlist', []) + response_data = response.json() + playlist = response_data.get('playlist', []) + version = response_data.get('playlist_version', None) + hashed_quickconnect = response_data.get('hashed_quickconnect', None) - # Validate the playlist structure - if isinstance(playlist, list) and all(isinstance(item, dict) for item in playlist): - Logger.info("python_functions: Playlist loaded successfully.") - Logger.debug(f"python_functions: Loaded playlist: {playlist}") - - # Save the playlist locally - with open(LOCAL_PLAYLIST_FILE, 'w') as local_file: - json.dump(playlist, local_file) - Logger.info("python_functions: Updated local playlist with server data.") - - return playlist + if version is not None and hashed_quickconnect is not None: + if bcrypt.checkpw(quick.encode('utf-8'), hashed_quickconnect.encode('utf-8')): + Logger.info("python_functions: Fetched updated playlist from server.") + return {'playlist': playlist, 'version': version} else: - Logger.error("python_functions: Invalid playlist structure from server.") - except json.JSONDecodeError as e: - Logger.error(f"python_functions: Failed to parse JSON response: {e}") + Logger.error("python_functions: Quickconnect code validation failed.") + else: + Logger.error("python_functions: Failed to retrieve playlist or hashed quickconnect from the response.") else: - Logger.error(f"python_functions: Failed to retrieve playlist. Status Code: {response.status_code}") + Logger.error(f"python_functions: Failed to fetch playlist. Status Code: {response.status_code}") except requests.exceptions.RequestException as e: - Logger.error(f"python_functions: Failed to load playlist: {e}") + Logger.error(f"python_functions: Failed to fetch playlist: {e}") - # Fallback to local playlist - return local_playlist + return {'playlist': [], 'version': 0} - -def load_local_playlist(): - """Load the playlist from local storage.""" - if os.path.exists(LOCAL_PLAYLIST_FILE): - try: - with open(LOCAL_PLAYLIST_FILE, 'r') as local_file: - local_playlist = json.load(local_file) - - # Validate the structure of the local playlist - if isinstance(local_playlist, list) and all(isinstance(item, dict) for item in local_playlist): - Logger.info("python_functions: Loaded and validated local playlist.") - return local_playlist - else: - Logger.error("python_functions: Invalid local playlist structure.") - return [] - except json.JSONDecodeError: - Logger.error("python_functions: Failed to parse local playlist file.") - return [] - else: - Logger.warning("python_functions: Local playlist file not found.") - return [] - -def download_media_files(playlist): - """Download media files from the playlist.""" +def download_media_files(playlist, version): + """Download media files from the server and update the local playlist.""" Logger.info("python_functions: Starting media file download...") - base_dir = os.path.join(os.path.dirname(__file__), 'static', 'resurse') # Update this to the correct path + base_dir = os.path.join(os.path.dirname(__file__), 'static', 'resurse') # Path to the local folder if not os.path.exists(base_dir): os.makedirs(base_dir) Logger.info(f"python_functions: Created directory {base_dir} for media files.") + updated_playlist = [] # List to store updated media entries + for media in playlist: file_name = media.get('file_name', '') file_url = media.get('url', '') + duration = media.get('duration', 10) # Default duration if not provided file_path = os.path.join(base_dir, file_name) - try: - response = requests.get(file_url) - if response.status_code == 200: - with open(file_path, 'wb') as file: - file.write(response.content) - Logger.info(f"python_functions: Downloaded {file_name} to {file_path}") - else: - Logger.error(f"python_functions: Failed to download {file_name}: {response.status_code}") - except requests.exceptions.RequestException as e: - Logger.error(f"python_functions: Failed to download {file_name}: {e}") + Logger.debug(f"python_functions: Preparing to download {file_name} from {file_url}...") + + if os.path.exists(file_path): + Logger.info(f"python_functions: File {file_name} already exists. Skipping download.") + else: + try: + response = requests.get(file_url, timeout=10) + if response.status_code == 200: + with open(file_path, 'wb') as file: + file.write(response.content) + Logger.info(f"python_functions: Successfully downloaded {file_name} to {file_path}") + else: + Logger.error(f"python_functions: Failed to download {file_name}. Status Code: {response.status_code}") + continue + except requests.exceptions.RequestException as e: + Logger.error(f"python_functions: Error downloading {file_name}: {e}") + continue + + updated_media = { + 'file_name': file_name, + 'url': file_path, # Update URL to local path + 'duration': duration + } + updated_playlist.append(updated_media) + + # Save the updated playlist locally + save_local_playlist({'playlist': updated_playlist, 'version': version}) def clean_unused_files(playlist): """Remove unused media files from the resource folder.""" Logger.info("python_functions: Cleaning unused media files...") - base_dir = os.path.join(os.path.dirname(__file__), 'static', 'resurse') # Update this to the correct path + base_dir = os.path.join(os.path.dirname(__file__), 'static', 'resurse') if not os.path.exists(base_dir): Logger.debug(f"python_functions: Directory {base_dir} does not exist. No files to clean.") return - # Get all file names from the playlist playlist_files = {media.get('file_name', '') for media in playlist} - - # Get all files in the directory all_files = set(os.listdir(base_dir)) - - # Determine unused files unused_files = all_files - playlist_files - # Delete unused files for file_name in unused_files: file_path = os.path.join(base_dir, file_name) try: diff --git a/src/python_functions2.py b/src/python_functions2.py new file mode 100644 index 0000000..48d330d --- /dev/null +++ b/src/python_functions2.py @@ -0,0 +1,248 @@ +import os +import json +import requests +from kivy.logger import Logger +import bcrypt +import time + +CONFIG_FILE = './Resurse/app_config.txt' +LOCAL_PLAYLIST_FILE = './static/local_playlist.json' # Path to the local playlist file +def load_config(): + """Load configuration from app_config.txt.""" + if os.path.exists(CONFIG_FILE): + try: + with open(CONFIG_FILE, 'r') as file: + Logger.info("python_functions: Configuration file loaded successfully.") + return json.load(file) + except json.JSONDecodeError as e: + Logger.error(f"python_functions: Failed to parse configuration file. Error: {e}") + return { + "screen_orientation": "Landscape", + "screen_name": "", + "quickconnect_key": "", + "server_ip": "", + "port": "" + } + else: + Logger.error(f"python_functions: Configuration file {CONFIG_FILE} not found.") + return { + "screen_orientation": "Landscape", + "screen_name": "", + "quickconnect_key": "", + "server_ip": "", + "port": "" + } + +# Load configuration and initialize variables +config_data = load_config() +server = config_data.get("server_ip", "") +host = config_data.get("screen_name", "") +quick = config_data.get("quickconnect_key", "") +port = config_data.get("port", "") +print(server, host, quick, port) +# Determine the configuration status +if server and host and quick and port: + config_status = "ok" +else: + config_status = "not_ok" + +Logger.info(f"python_functions: Configuration loaded: server={server}, host={host}, quick={quick}, port={port}") +Logger.info(f"python_functions: Configuration status: {config_status}") + + +def load_playlist(): + """Load playlist from the server or local storage and periodically check for updates.""" + local_playlist = load_local_playlist() + local_version = local_playlist.get('version', 0) if local_playlist else 0 + + while True: + try: + Logger.info("python_functions: Checking playlist version on the server...") + server_ip = f'{server}:{port}' # Construct the server IP with port + url = f'http://{server_ip}/api/playlist_version' + params = { + 'hostname': host, + 'quickconnect_code': quick + } + response = requests.get(url, params=params) + + if response.status_code == 200: + response_data = response.json() + server_version = response_data.get('playlist_version', None) + hashed_quickconnect = response_data.get('hashed_quickconnect', None) + + if server_version is not None and hashed_quickconnect is not None: + # Validate the quickconnect code using bcrypt + if bcrypt.checkpw(quick.encode('utf-8'), hashed_quickconnect.encode('utf-8')): + Logger.info(f"python_functions: Server playlist version: {server_version}, Local playlist version: {local_version}") + + if server_version != local_version: + Logger.info("python_functions: Playlist versions differ. Updating local playlist...") + updated_playlist = fetch_server_playlist() + if updated_playlist and 'playlist' in updated_playlist: + save_local_playlist(updated_playlist) # Update local playlist + local_version = server_version # Update local version + else: + Logger.error("python_functions: Failed to update local playlist. Using existing playlist.") + else: + Logger.info("python_functions: Playlist versions match. No update needed.") + else: + Logger.error("python_functions: Quickconnect code validation failed.") + else: + Logger.error("python_functions: Failed to retrieve playlist version or hashed quickconnect from the response.") + else: + Logger.error(f"python_functions: Failed to retrieve playlist version. Status Code: {response.status_code}") + except requests.exceptions.RequestException as e: + Logger.error(f"python_functions: Failed to check playlist version: {e}") + + # Wait for 5 minutes before checking again + time.sleep(300) + +def load_local_playlist(): + """Load the playlist from local storage.""" + if os.path.exists(LOCAL_PLAYLIST_FILE): + try: + with open(LOCAL_PLAYLIST_FILE, 'r') as local_file: + local_playlist = json.load(local_file) + + # Validate the structure of the local playlist + if isinstance(local_playlist, dict) and 'playlist' in local_playlist and 'version' in local_playlist: + Logger.info("python_functions: Loaded and validated local playlist.") + return local_playlist + else: + Logger.error("python_functions: Invalid local playlist structure.") + return None + except json.JSONDecodeError: + Logger.error("python_functions: Failed to parse local playlist file.") + return None + else: + Logger.warning("python_functions: Local playlist file not found.") + return None + +def download_media_files(playlist): + """Download media files from the server and update the local playlist.""" + Logger.info("python_functions: Starting media file download...") + base_dir = os.path.join(os.path.dirname(__file__), 'static', 'resurse') # Path to the local folder + if not os.path.exists(base_dir): + os.makedirs(base_dir) + Logger.info(f"python_functions: Created directory {base_dir} for media files.") + + updated_playlist = [] # List to store updated media entries + + for media in playlist: + file_name = media.get('file_name', '') + file_url = media.get('url', '') + duration = media.get('duration', 10) # Default duration if not provided + file_path = os.path.join(base_dir, file_name) + + Logger.debug(f"python_functions: Preparing to download {file_name} from {file_url}...") + + if os.path.exists(file_path): + Logger.info(f"python_functions: File {file_name} already exists. Skipping download.") + else: + try: + response = requests.get(file_url, timeout=10) # Add timeout for better error handling + if response.status_code == 200: + with open(file_path, 'wb') as file: + file.write(response.content) + Logger.info(f"python_functions: Successfully downloaded {file_name} to {file_path}") + else: + Logger.error(f"python_functions: Failed to download {file_name}. Status Code: {response.status_code}") + continue + except requests.exceptions.RequestException as e: + Logger.error(f"python_functions: Error downloading {file_name}: {e}") + continue + + # Update the media entry with the local file path and duration + updated_media = { + 'file_name': file_name, + 'url': file_path, # Update URL to local path + 'duration': duration + } + updated_playlist.append(updated_media) + + # Save the updated playlist locally + save_local_playlist({'playlist': updated_playlist, 'version': playlist.get('version', 0)}) + +def clean_unused_files(playlist): + """Remove unused media files from the resource folder.""" + Logger.info("python_functions: Cleaning unused media files...") + base_dir = os.path.join(os.path.dirname(__file__), 'static', 'resurse') # Update this to the correct path + if not os.path.exists(base_dir): + Logger.debug(f"python_functions: Directory {base_dir} does not exist. No files to clean.") + return + + # Get all file names from the playlist + playlist_files = {media.get('file_name', '') for media in playlist} + + # Get all files in the directory + all_files = set(os.listdir(base_dir)) + + # Determine unused files + unused_files = all_files - playlist_files + + # Delete unused files + for file_name in unused_files: + file_path = os.path.join(base_dir, file_name) + try: + os.remove(file_path) + Logger.info(f"python_functions: Deleted unused file: {file_path}") + except OSError as e: + Logger.error(f"python_functions: Failed to delete {file_path}: {e}") + +def fetch_server_playlist(): + """Fetch the updated playlist from the server.""" + try: + server_ip = f'{server}:{port}' # Construct the server IP with port + url = f'http://{server_ip}/api/playlists' + params = { + 'hostname': host, + 'quickconnect_code': quick + } + response = requests.get(url, params=params) + + if response.status_code == 200: + response_data = response.json() + playlist = response_data.get('playlist', []) + version = response_data.get('playlist_version', None) + hashed_quickconnect = response_data.get('hashed_quickconnect', None) + + if version is not None and hashed_quickconnect is not None: + # Validate the quickconnect code using bcrypt + if bcrypt.checkpw(quick.encode('utf-8'), hashed_quickconnect.encode('utf-8')): + Logger.info("python_functions: Fetched updated playlist from server.") + return {'playlist': playlist, 'version': version} + else: + Logger.error("python_functions: Quickconnect code validation failed.") + else: + Logger.error("python_functions: Failed to retrieve playlist or hashed quickconnect from the response.") + else: + Logger.error(f"python_functions: Failed to fetch playlist. Status Code: {response.status_code}") + except requests.exceptions.RequestException as e: + Logger.error(f"python_functions: Failed to fetch playlist: {e}") + + # Return an empty playlist if fetching fails + return {'playlist': [], 'version': 0} + +def save_local_playlist(playlist): + """Save the updated playlist locally.""" + if not playlist or 'playlist' not in playlist: + Logger.error("python_functions: Invalid playlist data. Cannot save local playlist.") + return + + try: + with open(LOCAL_PLAYLIST_FILE, 'w') as local_file: + json.dump(playlist, local_file) + Logger.info("python_functions: Updated local playlist with server data.") + except IOError as e: + Logger.error(f"python_functions: Failed to save local playlist: {e}") + +def check_playlist_updates(self, dt): + """Check for updates to the playlist.""" + new_playlist = load_playlist() # Load the new playlist + if new_playlist != self.playlist: # Compare the new playlist with the current one + Logger.info("Playlist updated. Changes detected.") + self.updated_playlist = new_playlist # Store the updated playlist + self.is_playlist_update_pending = True # Mark the update as pending + else: + Logger.info("Playlist update skipped. No changes detected.") \ No newline at end of file diff --git a/src/static/local_playlist.json b/src/static/local_playlist.json index e9dfd9e..8a0e395 100644 --- a/src/static/local_playlist.json +++ b/src/static/local_playlist.json @@ -1 +1 @@ -[{"duration": 20, "file_name": "IMG-20250526-WA0003.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG-20250526-WA0003.jpg"}, {"duration": 20, "file_name": "IMG-20250602-WA0011.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG-20250602-WA0011.jpg"}, {"duration": 20, "file_name": "IMG_20250601_192845.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_192845.jpg"}, {"duration": 20, "file_name": "IMG_20250601_185017.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_185017.jpg"}, {"duration": 20, "file_name": "IMG_20250601_185019.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_185019.jpg"}, {"duration": 20, "file_name": "IMG_20250601_180727.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_180727.jpg"}, {"duration": 20, "file_name": "IMG_20250601_174724.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG_20250601_174724.jpg"}, {"duration": 20, "file_name": "IMG-20250531-WA0070.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG-20250531-WA0070.jpg"}, {"duration": 20, "file_name": "IMG-20250604-WA0006.jpg", "url": "http://digi-signage.moto-adv.com/media/IMG-20250604-WA0006.jpg"}] \ No newline at end of file +{"playlist": [{"file_name": "edit_pencil.png", "url": "/home/pi/Desktop/signage-player/src/static/resurse/edit_pencil.png", "duration": 20}, {"file_name": "delete.png", "url": "/home/pi/Desktop/signage-player/src/static/resurse/delete.png", "duration": 20}], "version": 2} \ No newline at end of file diff --git a/src/static/resurse/IMG-20250526-WA0003.jpg b/src/static/resurse/IMG-20250526-WA0003.jpg deleted file mode 100644 index 8e0b2b3..0000000 Binary files a/src/static/resurse/IMG-20250526-WA0003.jpg and /dev/null differ diff --git a/src/static/resurse/IMG-20250531-WA0070.jpg b/src/static/resurse/IMG-20250531-WA0070.jpg deleted file mode 100644 index 7bf5432..0000000 Binary files a/src/static/resurse/IMG-20250531-WA0070.jpg and /dev/null differ diff --git a/src/static/resurse/IMG-20250602-WA0011.jpg b/src/static/resurse/IMG-20250602-WA0011.jpg deleted file mode 100644 index 4e6aad5..0000000 Binary files a/src/static/resurse/IMG-20250602-WA0011.jpg and /dev/null differ diff --git a/src/static/resurse/IMG-20250604-WA0006.jpg b/src/static/resurse/IMG-20250604-WA0006.jpg deleted file mode 100644 index bc5f7e0..0000000 Binary files a/src/static/resurse/IMG-20250604-WA0006.jpg and /dev/null differ diff --git a/src/static/resurse/IMG_20250601_174724.jpg b/src/static/resurse/IMG_20250601_174724.jpg deleted file mode 100644 index ca638cd..0000000 Binary files a/src/static/resurse/IMG_20250601_174724.jpg and /dev/null differ diff --git a/src/static/resurse/IMG_20250601_180727.jpg b/src/static/resurse/IMG_20250601_180727.jpg deleted file mode 100644 index 04b2082..0000000 Binary files a/src/static/resurse/IMG_20250601_180727.jpg and /dev/null differ diff --git a/src/static/resurse/IMG_20250601_185017.jpg b/src/static/resurse/IMG_20250601_185017.jpg deleted file mode 100644 index 09feaa1..0000000 Binary files a/src/static/resurse/IMG_20250601_185017.jpg and /dev/null differ diff --git a/src/static/resurse/IMG_20250601_185019.jpg b/src/static/resurse/IMG_20250601_185019.jpg deleted file mode 100644 index 77b35f3..0000000 Binary files a/src/static/resurse/IMG_20250601_185019.jpg and /dev/null differ diff --git a/src/static/resurse/IMG_20250601_192845.jpg b/src/static/resurse/IMG_20250601_192845.jpg deleted file mode 100644 index be083e5..0000000 Binary files a/src/static/resurse/IMG_20250601_192845.jpg and /dev/null differ diff --git a/src/static/resurse/delete.png b/src/static/resurse/delete.png new file mode 100644 index 0000000..eb96774 Binary files /dev/null and b/src/static/resurse/delete.png differ diff --git a/src/static/resurse/edit_pencil.png b/src/static/resurse/edit_pencil.png new file mode 100644 index 0000000..da079d9 Binary files /dev/null and b/src/static/resurse/edit_pencil.png differ