Fix syntax and indentation errors in tkinter_simple_player.py, improve stability of settings UI and video playback
This commit is contained in:
@@ -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
|
||||
|
||||
Binary file not shown.
Binary file not shown.
0
tkinter_app/src/player_app.py
Normal file
0
tkinter_app/src/player_app.py
Normal file
0
tkinter_app/src/settings_screen.py
Normal file
0
tkinter_app/src/settings_screen.py
Normal file
@@ -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
|
||||
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:
|
||||
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}")
|
||||
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)))
|
||||
|
||||
player.set_fullscreen(True)
|
||||
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.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
|
||||
time.sleep(0.5)
|
||||
player.stop()
|
||||
Logger.info(f"VLC finished: {file_path}")
|
||||
except Exception as e:
|
||||
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,13 +1041,11 @@ 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])
|
||||
|
||||
style.configure('Dark.TNotebook.Tab',
|
||||
padding=[20, 12],
|
||||
font=('Segoe UI', 11, 'bold'),
|
||||
@@ -1109,19 +1053,16 @@ class SettingsWindow:
|
||||
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'])])
|
||||
|
||||
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))
|
||||
|
||||
style.configure('Dark.TEntry',
|
||||
fieldbackground=self.colors['bg_tertiary'],
|
||||
foreground=self.colors['text_primary'],
|
||||
|
||||
Reference in New Issue
Block a user