MainContext is now basically just a wrapper with a simple event loop
implementation so it's not really necessary, but having a separate type
for the 'main' IO context still makes everything much clearer.
This will also cause plugins to update their editors at 60 FPS. This was
kept at a lower value for performance reasons, but since the message
loop now no longer blocks event handling we can safely increase this.
This will double the amount of resources spent on drawing, but since
audio processing in a real world scenario almost never utilizes all
cores anyways this should not be an issue.
Since it does something way more involved than
`SocketHandler::{send,receive_multi}`, and that makes it a bit confusing
if you don't already know about that (and even if you do).
This way the sockets can be destroyed before the threads, and we can
safely wait for the threads to shut down. I initially had Win32Thread
imitate std::jthread's join-on-destruct, but that was causing group
processes to hang. Now we can safely add that back again, and this will
fix some spurious segfaults during plugin scans when using plugin groups
containing a massive amount of plugins.
This will require more testing of course, but I think it should be safe.
This would increase the potential maximal throughput in group hosts
significantly.
std::function does not allow non-movable lambdas, so capturing by move
doesn't work there. And the old solution of course has issues with
dangling pointers (but because this is C++ the compiler still thinks
it's A-Ok).
When the message loop is active and we get an incoming dispatch() event,
we'll just handle it directly. In practice this would only be needed
when the event is a response to an `audioMaster()` call made during the
event loop, but we can't know that. This allows the `getProgram()`
during `audioMasterUpdateDisplay()` in REAPER and Renoise to work
correctly. Hopefully this doesn't cause random rare breakage.
On the Wine side we want to handle most events on the main UI thread.
We'll assume any events coming in from a secondary socket are safe and
can be handled directly.
This is a pretty huge change that will be important for being able to
handle nested or mutually recursive `dispatch()` and `audioMaster()`
calls. This sadly all had to be done in a single commit, so here's a
summary:
- `src/common/sockets.h:Sockets` contains all sockets on both the plugin
and the Wine host side, and is used to both listen on and connect to
the sockets.
- Sockets and other temporary files respect `$XDG_RUNTIME_DIR` instead
of being dumped in `/tmp`.
- All sockets now have a unique endpoint in
`/run/user/<uid>/yabridge-<plugin_name>-<random_id>/`. This is
important for when we want to have multiple socket connections for
handling `dispatch()` and `audioMaster()`.
- Because of the above, we no longer clean up the socket endpoint files
after the connection gets established during initialization. Instead
we'll remove the socket base directory when shutting down.
I'm still really curious why this double reparent would be needed
though. Everything works fine on any other i3 config I've tried, and
even the exact same config in a VM works fine for me.
I'm not sure how many people use WMs that don't implement
`_NET_ACTIVE_WINDOW`, but at least this will give those people some way
to grab input focus, even if it's not as good as the new method.
These things should not fail (and I've never seen one of these thing
error out with yabridge), but in the case they do an assertion is at
least a lot trace down than a segfault.
This fixes keyboard focus not returning when closing dialogs in Melda
plugins. I'll have to do some more testing to see if this does not
introduce any unwanted side effects.
This is not ideal since it requires the user to know about this option
and to create a config file, but I think it's the best we can do without
compromising on yabridge's transparency and 'zero hacks' philosophy.
See #29 and #32.
This works around Waves plugins causing an infinite message loop. Since
we run the loop 30 times per second anyways splitting the loop up into
chunks of 20 shouldn't be an issue.
This significantly reduces the latency with no real drawbacks from what
I've noticed. Wineserver is still run using the normal scheduling
policies because from my testing running that with realtime priority
that can actually increase latencies, although doing so will greatly
reduce the variance in processing time.
This sounds like it would the simplest way to work around the issue of
E27 calculating its own coordinates based on the parent window's
coordinates. I have not noticed any weird issues with having this
enabled all the time, but less moving parts is always better so it's
still behind an option.