Move EventPayload to Vst2Event::Payload

This commit is contained in:
Robbert van der Helm
2021-05-20 15:50:22 +02:00
parent b1c9d75112
commit 2bf41c6fe1
7 changed files with 140 additions and 134 deletions
+5 -5
View File
@@ -18,10 +18,10 @@
DefaultDataConverter::~DefaultDataConverter() noexcept {} DefaultDataConverter::~DefaultDataConverter() noexcept {}
EventPayload DefaultDataConverter::read_data(const int /*opcode*/, Vst2Event::Payload DefaultDataConverter::read_data(const int /*opcode*/,
const int /*index*/, const int /*index*/,
const intptr_t /*value*/, const intptr_t /*value*/,
const void* data) const { const void* data) const {
if (!data) { if (!data) {
return nullptr; return nullptr;
} }
@@ -38,7 +38,7 @@ EventPayload DefaultDataConverter::read_data(const int /*opcode*/,
} }
} }
std::optional<EventPayload> DefaultDataConverter::read_value( std::optional<Vst2Event::Payload> DefaultDataConverter::read_value(
const int /*opcode*/, const int /*opcode*/,
const intptr_t /*value*/) const { const intptr_t /*value*/) const {
return std::nullopt; return std::nullopt;
+27 -23
View File
@@ -34,21 +34,23 @@ class DefaultDataConverter {
virtual ~DefaultDataConverter() noexcept; virtual ~DefaultDataConverter() noexcept;
/** /**
* Read data from the `data` void pointer into a an `EventPayload` value * Read data from the `data` void pointer into a an `Vst2Event::Payload`
* that can be serialized and conveys the meaning of the event. * value that can be serialized and conveys the meaning of the event.
*/ */
virtual EventPayload read_data(const int opcode, virtual Vst2Event::Payload read_data(const int opcode,
const int index, const int index,
const intptr_t value, const intptr_t value,
const void* data) const; const void* data) const;
/** /**
* Read data from the `value` pointer into a an `EventPayload` value that * Read data from the `value` pointer into a an `Vst2Event::Payload` value
* can be serialized and conveys the meaning of the event. This is only used * that can be serialized and conveys the meaning of the event. This is only
* for the `effSetSpeakerArrangement` and `effGetSpeakerArrangement` events. * used for the `effSetSpeakerArrangement` and `effGetSpeakerArrangement`
* events.
*/ */
virtual std::optional<EventPayload> read_value(const int opcode, virtual std::optional<Vst2Event::Payload> read_value(
const intptr_t value) const; const int opcode,
const intptr_t value) const;
/** /**
* Write the response back to the `data` pointer. * Write the response back to the `data` pointer.
@@ -153,8 +155,9 @@ class Vst2EventHandler : public AdHocSocketHandler<Thread> {
* write data back to the `data` void pointer. For host callbacks this * write data back to the `data` void pointer. For host callbacks this
* parameter contains either a string or a null pointer while `dispatch()` * parameter contains either a string or a null pointer while `dispatch()`
* calls might contain opcode specific structs. See the documentation for * calls might contain opcode specific structs. See the documentation for
* `EventPayload` for more information. The `DefaultDataConverter` defined * `Vst2Event::Payload` for more information. The `DefaultDataConverter`
* above handles the basic behavior that's sufficient for host callbacks. * defined above handles the basic behavior that's sufficient for host
* callbacks.
* @param logging A pair containing a logger instance and whether or not * @param logging A pair containing a logger instance and whether or not
* this is for sending `dispatch()` events or host callbacks. Optional * this is for sending `dispatch()` events or host callbacks. Optional
* since it doesn't have to be done on both sides. * since it doesn't have to be done on both sides.
@@ -171,12 +174,13 @@ class Vst2EventHandler : public AdHocSocketHandler<Thread> {
void* data, void* data,
float option) { float option) {
// Encode the right payload types for this event. Check the // Encode the right payload types for this event. Check the
// documentation for `EventPayload` for more information. These types // documentation for `Vst2Event::Payload` for more information. These
// are converted to C-style data structures in `passthrough_event()` so // types are converted to C-style data structures in
// they can be passed to a plugin or callback function. // `passthrough_event()` so they can be passed to a plugin or callback
const EventPayload payload = // function.
const Vst2Event::Payload payload =
data_converter.read_data(opcode, index, value, data); data_converter.read_data(opcode, index, value, data);
const std::optional<EventPayload> value_payload = const std::optional<Vst2Event::Payload> value_payload =
data_converter.read_value(opcode, value); data_converter.read_value(opcode, value);
if (logging) { if (logging) {
@@ -224,8 +228,8 @@ class Vst2EventHandler : public AdHocSocketHandler<Thread> {
* *
* The specified function will be used to create an `EventResult` from an * The specified function will be used to create an `EventResult` from an
* `Vst2Event`. This is almost always uses `passthrough_event()`, which * `Vst2Event`. This is almost always uses `passthrough_event()`, which
* converts a `EventPayload` into the format used by VST2, calls either * converts a `Vst2Event::Payload` into the format used by VST2, calls
* `dispatch()` or `audioMaster()` depending on the context, and then * either `dispatch()` or `audioMaster()` depending on the context, and then
* serializes the result back into an `EventResultPayload`. * serializes the result back into an `EventResultPayload`.
* *
* @param logging A pair containing a logger instance and whether or not * @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 * Unmarshall an `Vst2Event::Payload` back to the representation used by VST2,
* that value to a callback function (either `AEffect::dispatcher()` for host -> * pass that value to a callback function (either `AEffect::dispatcher()` for
* plugin events or `audioMaster()` for plugin -> host events), and then * host -> plugin events or `audioMaster()` for plugin -> host events), and then
* serialize the results back into an `EventResult`. * serialize the results back into an `EventResult`.
* *
* This is the receiving analogue of the `*DataCovnerter` objects. * This is the receiving analogue of the `*DataCovnerter` objects.
+2 -2
View File
@@ -360,9 +360,9 @@ void Vst2Logger::log_event(bool is_dispatch,
int opcode, int opcode,
int index, int index,
intptr_t value, intptr_t value,
const EventPayload& payload, const Vst2Event::Payload& payload,
float option, float option,
const std::optional<EventPayload>& value_payload) { const std::optional<Vst2Event::Payload>& value_payload) {
if (BOOST_UNLIKELY(logger.verbosity >= Logger::Verbosity::most_events)) { if (BOOST_UNLIKELY(logger.verbosity >= Logger::Verbosity::most_events)) {
if (should_filter_event(is_dispatch, opcode)) { if (should_filter_event(is_dispatch, opcode)) {
return; return;
+2 -2
View File
@@ -66,9 +66,9 @@ class Vst2Logger {
int opcode, int opcode,
int index, int index,
intptr_t value, intptr_t value,
const EventPayload& payload, const Vst2Event::Payload& payload,
float option, float option,
const std::optional<EventPayload>& value_payload); const std::optional<Vst2Event::Payload>& value_payload);
void log_event_response( void log_event_response(
bool is_dispatch, bool is_dispatch,
int opcode, int opcode,
+94 -92
View File
@@ -304,60 +304,103 @@ struct WantsVstTimeInfo {};
struct WantsString {}; struct WantsString {};
/** /**
* VST events are passed a void pointer that can contain a variety of different * An event as dispatched by the VST host. These events will get forwarded to
* data types depending on the event's opcode. This is typically either: * the VST host process running under Wine. The fields here mirror those
* * arguments sent to the `AEffect::dispatch` function.
* - 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 EventPayload = std::variant<std::nullptr_t, struct Vst2Event {
std::string, /**
native_size_t, * VST events are passed a void pointer that can contain a variety of
AEffect, * different data types depending on the event's opcode. This is typically
ChunkData, * either:
DynamicVstEvents, *
DynamicSpeakerArrangement, * - A null pointer, used for simple events.
WantsAEffectUpdate, * - A char pointer to a null terminated string, used for passing strings to
WantsChunkBuffer, * the plugin such as when renaming presets. Bitsery handles the
VstIOProperties, * serialization for us.
VstMidiKeyName, *
VstParameterProperties, * NOTE: Bitsery does not support null terminated C-strings without a
WantsVstRect, * known size. We can replace `std::string` with `char*` once it
WantsVstTimeInfo, * does for clarity's sake.
WantsString>; *
* - 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<std::nullptr_t,
std::string,
native_size_t,
AEffect,
ChunkData,
DynamicVstEvents,
DynamicSpeakerArrangement,
WantsAEffectUpdate,
WantsChunkBuffer,
VstIOProperties,
VstMidiKeyName,
VstParameterProperties,
WantsVstRect,
WantsVstTimeInfo,
WantsString>;
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<Payload> value_payload;
template <typename S>
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 <typename S> template <typename S>
void serialize(S& s, EventPayload& payload) { void serialize(S& s, Vst2Event::Payload& payload) {
s.ext(payload, s.ext(payload,
bitsery::ext::StdVariant{ bitsery::ext::StdVariant{
[](S&, std::nullptr_t&) {}, [](S&, std::nullptr_t&) {},
@@ -383,47 +426,6 @@ void serialize(S& s, EventPayload& payload) {
[](S&, WantsString&) {}}); [](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<EventPayload> value_payload;
template <typename S>
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: * The response for an event. This is usually either:
* *
+5 -5
View File
@@ -190,10 +190,10 @@ class DispatchDataConverter : public DefaultDataConverter {
VstRect& editor_rectangle) noexcept VstRect& editor_rectangle) noexcept
: chunk(chunk_data), plugin(plugin), rect(editor_rectangle) {} : chunk(chunk_data), plugin(plugin), rect(editor_rectangle) {}
EventPayload read_data(const int opcode, Vst2Event::Payload read_data(const int opcode,
const int index, const int index,
const intptr_t value, const intptr_t value,
const void* data) const override { const void* data) const override {
// There are some events that need specific structs that we can't simply // There are some events that need specific structs that we can't simply
// serialize as a string because they might contain null bytes // serialize as a string because they might contain null bytes
switch (opcode) { switch (opcode) {
@@ -307,7 +307,7 @@ class DispatchDataConverter : public DefaultDataConverter {
} }
} }
std::optional<EventPayload> read_value( std::optional<Vst2Event::Payload> read_value(
const int opcode, const int opcode,
const intptr_t value) const override { const intptr_t value) const override {
switch (opcode) { switch (opcode) {
+5 -5
View File
@@ -519,10 +519,10 @@ class HostCallbackDataConverter : public DefaultDataConverter {
last_time_info(last_time_info), last_time_info(last_time_info),
mutual_recursion(mutual_recursion) {} mutual_recursion(mutual_recursion) {}
EventPayload read_data(const int opcode, Vst2Event::Payload read_data(const int opcode,
const int index, const int index,
const intptr_t value, const intptr_t value,
const void* data) const override { const void* data) const override {
switch (opcode) { switch (opcode) {
case audioMasterGetTime: case audioMasterGetTime:
return WantsVstTimeInfo{}; return WantsVstTimeInfo{};
@@ -580,7 +580,7 @@ class HostCallbackDataConverter : public DefaultDataConverter {
} }
} }
std::optional<EventPayload> read_value( std::optional<Vst2Event::Payload> read_value(
const int opcode, const int opcode,
const intptr_t value) const override { const intptr_t value) const override {
return DefaultDataConverter::read_value(opcode, value); return DefaultDataConverter::read_value(opcode, value);