Fix VST2 editor resizing in REAPER

After solving this for VST3 plugins it become clear that REAPER required
us to do the exact same thing for VST2 plugins.
This commit is contained in:
Robbert van der Helm
2021-01-19 17:42:11 +01:00
parent d252ace189
commit 36535fc3b5
3 changed files with 65 additions and 21 deletions
+2
View File
@@ -84,6 +84,8 @@ TODO: Add an updated screenshot with some fancy VST3-only plugins to the readme
### Fixed
- VST2 plugin editor resizing in **REAPER** would not cause the FX window to be
resized like it would in every other host. This has now been fixed.
- The function for suspending and resuming audio, `effMainsChanged()`, is now
always executed from the GUI thread. This fixes **EZdrummer** not producing
any sound because the plugin makes the incorrect assumption that
+52 -21
View File
@@ -75,29 +75,43 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
sockets.vst_host_callback.receive_events(
std::pair<Vst2Logger&, bool>(logger, false),
[&](Event& event, bool /*on_main_thread*/) {
// MIDI events sent from the plugin back to the host are a
// special case here. They have to sent during the
// `processReplacing()` function or else the host will ignore
// them. Because of this we'll temporarily save any MIDI events
// we receive here, and then we'll actually send them to the
// host at the end of the `process_replacing()` function.
// TODO: We might be able to make editor resizing work in REAPER
// by calling `audioMasterSizeWindow()` from within
// `effEditIdle()`. Something similar was required for
// VST3 plugins in REAPER.
if (event.opcode == audioMasterProcessEvents) {
std::lock_guard lock(incoming_midi_events_mutex);
switch (event.opcode) {
// MIDI events sent from the plugin back to the host are
// a special case here. They have to sent during the
// `processReplacing()` function or else the host will
// ignore them. Because of this we'll temporarily save
// any MIDI events we receive here, and then we'll
// actually send them to the host at the end of the
// `process_replacing()` function.
case audioMasterProcessEvents: {
std::lock_guard lock(incoming_midi_events_mutex);
incoming_midi_events.push_back(
std::get<DynamicVstEvents>(event.payload));
EventResult response{.return_value = 1,
.payload = nullptr,
.value_payload = std::nullopt};
incoming_midi_events.push_back(
std::get<DynamicVstEvents>(event.payload));
EventResult response{.return_value = 1,
.payload = nullptr,
.value_payload = std::nullopt};
return response;
} else {
return passthrough_event(&plugin, host_callback_function,
event);
return response;
} break;
// REAPER requires that `audioMasterSizeWindow()` calls are
// handled from the GUI thread, which is the thread that
// will call `effEditIdle()`. To account for this, we'll
// store the last resize request and then only pass it to
// the host when it calls `effEditIdle()`.
case audioMasterSizeWindow: {
std::lock_guard lock(incoming_resize_mutex);
incoming_resize = std::pair(event.index, event.value);
EventResult response{.return_value = 1,
.payload = nullptr,
.value_payload = std::nullopt};
return response;
} break;
default:
return passthrough_event(&plugin,
host_callback_function, event);
}
});
});
@@ -413,6 +427,23 @@ intptr_t Vst2PluginBridge::dispatch(AEffect* /*plugin*/,
// blocked by for instance an open dropdown.
logger.log_event(true, opcode, index, value, nullptr, option,
std::nullopt);
// REAPEr requires `audioMasterSizeWindow()` calls to be done from
// the GUI thread. In every other host this doesn't make a
// difference, but in REAPER the FX window only resizes when this is
// called from here.
{
std::unique_lock lock(incoming_resize_mutex);
if (incoming_resize) {
const auto& [width, height] = *incoming_resize;
incoming_resize.reset();
lock.unlock();
host_callback_function(&plugin, audioMasterSizeWindow,
width, height, nullptr, 0.0);
}
}
logger.log_event_response(true, opcode, 0, nullptr, std::nullopt);
return 0;
}; break;
+11
View File
@@ -187,4 +187,15 @@ class Vst2PluginBridge : PluginBridge<Vst2Sockets<std::jthread>> {
* now happens in two different threads.
*/
std::mutex incoming_midi_events_mutex;
/**
* REAPER requires us to call `audioMasterSizeWidnow()` from the same thread
* that's calling `effEditIdle()`. If we call this from any other thread,
* then the FX window won't be resized. To accommodate for this, we'll store
* the width and the height passed to the last call to
* `audioMasterSizeWindow`. If this contains a value, we'll then call
* `audioMasterSizeWindow()` with the new size during `effEditIdle()`.
*/
std::optional<std::pair<int, int>> incoming_resize;
std::mutex incoming_resize_mutex;
};