GroupHost::running() would sometimes cause plugins to get terminated
prematurely when connecting to another plugin's group host process since
the plugin's own group host process has exited.
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).
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.
As per Boost.Asio's manual, an explicit `socket.shutdown()` is needed
before calling `close()`. For some reason this worked fine in almost
every situation, but when hosting both a plugin hosted within a group
host process and a normal individually hosted plugin within a single
process, and then removing those two plugins in order, the
`host_vst_dispatch` socket of the first plugin never got closed. This
would hang the entire shutdown sequence to hang on the
`dispatch_handler` jthread.
First discovered in #45
Boost.Process's `boost::process::environment::at` throws when the
environment variable does not exist, as opposed to `operator[]` which
falls back to an empty value.
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 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.
When creating copies with yabridgectl. This should at least give an
advance warning that some additional steps are required when first
setting up yabridge.
It's a bit clearer this way. I would prefer using jthreads here, but we
would still need this try-catch block since there's no way to cancel
synchronous Boost.Asio socket operations other than closing the socket.
Not sure how this got in, and I'm even less sure why this has not caused
any issues before this. In the particular case that was causing a crash,
the host was sending 138 sample sized buffers. This error likely only
became visible because the lack of memory alignment caused writes to
parts of the vector objects themselves.