Commit Graph

107 Commits

Author SHA1 Message Date
Robbert van der Helm 27c96135cb Fix thread safety issue with VST2 plugin groups
While a VST2 plugin is being initialized in a plugin group, all host
callbacks would go over that new plugin instance's sockets. This would
cause a race condition if the host processes audio while loading
plugins. This issue has been there since the introduction of plugin
groups, but it's only noticeable in Bitwig Studio, and only when using
over thirty instances of the same plugin in a plugin group.
2021-05-30 02:06:52 +02:00
Robbert van der Helm d610c07e11 Enable mutual recursion on effGetProgramName()
PG-8X in REAPER has the same mutual recursion limitation the Voxengo
plugins had in Renoise, but with `effGetProgramName()` instead of
`effGetProgram()`.
2021-05-23 19:00:16 +02:00
Robbert van der Helm 0b9b1330ad Make sure effProcessEvents() also never allocates
This basically changes the default small vectors during VST2 event
processing from 256 bytes to the size of a `DynamicVstEvents`
object (which also includes a small_vector to hold MIDI events without
allocating) and makes them thread local. We already have a similar
optimization for VST3. There it's a bit neater since we already had to
separate audio processing functions from non-time critical functions.
Here we don't have that separation, so we just made these buffers thread
local, large enough to hold our predefined number of events, and we then
just shrink them to fit if these buffers grow even more (which can only
happen after reading or writing chunk data).

The change doesn't specifically target `effProcessEvents()`, but that's
where you would see the differences. This is also relevant for
`audioMasterProcessEvents()`.
2021-05-23 17:37:09 +02:00
Robbert van der Helm 29e0a0fd36 Reuse VST2 audio processing buffers on Wine side
Just like we made similar changes on the plugin side a few commits ago
to prevent allocations there.
2021-05-23 16:37:01 +02:00
Robbert van der Helm 4e81c1c2b3 Reuse request on Wine side during VST2 processing
The object was constantly being recreated, resulting in memory
allocations caused by creating and destroying the audio buffer vectors.
2021-05-23 15:02:53 +02:00
Robbert van der Helm 6f321649c4 Do small vector optimization for all communication
I once read years ago somewhere on Stack Overflow that `std::vectors`
with that are preinitialized to a default size would allocate the
initial capacity on the stack. This of course doesn't make any
sense (run time sized stack allocations can cause all kinds of issues),
so we were still allocating with our default 64-byte sized buffers, but
just not as often.
2021-05-23 14:43:02 +02:00
Robbert van der Helm bd0dd63ad2 Rename the EventResult struct to Vst2EventResult 2021-05-20 15:53:16 +02:00
Robbert van der Helm 2bf41c6fe1 Move EventPayload to Vst2Event::Payload 2021-05-20 15:52:40 +02:00
Robbert van der Helm b1c9d75112 Rename the Event struct to Vst2Event 2021-05-20 15:50:09 +02:00
Robbert van der Helm 0bc91443b0 Remove old Ardour effEditIdle() hack
We no longer pass effEditIdle() to the plugin (we now use a timer to be
more consistent and configurable), so this is not needed anymore.
2021-05-20 15:29:23 +02:00
Robbert van der Helm a96cfc8090 Allow mutual recursion between audioMasterUpdateDisplay and effGetProgram
This prevents Voxengo VST2 plugins from freezing in Renoise when
recalling their state. See the comments in the diff for why this is
necessary.
2021-05-20 15:28:00 +02:00
Robbert van der Helm ccfda51a69 Clarify the DefaultDataConverter method names 2021-05-20 14:49:11 +02:00
Robbert van der Helm c2186fa55b Use the std::derived_from concept when applicable
This probably makes things much clearer at a glance instead of using a
blanked typename.
2021-05-20 14:31:59 +02:00
Robbert van der Helm 57d7141681 Remove redundant template arguments in MainContext 2021-05-19 22:56:37 +02:00
Robbert van der Helm a9643577fd Also add noexcept qualifications on the Wine side
See the last few commits.
2021-05-14 18:27:19 +02:00
Robbert van der Helm b103723df2 Make the watchdog much more aggressive
For individually hosted plugins this will behave the same. For plugin
groups it would have been nice if we could shut down individual plugins,
but dangling threads are apparently a real issue. This should be
equivalent in all use cases.

