147 lines
6.1 KiB
Python
147 lines
6.1 KiB
Python
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}")
|