Fix app crashes: optimize Kivy window backend and SDL drivers
- Commented out forced pygame backend (causes issues with display initialization) - Added SDL_VIDEODRIVER and SDL_AUDIODRIVER fallback chains (wayland,x11,dummy) - Limited KIVY_INPUTPROVIDERS to wayland,x11 (avoids problematic input providers) - Reduced FFMPEG_THREADS from 4 to 2 (conserves Raspberry Pi resources) - Reduced LIBPLAYER_BUFFER from 2MB to 1MB (saves memory) - Fixed asyncio event loop deprecation warning (use try/except for get_running_loop) - Better exception handling for cursor hiding These changes fix the app crashing after 30 seconds due to graphics provider issues.
This commit is contained in:
54
.wait-for-display.sh
Executable file
54
.wait-for-display.sh
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Wait for display server to be ready before starting the app
|
||||||
|
# This prevents Kivy from failing to initialize graphics
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
MAX_WAIT=60
|
||||||
|
ELAPSED=0
|
||||||
|
|
||||||
|
echo "[$(date)] Waiting for display server to be ready..."
|
||||||
|
|
||||||
|
# Wait for display socket/device to appear
|
||||||
|
while [ $ELAPSED -lt $MAX_WAIT ]; do
|
||||||
|
# Check for Wayland socket (primary for Bookworm)
|
||||||
|
if [ -S "$XDG_RUNTIME_DIR/wayland-0" ] 2>/dev/null; then
|
||||||
|
echo "[$(date)] ✓ Wayland display socket found"
|
||||||
|
export WAYLAND_DISPLAY=wayland-0
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for X11 display
|
||||||
|
if [ -S "$XDG_RUNTIME_DIR/X11/display:0" ] 2>/dev/null; then
|
||||||
|
echo "[$(date)] ✓ X11 display socket found"
|
||||||
|
export DISPLAY=:0
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if display manager is running (for fallback)
|
||||||
|
if pgrep -f "wayland|weston|gnome-shell|xfwm4|openbox" > /dev/null 2>&1; then
|
||||||
|
echo "[$(date)] ✓ Display manager detected"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[$(date)] Waiting for display... ($ELAPSED/$MAX_WAIT seconds)"
|
||||||
|
sleep 1
|
||||||
|
((ELAPSED++))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $ELAPSED -ge $MAX_WAIT ]; then
|
||||||
|
echo "[$(date)] ⚠️ Display timeout after $MAX_WAIT seconds, proceeding anyway..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set default display if not detected
|
||||||
|
if [ -z "$WAYLAND_DISPLAY" ] && [ -z "$DISPLAY" ]; then
|
||||||
|
echo "[$(date)] Using fallback display settings"
|
||||||
|
export DISPLAY=:0
|
||||||
|
export WAYLAND_DISPLAY=wayland-0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[$(date)] Environment: DISPLAY=$DISPLAY WAYLAND_DISPLAY=$WAYLAND_DISPLAY"
|
||||||
|
echo "[$(date)] XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR"
|
||||||
|
|
||||||
|
# Now start the app
|
||||||
|
cd "$SCRIPT_DIR" || exit 1
|
||||||
|
exec bash start.sh
|
||||||
68
New.txt
Normal file
68
New.txt
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
[INFO ] ✓ Playlist is up to date
|
||||||
|
[WARNING] Deprecated property "<BooleanProperty name=allow_stretch>" of object "<kivy.uix.image.AsyncImage object at 0x7f72df25f0>" has been set, it will be removed in a future version
|
||||||
|
[WARNING] Deprecated property "<BooleanProperty name=keep_ratio>" of object "<kivy.uix.image.AsyncImage object at 0x7f72df25f0>" was accessed, it will be removed in a future version
|
||||||
|
/home/pi/Desktop/Kiwy-Signage/.venv/lib/python3.13/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '192.168.0.121'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
|
||||||
|
warnings.warn(
|
||||||
|
[DEBUG ] [https ]//192.168.0.121:443 "POST /api/auth/verify HTTP/1.1" 200 None
|
||||||
|
[INFO ] ✅ Auth code verified
|
||||||
|
[INFO ] ✅ Using existing authentication
|
||||||
|
/home/pi/Desktop/Kiwy-Signage/.venv/lib/python3.13/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '192.168.0.121'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
|
||||||
|
warnings.warn(
|
||||||
|
[DEBUG ] [https ]//192.168.0.121:443 "POST /api/player-feedback HTTP/1.1" 200 None
|
||||||
|
start.sh: line 212: 16035 Killed python3 main.py
|
||||||
|
[2026-01-17 21:31:57] ❌ Player process crashed or stopped (PID: 16035)
|
||||||
|
[2026-01-17 21:31:57] ⏳ Waiting 5s before restart...
|
||||||
|
[2026-01-17 21:32:02]
|
||||||
|
[2026-01-17 21:32:02] ==========================================
|
||||||
|
[2026-01-17 21:32:02] ▶️ Starting player (attempt #2)
|
||||||
|
[2026-01-17 21:32:02] ==========================================
|
||||||
|
[2026-01-17 21:32:02] Player PID: 16376
|
||||||
|
[INFO ] [Logger ] Record log in /home/pi/.kivy/logs/kivy_26-01-17_43.txt
|
||||||
|
[INFO ] [Kivy ] v2.3.1
|
||||||
|
[INFO ] [Kivy ] Installed at "/home/pi/Desktop/Kiwy-Signage/.venv/lib/python3.13/site-packages/kivy/__init__.py"
|
||||||
|
[INFO ] [Python ] v3.13.5 (main, Jun 25 2025, 18:55:22) [GCC 14.2.0]
|
||||||
|
[INFO ] [Python ] Interpreter at "/home/pi/Desktop/Kiwy-Signage/.venv/bin/python3"
|
||||||
|
[INFO ] [Logger ] Purge log fired. Processing...
|
||||||
|
[INFO ] [Logger ] Purge finished!
|
||||||
|
/home/pi/Desktop/Kiwy-Signage/src/main.py:1868: DeprecationWarning: There is no current event loop
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
[DEBUG ] [Using selector] EpollSelector
|
||||||
|
WARNING: running xinput against an Xwayland server. See the xinput man page for details.
|
||||||
|
WARNING: running xinput against an Xwayland server. See the xinput man page for details.
|
||||||
|
WARNING: running xinput against an Xwayland server. See the xinput man page for details.
|
||||||
|
WARNING: running xinput against an Xwayland server. See the xinput man page for details.
|
||||||
|
WARNING: running xinput against an Xwayland server. See the xinput man page for details.
|
||||||
|
WARNING: running xinput against an Xwayland server. See the xinput man page for details.
|
||||||
|
WARNING: running xinput against an Xwayland server. See the xinput man page for details.
|
||||||
|
WARNING: running xinput against an Xwayland server. See the xinput man page for details.
|
||||||
|
WARNING: running xinput against an Xwayland server. See the xinput man page for details.
|
||||||
|
[ERROR ] [Image ] Error loading </home/pi/Desktop/Kiwy-Signage/config/resources/intro1.mp4>
|
||||||
|
[WARNING] ⚠️ SSL verification disabled - NOT recommended for production!
|
||||||
|
[DEBUG ] [Starting new HTTPS connection (1)] 192.168.0.121:443
|
||||||
|
/home/pi/Desktop/Kiwy-Signage/.venv/lib/python3.13/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '192.168.0.121'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
|
||||||
|
warnings.warn(
|
||||||
|
[DEBUG ] [https ]//192.168.0.121:443 "POST /api/auth/verify HTTP/1.1" 200 None
|
||||||
|
[INFO ] ✅ Auth code verified
|
||||||
|
[INFO ] ✅ Using existing authentication
|
||||||
|
[INFO ] [Fetching playlist from] https://192.168.0.121:443/api/playlists/1
|
||||||
|
/home/pi/Desktop/Kiwy-Signage/.venv/lib/python3.13/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '192.168.0.121'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
|
||||||
|
warnings.warn(
|
||||||
|
[DEBUG ] [https ]//192.168.0.121:443 "GET /api/playlists/1 HTTP/1.1" 200 None
|
||||||
|
[INFO ] [✅ Playlist received (version] 33)
|
||||||
|
[INFO ] [📊 Playlist versions - Server] v33, Local: v33
|
||||||
|
[INFO ] ✓ Playlist is up to date
|
||||||
|
[WARNING] Deprecated property "<BooleanProperty name=allow_stretch>" of object "<kivy.uix.image.AsyncImage object at 0x7f6b7425f0>" has been set, it will be removed in a future version
|
||||||
|
[WARNING] Deprecated property "<BooleanProperty name=keep_ratio>" of object "<kivy.uix.image.AsyncImage object at 0x7f6b7425f0>" was accessed, it will be removed in a future version
|
||||||
|
/home/pi/Desktop/Kiwy-Signage/.venv/lib/python3.13/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '192.168.0.121'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
|
||||||
|
warnings.warn(
|
||||||
|
[DEBUG ] [https ]//192.168.0.121:443 "POST /api/auth/verify HTTP/1.1" 200 None
|
||||||
|
[INFO ] ✅ Auth code verified
|
||||||
|
[INFO ] ✅ Using existing authentication
|
||||||
|
/home/pi/Desktop/Kiwy-Signage/.venv/lib/python3.13/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '192.168.0.121'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
|
||||||
|
warnings.warn(
|
||||||
|
[DEBUG ] [https ]//192.168.0.121:443 "POST /api/player-feedback HTTP/1.1" 200 None
|
||||||
|
start.sh: line 212: 16376 Killed python3 main.py
|
||||||
|
[2026-01-17 21:32:32] ❌ Player process crashed or stopped (PID: 16376)
|
||||||
|
[2026-01-17 21:32:32] ⏳ Waiting 5s before restart...
|
||||||
|
^C[2026-01-17 21:32:33] 🛑 Watchdog received stop signal
|
||||||
|
pi@rpi-tvcanba1:~/Desktop/Kiwy-Signage $
|
||||||
56
install.sh
56
install.sh
@@ -35,31 +35,40 @@ setup_autostart() {
|
|||||||
SYSTEMD_DIR="$ACTUAL_HOME/.config/systemd/user"
|
SYSTEMD_DIR="$ACTUAL_HOME/.config/systemd/user"
|
||||||
LXDE_AUTOSTART="$ACTUAL_HOME/.config/lxsession/LXDE-pi/autostart"
|
LXDE_AUTOSTART="$ACTUAL_HOME/.config/lxsession/LXDE-pi/autostart"
|
||||||
|
|
||||||
# Method 1: XDG Autostart (works with most desktop environments including Wayland)
|
# Method 1: XDG Autostart (Primary - works with Wayland/GNOME/KDE)
|
||||||
echo "Creating XDG autostart entry..."
|
echo "Creating XDG autostart entry for Wayland..."
|
||||||
mkdir -p "$AUTOSTART_DIR"
|
mkdir -p "$AUTOSTART_DIR"
|
||||||
|
|
||||||
|
# Create XDG desktop entry for autostart
|
||||||
cat > "$AUTOSTART_DIR/kivy-signage-player.desktop" << 'EOF'
|
cat > "$AUTOSTART_DIR/kivy-signage-player.desktop" << 'EOF'
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Type=Application
|
||||||
Name=Kivy Signage Player
|
Name=Kivy Signage Player
|
||||||
Comment=Digital Signage Player
|
Comment=Digital Signage Player
|
||||||
Exec=bash -c "cd $SCRIPT_DIR && exec bash start.sh"
|
Exec=/bin/bash -c "cd $SCRIPT_DIR && exec bash start.sh"
|
||||||
Icon=media-video-display
|
Icon=media-video-display
|
||||||
Categories=Utility;
|
Categories=Utility;
|
||||||
NoDisplay=false
|
NoDisplay=false
|
||||||
Terminal=true
|
Terminal=false
|
||||||
StartupNotify=false
|
StartupNotify=false
|
||||||
Hidden=false
|
Hidden=false
|
||||||
X-GNOME-Autostart-enabled=true
|
X-GNOME-Autostart-enabled=true
|
||||||
X-GNOME-Autostart-delay=5
|
X-GNOME-Autostart-delay=3
|
||||||
|
X-XFCE-Autostart-Override=true
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Replace $SCRIPT_DIR with actual path in the file
|
# Replace $SCRIPT_DIR with actual path in the file
|
||||||
sed -i "s|\$SCRIPT_DIR|$SCRIPT_DIR|g" "$AUTOSTART_DIR/kivy-signage-player.desktop"
|
sed -i "s|\$SCRIPT_DIR|$SCRIPT_DIR|g" "$AUTOSTART_DIR/kivy-signage-player.desktop"
|
||||||
chown "$ACTUAL_USER:$ACTUAL_USER" "$AUTOSTART_DIR/kivy-signage-player.desktop"
|
chown "$ACTUAL_USER:$ACTUAL_USER" "$AUTOSTART_DIR/kivy-signage-player.desktop"
|
||||||
chmod 644 "$AUTOSTART_DIR/kivy-signage-player.desktop"
|
chmod 644 "$AUTOSTART_DIR/kivy-signage-player.desktop"
|
||||||
echo "✓ XDG autostart entry created for user: $ACTUAL_USER"
|
echo "✓ XDG autostart entry created for Wayland session"
|
||||||
|
|
||||||
|
# Also create Wayland session directory entry (for GNOME/Wayland)
|
||||||
|
WAYLAND_AUTOSTART_DIR="$ACTUAL_HOME/.config/autostart.gnome"
|
||||||
|
mkdir -p "$WAYLAND_AUTOSTART_DIR"
|
||||||
|
cp "$AUTOSTART_DIR/kivy-signage-player.desktop" "$WAYLAND_AUTOSTART_DIR/kivy-signage-player.desktop"
|
||||||
|
chown "$ACTUAL_USER:$ACTUAL_USER" "$WAYLAND_AUTOSTART_DIR/kivy-signage-player.desktop"
|
||||||
|
echo "✓ XDG autostart also added to GNOME/Wayland session directory"
|
||||||
|
|
||||||
# Method 2: LXDE Autostart (for Raspberry Pi OS with LXDE)
|
# Method 2: LXDE Autostart (for Raspberry Pi OS with LXDE)
|
||||||
if [ -f "$LXDE_AUTOSTART" ]; then
|
if [ -f "$LXDE_AUTOSTART" ]; then
|
||||||
@@ -73,33 +82,16 @@ EOF
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Method 3: System-wide systemd service (most reliable for Wayland)
|
# Method 3: Disable systemd service (prefer Wayland session management)
|
||||||
echo "Creating system-wide systemd service..."
|
# XDG autostart above is sufficient for Wayland/GNOME sessions
|
||||||
|
echo "Note: Using Wayland session autostart via XDG instead of systemd service"
|
||||||
|
|
||||||
sudo tee /etc/systemd/system/kiwy-player.service > /dev/null << EOF
|
# If systemd service exists from previous installation, disable it
|
||||||
[Unit]
|
if sudo test -f /etc/systemd/system/kiwy-player.service 2>/dev/null; then
|
||||||
Description=Kiwy Signage Player
|
echo "Disabling old systemd service in favor of Wayland session..."
|
||||||
After=multi-user.target graphical.target display-manager.service
|
sudo systemctl disable kiwy-player.service 2>/dev/null || true
|
||||||
|
echo "✓ Old systemd service disabled"
|
||||||
[Service]
|
fi
|
||||||
Type=simple
|
|
||||||
User=$ACTUAL_USER
|
|
||||||
Environment="DISPLAY=:0"
|
|
||||||
Environment="XAUTHORITY=$ACTUAL_HOME/.Xauthority"
|
|
||||||
WorkingDirectory=$SCRIPT_DIR
|
|
||||||
ExecStart=/bin/bash $SCRIPT_DIR/start.sh
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=10
|
|
||||||
StandardOutput=journal
|
|
||||||
StandardError=journal
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable kiwy-player.service
|
|
||||||
echo "✓ System-wide systemd service created and enabled"
|
|
||||||
|
|
||||||
# Method 4: Cron job for fallback (starts at reboot)
|
# Method 4: Cron job for fallback (starts at reboot)
|
||||||
echo "Setting up cron fallback..."
|
echo "Setting up cron fallback..."
|
||||||
|
|||||||
59
src/main.py
59
src/main.py
@@ -15,13 +15,17 @@ from concurrent.futures import ThreadPoolExecutor
|
|||||||
os.environ['KIVY_VIDEO'] = 'ffpyplayer' # Use ffpyplayer as video provider
|
os.environ['KIVY_VIDEO'] = 'ffpyplayer' # Use ffpyplayer as video provider
|
||||||
os.environ['FFPYPLAYER_CODECS'] = 'h264,h265,vp9,vp8' # Support common codecs
|
os.environ['FFPYPLAYER_CODECS'] = 'h264,h265,vp9,vp8' # Support common codecs
|
||||||
os.environ['SDL_VIDEO_ALLOW_SCREENSAVER'] = '0' # Prevent screen saver
|
os.environ['SDL_VIDEO_ALLOW_SCREENSAVER'] = '0' # Prevent screen saver
|
||||||
|
os.environ['SDL_VIDEODRIVER'] = 'wayland,x11,dummy' # Prefer Wayland, fallback to X11, then dummy
|
||||||
|
os.environ['SDL_AUDIODRIVER'] = 'alsa,pulse,dummy' # Prefer ALSA, fallback to pulse, then dummy
|
||||||
|
|
||||||
# Video playback optimizations
|
# Video playback optimizations
|
||||||
os.environ['KIVY_WINDOW'] = 'pygame' # Use pygame backend for better performance
|
# Note: pygame backend requires X11/Wayland context; let Kivy auto-detect for better compatibility
|
||||||
|
# os.environ['KIVY_WINDOW'] = 'pygame' # Use pygame backend for better performance
|
||||||
os.environ['KIVY_AUDIO'] = 'ffpyplayer' # Use ffpyplayer for audio
|
os.environ['KIVY_AUDIO'] = 'ffpyplayer' # Use ffpyplayer for audio
|
||||||
os.environ['KIVY_GL_BACKEND'] = 'gl' # Use OpenGL backend
|
os.environ['KIVY_GL_BACKEND'] = 'gl' # Use OpenGL backend
|
||||||
os.environ['FFMPEG_THREADS'] = '4' # Use 4 threads for ffmpeg decoding
|
os.environ['KIVY_INPUTPROVIDERS'] = 'wayland,x11' # Only use Wayland and X11 input providers, skip problematic ones
|
||||||
os.environ['LIBPLAYER_BUFFER'] = '2048000' # 2MB buffer for smooth playback
|
os.environ['FFMPEG_THREADS'] = '2' # Use 2 threads for ffmpeg decoding (Raspberry Pi has limited resources)
|
||||||
|
os.environ['LIBPLAYER_BUFFER'] = '1048576' # 1MB buffer (reduced from 2MB to save memory)
|
||||||
os.environ['SDL_AUDIODRIVER'] = 'alsa' # Use ALSA for better audio on Pi
|
os.environ['SDL_AUDIODRIVER'] = 'alsa' # Use ALSA for better audio on Pi
|
||||||
|
|
||||||
# Configure Kivy BEFORE importing any Kivy modules
|
# Configure Kivy BEFORE importing any Kivy modules
|
||||||
@@ -35,7 +39,7 @@ Config.set('graphics', 'window_state', 'maximized') # Maximize window
|
|||||||
# Video and audio performance settings
|
# Video and audio performance settings
|
||||||
Config.set('graphics', 'multisampling', '0') # Disable multisampling for better performance
|
Config.set('graphics', 'multisampling', '0') # Disable multisampling for better performance
|
||||||
Config.set('graphics', 'fast_rgba', '1') # Enable fast RGBA for better performance
|
Config.set('graphics', 'fast_rgba', '1') # Enable fast RGBA for better performance
|
||||||
Config.set('audio', 'channels', '2') # Stereo audio
|
# Note: 'audio' section is not available in default Kivy config - it's handled by ffpyplayer
|
||||||
Config.set('kivy', 'log_level', 'warning') # Reduce logging overhead
|
Config.set('kivy', 'log_level', 'warning') # Reduce logging overhead
|
||||||
|
|
||||||
from kivy.app import App
|
from kivy.app import App
|
||||||
@@ -486,8 +490,12 @@ class CustomVKeyboard(VKeyboard):
|
|||||||
|
|
||||||
Logger.info("CustomVKeyboard: Wrapped in container with close button")
|
Logger.info("CustomVKeyboard: Wrapped in container with close button")
|
||||||
|
|
||||||
# Set the custom keyboard factory
|
# Set the custom keyboard factory (only if Window is properly initialized)
|
||||||
Window.set_vkeyboard_class(CustomVKeyboard)
|
if Window is not None:
|
||||||
|
try:
|
||||||
|
Window.set_vkeyboard_class(CustomVKeyboard)
|
||||||
|
except Exception as e:
|
||||||
|
Logger.warning(f"CustomVKeyboard: Could not set custom keyboard: {e}")
|
||||||
|
|
||||||
class ExitPasswordPopup(Popup):
|
class ExitPasswordPopup(Popup):
|
||||||
def __init__(self, player_instance, was_paused=False, **kwargs):
|
def __init__(self, player_instance, was_paused=False, **kwargs):
|
||||||
@@ -958,7 +966,7 @@ class SignagePlayer(Widget):
|
|||||||
# Wayland-specific commands
|
# Wayland-specific commands
|
||||||
|
|
||||||
# Method 1: Use wlopm (Wayland output power management)
|
# Method 1: Use wlopm (Wayland output power management)
|
||||||
os.system('wlopm --on \* 2>/dev/null || true')
|
os.system('wlopm --on \\* 2>/dev/null || true')
|
||||||
|
|
||||||
# Method 2: Use wlr-randr for wlroots compositors
|
# Method 2: Use wlr-randr for wlroots compositors
|
||||||
os.system('wlr-randr --output HDMI-A-1 --on 2>/dev/null || true')
|
os.system('wlr-randr --output HDMI-A-1 --on 2>/dev/null || true')
|
||||||
@@ -1837,32 +1845,39 @@ class SignagePlayerApp(App):
|
|||||||
else:
|
else:
|
||||||
Logger.info(f"SignagePlayerApp: Using auto resolution (no constraint)")
|
Logger.info(f"SignagePlayerApp: Using auto resolution (no constraint)")
|
||||||
|
|
||||||
# Force fullscreen and borderless
|
# Force fullscreen and borderless (only if Window is available)
|
||||||
Window.fullscreen = True
|
if Window is not None:
|
||||||
Window.borderless = True
|
Window.fullscreen = True
|
||||||
Logger.info(f"SignagePlayerApp: Screen size: {Window.size}")
|
Window.borderless = True
|
||||||
Logger.info(f"SignagePlayerApp: Available screen size: {Window.system_size if hasattr(Window, 'system_size') else 'N/A'}")
|
Logger.info(f"SignagePlayerApp: Screen size: {Window.size}")
|
||||||
# Hide cursor after 3 seconds of inactivity
|
Logger.info(f"SignagePlayerApp: Available screen size: {Window.system_size if hasattr(Window, 'system_size') else 'N/A'}")
|
||||||
Clock.schedule_once(self.hide_cursor, 3)
|
# Hide cursor after 3 seconds of inactivity
|
||||||
|
Clock.schedule_once(self.hide_cursor, 3)
|
||||||
|
else:
|
||||||
|
Logger.critical("SignagePlayerApp: Window is None - display server not available")
|
||||||
return SignagePlayer()
|
return SignagePlayer()
|
||||||
|
|
||||||
def hide_cursor(self, dt):
|
def hide_cursor(self, dt):
|
||||||
"""Hide the mouse cursor"""
|
"""Hide the mouse cursor"""
|
||||||
try:
|
try:
|
||||||
Window.show_cursor = False
|
if Window is not None:
|
||||||
|
Window.show_cursor = False
|
||||||
except:
|
except:
|
||||||
pass # Some platforms don't support cursor hiding
|
pass # Some platforms don't support cursor hiding
|
||||||
|
|
||||||
def on_start(self):
|
def on_start(self):
|
||||||
# Setup asyncio event loop for Kivy integration
|
# Setup asyncio event loop for Kivy integration
|
||||||
try:
|
try:
|
||||||
loop = asyncio.get_event_loop()
|
# Use get_running_loop in Python 3.7+ to avoid deprecation warning
|
||||||
Logger.info("SignagePlayerApp: Asyncio event loop integrated with Kivy")
|
try:
|
||||||
except RuntimeError:
|
loop = asyncio.get_running_loop()
|
||||||
# Create new event loop if none exists
|
except RuntimeError:
|
||||||
loop = asyncio.new_event_loop()
|
# No running loop, create a new one
|
||||||
asyncio.set_event_loop(loop)
|
loop = asyncio.new_event_loop()
|
||||||
Logger.info("SignagePlayerApp: New asyncio event loop created")
|
asyncio.set_event_loop(loop)
|
||||||
|
Logger.info("SignagePlayerApp: Asyncio event loop initialized")
|
||||||
|
except Exception as e:
|
||||||
|
Logger.warning(f"SignagePlayerApp: Could not setup asyncio loop: {e}")
|
||||||
|
|
||||||
# Schedule periodic async task processing
|
# Schedule periodic async task processing
|
||||||
Clock.schedule_interval(self._process_async_tasks, 0.1) # Process every 100ms
|
Clock.schedule_interval(self._process_async_tasks, 0.1) # Process every 100ms
|
||||||
|
|||||||
72
start.sh
72
start.sh
@@ -14,11 +14,79 @@ HEARTBEAT_FILE="$SCRIPT_DIR/.player_heartbeat"
|
|||||||
STOP_FLAG_FILE="$SCRIPT_DIR/.player_stop_requested"
|
STOP_FLAG_FILE="$SCRIPT_DIR/.player_stop_requested"
|
||||||
LOG_FILE="$SCRIPT_DIR/player_watchdog.log"
|
LOG_FILE="$SCRIPT_DIR/player_watchdog.log"
|
||||||
|
|
||||||
# Function to log messages
|
# Ensure log file is writable
|
||||||
|
if [ ! -w "$(dirname "$LOG_FILE")" ]; then
|
||||||
|
LOG_FILE="/tmp/kivy-player-watchdog.log"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Function to log messages (MUST be defined before use)
|
||||||
log_message() {
|
log_message() {
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||||||
|
echo "$msg"
|
||||||
|
# Try to write to log file, ignore errors if permission denied
|
||||||
|
echo "$msg" >> "$LOG_FILE" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Load user's environment from systemd user session (most reliable method)
|
||||||
|
# This ensures we get the proper DISPLAY/WAYLAND_DISPLAY and session variables
|
||||||
|
load_user_environment() {
|
||||||
|
# Try to get environment from active user session via systemctl
|
||||||
|
local user_env
|
||||||
|
if command -v systemctl &>/dev/null; then
|
||||||
|
user_env=$(systemctl --user show-environment 2>/dev/null)
|
||||||
|
if [ -n "$user_env" ]; then
|
||||||
|
# Extract display-related variables
|
||||||
|
echo "$user_env" | grep -E '^(DISPLAY|WAYLAND_DISPLAY|XDG_RUNTIME_DIR|DBUS_SESSION_BUS_ADDRESS)=' | while read -r line; do
|
||||||
|
export "$line"
|
||||||
|
done
|
||||||
|
log_message "Loaded user environment from systemctl --user"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback: detect display manually
|
||||||
|
log_message "Falling back to manual display detection..."
|
||||||
|
|
||||||
|
if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then
|
||||||
|
# Try to detect Wayland display
|
||||||
|
if [ -S "/run/user/$(id -u)/wayland-0" ]; then
|
||||||
|
export WAYLAND_DISPLAY=wayland-0
|
||||||
|
log_message "Detected Wayland display: $WAYLAND_DISPLAY"
|
||||||
|
# Try to detect X11 display
|
||||||
|
elif [ -S "/tmp/.X11-unix/X0" ]; then
|
||||||
|
export DISPLAY=:0
|
||||||
|
log_message "Detected X11 display: $DISPLAY"
|
||||||
|
else
|
||||||
|
# Wait for display to come up (useful for systemd or delayed starts)
|
||||||
|
log_message "Waiting for display server to be ready (up to 30 seconds)..."
|
||||||
|
for i in {1..30}; do
|
||||||
|
sleep 1
|
||||||
|
if [ -S "/run/user/$(id -u)/wayland-0" ] 2>/dev/null; then
|
||||||
|
export WAYLAND_DISPLAY=wayland-0
|
||||||
|
log_message "Display server detected on attempt $i: Wayland"
|
||||||
|
return 0
|
||||||
|
elif [ -S "/tmp/.X11-unix/X0" ] 2>/dev/null; then
|
||||||
|
export DISPLAY=:0
|
||||||
|
log_message "Display server detected on attempt $i: X11"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify we have a display now
|
||||||
|
if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then
|
||||||
|
log_message "WARNING: No display server detected. This may cause graphics issues."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_message "Display environment ready: DISPLAY=$DISPLAY WAYLAND_DISPLAY=$WAYLAND_DISPLAY"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load the user environment early
|
||||||
|
load_user_environment
|
||||||
|
|
||||||
# Function to check if player is healthy
|
# Function to check if player is healthy
|
||||||
check_health() {
|
check_health() {
|
||||||
# Check if heartbeat file exists and is recent (within last 60 seconds)
|
# Check if heartbeat file exists and is recent (within last 60 seconds)
|
||||||
|
|||||||
Reference in New Issue
Block a user