This also reverts commit bda9a0b75f.
2021-05-01 19:05:55 +02:00
Robbert van der Helm bda9a0b75f Catch exceptions in failing host callbacks
This will let us more or less gracefully handle failing host callbacks
during initialization. We cannot catch this from anywhere else since
this these functions get called from unmanaged code.
2021-05-01 17:57:41 +02:00
Robbert van der Helm 832089d4d1 Implement the Wine host process watchdog
This will shut down a bridge's sockets when the connected native host
process exits, to prevent dangling Wine processes.
2021-05-01 17:54:22 +02:00
Robbert van der Helm d8ca4022d1 Add universal way to shutdown sockets on Wine side 2021-05-01 16:51:55 +02:00
Robbert van der Helm b22f207aee Move the MainContext to HostBridge
We'll use this to create a watchdog timer that shuts down the sockets
when the native host gets terminated.
2021-05-01 15:06:13 +02:00
Robbert van der Helm 6f6e6c5b94 Reword caching to prefetching
Since that makes it much clearer what we're actually doing. With old
`cache_time_info` was actually caching the response, but now we're
querying it before the plugin has even requested the information.
2021-04-29 01:07:14 +02:00
Robbert van der Helm c82eb35243 Also cache audioMasterGetCurrentProcessLevel()
Melda plugins seem to call this during every processing cycle.
2021-04-29 01:02:10 +02:00
Robbert van der Helm b8f8dd7236 Log cached audioMasterGetTime() calls
Just like we log cached VST3 function calls.
2021-04-29 00:41:56 +02:00
Robbert van der Helm 1deb4cf664 Send the VST2 transport info along with processing
And cache it during the processing cycle. This greatly reduces the
overhead of bridging VST2 plugins.
2021-04-29 00:32:25 +02:00
Robbert van der Helm 70adf5493e Add a logger to the Wine VST2 bridge 2021-04-29 00:31:11 +02:00
Robbert van der Helm 93f089eca7 Always set FTZ instead of gating it behind a flag
After a quick round of testing it seems like REAPER doesn't always
enable this on the audio thread, but Bitwig, Ardour, Carla and Renoise
do. So it should be safe to just get rid of the option and to leave this
enabled all the time.
2021-04-28 12:07:14 +02:00
Robbert van der Helm 2be41da9b6 Add compatibility option to force flushing to zero
This prevents Kush Audio REDDI from taking down the DAW when the host
passes it denormalized audio to process. I've discovered that the issue
with this plugin had to do with denormals in the issue linked below, but
I didn't realize that we can just enable the FTZ flag for plugins that
don't already do so.

https://github.com/osxmidi/LinVst/issues/174
2021-04-27 23:33:50 +02:00
Robbert van der Helm b52362e698 Fix time info cache being applied to other opcodes
I don't know how I've never noticed this, but we should of course only
be handling `audioMasterGetTime()` this way. This also explains why
enabling this permanently in the past broke some plugins.
2021-04-27 17:32:32 +02:00
Robbert van der Helm a42ee0400f Print warning explicit COM init was necessary
So far only PSPaudioware InfiniStrip needed this. but it may be a good
idea to make this visible since it's probably an issue with the
plugin (even if most Windows hosts will have COM initialized).
2021-04-26 00:42:17 +02:00
Robbert van der Helm 3e71fc19b8 Explicitly handle VST2 callbacks with nullptrs
This is probably not needed, but we'll do it just in case another plugin
does something similar.
2021-04-25 22:44:15 +02:00
Robbert van der Helm 86bd19cd80 Fix loading plugins expecting COM to be available
The `LoadLibrary()` call for PSPaudioware InfiniStrip would fail because
the plugin would always expect COM to be initialized. Now if loading a
VST2 or VST3 module fails, we'll initialize COM and try again before
throwing an error. This may fix #94.
2021-04-25 21:54:34 +02:00
Robbert van der Helm 671c6a4c18 Specifically not read data for audioMasterWantMidi
Plugsound Free by UVI will pass random garbage to the data parameter for
this function call for whatever reason, and we'll run into a memory
error if we try to read it. Mentioned in #93.
2021-04-24 20:28:58 +02:00
Robbert van der Helm afefb725b5 Postpone clearing old MIDI events until next event
This fixes Native Instrument's FM7 crashing on MIDI input. The plugin
expects the last received MIDI event to always be alive during audio
processing, even if there have not been any new events in this
processing cycle.
2021-04-23 01:08:21 +02:00
Robbert van der Helm d97e699db1 Run effSetChunk and effGetChunk from main thread 2021-04-14 21:38:15 +02:00
Robbert van der Helm 4937010557 Fix some of the clang-tidy lints 2021-04-14 16:09:54 +02:00
Robbert van der Helm 3fbffa532d Move Win32 event handling to one place
Or technically, two, since the group bridge also does the same loop. We
no longer need special handling for VST2 and VST3 plugins, so we can
simplify things a bit here.
2021-02-09 23:45:33 +01:00
Robbert van der Helm 0adca3e33c Revert "Remove cache_time_info and always cache time info"
This reverts commit cfb171c991.

