We need to silence the warning about this because Steinberg doesn't
declare their base class destructors as virtual (because of Windows ABI
compatibility issues). But we can still do it inside of yabridge to have
at least a bit more safety.
They were 95% the same, so this makes a lot more sense this way. When
group host processes were introduced yabridge only did VST2 bridging,
but we already have a plugin type argument anyways so might as well
reuse that for group hosts.
We had to add an even hackier hack now to get Boost.Process to
interoperate with Asio's IO contexts. This will be replaced later when
we replace Boost.Process.
With the `ghc::filesystem` dependency from the previous commit. If we
can replace the rest of the Boost.Filesystem dependency then we can get
rid the one nasty runtime dependency we have, and it will make
implementing the chainloading simpler since can reuse more code without
bringing in Boost.
I'm not a fan of Hungarian notation, but C++ kind of needs it with its
implicit `this`. And of all the common options for this, I find
suffixing members with an underscore the least offensive one.
Apparently these arguments are all passed as a space separated Win32
command line, so we need to do our own quoting. I was about to submit a
patch for this to Wine, but escaping escaped quotes sounds like a pain.
We sadly cannot call `shared_library()` and `executable()` in these
subdirectories while still maintaining the same `build/` directory
structure, but this is still much cleaner. All of the other build
artifacts are now also gone from the root of `build/` so it's cleaner
overall.
For some reason ujam plugins (and other plugins made with the Gorilla
Engine, like the LoopCloud plugins) will throw a `JS_EXEC_FAILED` error
when trying to load the plugin while either of the STDOUT or STDERR
streams is pointing to a pipe. Simply redirecting the output to a file
fixes this. By default we'll write the output to
`<temporary_directory>/yabridge-plugin-output.log`, but you can also set
the new `disable_pipes` option to `"/dev/null"` to completely throw away
all output.
This addresses #47.
This may also fix some weird cases where everything appeared to work
fine, but where the file descriptors weren't actually assigned
correctly. Not sure what that happened, but it with carla-single the
Wine host's STDOUT and STDERR would still point to the orignal pty even
though everything still went through the pipes.
With `vfork()` the child process inherits the parents process image and
prevents copying them, but if it outlives its parent then the file
descriptors will still remain open. Manually closing all file
descriptors is the only solution here.
This was only an issue with Ardour since they don't open all of their
files with `FD_CLOEXEC`. Last update's watchdog timer somewhat mitigated
the issue, but Ardour should now no longer freeze when reopening because
of this. The watchdog timer is still necessary, since hanging Wine
processes will still prevent the Wine server from shutting down.
To account for the differences in VST2 plugins and VST3 modules we had
to wrap most of our old functions from `src/plugin/utils.h` in a new
`PluginInfo` struct that gathers all of this information while taking
into account the differences between VST2 and VST3 plugins.
With this change things are also a lot more organized. We can just query
the plugin information we need rather than having to store things
separately or having to recalculate things. This also moved the
responsibility of all the weird `WINEPREFIX` behaviour to a single place
instead of having it spread around `utils.pp`, the initialisation
message, and `host-procoess.cpp`.
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.
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.