Playlist logic fixes, always use latest playlist version, VLC-only image display, and bugfixes
This commit is contained in:
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
"screen_orientation": "Landscape",
|
||||
"screen_name": "tv-terasa",
|
||||
"quickconnect_key": "8887779",
|
||||
"server_ip": "digi-signage.moto-adv.com",
|
||||
"server_ip": "192.168.1.22",
|
||||
"port": "80",
|
||||
"screen_w": "1920",
|
||||
"screen_h": "1080",
|
||||
|
||||
@@ -323,3 +323,69 @@
|
||||
[INFO] [SignageApp] File Banner_poarta_2_x6.jpg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download WhatsApp_Video_2025-08-21_at_18.34.19_86a6f243.mp4 from http://digi-signage.moto-adv.com/media/WhatsApp_Video_2025-08-21_at_18.34.19_86a6f243.mp4...
|
||||
[INFO] [SignageApp] File WhatsApp_Video_2025-08-21_at_18.34.19_86a6f243.mp4 already exists. Skipping download.
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://192.168.1.22:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[ERROR] [SignageApp] Failed to fetch playlist. Status Code: 404
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 0
|
||||
[INFO] [SignageApp] Local playlist is already up to date.
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://192.168.1.22:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4'}, {'duration': 15, 'file_name': 'demo2.jpeg', 'url': 'http://192.168.1.22/media/demo2.jpeg'}], 'playlist_version': 3}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 3
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] Successfully downloaded big-buck-bunny-1080p-60fps-30sec.mp4 to /home/pi/Desktop/tkinter_player/signage_player/static_data/media/big-buck-bunny-1080p-60fps-30sec.mp4
|
||||
[INFO] [SignageApp] Preparing to download demo2.jpeg from http://192.168.1.22/media/demo2.jpeg...
|
||||
[INFO] [SignageApp] Successfully downloaded demo2.jpeg to /home/pi/Desktop/tkinter_player/signage_player/static_data/media/demo2.jpeg
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://192.168.1.22:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4'}, {'duration': 15, 'file_name': 'demo2.jpeg', 'url': 'http://192.168.1.22/media/demo2.jpeg'}], 'playlist_version': 3}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 3
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] Successfully downloaded big-buck-bunny-1080p-60fps-30sec.mp4 to /home/pi/Desktop/tkinter_player/signage_player/static_data/media/big-buck-bunny-1080p-60fps-30sec.mp4
|
||||
[INFO] [SignageApp] Preparing to download demo2.jpeg from http://192.168.1.22/media/demo2.jpeg...
|
||||
[INFO] [SignageApp] Successfully downloaded demo2.jpeg to /home/pi/Desktop/tkinter_player/signage_player/static_data/media/demo2.jpeg
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://192.168.1.22:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4'}, {'duration': 15, 'file_name': 'demo2.jpeg', 'url': 'http://192.168.1.22/media/demo2.jpeg'}], 'playlist_version': 3}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 3
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] File big-buck-bunny-1080p-60fps-30sec.mp4 already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download demo2.jpeg from http://192.168.1.22/media/demo2.jpeg...
|
||||
[INFO] [SignageApp] File demo2.jpeg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://192.168.1.22:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4'}, {'duration': 15, 'file_name': 'demo2.jpeg', 'url': 'http://192.168.1.22/media/demo2.jpeg'}], 'playlist_version': 3}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 3
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] File big-buck-bunny-1080p-60fps-30sec.mp4 already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download demo2.jpeg from http://192.168.1.22/media/demo2.jpeg...
|
||||
[INFO] [SignageApp] File demo2.jpeg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://192.168.1.22:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4'}, {'duration': 50, 'file_name': 'demo2.jpeg', 'url': 'http://192.168.1.22/media/demo2.jpeg'}, {'duration': 30, 'file_name': 'call-of-duty-black-3840x2160-23674.jpg', 'url': 'http://192.168.1.22/media/call-of-duty-black-3840x2160-23674.jpg'}], 'playlist_version': 4}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 4
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] File big-buck-bunny-1080p-60fps-30sec.mp4 already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download demo2.jpeg from http://192.168.1.22/media/demo2.jpeg...
|
||||
[INFO] [SignageApp] File demo2.jpeg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download call-of-duty-black-3840x2160-23674.jpg from http://192.168.1.22/media/call-of-duty-black-3840x2160-23674.jpg...
|
||||
[INFO] [SignageApp] Successfully downloaded call-of-duty-black-3840x2160-23674.jpg to /home/pi/Desktop/tkinter_player/signage_player/static_data/media/call-of-duty-black-3840x2160-23674.jpg
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://192.168.1.22:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4'}, {'duration': 50, 'file_name': 'demo2.jpeg', 'url': 'http://192.168.1.22/media/demo2.jpeg'}, {'duration': 30, 'file_name': 'call-of-duty-black-3840x2160-23674.jpg', 'url': 'http://192.168.1.22/media/call-of-duty-black-3840x2160-23674.jpg'}], 'playlist_version': 4}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 4
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] File big-buck-bunny-1080p-60fps-30sec.mp4 already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download demo2.jpeg from http://192.168.1.22/media/demo2.jpeg...
|
||||
[INFO] [SignageApp] File demo2.jpeg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download call-of-duty-black-3840x2160-23674.jpg from http://192.168.1.22/media/call-of-duty-black-3840x2160-23674.jpg...
|
||||
[INFO] [SignageApp] File call-of-duty-black-3840x2160-23674.jpg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Fetching playlist from URL: http://192.168.1.22:80/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'}
|
||||
[INFO] [SignageApp] Server response: {'hashed_quickconnect': '$2b$12$Prw4EUYn4j59CAdsZCsvsug6.xociqbOPaNr0oxOA2zwD9S2MSiK6', 'playlist': [{'duration': 30, 'file_name': 'big-buck-bunny-1080p-60fps-30sec.mp4', 'url': 'http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4'}, {'duration': 50, 'file_name': 'demo2.jpeg', 'url': 'http://192.168.1.22/media/demo2.jpeg'}, {'duration': 30, 'file_name': 'call-of-duty-black-3840x2160-23674.jpg', 'url': 'http://192.168.1.22/media/call-of-duty-black-3840x2160-23674.jpg'}], 'playlist_version': 4}
|
||||
[INFO] [SignageApp] Fetched updated playlist from server.
|
||||
[INFO] [SignageApp] Local playlist version: 0, Server playlist version: 4
|
||||
[INFO] [SignageApp] Preparing to download big-buck-bunny-1080p-60fps-30sec.mp4 from http://192.168.1.22/media/big-buck-bunny-1080p-60fps-30sec.mp4...
|
||||
[INFO] [SignageApp] File big-buck-bunny-1080p-60fps-30sec.mp4 already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download demo2.jpeg from http://192.168.1.22/media/demo2.jpeg...
|
||||
[INFO] [SignageApp] File demo2.jpeg already exists. Skipping download.
|
||||
[INFO] [SignageApp] Preparing to download call-of-duty-black-3840x2160-23674.jpg from http://192.168.1.22/media/call-of-duty-black-3840x2160-23674.jpg...
|
||||
[INFO] [SignageApp] File call-of-duty-black-3840x2160-23674.jpg already exists. Skipping download.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import os
|
||||
import json
|
||||
import tkinter as tk
|
||||
from PIL import Image, ImageTk
|
||||
import vlc
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -121,8 +120,21 @@ class SimpleTkPlayer:
|
||||
self.show_current_media()
|
||||
|
||||
def next_media(self):
|
||||
self.current_index = (self.current_index + 1) % len(self.playlist)
|
||||
self.show_current_media()
|
||||
# If at the last media, update playlist before looping
|
||||
if self.current_index == len(self.playlist) - 1:
|
||||
self.update_playlist_from_server()
|
||||
self.current_index = 0
|
||||
self.show_current_media()
|
||||
else:
|
||||
self.current_index = (self.current_index + 1) % len(self.playlist)
|
||||
self.show_current_media()
|
||||
|
||||
def update_playlist_from_server(self):
|
||||
# Dummy implementation: replace with your actual update logic
|
||||
# For example, call a function to fetch and reload the playlist
|
||||
print("[INFO] Updating playlist from server...")
|
||||
# You can import and call your real update function here
|
||||
# Example: self.playlist = get_latest_playlist()
|
||||
|
||||
def toggle_pause(self):
|
||||
if not self.paused:
|
||||
@@ -184,39 +196,49 @@ class SimpleTkPlayer:
|
||||
return
|
||||
media = self.playlist[self.current_index]
|
||||
file_path = os.path.join(MEDIA_DATA_PATH, media['file_name'])
|
||||
if file_path.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')):
|
||||
ext = file_path.lower()
|
||||
if ext.endswith(('.mp4', '.avi', '.mov', '.mkv')):
|
||||
self.show_video(file_path, on_end=self.next_media)
|
||||
elif file_path.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif')):
|
||||
try:
|
||||
img = Image.open(file_path)
|
||||
# Fit to screen without crop or stretch
|
||||
screen_w = self.root.winfo_screenwidth()
|
||||
screen_h = self.root.winfo_screenheight()
|
||||
img_w, img_h = img.size
|
||||
scale = min(screen_w / img_w, screen_h / img_h)
|
||||
new_w = int(img_w * scale)
|
||||
new_h = int(img_h * scale)
|
||||
img = img.resize((new_w, new_h), Image.LANCZOS)
|
||||
bg = Image.new('RGB', (screen_w, screen_h), 'black')
|
||||
x = (screen_w - new_w) // 2
|
||||
y = (screen_h - new_h) // 2
|
||||
bg.paste(img, (x, y))
|
||||
photo = ImageTk.PhotoImage(bg)
|
||||
self.label.config(image=photo, text='')
|
||||
self.label.image = photo
|
||||
except Exception as e:
|
||||
self.label.config(text=f"Image error: {e}", fg='red')
|
||||
elif ext.endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif')):
|
||||
self.show_image_via_vlc(file_path, media.get('duration', 10), on_end=self.next_media)
|
||||
else:
|
||||
self.label.config(text=f"Unsupported: {media['file_name']}", fg='yellow')
|
||||
|
||||
def show_image_via_vlc(self, file_path, duration, on_end=None):
|
||||
# Use VLC to show image for a set duration
|
||||
if hasattr(self, 'vlc_player') and self.vlc_player:
|
||||
self.vlc_player.stop()
|
||||
if not hasattr(self, 'video_canvas'):
|
||||
self.video_canvas = tk.Canvas(self.root, bg='black', highlightthickness=0)
|
||||
self.video_canvas.pack(fill=tk.BOTH, expand=True)
|
||||
self.label.pack_forget()
|
||||
self.video_canvas.pack(fill=tk.BOTH, expand=True)
|
||||
self.root.attributes('-fullscreen', True)
|
||||
self.root.update_idletasks()
|
||||
self.vlc_instance = vlc.Instance('--vout=x11')
|
||||
self.vlc_player = self.vlc_instance.media_player_new()
|
||||
self.vlc_player.set_mrl(file_path)
|
||||
self.vlc_player.set_fullscreen(True)
|
||||
self.vlc_player.set_xwindow(self.video_canvas.winfo_id())
|
||||
self.vlc_player.play()
|
||||
# Schedule stop and next after duration
|
||||
def finish_image():
|
||||
self.vlc_player.stop()
|
||||
self.video_canvas.pack_forget()
|
||||
self.label.pack(fill=tk.BOTH, expand=True)
|
||||
if on_end:
|
||||
on_end()
|
||||
self.root.after(int(duration * 1000), finish_image)
|
||||
|
||||
def next_media(self):
|
||||
self.current_index = (self.current_index + 1) % len(self.playlist)
|
||||
self.show_current_media()
|
||||
|
||||
def next_media_loop(self):
|
||||
if not self.playlist or self.paused:
|
||||
self.root.after(1000, self.next_media_loop)
|
||||
return
|
||||
duration = self.playlist[self.current_index].get('duration', 10)
|
||||
self.current_index = (self.current_index + 1) % len(self.playlist)
|
||||
self.show_current_media()
|
||||
self.root.after(duration * 1000, self.next_media_loop)
|
||||
|
||||
def exit_app(self):
|
||||
# Signal the update thread to stop if stop_event is present
|
||||
@@ -281,20 +303,9 @@ def load_latest_playlist():
|
||||
files = [f for f in os.listdir(PLAYLIST_DIR) if f.startswith('server_playlist_v') and f.endswith('.json')]
|
||||
if not files:
|
||||
return []
|
||||
# Sort by version number descending
|
||||
files.sort(key=lambda x: int(x.split('_v')[-1].split('.json')[0]), reverse=True)
|
||||
with open(os.path.join(PLAYLIST_DIR, files[0]), 'r') as f:
|
||||
latest_file = files[0]
|
||||
with open(os.path.join(PLAYLIST_DIR, latest_file), 'r') as f:
|
||||
data = json.load(f)
|
||||
return data.get('playlist', [])
|
||||
|
||||
def main():
|
||||
root = tk.Tk()
|
||||
root.title("Simple Tkinter Player")
|
||||
root.configure(bg='black')
|
||||
root.attributes('-fullscreen', True)
|
||||
playlist = load_latest_playlist()
|
||||
player = SimpleTkPlayer(root, playlist)
|
||||
player.main_start()
|
||||
root.mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 848 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 410 KiB |
BIN
signage_player/static_data/media/demo2.jpeg
Normal file
BIN
signage_player/static_data/media/demo2.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 537 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 737 KiB |
20
signage_player/static_data/playlist/server_playlist_v4.json
Normal file
20
signage_player/static_data/playlist/server_playlist_v4.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"playlist": [
|
||||
{
|
||||
"file_name": "big-buck-bunny-1080p-60fps-30sec.mp4",
|
||||
"url": "media/big-buck-bunny-1080p-60fps-30sec.mp4",
|
||||
"duration": 30
|
||||
},
|
||||
{
|
||||
"file_name": "demo2.jpeg",
|
||||
"url": "media/demo2.jpeg",
|
||||
"duration": 50
|
||||
},
|
||||
{
|
||||
"file_name": "call-of-duty-black-3840x2160-23674.jpg",
|
||||
"url": "media/call-of-duty-black-3840x2160-23674.jpg",
|
||||
"duration": 30
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"playlist": [
|
||||
{
|
||||
"file_name": "cropped-cropped-main-picture-scaled-1.jpeg",
|
||||
"url": "media/cropped-cropped-main-picture-scaled-1.jpeg",
|
||||
"duration": 15
|
||||
},
|
||||
{
|
||||
"file_name": "start_page.jpeg",
|
||||
"url": "media/start_page.jpeg",
|
||||
"duration": 15
|
||||
},
|
||||
{
|
||||
"file_name": "Banner_poarta_2_x6.jpg",
|
||||
"url": "media/Banner_poarta_2_x6.jpg",
|
||||
"duration": 10
|
||||
},
|
||||
{
|
||||
"file_name": "WhatsApp_Video_2025-08-21_at_18.34.19_86a6f243.mp4",
|
||||
"url": "media/WhatsApp_Video_2025-08-21_at_18.34.19_86a6f243.mp4",
|
||||
"duration": 101
|
||||
}
|
||||
],
|
||||
"version": 5
|
||||
}
|
||||
Reference in New Issue
Block a user