mpv-examples
mpv-examples copied to clipboard
Add GTK render example
I was able to get libmpv working with GTK, utilizing the render API and the GtkGLArea
widget. I couldn't find any tutorials or examples of such a use-case, so I figured it would be good to contribute here. Right now source code comments as well as error handling are not good by any means, so please let me know if you would like me to add them before a merge. I also am unsure if I am using libmpv in every best way, so let me know if I am not (I used the sdl and qt_opengl examples for reference). This is also GTK 3.0, so although it shouldn't be hard to get it working on the new GTK 4.0, I haven't been able to use that library or test it at all.
Thanks. The code looks generally good, though I have no experience embedding libmpv, nor with GTK, so this is not a review, just some comments.
- You probably want to squash the commits, unless you think referencing m3u-tv at the history has some value?
- It's not obvious to me where error checking is missing (especially when interacting with libmpv), but IMHO there should be at least one such error checking at the code (possibly elaborate) with some comment on where else it should be checked.
- It seems that you dequeue events only at
render()
. I don't know when render is called, but if it's not frequently enough (e.g. consider paused state - events might still arrive) then the queue could overflow and events will get dropped (by libmpv). As far as I know the general approach should to have the event loop constantly waiting for new events, probably in a thread (with negative timeout so that it doesn't busy-wait), and handling or dispatching them to the application as they arrive.
Generally the code looks nice though.
Ok, after a bit of work I finally got the force-push to squash my commits correctly. Thank you for the comments, they are very helpful.
- With regards to the error checking, I was referring to checking the returned value on the libmpv functions and then exiting gracefully like how the sdl example behaves. But I suppose it is not necessary and I won't add it if you don't think it is necessary. I can comment on the libmpv function calls however.
- For event handling, calling
gtk_gl_area_queue_render()
makes the GtkGLArea callrender()
in what is essentially a continuous loop (even when paused), but I tested further and it looks like moving the window to a different workspace (or adding other GTK widgets such that the GtkGLArea is not visible) signals to the widget not to callrender()
. I suppose this could be a problem because audio can still be heard. I can look into running the event loop in a different thread but will have to figure that out. - In addition to that last point, I tried simply looping through all events directly inside the mpv callback, but after a few runs in the loop, libmpv seems to hang indefinitely on
mpv_wait_event()
(even with a timeout of zero). I suspect this has something to do with the callback thread accessingmpv_wait_event()
, but I couldn't find any information about this in the header files. It would be a lot easier to just loop through current events in the callback, but perhaps I am missing something.
Ok, I was able to solve the issue. At first I learned how to use pthreads and did a full implementation of the event-loop in a different thread (See https://github.com/caseyavila/m3u-tv/commit/2c133b1ed6625704cb1b99e9d50f1df1ed5ab73e). That implementation had a bug because of thread-safety, and I didn't like the solutions I developed.
Instead I discovered that you can queue function-calls to be run on the main GTK thread. Because g_idle_add
is meant to be called from other threads, it provides an elegant way to begin looping through events. It should now loop through events whenever mpv executes its wakeup callback, regardless of whether the video is paused. Let me know if this is good to merge.