j_e_f_f_g wrote:
Because it can make the desktop less responsive. You're not handling messages when you're sleeping, and sometimes the window manager requires you to process a message before it can interact further with the enduser. This is particularly true when the user moves/sizes/reorders windows, or changes focus to another app's window. Granted, you're only sleeping for 30 ms, and most window managers have a longer timeout before they pop up that message box saying "This app is not responding. Terminate it?". But if everyone did what you're doing, it would make every desktop "stutter".
Change your usleep to a couple seconds and see what it does to your desktop and plugin host.
You're not supposed to sleep in a gui thread (nor do anything that would prevent your gui thread from processing messages for "a long time").
i understand..
first, this is a for the editor of a vst plugin, so the 'window manager' is quite a bit less complex (and also restrictive) than a desktop.. and my window is a child of a host-controlled window, and i don't get many move/resize/minimize, etc, events..
so, hmmm... the problem is the sluggishness that can result from the sleeping and not processing events immediately.. i have not noticed much when sleeping for 30ms.. and 30ms is the worst case, it can be 0, if the sleep is almost over when the event is pushed onto the event queue.. and also, when i wake up, i process all events in the queue, not just one.. so, now and then, there can be a (up to) 30ms delay between the handling of two events..
when i'm recording guitars through my audio interface, with a latency of 128*3 samples (8.71ms) i can not notice any delay.. normally, anything shorter than around 20m feels "instanteous"..
i have been thinking about sleeping for even shorter.. for example 1ms, and then have a counter, and call my update function when this counter has reached 30, or something like that.. or i could have a kind of timer pool, and various widgets could register callbacks, and how many ticks between each call..
j_e_f_f_g wrote:You say that you know how to wake up from XNextEvent. Why then are you using XPending and usleep in a busy wait loop? That's unnecessary.
first i did it the 'normal' way, by using XNextEvent in a thread like you said.. and things worked well.. (this is for a vst plugin editor, not standalone executable, by the way).. my plugin is being called regularly by the host (dispatcher/effEditIdle), and i update the gui in reponse to these calls.. i check if any parameters have changed, and repaint the on-screen widgets, do some animation, etc..
then i noticed that various hosts call this effEditIdle callback at different intervals.. normally around 20-30hz, which is kind of ok, and feels quite smooth.. some call it more often, some a LOT slower.. qtractor only around 5 times per second, it seems.. so, if i animate a parameter in the host, the smoothness of the visual updates depends on the host and how often it calls effEditIdle.. to have a similar experience in various hosts and platforms, and to have a bit more control, i wanted my own timer instead of relying on the host calling my plugin (hopefully) regularly..
so, then i added another thread that just sent a clientmessage ('sts_idle') to my window, went to sleep for 20-30 ms or so, then wake up, and did it all again, until i closed the window.. the main event thread receives the event (with XNextEvent), passed it on to the window class, and then i did the same thing as before, checked parameters, did the painting, etc..
then i combined these two threads into one, so that it works like this (until i close the window):
1. check if there are any events in the queue (XPending)
2. if so, read it, and process it..
3. repeat 1-2 until the event queue is empty
4. do the gui update (effEditIdle/on_idle)
5. sleep for a little while, so that we reach a certain framerate. 30ms = 33.3hz
6. wake up, goto 1
XPending so that it doesn't block.. if i call XNextEvent and the event queue is empty, it would block, and the gui would not be updated until next time an event is coming in..
the sleep is there to control how often the on_idle() method is called.. i don't need (or want) to redraw the gui thousands of times per second :-/
---
as i see it, the alternatives i have:
1. update gui from effEditIdle callback.. accept that i have to live with varying gui updates in various hosts
2. use a second (timer) thread to regularly post (sts_idle) clientmessages to the first/main (event handler) thread, and update the gui when i receive these messages.. this thread can sleep between posting these messages, i guess?
3. combined thread, xpending/sleeping, and accept the (up to/in worst case) 30ms (or lower) delay now and then..
- tor-helge