import threading import os from logging_config import Logger from PIL import Image, ImageTk class MediaPlaybackController: def __init__(self, app, ui): self.app = app # Reference to SimpleMediaPlayerApp self.ui = ui # Reference to PlayerUI self.auto_advance_timer = None self.current_index = 0 self.playlist = [] self.scaling_mode = 'fit' def set_playlist(self, playlist): self.playlist = playlist self.current_index = 0 def play_current_media(self): if not self.playlist or self.current_index >= len(self.playlist): self.show_no_content_message() return media = self.playlist[self.current_index] file_path = media.get('url', '') file_name = media.get('file_name', '') duration = media.get('duration', 10) if file_path.startswith('static/resurse/'): absolute_path = os.path.join(os.path.dirname(__file__), file_path) file_path = absolute_path Logger.info(f"Playing media: {file_name} from {file_path}") self.log_event(file_name, "STARTED") self.cancel_timers() if file_path.startswith('text://'): self.show_text_content(file_path[7:], duration) elif file_path.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')): self.play_video(file_path) elif os.path.exists(file_path) and file_path.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp')): self.show_image(file_path, duration) else: Logger.error(f"Unsupported or missing media: {file_path}") self.ui.status_label.config(text=f"Missing or unsupported media:\n{file_name}") self.auto_advance_timer = self.ui.root.after(5000, self.next_media) def play_video(self, file_path): self.ui.status_label.place_forget() def run_vlc_subprocess(): import subprocess try: Logger.info(f"Starting system VLC subprocess for video: {file_path}") vlc_cmd = [ 'cvlc', '--fullscreen', '--no-osd', '--no-video-title-show', '--play-and-exit', '--quiet', file_path ] proc = subprocess.Popen(vlc_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) proc.wait() Logger.info(f"VLC subprocess finished: {file_path}") except Exception as e: Logger.error(f"VLC subprocess error: {e}") finally: self.ui.root.after_idle(lambda: setattr(self, 'auto_advance_timer', self.ui.root.after(1000, self.next_media))) threading.Thread(target=run_vlc_subprocess, daemon=True).start() def show_image(self, file_path, duration): try: self.ui.status_label.place_forget() self.ui.status_label.config(text="") img = Image.open(file_path) original_size = img.size screen_width = self.ui.root.winfo_width() screen_height = self.ui.root.winfo_height() if screen_width <= 1 or screen_height <= 1: screen_width = 1920 screen_height = 1080 final_img, offset = self.ui.scale_image_to_screen(img, screen_width, screen_height, self.scaling_mode) photo = ImageTk.PhotoImage(final_img) self.ui.image_label.config(image=photo) self.ui.image_label.image = photo Logger.info(f"Successfully displayed image: {os.path.basename(file_path)} " f"(Original: {original_size}, Screen: {screen_width}x{screen_height}, " f"Mode: {self.scaling_mode}, Offset: {offset})") self.auto_advance_timer = self.ui.root.after( int(duration * 1000), self.next_media ) except Exception as e: Logger.error(f"Failed to show image {file_path}: {e}") self.ui.image_label.config(image='') self.ui.status_label.config(text=f"Image Error:\n{os.path.basename(file_path)}\n{str(e)}") self.ui.status_label.place(relx=0.5, rely=0.5, anchor='center') self.auto_advance_timer = self.ui.root.after(5000, self.next_media) def show_text_content(self, text, duration): self.ui.image_label.config(image='') self.ui.status_label.config(text=text) self.auto_advance_timer = self.ui.root.after( int(duration * 1000), self.next_media ) def next_media(self): self.cancel_timers() if not self.playlist: return self.current_index = (self.current_index + 1) % len(self.playlist) self.play_current_media() def previous_media(self): self.cancel_timers() if not self.playlist: return self.current_index = (self.current_index - 1) % len(self.playlist) self.play_current_media() def toggle_play_pause(self): self.app.is_paused = not self.app.is_paused if self.app.is_paused: self.ui.play_pause_btn.config(text="▶ Play") self.cancel_timers() else: self.ui.play_pause_btn.config(text="⏸ Pause") self.play_current_media() Logger.info(f"Media {'paused' if self.app.is_paused else 'resumed'}") def cancel_timers(self): if self.auto_advance_timer: self.ui.root.after_cancel(self.auto_advance_timer) self.auto_advance_timer = None def show_no_content_message(self): self.ui.status_label.config(text="No content available.") def log_event(self, file_name, event): import datetime try: timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') log_message = f"{timestamp} - {event}: {file_name}\n" log_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'resources', 'log.txt') with open(log_file, 'a') as f: f.write(log_message) except Exception as e: Logger.error(f"Failed to log event: {e}")