Writing GUI applications on the Raspberry Pi without a desktop environment (2019)
avikdas.com
avikdas.com
NativeAOT is on the way, so that you can compile small binaries without any dependencies.
If that does not work, you can compile your project as "ReadyToRun" with "Trimming", which will treeshake all unneeded runtime stuff and prepare an acceptable small binary.
One way to overcome the problem with missing drivers is to setup a python API (e.g. Flask) and triggering things through the Avalonia UI. Or you could wrap a binary execution via CliWrap, an excellent library for .NET to run external processes.
I once wrote a little eventhub[1] to run on the Raspberry PI, it is just an experiment but worked ok.
There is also .NET IoT[2], which exactly targets these platforms.
Although I had to rewrite the software, because the original was WinForms, it was a pretty simple application.
Right now, the best of breed thought that I have is to run Weston, have a Qt application that is full screen, and to use DMA buffers so I can do some zero copy processing. Rockchip has their own MPP and RGA libraries that are tied into the Mali GPU, and I'm not smart enough to understand the current level of driver/userspace support to not leverage these libraries.
Rockchip and the ARM ecosystem is such a mess.
If anyone has any pointers, experience, approaches, code, etc, I would love to see it.
The advantage would be that you can directly run without starting into any kind of visual environment first. But it's a huge mess to get going: I wrote quite a bit of Pi4/5 code recently to make a zero copy HEVC/H264 decoder working and it was a quite a challenge. Maybe code like https://github.com/dvdhrm/docs/tree/master/drm-howto can help?
Until that happens, working driver code is in a very transitive space.
To get going, and sidestep that problem, I've purchased an HDMI to USB capture cards that use MacroSilicon chips. I've some thought of using a cheaper CPU in the future with a daughter board based on this project which uses MacoSilicon chips: https://github.com/YuzukiHD/YuzukiLOHCC-PRO, which made it potentially not a waste of time to dig into.
The MacroSilicon HDMI to USB capture cards output MJEPG, which Rockchip's MPP library has decoder for.
So the thought is: (1) allocate a DMA buffer (2) set that DMA buffer as the MJEPG decoder target (3) get the decoded data to display (sounds like I may need to encode again?) & a parallel processing pipeline
I'll dig into the stuff you've sent over, very helpful thanks for the pointers!
I've thought about switching to Pi4/5 for this. Based on your experience, would you recommend that platform?
Their kernel fork is well maintained and if there is a reproducible problem it usually gets fixed quite quickly. Overall pretty happy. KMS/DRM was a bit wonky as there was a transition phase where they used a hacky mix between KMS and the old proprietary broadcom APIs (FakeKMS). But those days are over and so far KMS/DRM works pretty well for what I'm using it.
Thanks for the pointer!
If the HDMI-USB capture card that outputs `mjpeg` exposes a `/dev/video` node, then it might be as simple as running:
`SDL_VIDEODRIVER=kmsdrm ffmpeg -f video4linux2 -input_format mjpeg -i /dev/video0 -f opengl "hdmi output"`
An alternative could be if you can get a Raspberry Pi 3 or even 2, and can get a distro where `omxplayer` can still be installed. You can then use `omxplayer` to display your mjpeg stream on the output of your choice, just make sure the `kms/fkms` dtoverlay is not loaded because `omxplayer` works directly with DispmanX/GPU (BTW, not compatible with Pi 4 and above and much less 5), which contains a hardware `mjpeg` decoder, so for the most part, bytes are sent directly to the GPU.
Hope some of this info can be of help.
$ ldd `which ffmpeg`
And you should get the list of dynamic libraries your build is linked against. If SDL2 is indeed included, you should see a line starting with "libSDL2-2...".
If I remember correctly you should be able to output to the framebuffer even if there is no support for SDL2, you just have to change the previous line provided from using `-f opengl "hdmi output"` to `-pix_fmt bgra -f fbdev /dev/fb0`.
You can also use any other framebuffer device if present and you'd prefer it (e.g. /dev/fb1, /dev/fb2). Also, you might need something different to `bgra` on your board, but usually `ffmpeg` will drop a hint as to what.
I have tested the mpp SDK a bit and the code is easy to work with, with examples for encode and decode, both sync and async.
You can also run it under X using an SDL backend.
One thing to note though, is that, unless they added it in 9.1, certain mouse control schemes that we've come to expect from desktop applications aren't supported. Since it was made primarily for touch screens, it only supports mouse click (tap) and long press, so it doesn't support things like mouse wheel scrolling in a scroll box, or mouse button right click for example. But tapping, sliding, flinging controls and screens like it's a smartphone work really well. I had made a first pass at implementing support for more desktop mouse functionality a while back, but the maintainer wanted a more generalized solution to what I had done, and I haven't had a chance to go back and play with it again. It's pretty easy and fun to hack on the code base. It might not fit the bill for all UI problems as it's pretty low level, but it's remarkably robust and featureful and I had a great time using it for a number of applications on a custom desktop OS in a similar vein to the linux framebuffer.
QML is nice, animations were much smoother than I expected.
id:5:initdefault:
x1:5:respawn:/etc/rc-x11
ff:5:respawn:/etc/rc-firefox
...where /etc/rc-∗ are few lines of shell that set up environment variables, and end with "exec chroot --userspec=... / /bin/firefox ..." - this way X and firefox run under same PIDs that sysvinit knows about, so they get restarted after a crash.Can you really use it without a desktop env though? Would be cool if one could launch it in full kiosk mode from the headless tty.
https://mesamatrix.net v3d conformant up to OpenGL 3.1.
The Pi has always supported OpenGL ES though.
http://tekui.neoscientists.org/
Only caveats: it's quite old and doesn't seem maintained anymore, although it still compiles fine, and it's Lua only, but being written in C it shouldn't be too hard to port it to other languages.
yeso is a very small and simple library, so you have to do more things from scratch than with libraries with more comprehensive functionality, but being able to test your app in a window before running it on the framebuffer could be useful
yeso's input handling on the linux framebuffer is not as complete as its x-windows handling, but it's good enough that yeso programs like ./tetris-fb (with wasd) and ./mand.lua do work on the framebuffer console. the terminal emulator admu-shell-fb mostly works, but it has the problem that things like control-z or control-c suspend or kill the terminal emulator instead of what you're running in it :)
(i haven't actually tried yeso on the pi, but if it doesn't work there i'll fix it)
It supports Vulkan, OpenGL, Cairo and other technologies.
Having slimmed down the RPi Lite OS as much as I can, running Wayfire with a Chromium kiosk is just too much for the Pi 3B+ I'm using once I add a streaming camera to the dashboard, and it can't cope. My goal is to have a responsive touch-screen display for Home Assistant using something in the form-factor of a Pi Zero 2W, so that I can put the SBC _inside_ the display and build a wooden picture frame to house it all, so it doesn't stick out like a sore thumb.
I'm not sure what kind of API HA has for the frontend, but my first thought, was to build a native application with a Go backend (I write Go for my day job) and use something like Wails[0] for the frontend and completely cut out the heavy-weight Chromium browser.
I have Pi4's and Pi5's but I really want to use the littlest amount of compute (and power) I can to achieve this, even it means writing the UI myself. I've tried looking for a lighter-weight browser that I can simply run the HA dashboard in to no avail.
Looks like this guy got Chromium to work? https://www.youtube.com/watch?v=XAnN1A_sye0
I might try it anyway but I'm not sure what their long term support would be like compared to Pi if I do get it to work.