from flask import Flask, jsonify, request, send_from_directory import vlc import os import json import requests import logging import threading import time # Configure logging logging.basicConfig(level=logging.INFO) Logger = logging.getLogger(__name__) app = Flask(__name__, static_folder='static') # VLC Media Player instance vlc_instance = vlc.Instance() player = vlc_instance.media_player_new() # File paths PLAYLIST_FILE = './static/resurse/playlist.json' APP_CONFIG_FILE = './app_config.json' RESOURCES_FOLDER = './static/resurse' # Ensure the resources folder exists os.makedirs(RESOURCES_FOLDER, exist_ok=True) # Load playlist def load_playlist(): if os.path.exists(PLAYLIST_FILE): with open(PLAYLIST_FILE, 'r') as file: return json.load(file) return [] # Save playlist def save_playlist(playlist): with open(PLAYLIST_FILE, 'w') as file: json.dump(playlist, file) # Load app configuration def load_app_config(): if os.path.exists(APP_CONFIG_FILE): with open(APP_CONFIG_FILE, 'r') as file: return json.load(file) return { "player_orientation": "portrait", "player_name": "", "quickconnect_code": "", "server_address": "", "port": 1025 } # Save app configuration def save_app_config(config): with open(APP_CONFIG_FILE, 'w') as file: json.dump(config, file) # Download media files def download_media_files(playlist): Logger.info("Starting media file download...") for media in playlist: file_name = media.get('file_name', '') file_url = media.get('url', '') file_path = os.path.join(RESOURCES_FOLDER, 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"Downloaded {file_name} to {file_path}") else: Logger.error(f"Failed to download {file_name}: {response.status_code}") except requests.exceptions.RequestException as e: Logger.error(f"Failed to download {file_name}: {e}") # Download playlist files from server def download_playlist_files_from_server(): Logger.info("Starting playlist file download using app configuration...") # Load app configuration app_config = load_app_config() server_address = app_config.get('server_address', '') port = app_config.get('port', 1025) hostname = app_config.get('player_name', '') quickconnect_code = app_config.get('quickconnect_code', '') if not server_address or not hostname or not quickconnect_code: Logger.error("Missing required configuration values.") return # Construct the request URL and parameters server_ip = f'{server_address}:{port}' url = f'http://{server_ip}/api/playlists' params = { 'hostname': hostname, 'quickconnect_code': quickconnect_code } try: # Send request to fetch the playlist response = requests.get(url, params=params) Logger.debug(f"Status Code: {response.status_code}") Logger.debug(f"Response Content: {response.text}") if response.status_code == 200: try: playlist = response.json().get('playlist', []) Logger.info("Playlist retrieved successfully.") save_playlist(playlist) # Save the playlist locally download_media_files(playlist) # Download media files except json.JSONDecodeError as e: Logger.error(f"Failed to parse playlist JSON: {e}") else: Logger.error(f"Failed to retrieve playlist: {response.text}") except requests.exceptions.RequestException as e: Logger.error(f"Failed to connect to server: {e}") @app.route('/') def serve_index(): """Serve the main index.html page.""" return send_from_directory(app.static_folder, 'index.html') @app.route('/api/playlist', methods=['GET']) def get_playlist(): """Get the current playlist.""" playlist = load_playlist() return jsonify({'playlist': playlist}) @app.route('/api/playlist', methods=['POST']) def update_playlist(): """Update the playlist.""" playlist = request.json.get('playlist', []) save_playlist(playlist) return jsonify({'status': 'success'}) @app.route('/api/play', methods=['POST']) def play_media(): """Play a media file.""" file_path = request.json.get('file_path') if not os.path.exists(file_path): return jsonify({'error': 'File not found'}), 404 media = vlc_instance.media_new(file_path) player.set_media(media) player.play() return jsonify({'status': 'playing', 'file': file_path}) @app.route('/api/stop', methods=['POST']) def stop_media(): """Stop media playback.""" player.stop() return jsonify({'status': 'stopped'}) @app.route('/api/config', methods=['GET']) def get_config(): """Get the app configuration.""" config = load_app_config() return jsonify(config) @app.route('/api/config', methods=['POST']) def update_config(): """Update the app configuration.""" config = request.json save_app_config(config) return jsonify({'status': 'success'}) @app.route('/api/download_playlist', methods=['POST']) def download_playlist(): """Download playlist files from the server.""" try: download_playlist_files_from_server() return jsonify({'status': 'success', 'message': 'Playlist files downloaded successfully.'}) except Exception as e: return jsonify({'status': 'error', 'message': str(e)}), 500 @app.route('/updated_playlist.json') def serve_updated_playlist(): """Serve the updated playlist file.""" return send_from_directory('.', 'updated_playlist.json') def create_updated_playlist(): """Create a new playlist file with local file paths.""" Logger.info("Creating updated playlist with local file paths...") # Load the existing playlist if not os.path.exists(PLAYLIST_FILE): Logger.error(f"Playlist file not found: {PLAYLIST_FILE}") return with open(PLAYLIST_FILE, 'r') as file: playlist = json.load(file) # Update the playlist with local file paths updated_playlist = [] for media in playlist: file_name = media.get('file_name', '') local_path = f"/static/resurse/{file_name}" # Use Flask's static folder path if os.path.exists(os.path.join(RESOURCES_FOLDER, file_name)): updated_media = { "type": "image" if file_name.lower().endswith(('.jpg', '.jpeg', '.png')) else "video", "url": local_path, "duration": media.get('duration', 0) # Keep the duration for images } updated_playlist.append(updated_media) else: Logger.warning(f"File not found in resurse folder: {file_name}") # Save the updated playlist to the root folder updated_playlist_file = './updated_playlist.json' with open(updated_playlist_file, 'w') as file: json.dump(updated_playlist, file, indent=4) Logger.info(f"Updated playlist saved to {updated_playlist_file}") # Check and download playlist on app startup def initialize_playlist(): Logger.info("Initializing playlist...") download_playlist_files_from_server() Logger.info("Playlist initialization complete.") # Function to check for playlist updates every 5 minutes def periodic_playlist_check(): while True: try: Logger.info("Checking for playlist updates...") # Download the playlist files from the server download_playlist_files_from_server() # Create the updated playlist with local file paths create_updated_playlist() Logger.info("Playlist check complete.") except Exception as e: Logger.error(f"Error during playlist check: {e}") time.sleep(300) # Wait for 5 minutes (300 seconds) before checking again # Start the periodic playlist check in a background thread def start_playlist_check_thread(): thread = threading.Thread(target=periodic_playlist_check, daemon=True) thread.start() if __name__ == '__main__': initialize_playlist() # Check and download playlist on startup create_updated_playlist() # Create the updated playlist start_playlist_check_thread() # Start the background thread for periodic checks app.run(host='0.0.0.0', port=1025)