- Removed 6 duplicate cron entries that were spawning multiple instances
- Enabled systemd kiwy-player.service for proper startup management
- Service is now the single source of truth for app startup
- App runs stably with proper DISPLAY environment from systemd
Issue: Player crashes after 2-3 minutes during editing
Hypothesis: The background upload thread may be interfering with playback
even with the Clock.schedule_once fix.
Action: Temporarily disable the background upload to see if this is
the root cause of the crashes.
Edits will still be saved locally, just not uploaded to server during
this diagnostic test.
If player is stable without this thread, the issue is in the upload
logic or thread management.
BUG: Background upload thread was crashing the app
Problem:
- _upload_to_server() runs in daemon thread
- Was directly setting self.player.should_refresh_playlist from thread
- Kivy is NOT thread-safe for direct state modifications
- App crashed after 2-3 minutes during editing
Root cause:
Line 503: self.player.should_refresh_playlist = True
This directly modified Kivy object state from non-main thread
Caused race conditions and memory corruption
Solution:
- Use Clock.schedule_once() to schedule flag update on main thread
- Ensures all Kivy state modifications happen on main thread
- Thread-safe and proper Kivy API usage
- No more app crashes during editing
This was causing the app to crash every 10-20 seconds during edits.
Should now be stable!
CRITICAL FIX - This was the main issue preventing edited images from appearing!
Problem:
- Edited media was being uploaded to server successfully
- Server updated the playlist (new version returned: 34)
- BUT player never reloaded the playlist
- So edited images stayed invisible until restart
Solution:
1. EditPopup now sets should_refresh_playlist flag when upload succeeds
2. Main player checks this flag in check_playlist_and_play()
3. When flag is set, player immediately reloads playlist
4. Edited media appears instantly without needing restart
Testing:
- Created diagnostic script test_edited_media_upload.py
- Confirmed server accepts edited media and returns new playlist version
- Verified SSL fix works correctly (verify=False)
Now edited images should appear immediately after save!
Root cause identified from logs:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate
The server uses a self-signed certificate (like production), but the edited media
upload endpoint was not disabling SSL verification while other API calls do.
Solution:
- Add verify=False to requests.post() call in _upload_to_server()
- Matches the SSL verification handling in get_playlists_v2.py
- Add warning about SSL verification being disabled
- Now edited images can upload successfully to server
This fixes the upload failures that were preventing edited images from being
synced to the server.
Critical fixes for image editing workflow:
1. Keep local edited files as backup (don't delete after server upload)
- Server may not process upload immediately
- Keeps edits safe locally in case server fails
- Prevents loss of edited images
2. Include original filename in metadata sent to server
- Server needs to know which file was edited
- Allows proper tracking and versioning
3. Improved error logging for server upload
- Now logs detailed errors (404, 401, timeout, connection)
- Shows clear messages when server doesn't support endpoint
- Helps diagnose why edits aren't syncing to server
4. Better user feedback during save
- Shows 'Saved to device' status first
- Then 'Upload in progress' to show server sync happening
- Clarifies local vs server save status
Bug symptoms fixed:
- Edited images now persist locally after restart
- Server upload now sends correct file information
- Clear error messages if server upload fails
- User understands 'local save' vs 'server sync' steps
Added support for both X11 and Wayland environments:
Display Server Detection:
- Auto-detects Wayland via WAYLAND_DISPLAY environment variable
- Falls back to X11 commands if not Wayland
- Works seamlessly on both display servers
Wayland-specific tools:
- wlopm - Wayland output power management (keeps display on)
- wlr-randr - Output management for wlroots compositors
- ydotool - Mouse movement for Wayland (alternative to xdotool)
- systemd-inhibit integration for idle prevention
Enhanced display keep-alive script:
- Detects display server type on startup
- Uses appropriate commands based on environment
- Wayland: wlopm, wlr-randr, ydotool
- X11: xset, xdotool, xrandr
- Both: tvservice for HDMI power control
App-level improvements (main.py):
- Detects Wayland via os.environ check
- Executes Wayland-specific commands when detected
- Maintains X11 compatibility for older systems
Installation improvements:
- Auto-installs Wayland tools if Wayland is detected
- Attempts to install: wlopm, wlr-randr, ydotool
- Graceful fallback if packages unavailable
This ensures HDMI power management works correctly on:
- Raspberry Pi OS with X11 (older versions)
- Raspberry Pi OS with Wayland (Bookworm and newer)
- Any Linux system using either display server
- Added signal_screen_activity() method to SignagePlayer class
- Runs every 20 seconds automatically
- Also triggered on any touch/user input events
Multiple methods used to keep display awake:
- xset s reset - Resets screensaver timer
- xset dpms force on - Forces display on
- xdotool - Subtle mouse movement to trigger activity
This complements the system-level power management:
- Works alongside display power management settings
- Non-blocking and non-critical (fails gracefully)
- Signals every 20 seconds + on user input
- Prevents display from sleeping during playback
Screen should now remain active throughout media playback.
- Created .keep-screen-alive.sh wrapper script with multiple methods:
* systemd-inhibit (primary - prevents OS-level sleep/suspend)
* xset commands (prevents X11 screensaver)
* Mouse movement (prevents idle timeout)
- Added screen-keepalive.service systemd unit:
* Runs xset s reset every 30 seconds
* Auto-restarts on failure
* Integrated with graphical session
- Multiple layers of screen protection:
* HDMI blanking disabled
* CPU power saving disabled
* System sleep/suspend disabled
* X11 screensaver disabled
* DPMS (Display Power Management) disabled
* Display forced on periodically
Screen will now remain active while player is running, preventing lockups or blank screens during playback.
- Enhanced install.sh with comprehensive autostart workflow:
* XDG autostart entry (desktop environment)
* systemd user service (most reliable)
* LXDE autostart support (Raspberry Pi OS)
* Cron fallback (@reboot)
* Terminal mode enabled for debugging
- Added Raspberry Pi power management features:
* Disable HDMI screen blanking
* Prevent CPU power saving (performance mode)
* Disable system sleep/suspend
* X11 screensaver disabled
* Display power management (DPMS) disabled
- Fixed sudo compatibility:
* Properly detects actual user when run with sudo
* Correct file ownership for user configs
* systemctl --user works correctly
- Player launches in terminal for error visibility
- Autostart configured to use start.sh (watchdog with auto-restart)