Build simple GUIs with MiniFB

I’d like to announce a little vacation project of mine. I’ve just released the first version of MiniFB.jl, a Julia wrapper around a small C library called MiniFB.

MiniFB is possibly the simplest way to get a graphical window up on a screen in a cross platform way on modern OSs. The basic idea is to create a 32bit buffer of pixels yourself, and pass it on to the framework to display. So you’d write code like this:

window = mfb_open_ex("my display", 800, 600, MiniFB.WF_RESIZABLE);
while true
	#TODO: add some fancy rendering to the buffer of size 800 * 600
	state = mfb_update(window, buffer);
	if state < 0
	    break
     end
end

Note that this is not a full fledged GUI framework – in particular, there is no widget library. There is however support for mouse and keyboard input, so pretty sophisticated UIs are indeed possible.

So, in summary, if you want to throw up an image viewer in a few dozen lines of code, with a TTFP of 1.5 seconds* (after precompilation), this may be what you need.

Documentation here: https://juliahub.com/docs/MiniFB/

Regards

Avik

*(I fully expect ttfp to go down to less than a second after Elliot’s chages to jll loading in 1.6)

34 Likes

Yep. There are those like us that like coding during vacations! Yay!

2 Likes

Theoretically, is it possible to write a MiniFB in pure Julia? Curious. I guess in that case it might take a while to compile. But I guess there would be a way to include Julia binaries in a _jll package.

Theoretically, is it possible to write a MiniFB in pure Julia?

Yes, I suppose. But you’ll have to call into the platform libraries (win32, cooca, X etc) for most of the actual functionality. MiniFB is a really small library that basically just does that, abstracting accross the different platforms. Because it does not have a widget library of it’s own, it is pretty simple. So I don’t see much point personally…

Now, in the days before BinaryBuilder, I had a different opinion. But these days, using most C libraries is great.

Regards

Avik

2 Likes

Stupid, stupid, stupid question. We like Pluto.jl notebooks. I know Pluto used webby stuff - Javascript.
Can we see a small toolkit like this being part of a Pluto notebook?

Sorry if I am proving my idiocy.

No, that’s a valid question, but I think the answer is probably not.

So the this library is pretty focussed on desktop UIs. The thing is, opening a window and listening to its event queue is non-trivial to do in a platform agnostic manner. That is the problem that this library solves. In a web environment, the browser handles all of this internally, with a much higher level api access only via Javascript… so I’m not sure a library like this would be useful.

It might be an interesting idea for Pluto to provide access to the Canvas drawing primitves to Julia code, then you’ll be able to use something like Luxor and Javis to draw on the browser, but I’m not sure is that is a good idea, or even feasible.

2 Likes

I guess that makes it not really worth it to do in Julia if there is something that exists. You can’t really compose that with Julia code anyway.

1 Like

How do you rate the stability of this vs Gtk.jl?

Gtk has a lot of problems (like on windows :grimacing:) so it would be nice to swap out something simpler for my interface package https://github.com/cesaraustralia/DynamicGridsGtk.jl. It already makes it’s own GUI with an array anyway, so Gtk is total overkill.

2 Likes

So I honestly haven’t used it for anything too big or difficult, so in that sense it’s caveat emptor, but I havent seen any major problems in my limited experience. In particular, it works well on windows. If you are not using Gtk’s widget library (buttons, text boxes, menus etc), it may be worth trying.

If you can create an array of Colors.jl/Colorant objects, it will be trivial to render it using MiniFB.

2 Likes

Great. That’s what we have already - and array of ARGB32.

It’s a trivial problem really, it would only be a 20 line package, DynamicGrids.jl does everything except actually putting the image on the screen. The refresh rate can be over 100fps sometimes, thats the only thing that could cause issues if it wasn’t optimized.

it works well on windows.

Also this is great. Reliably cross-platform is what we need.

It’s a trivial problem really, it would only be a 20 line package,

Yeah, I’ve always wondered why opening a window and displaying an image on it is not 5 lines of code. That’s one of the reasons why I was interested in this library.

The refresh rate can be over 100fps sometimes,

This made me curious, so I changed my image viewer demo to update the buffer every frame (rather than only on user input), and change the loop to go as fast as possible (using while true instead of while mfb_wait_sync). Every frame, we rezise the image, update the raw buffer with the image data, and then render the screen. This causes my laptop (two year old i7) to use about 25-30% cpu and results in a frame rate of 175 fps. If I constraint the frame rate to 100 using mfb_set_target_fps and mfb_wait_sync, CPU utilisation drops to around 15-18%, with an eventual frame rate of 96.

So a very simple test, takes a bit of CPU, but hopefully shows that things are not terrible. I can see there are some allocations that can be removed, so I hope this can be improved.

[Edit] to clarify, this was with a 600x400 pixel window.

Regards

Avik

5 Likes

Thanks for this!

To try it, I replaced GLFW with it in a simple project. You can see that it reduces the amount of boilerplate code by quite a bit!

1 Like

Nice! Nothing makes an open source developer happier than to see their code being used by someone else.

What kind of FPS are you seeing compared to GLFW? As far as I understand, MiniFB renders everything on the CPU.

1 Like

The FPS is largely constrained by the function computing the buffer. The work is all done on the CPU, and benchmarking it each execution takes ~6ms on my PC.

I get 100 to 120 FPS, so I assume MiniFB takes around 2 ms to update the window.

2 Likes

That sounds pretty good. That’s often roughly the pixel size too, although we use 1200*800 too, but that’s a little slower anyway

I couldn’t find anything online but I would’ve thought someone would have tried making a widgets library in minifb

Brilliant stuff, Avik.

Who needs Processing? :slight_smile:

13 Likes

Is the FPS counter/text a feature of MiniFB or do you just draw it manually on the buffer?

Yes, just drawn with Luxor.text(). (And thanks for the code! :joy_cat:)

2 Likes

@cormullion would you be able to paste the example code for your animation above? it looks slick!