diff --git a/tkinter_app/resources/log.txt b/tkinter_app/resources/log.txt index 5576e56..5652d5b 100644 --- a/tkinter_app/resources/log.txt +++ b/tkinter_app/resources/log.txt @@ -1184,3 +1184,80 @@ [INFO] [SignageApp] python_functions: Starting load_config function. [INFO] [SignageApp] python_functions: Configuration file loaded successfully. [INFO] [SignageApp] Application exit requested +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-signage.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=digi-signage.moto-adv.com, host=tv-terasa, port=8880 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://digi-signage.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist. Status Code: 522 +[WARNING] [SignageApp] Server returned empty playlist, falling back to local playlist +[INFO] [SignageApp] Loaded fallback playlist with 3 items +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-22 10:13:23 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Successfully displayed image: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg (Original: (1600, 1000), Screen: 1920x1080, Mode: fit, Offset: (96, 0)) +[INFO] [SignageApp] Starting Simple Tkinter Media Player +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-22 10:13:35 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Successfully displayed image: wp2782770-1846651530.jpg (Original: (3840, 2400), Screen: 1920x1080, Mode: fit, Offset: (96, 0)) +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-22 10:13:38 - STARTED: SampleVideo_1280x720_1mb.mp4 +[INFO] [SignageApp] Video dimensions: 1280x720, Screen dimensions: 1920x1080 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Application exit requested +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-signage.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=digi-signage.moto-adv.com, host=tv-terasa, port=8880 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://digi-signage.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist. Status Code: 522 +[WARNING] [SignageApp] Server returned empty playlist, falling back to local playlist +[INFO] [SignageApp] Loaded fallback playlist with 3 items +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-22 11:10:25 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Successfully displayed image: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg (Original: (1600, 1000), Screen: 1920x1080, Mode: fit, Offset: (96, 0)) +[INFO] [SignageApp] Starting Simple Tkinter Media Player +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-22 11:10:45 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Successfully displayed image: wp2782770-1846651530.jpg (Original: (3840, 2400), Screen: 1920x1080, Mode: fit, Offset: (96, 0)) +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-22 11:11:01 - STARTED: SampleVideo_1280x720_1mb.mp4 +[INFO] [SignageApp] Starting VLC for video: /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +[INFO] [SignageApp] VLC finished: /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Fetching playlist from URL: http://digi-signage.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +2025-08-22 11:11:09 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Successfully displayed image: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg (Original: (1600, 1000), Screen: 1920x1080, Mode: fit, Offset: (96, 0)) +[INFO] [SignageApp] Loading configuration in enhanced settings window +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Config loaded: {'screen_orientation': 'Landscape', 'screen_name': 'tv-terasa', 'quickconnect_key': '8887779', 'server_ip': 'digi-signage.moto-adv.com', 'port': '8880', 'screen_w': '1920', 'screen_h': '1080', 'playlist_version': 5} +[INFO] [SignageApp] Configuration values loaded successfully in enhanced settings +[ERROR] [SignageApp] Failed to fetch playlist. Status Code: 522 +[INFO] [SignageApp] No playlist updates available +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-22 11:11:29 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Successfully displayed image: wp2782770-1846651530.jpg (Original: (3840, 2400), Screen: 1920x1080, Mode: fit, Offset: (96, 0)) +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-22 11:11:45 - STARTED: SampleVideo_1280x720_1mb.mp4 +[INFO] [SignageApp] Starting VLC for video: /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 diff --git a/tkinter_app/src/__pycache__/tkinter_simple_player.cpython-311.pyc b/tkinter_app/src/__pycache__/tkinter_simple_player.cpython-311.pyc index 789a54a..7c6c5fb 100644 Binary files a/tkinter_app/src/__pycache__/tkinter_simple_player.cpython-311.pyc and b/tkinter_app/src/__pycache__/tkinter_simple_player.cpython-311.pyc differ diff --git a/tkinter_app/src/__pycache__/virtual_keyboard.cpython-311.pyc b/tkinter_app/src/__pycache__/virtual_keyboard.cpython-311.pyc index b664ca8..4bc97e3 100644 Binary files a/tkinter_app/src/__pycache__/virtual_keyboard.cpython-311.pyc and b/tkinter_app/src/__pycache__/virtual_keyboard.cpython-311.pyc differ diff --git a/tkinter_app/src/player_app.py b/tkinter_app/src/player_app.py new file mode 100644 index 0000000..e69de29 diff --git a/tkinter_app/src/settings_screen.py b/tkinter_app/src/settings_screen.py new file mode 100644 index 0000000..e69de29 diff --git a/tkinter_app/src/tkinter_simple_player.py b/tkinter_app/src/tkinter_simple_player.py index b43a3dc..3350f7e 100644 --- a/tkinter_app/src/tkinter_simple_player.py +++ b/tkinter_app/src/tkinter_simple_player.py @@ -533,88 +533,34 @@ class SimpleMediaPlayerApp: self.auto_advance_timer = self.root.after(5000, self.next_media) def play_video(self, file_path): - """Play video file""" - # Clear any status text and hide status label + """Play video file using python-vlc-wrapper for robust hardware acceleration.""" self.status_label.place_forget() - - # Check if PIL is available for video playback - if not PIL_AVAILABLE: - Logger.error("PIL not available - cannot play video") - self.status_label.config(text="PIL/Pillow not available\nCannot play video files") - self.status_label.place(relx=0.5, rely=0.5, anchor='center') - self.auto_advance_timer = self.root.after(5000, self.next_media) - return - - # Use OpenCV to play video in a separate thread - def video_player(): + def run_vlc(): try: - cap = cv2.VideoCapture(file_path) - - if not cap.isOpened(): - raise ValueError(f"Cannot open video file: {file_path}") - - # Get video properties - fps = cap.get(cv2.CAP_PROP_FPS) - delay = int(1000 / fps) if fps > 0 else 30 # Default to 30 FPS if unknown - - # Get video dimensions - video_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) - video_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) - - # Get screen dimensions - screen_width = self.root.winfo_width() - screen_height = self.root.winfo_height() - - # Ensure we have valid screen dimensions - if screen_width <= 1 or screen_height <= 1: - screen_width = 1920 # Default fallback - screen_height = 1080 - - Logger.info(f"Video dimensions: {video_width}x{video_height}, " - f"Screen dimensions: {screen_width}x{screen_height}") - - while self.current_index < len(self.playlist) and not self.is_paused and self.running: - ret, frame = cap.read() - - if not ret: - break # End of video - - # Convert color from BGR to RGB - frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) - - # Convert to PIL Image for better scaling - try: - img = Image.fromarray(frame) - - # Scale video frame using the scaling helper - final_img, offset = self.scale_image_to_screen(img, screen_width, screen_height, self.scaling_mode) - - # Convert to PhotoImage - photo = ImageTk.PhotoImage(final_img) - - # Update UI from main thread - self.root.after_idle(lambda p=photo: self._update_video_frame(p)) - - except Exception as img_error: - Logger.error(f"Video frame processing error: {img_error}") + Logger.info(f"Starting VLC for video: {file_path}") + import vlc + instance = vlc.Instance('--no-osd', '--no-video-title-show', '--intf', 'dummy', '--no-video-deco', '--no-embedded-video', '--quiet') + player = instance.media_player_new() + media = instance.media_new(file_path) + player.set_media(media) + player.play() + time.sleep(0.5) + try: + player.set_fullscreen(True) + except Exception as e: + Logger.warning(f"Could not set VLC fullscreen: {e}") + while True: + state = player.get_state() + if state in [vlc.State.Ended, vlc.State.Error, vlc.State.Stopped]: break - - # Wait for the next frame - time.sleep(delay / 1000) - - cap.release() - - # Schedule next media from main thread - self.root.after_idle(lambda: setattr(self, 'auto_advance_timer', - self.root.after(1000, self.next_media))) - + time.sleep(0.5) + player.stop() + Logger.info(f"VLC finished: {file_path}") except Exception as e: - Logger.error(f"Error playing video {file_path}: {e}") - # Show error from main thread - self.root.after_idle(lambda: self._show_video_error(str(e))) - - # Start video player thread - threading.Thread(target=video_player, daemon=True).start() + Logger.error(f"VLC error: {e}") + finally: + self.root.after_idle(lambda: setattr(self, 'auto_advance_timer', self.root.after(1000, self.next_media))) + threading.Thread(target=run_vlc, daemon=True).start() def _update_video_frame(self, photo): """Update video frame from main thread""" @@ -1095,41 +1041,36 @@ class SettingsWindow: # Configure enhanced custom styles style = ttk.Style() style.theme_use('clam') - # Enhanced dark theme styles style.configure('Dark.TNotebook', - background=self.colors['bg_secondary'], - borderwidth=0, - tabmargins=[2, 5, 2, 0]) - + background=self.colors['bg_secondary'], + borderwidth=0, + tabmargins=[2, 5, 2, 0]) style.configure('Dark.TNotebook.Tab', - padding=[20, 12], - font=('Segoe UI', 11, 'bold'), - background=self.colors['bg_tertiary'], - foreground=self.colors['text_secondary'], - borderwidth=1, - focuscolor='none') - + padding=[20, 12], + font=('Segoe UI', 11, 'bold'), + background=self.colors['bg_tertiary'], + foreground=self.colors['text_secondary'], + borderwidth=1, + focuscolor='none') style.map('Dark.TNotebook.Tab', - background=[('selected', self.colors['accent']), - ('active', self.colors['accent_hover'])], - foreground=[('selected', self.colors['text_primary']), - ('active', self.colors['text_primary'])]) - + background=[('selected', self.colors['accent']), + ('active', self.colors['accent_hover'])], + foreground=[('selected', self.colors['text_primary']), + ('active', self.colors['text_primary'])]) style.configure('Dark.TFrame', background=self.colors['bg_secondary']) style.configure('Dark.TLabel', - background=self.colors['bg_secondary'], - foreground=self.colors['text_primary'], - font=('Segoe UI', 10)) - + background=self.colors['bg_secondary'], + foreground=self.colors['text_primary'], + font=('Segoe UI', 10)) style.configure('Dark.TEntry', - fieldbackground=self.colors['bg_tertiary'], - foreground=self.colors['text_primary'], - bordercolor=self.colors['border'], - lightcolor=self.colors['bg_tertiary'], - darkcolor=self.colors['bg_tertiary'], - font=('Segoe UI', 10), - insertcolor=self.colors['text_primary']) + fieldbackground=self.colors['bg_tertiary'], + foreground=self.colors['text_primary'], + bordercolor=self.colors['border'], + lightcolor=self.colors['bg_tertiary'], + darkcolor=self.colors['bg_tertiary'], + font=('Segoe UI', 10), + insertcolor=self.colors['text_primary']) # Main container frame main_frame = tk.Frame(self.window, bg=self.colors['bg_primary'])