Issue
Tl;dr
I need to use pygame
but it can't initialize the screen as a normal user because of the permissions for the framebuffer driver. root can do pygame.display.init()
but not the user. User is in the group 'video' and can write on /dev/fb0
. What permission is missing to the user so pygame.display.init()
would work.
Error encountered : pygame.error: Unable to open a console terminal
Description
So, I am trying to use pygame in order to display things on a framebuffer /dev/fb0
.
To use some functions I need (e.g pygame.Surface.convert
) the display must be initialized. However, when calling pygame.display.init()
I have an error, but only when not doing so as root.
According to @Nodraak (ref) it is related to the permissions of the framebuffer driver.
Late answer but I wish I would have tried that earlier :
You may need to be root to use a frame buffer driver.
(It helped in my case: RaspberryPi 2 without X running but with a screen connected. I can now open a display through SSH or directly on the RPi)
A tree -fupg / | grep fb | grep rwx
doesn't seem to show any binary which would be executable by root but not by others. I am quite sure that adding my user to a group, or tweaking the file permissions somewhere would be enough to fix the issue.
Note: For Security reasons, running the software as root is not an option.
Context
- System : RaspberryPi
- X Server: None
- Screen: 1 (HDMI)
- Connection: remote (SSH)
Origin of the error
I am trying to convert a surface with pygame.Surface.convert(...)
function. But receive the following error :
pygame.error: cannot convert without pygame.display initialized
Nevertheless, initializing pygame.display with pygame.display.init()
is giving the following error:
pygame.error: Unable to open a console terminal
I have the rights to write to the screen as I am part of the video
group, and cat /dev/urandom > /dev/fb0
is effectively displaying snow on the screen.
Also I tried setting up the SDL_... environment variable to fbcon
or dummy
but it doesn't help. I also tried keeping the root env with user su -m user
and same result.
Reproduce the error
On a raspberrypi without XServer, connect an HDMI screen, install pygame.
import pygame
pygame.display.init()
Error message:
pygame.error: Unable to open a console terminal
Software Versions
python 3.7.3
pygame 1.9.4.post1
OS Raspbian Buster
libsdl 2
Related
Solution
Solution to the problem
OpenVT
So it appears that the best solution, which meet all requirement I listed, is to use openvt
.
How ?
The procedure holds in a few bullet points :
1. Add User to tty
group
As root, add your user to the group named tty
, that will allow us to give it access to the TTYs.
# As root:
usermod -a -G tty $username
2. Give TTY access to users in group tty
Now that the user is part of the group tty
we need it to be allowed to write on it, as openvt will use a tty. By default, the mode should be set at 620
we need to set it at 660
to allow the group to write on it.
# Edit file: /lib/udev/rules.d/50-udev-default.rules
SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0660"
# ensure mode is 0660 ^
3. Set SDL environment variables
Inside your software, make sure to set up the environment variables of SDL.
import os
# ...
os.environ['SDL_VIDEODRIVER'] = 'fbcon'
os.environ["SDL_FBDEV"] = "/dev/fb0"
4. Reboot the Raspberry
Ok, you don't need a snippet for that.. Whether ? Well ok.
# as root / with sudo
reboot
5. Start software with openvt
openvt
(open Virtual Terminal) allows us to run the interface directly with screen access. This must be executed by the final user, in the same directory as the software (preferably).
openvt -s -- python3 ./interface.py
And that should work.
Of course you can then integrate this in a Linux service so it starts at boot. but you may need to add After: [email protected]
in the [Unit]
section of the service file.
Well, it took me lots of time to figure that one out, so I hope it helps someone else as well.
Answered By - vinalti Answer Checked By - Pedro (WPSolving Volunteer)