diff --git a/src/common/communication.h b/src/common/communication.h index 5c7bdc71..c01e67af 100644 --- a/src/common/communication.h +++ b/src/common/communication.h @@ -788,10 +788,6 @@ class Sockets { host_vst_dispatch(io_context, (base_dir / "host_vst_dispatch.sock").string(), listen), - host_vst_dispatch_midi_events( - io_context, - (base_dir / "host_vst_dispatch_midi_events.sock").string(), - listen), vst_host_callback(io_context, (base_dir / "vst_host_callback.sock").string(), listen), @@ -814,7 +810,6 @@ class Sockets { // Manually close all sockets so we break out of any blocking operations // that may still be active host_vst_dispatch.close(); - host_vst_dispatch_midi_events.close(); vst_host_callback.close(); host_vst_parameters.close(); host_vst_process_replacing.close(); @@ -838,7 +833,6 @@ class Sockets { */ void connect() { host_vst_dispatch.connect(); - host_vst_dispatch_midi_events.connect(); vst_host_callback.connect(); host_vst_parameters.connect(); host_vst_process_replacing.connect(); @@ -861,13 +855,6 @@ class Sockets { * the plugin. */ EventHandler host_vst_dispatch; - /** - * Used specifically for the `effProcessEvents` opcode. This is needed - * because the Win32 API is designed to block during certain GUI - * interactions such as resizing a window or opening a dropdown. Without - * this MIDI input would just stop working at times. - */ - EventHandler host_vst_dispatch_midi_events; /** * The socket that forwards all `audioMaster()` calls from the Windows VST * plugin to the host. diff --git a/src/plugin/plugin-bridge.cpp b/src/plugin/plugin-bridge.cpp index bb49d412..2576bb7e 100644 --- a/src/plugin/plugin-bridge.cpp +++ b/src/plugin/plugin-bridge.cpp @@ -446,15 +446,6 @@ intptr_t PluginBridge::dispatch(AEffect* /*plugin*/, return return_value; }; break; - case effProcessEvents: - // Because of limitations of the Win32 API we have to use a seperate - // thread and socket to pass MIDI events. Otherwise plugins will - // stop receiving MIDI data when they have an open dropdowns or - // message box. - return sockets.host_vst_dispatch_midi_events.send_event( - converter, std::pair(logger, true), opcode, - index, value, data, option); - break; case effCanDo: { const std::string query(static_cast(data)); diff --git a/src/wine-host/bridges/vst2.cpp b/src/wine-host/bridges/vst2.cpp index 9792177c..d0f276c7 100644 --- a/src/wine-host/bridges/vst2.cpp +++ b/src/wine-host/bridges/vst2.cpp @@ -128,59 +128,6 @@ Vst2Bridge::Vst2Bridge(MainContext& main_context, // configuration as a response config = sockets.host_vst_control.receive_single(); - // This works functionally identically to the `handle_dispatch()` function, - // but this socket will only handle MIDI events and it will handle them - // eagerly. This is needed because of Win32 API limitations. - dispatch_midi_events_handler = Win32Thread([&]() { - sockets.host_vst_dispatch_midi_events.receive_events( - std::nullopt, [&](Event& event, bool /*on_main_thread*/) { - if (BOOST_LIKELY(event.opcode == effProcessEvents)) { - // For 99% of the plugins we can just call - // `effProcessReplacing()` and be done with it, but a select - // few plugins (I could only find Kontakt that does this) - // don't actually make copies of the events they receive and - // only store pointers, meaning that they have to live at - // least until the next audio buffer gets processed. We're - // not using `passthrough_events()` here directly because we - // need to store a copy of the `DynamicVstEvents` struct - // before passing the generated `VstEvents` object to the - // plugin. - std::lock_guard lock(next_buffer_midi_events_mutex); - - next_audio_buffer_midi_events.push_back( - std::get(event.payload)); - DynamicVstEvents& events = - next_audio_buffer_midi_events.back(); - - // Exact same handling as in `passthrough_event()`, apart - // from making a copy of the events first - const intptr_t return_value = plugin->dispatcher( - plugin, event.opcode, event.index, event.value, - &events.as_c_events(), event.option); - - EventResult response{.return_value = return_value, - .payload = nullptr, - .value_payload = std::nullopt}; - - return response; - } else { - using namespace std::placeholders; - - std::cerr << "[Warning] Received non-MIDI " - "event on MIDI processing thread" - << std::endl; - - // Maybe this should just be a hard error instead, since it - // should never happen - return passthrough_event( - plugin, - std::bind(&Vst2Bridge::dispatch_wrapper, this, _1, _2, - _3, _4, _5, _6), - event); - } - }); - }); - parameters_handler = Win32Thread([&]() { sockets.host_vst_parameters.receive_multi( [&](Parameter request, std::vector& buffer) { @@ -322,31 +269,62 @@ bool Vst2Bridge::should_skip_message_loop() const { void Vst2Bridge::handle_dispatch() { sockets.host_vst_dispatch.receive_events( std::nullopt, [&](Event& event, bool /*on_main_thread*/) { - return passthrough_event( - plugin, - [&](AEffect* plugin, int opcode, int index, intptr_t value, - void* data, float option) -> intptr_t { - // Certain functions will most definitely involve the GUI or - // the Win32 message loop. These functions have to be - // performed on the thread that is running the IO context, - // since this is also where the plugins were instantiated - // and where the Win32 message loop is handled. - if (unsafe_opcodes.contains(opcode)) { - std::promise dispatch_result; - boost::asio::dispatch(main_context.context, [&]() { - const intptr_t result = dispatch_wrapper( - plugin, opcode, index, value, data, option); + if (event.opcode == effProcessEvents) { + // For 99% of the plugins we can just call + // `effProcessReplacing()` and be done with it, but a select few + // plugins (I could only find Kontakt that does this) don't + // actually make copies of the events they receive and only + // store pointers to those events, meaning that they have to + // live at least until the next audio buffer gets processed. + // We're not using `passthrough_events()` here directly because + // we need to store a copy of the `DynamicVstEvents` struct + // before passing the generated `VstEvents` object to the + // plugin. + std::lock_guard lock(next_buffer_midi_events_mutex); - dispatch_result.set_value(result); - }); + next_audio_buffer_midi_events.push_back( + std::get(event.payload)); + DynamicVstEvents& events = next_audio_buffer_midi_events.back(); - return dispatch_result.get_future().get(); - } else { - return dispatch_wrapper(plugin, opcode, index, value, - data, option); - } - }, - event); + // Exact same handling as in `passthrough_event()`, apart + // from making a copy of the events first + const intptr_t return_value = plugin->dispatcher( + plugin, event.opcode, event.index, event.value, + &events.as_c_events(), event.option); + + EventResult response{.return_value = return_value, + .payload = nullptr, + .value_payload = std::nullopt}; + + return response; + } else { + return passthrough_event( + plugin, + [&](AEffect* plugin, int opcode, int index, intptr_t value, + void* data, float option) -> intptr_t { + // Certain functions will most definitely involve the + // GUI or the Win32 message loop. These functions have + // to be performed on the thread that is running the IO + // context, since this is also where the plugins were + // instantiated and where the Win32 message loop is + // handled. + if (unsafe_opcodes.contains(opcode)) { + std::promise dispatch_result; + boost::asio::dispatch(main_context.context, [&]() { + const intptr_t result = dispatch_wrapper( + plugin, opcode, index, value, data, option); + + dispatch_result.set_value(result); + }); + + return dispatch_result.get_future().get(); + } else { + return dispatch_wrapper(plugin, opcode, index, + value, data, option); + } + }, + event); + } }); } diff --git a/src/wine-host/bridges/vst2.h b/src/wine-host/bridges/vst2.h index db1b68ac..de195f03 100644 --- a/src/wine-host/bridges/vst2.h +++ b/src/wine-host/bridges/vst2.h @@ -186,12 +186,6 @@ class Vst2Bridge { */ AEffect* plugin; - /** - * The thread that specifically handles `effProcessEvents` opcodes so the - * plugin can still receive MIDI during GUI interaction to work around Win32 - * API limitations. - */ - Win32Thread dispatch_midi_events_handler; /** * The thread that responds to `getParameter` and `setParameter` requests. */