diff --git a/src/common/communication/vst2.cpp b/src/common/communication/vst2.cpp index c8eac1e9..cdad7d59 100644 --- a/src/common/communication/vst2.cpp +++ b/src/common/communication/vst2.cpp @@ -18,10 +18,10 @@ DefaultDataConverter::~DefaultDataConverter() noexcept {} -EventPayload DefaultDataConverter::read_data(const int /*opcode*/, - const int /*index*/, - const intptr_t /*value*/, - const void* data) const { +Vst2Event::Payload DefaultDataConverter::read_data(const int /*opcode*/, + const int /*index*/, + const intptr_t /*value*/, + const void* data) const { if (!data) { return nullptr; } @@ -38,7 +38,7 @@ EventPayload DefaultDataConverter::read_data(const int /*opcode*/, } } -std::optional DefaultDataConverter::read_value( +std::optional DefaultDataConverter::read_value( const int /*opcode*/, const intptr_t /*value*/) const { return std::nullopt; diff --git a/src/common/communication/vst2.h b/src/common/communication/vst2.h index 4f699118..9401f9df 100644 --- a/src/common/communication/vst2.h +++ b/src/common/communication/vst2.h @@ -34,21 +34,23 @@ class DefaultDataConverter { virtual ~DefaultDataConverter() noexcept; /** - * Read data from the `data` void pointer into a an `EventPayload` value - * that can be serialized and conveys the meaning of the event. + * Read data from the `data` void pointer into a an `Vst2Event::Payload` + * value that can be serialized and conveys the meaning of the event. */ - virtual EventPayload read_data(const int opcode, - const int index, - const intptr_t value, - const void* data) const; + virtual Vst2Event::Payload read_data(const int opcode, + const int index, + const intptr_t value, + const void* data) const; /** - * Read data from the `value` pointer into a an `EventPayload` value that - * can be serialized and conveys the meaning of the event. This is only used - * for the `effSetSpeakerArrangement` and `effGetSpeakerArrangement` events. + * Read data from the `value` pointer into a an `Vst2Event::Payload` value + * that can be serialized and conveys the meaning of the event. This is only + * used for the `effSetSpeakerArrangement` and `effGetSpeakerArrangement` + * events. */ - virtual std::optional read_value(const int opcode, - const intptr_t value) const; + virtual std::optional read_value( + const int opcode, + const intptr_t value) const; /** * Write the response back to the `data` pointer. @@ -153,8 +155,9 @@ class Vst2EventHandler : public AdHocSocketHandler { * write data back to the `data` void pointer. For host callbacks this * parameter contains either a string or a null pointer while `dispatch()` * calls might contain opcode specific structs. See the documentation for - * `EventPayload` for more information. The `DefaultDataConverter` defined - * above handles the basic behavior that's sufficient for host callbacks. + * `Vst2Event::Payload` for more information. The `DefaultDataConverter` + * defined above handles the basic behavior that's sufficient for host + * callbacks. * @param logging A pair containing a logger instance and whether or not * this is for sending `dispatch()` events or host callbacks. Optional * since it doesn't have to be done on both sides. @@ -171,12 +174,13 @@ class Vst2EventHandler : public AdHocSocketHandler { void* data, float option) { // Encode the right payload types for this event. Check the - // documentation for `EventPayload` for more information. These types - // are converted to C-style data structures in `passthrough_event()` so - // they can be passed to a plugin or callback function. - const EventPayload payload = + // documentation for `Vst2Event::Payload` for more information. These + // types are converted to C-style data structures in + // `passthrough_event()` so they can be passed to a plugin or callback + // function. + const Vst2Event::Payload payload = data_converter.read_data(opcode, index, value, data); - const std::optional value_payload = + const std::optional value_payload = data_converter.read_value(opcode, value); if (logging) { @@ -224,8 +228,8 @@ class Vst2EventHandler : public AdHocSocketHandler { * * The specified function will be used to create an `EventResult` from an * `Vst2Event`. This is almost always uses `passthrough_event()`, which - * converts a `EventPayload` into the format used by VST2, calls either - * `dispatch()` or `audioMaster()` depending on the context, and then + * converts a `Vst2Event::Payload` into the format used by VST2, calls + * either `dispatch()` or `audioMaster()` depending on the context, and then * serializes the result back into an `EventResultPayload`. * * @param logging A pair containing a logger instance and whether or not @@ -381,9 +385,9 @@ class Vst2Sockets : public Sockets { }; /** - * Unmarshall an `EventPayload` back to the representation used by VST2, pass - * that value to a callback function (either `AEffect::dispatcher()` for host -> - * plugin events or `audioMaster()` for plugin -> host events), and then + * Unmarshall an `Vst2Event::Payload` back to the representation used by VST2, + * pass that value to a callback function (either `AEffect::dispatcher()` for + * host -> plugin events or `audioMaster()` for plugin -> host events), and then * serialize the results back into an `EventResult`. * * This is the receiving analogue of the `*DataCovnerter` objects. diff --git a/src/common/logging/vst2.cpp b/src/common/logging/vst2.cpp index 81634ac7..f8ef2311 100644 --- a/src/common/logging/vst2.cpp +++ b/src/common/logging/vst2.cpp @@ -360,9 +360,9 @@ void Vst2Logger::log_event(bool is_dispatch, int opcode, int index, intptr_t value, - const EventPayload& payload, + const Vst2Event::Payload& payload, float option, - const std::optional& value_payload) { + const std::optional& value_payload) { if (BOOST_UNLIKELY(logger.verbosity >= Logger::Verbosity::most_events)) { if (should_filter_event(is_dispatch, opcode)) { return; diff --git a/src/common/logging/vst2.h b/src/common/logging/vst2.h index e88e912b..c3e3db4e 100644 --- a/src/common/logging/vst2.h +++ b/src/common/logging/vst2.h @@ -66,9 +66,9 @@ class Vst2Logger { int opcode, int index, intptr_t value, - const EventPayload& payload, + const Vst2Event::Payload& payload, float option, - const std::optional& value_payload); + const std::optional& value_payload); void log_event_response( bool is_dispatch, int opcode, diff --git a/src/common/serialization/vst2.h b/src/common/serialization/vst2.h index 702e4d1e..813af163 100644 --- a/src/common/serialization/vst2.h +++ b/src/common/serialization/vst2.h @@ -304,60 +304,103 @@ struct WantsVstTimeInfo {}; struct WantsString {}; /** - * VST events are passed a void pointer that can contain a variety of different - * data types depending on the event's opcode. This is typically either: - * - * - A null pointer, used for simple events. - * - A char pointer to a null terminated string, used for passing strings to the - * plugin such as when renaming presets. Bitsery handles the serialization for - * us. - * - * NOTE: Bitsery does not support null terminated C-strings without a known - * size. We can replace `std::string` with `char*` once it does for - * clarity's sake. - * - * - A byte vector for handling chunk data during `effSetChunk()`. We can't - * reuse the regular string handling here since the data may contain null - * bytes and `std::string::as_c_str()` might cut off everything after the - * first null byte. - * - An X11 window handle. - * - Specific data structures from `aeffextx.h`. For instance an event with the - * opcode `effProcessEvents` the hosts passes a `VstEvents` struct containing - * MIDI events, and `audioMasterIOChanged` lets the host know that the - * `AEffect` struct has changed. - * - * - Some empty buffer for the plugin to write its own data to, for instance for - * a plugin to report its name or the label for a certain parameter. There are - * two separate cases here. This is typically a short null terminated - * C-string. We'll assume this as the default case when none of the above - * options apply. - * - * - Either the plugin writes arbitrary data and uses its return value to - * indicate how much data was written (i.e. for the `effGetChunk` opcode). - * For this we use a vector of bytes instead of a string since - * - Or the plugin will write a short null terminated C-string there. We'll - * assume that this is the default if none of the above options apply. - * - * @relates passthrough_event + * An event as dispatched by the VST host. These events will get forwarded to + * the VST host process running under Wine. The fields here mirror those + * arguments sent to the `AEffect::dispatch` function. */ -using EventPayload = std::variant; +struct Vst2Event { + /** + * VST events are passed a void pointer that can contain a variety of + * different data types depending on the event's opcode. This is typically + * either: + * + * - A null pointer, used for simple events. + * - A char pointer to a null terminated string, used for passing strings to + * the plugin such as when renaming presets. Bitsery handles the + * serialization for us. + * + * NOTE: Bitsery does not support null terminated C-strings without a + * known size. We can replace `std::string` with `char*` once it + * does for clarity's sake. + * + * - A byte vector for handling chunk data during `effSetChunk()`. We can't + * reuse the regular string handling here since the data may contain null + * bytes and `std::string::as_c_str()` might cut off everything after the + * first null byte. + * - An X11 window handle. + * - Specific data structures from `aeffextx.h`. For instance an event with + * the opcode `effProcessEvents` the hosts passes a `VstEvents` struct + * containing MIDI events, and `audioMasterIOChanged` lets the host know + * that the `AEffect` struct has changed. + * + * - Some empty buffer for the plugin to write its own data to, for instance + * for a plugin to report its name or the label for a certain parameter. + * There are two separate cases here. This is typically a short null + * terminated C-string. We'll assume this as the default case when none of + * the above options apply. + * + * - Either the plugin writes arbitrary data and uses its return value to + * indicate how much data was written (i.e. for the `effGetChunk` + * opcode). For this we use a vector of bytes instead of a string since + * - Or the plugin will write a short null terminated C-string there. + * We'll assume that this is the default if none of the above options + * apply. + * + * @relates passthrough_event + */ + using Payload = std::variant; + + int opcode; + int index; + native_intptr_t value; + float option; + /** + * The event dispatch function has a void pointer parameter that's often + * used to either pass additional data for the event or to provide a buffer + * for the plugin to write a string into. + * + * The `VstEvents` struct passed for the `effProcessEvents` event contains + * an array of pointers. This requires some special handling which is why we + * have to use an `std::variant` instead of a simple string buffer. Luckily + * Bitsery can do all the hard work for us. + */ + Payload payload; + /** + * The same as the above value, but for values passed through the `intptr_t` + * value parameter. `effGetSpeakerArrangement` and + * `effSetSpeakerArrangement` are the only events that use this. + */ + std::optional value_payload; + + template + void serialize(S& s) { + s.value4b(opcode); + s.value4b(index); + s.value8b(value); + s.value4b(option); + + s.object(payload); + s.ext(value_payload, bitsery::ext::StdOptional(), + [](S& s, auto& v) { s.object(v); }); + } +}; template -void serialize(S& s, EventPayload& payload) { +void serialize(S& s, Vst2Event::Payload& payload) { s.ext(payload, bitsery::ext::StdVariant{ [](S&, std::nullptr_t&) {}, @@ -383,47 +426,6 @@ void serialize(S& s, EventPayload& payload) { [](S&, WantsString&) {}}); } -/** - * An event as dispatched by the VST host. These events will get forwarded to - * the VST host process running under Wine. The fields here mirror those - * arguments sent to the `AEffect::dispatch` function. - */ -struct Vst2Event { - int opcode; - int index; - native_intptr_t value; - float option; - /** - * The event dispatch function has a void pointer parameter that's often - * used to either pass additional data for the event or to provide a buffer - * for the plugin to write a string into. - * - * The `VstEvents` struct passed for the `effProcessEvents` event contains - * an array of pointers. This requires some special handling which is why we - * have to use an `std::variant` instead of a simple string buffer. Luckily - * Bitsery can do all the hard work for us. - */ - EventPayload payload; - /** - * The same as the above value, but for values passed through the `intptr_t` - * value parameter. `effGetSpeakerArrangement` and - * `effSetSpeakerArrangement` are the only events that use this. - */ - std::optional value_payload; - - template - void serialize(S& s) { - s.value4b(opcode); - s.value4b(index); - s.value8b(value); - s.value4b(option); - - s.object(payload); - s.ext(value_payload, bitsery::ext::StdOptional(), - [](S& s, auto& v) { s.object(v); }); - } -}; - /** * The response for an event. This is usually either: * diff --git a/src/plugin/bridges/vst2.cpp b/src/plugin/bridges/vst2.cpp index e4b4d03a..7e696c19 100644 --- a/src/plugin/bridges/vst2.cpp +++ b/src/plugin/bridges/vst2.cpp @@ -190,10 +190,10 @@ class DispatchDataConverter : public DefaultDataConverter { VstRect& editor_rectangle) noexcept : chunk(chunk_data), plugin(plugin), rect(editor_rectangle) {} - EventPayload read_data(const int opcode, - const int index, - const intptr_t value, - const void* data) const override { + Vst2Event::Payload read_data(const int opcode, + const int index, + const intptr_t value, + const void* data) const override { // There are some events that need specific structs that we can't simply // serialize as a string because they might contain null bytes switch (opcode) { @@ -307,7 +307,7 @@ class DispatchDataConverter : public DefaultDataConverter { } } - std::optional read_value( + std::optional read_value( const int opcode, const intptr_t value) const override { switch (opcode) { diff --git a/src/wine-host/bridges/vst2.cpp b/src/wine-host/bridges/vst2.cpp index 029eb813..8e32a3d6 100644 --- a/src/wine-host/bridges/vst2.cpp +++ b/src/wine-host/bridges/vst2.cpp @@ -519,10 +519,10 @@ class HostCallbackDataConverter : public DefaultDataConverter { last_time_info(last_time_info), mutual_recursion(mutual_recursion) {} - EventPayload read_data(const int opcode, - const int index, - const intptr_t value, - const void* data) const override { + Vst2Event::Payload read_data(const int opcode, + const int index, + const intptr_t value, + const void* data) const override { switch (opcode) { case audioMasterGetTime: return WantsVstTimeInfo{}; @@ -580,7 +580,7 @@ class HostCallbackDataConverter : public DefaultDataConverter { } } - std::optional read_value( + std::optional read_value( const int opcode, const intptr_t value) const override { return DefaultDataConverter::read_value(opcode, value);