helgeerbe / picframe

Picture frame viewer for raspi, controlled via mqtt and automatticly integrated as mqtt device in homeassistant.
MIT License
91 stars 27 forks source link

RPi-5 BookWorm - Does not survive monitor being switched off #361

Open Dropbear67 opened 6 months ago

Dropbear67 commented 6 months ago

Instructions to re-produce: Install via Wolfgang's instructions https://www.thedigitalpictureframe.com/how-to-build-a-gorgeous-digital-photo-frame-with-a-raspberry-pi-based-on-2023-bookworm/

Issue: Switch monitor off and when switched back on, we get a blank black screen with the mouse pointer showing. This does not occur on my RPI-3 running the old Buster version - I can switch my TV off and on and the PicFrame displays normally when the TV comes back on.

Dropbear67 commented 6 months ago

May be related to this

https://forums.raspberrypi.com/viewtopic.php?t=360888

Dropbear67 commented 6 months ago

$ wlr-randr --output HDMI-A-1 --off

will software power off but picframe does not survive this.. crashes with nothing written to DEBUG

$ wlr-randr --output HDMI-A-1 --on --mode "3840x2160,59.981998"; picframe &

works and displays normally.

btw getting these messages in DEBUG

DEBUG:viewer_display.ViewerDisplay:Display ON/OFF is vcgencmd, but an error occurred DEBUG:viewer_display.ViewerDisplay:Cause: Command '['vcgencmd', 'display_power']' returned non-zero exit status 255.

helgeerbe commented 6 months ago

I setup a debugger on my pi3 and found that picframe crashes in Display.pyline 340 after calling wlr-randr --output HDMI-A-1 --off

while sdl2.SDL_PollEvent(byref(self.ev)). == 1:
helgeerbe commented 6 months ago

Got one step further.

pip install pysdl-dll upgrades sdl2 from 2.28.0 to 2.28.5 and picframe can run through

while sdl2.SDL_PollEvent(byref(self.ev)). == 1:

So picframe does not crash anymore. But unfortunately, the display seems to be lost and the picframe window disappears.

I got this on the log

UserWarning: Using SDL2 binaries from pysdl2-dll 2.28.5
gl_id  b'GL' b'2.1 Mesa 23.2.1-1~bpo12+rpt2'
wl_registry@2: error 0: invalid global wl_output (59)

@paddywwoof do you know where the wl_registrycomes from? Can we catch it and reinitialize the display?

paddywwoof commented 6 months ago

Hmm, no I've not come across that. I imagine it's either part of SDL or GL driver interface to the Wayland display and event system. I will have a search around when I get home after new year.

Paddy

Dropbear67 commented 5 months ago

Happy New Year to all. Any progress at all on this issue? would love to get this sorted.

paddywwoof commented 5 months ago

Cheers, Sorry I've not done anything on this over the last couple of weeks. Once I get home I will start checking this again. Hopefully there will be some more info around on the issue of wayland not allowing screen saver mode when started from a bash script. This must be something other people need too. Paddy

helgeerbe commented 5 months ago

I did a little debugging. Problem is sdl2 lib which is crashing.

Only solution I see so far.

picframe becomes master of screen blanking.

To blank screen

  1. picframe reciveve command for screen blanking (mqtt, webinterface)
  2. picframe stops image display (no sdl calls)
  3. picframe runs "wlr-randr --output HDMI-A-1 --off"

To continue:

  1. picframe reciveve command for continue (mqtt, webinterface)
  2. picframe runs "wlr-randr --output HDMI-A-1 --on"
  3. picframe reinitialise display (sdl)
  4. picframe starts displaying images

What I don't know, if this issue is already solved in sdl3 or will be solved in sdl2

paddywwoof commented 5 months ago

Helge, I need to recheck this but I thought that I couldn't get a 'dummy' application, replacing picframe in the startup mechanism to work. The 'dummy' app simply looped with a time delay, calling wlr-randr on and off. Does that work for you?

helgeerbe commented 5 months ago

Hi Pady,

yes. If I remember right it's sdl2.SDL_PollEvent which causes the segmentation fault. I used Visual Studio Code with remote debuging.

helgeerbe commented 5 months ago

I forgot, you have to update sdl2 pip install pysdl2-dll Otherwise I had a lot of other issues.

paddywwoof commented 5 months ago

I've done a few experiments. It took a while to convince myself that I could turn the screen on and off using a python script, run from a bash script, started by wayfire.ini. But it does seem to work (at least with the desktop running), from time to time I get a log in pop-up and another instance of wayland starts - not sure why. Anyway, I then changed picframe.viewer_display.display_is_on()

    @display_is_on.setter
    def display_is_on(self, on_off): #on_off is True turns screen on, False turns it off
        if on_off is True:
            os.system("WAYLAND_DISPLAY='wayland-1' wlr-randr --output HDMI-A-1 --on")
            self.__display.set_check_events(True)
        else:
            self.__display.set_check_events(False)
            os.system("WAYLAND_DISPLAY='wayland-1' wlr-randr --output HDMI-A-1 --off")

and pi3d.display


  def set_check_events(self, on_off=True):
    self._check_events = on_off

  def _loop_begin(self):
    # TODO(rec):  check if the window was resized and resize it, removing
    # code from MegaStation to here.
    if pi3d.USE_SDL2 and self._check_events:
      import sdl2 # although done in __init__ ...python namespaces aarg!!!
      while sdl2.SDL_PollEvent(byref(self.ev)) == 1:

just to be on the safe side I commented out #self.__interface_peripherals.check_input() in picframe.controller.loop() the screen turns off but the python application still dies. I haven't set up debugging to see where, I suppose that will be my next task!

helgeerbe commented 5 months ago

Hi @paddywwoof, which version of sdl2 are you using? Should be in the log file of picframe.

paddywwoof commented 5 months ago

Hi, I can't see a ref in the log file (I've set it to INFO) the python sdl2 version is 0.9.16 and I did pip install pysdl2-dll as you suggested. Debian says the version of sdl2-dev is 2.26.5, not sure how to get that info from an .so library file.

My initial attempt was to set a flag in viewer_display to stop Display.loop_running() being called at all but this didn't seem to do the trick either.