No idea why, but this cache breaks SPL Transient Designer Plus. Perhaps
it overwrites the time info?
2021-01-30 02:37:27 +01:00
Robbert van der Helm cfb171c991 Remove cache_time_info and always cache time info
It sort of goes against yabridge's principles to not do these
unnecessary `audioMasterGetTime()` calls if the plugin does that, but it
also hurts the user experience to not have this as a default.
2021-01-30 00:20:35 +01:00
Robbert van der Helm 3f7f67fc2d Get rid of no longer used mutex
This was left over from a very early version of yabridge. It's not
needed since we have to initialize all VST2 plugins from the same thread
anyways.
2021-01-28 23:45:44 +01:00
Robbert van der Helm 72e29d044a Add a function for temporarily blocking event loop
This can be used to prevent the Win32 message loop from running while
there are plugins in some partially initialized state.
2021-01-27 19:00:11 +01:00
Robbert van der Helm f03b9b1497 Sync VST2 audio thread scheduling priorities
We'll periodically copy the scheduling priorities from the host's audio
threads to the Wine plugin host's audio threads. The overhead of doing
this is about 1 microsecond on my system, so doing this every cycle
really adds up. But getting the Unix epoch time and comparing some
timestamps has a neglegible overhead, so this should give you the best
of both worlds.

Next we'll do the same thing for VST3 plugins.

As suggested by @jhernberg
2021-01-23 15:14:52 +01:00
Robbert van der Helm 2ca1d5b8ca Greatly increase reliability of deferred closing
It's pretty hard to find a solution that checks all of the boxes. I want
something that:

- Closes instantly when you close the editor, and in REAPER you should
  be able to instantly switch between docked and floating modes
- Where there should not be a delay in user interaction when quickly
  reopening the editor (or doing that switching thing in REAPER since that's
  the same thing)
- Where the window manager should not try to reparent the window during
  the losing process as that can cause some jarring flickering
- And, of course, there should be no weird Wine X11Drv crashes

And it should do all of that in Bitwig, REAPER, Carla, Ardour and
Renoise. Apparently it's quite the task to find an approach that checks
all the boxes there.
2021-01-21 16:47:35 +01:00
Robbert van der Helm bf3a4e7296 Allow changing the event loop tick rate
This also changes the refresh rate for most plugins. You can now lower
this setting if your computer is struggling to keep up with rendering a
certain heavy plugin.
2021-01-11 23:38:21 +01:00
Robbert van der Helm 8f15578d8c Also disable realtime priority during effEditGetRect
Since on some hosts this is called before effEditOpen.
2021-01-11 18:53:36 +01:00
Robbert van der Helm f015739942 Open and close editors without realtime priority 2021-01-11 18:50:53 +01:00
Robbert van der Helm 2f5d22ca17 Handle effMainsChanged on the main UI thread #75
This fixes EZdrummer not producing any sound, as the plugin presumably
schedules some task on the Win32 message loop to load its resources,
which won't happen if this is run from any other thread.
2021-01-05 23:04:18 +01:00
Robbert van der Helm 4ec8b01bcc Completely run effEditIdle from a timer
Although it hasn't shown up, this will get rid of the possibility of
off-thread effEditIdle calls causing issues. And since we need some way
to run call this function while the event loop is running anyways, doing
it entirely from a timer similar to how hosts on Windows would do it
seems like the best solution.
2021-01-04 15:50:17 +01:00
Robbert van der Helm 34f8d3b1d2 Update the copyright notices for 2021 2021-01-01 18:54:02 +01:00
Robbert van der Helm fa0753f520 Use atomic fetch-and-add for unique window classes 2020-12-31 14:12:14 +01:00
Robbert van der Helm 7e34cf69fe Remove Editor::handle_win32_events
This apparently isn't needed anymore.
2020-12-21 18:24:07 +01:00