diff --git a/src/common/communication.h b/src/common/communication.h index 8ffa0a85..7cf38b29 100644 --- a/src/common/communication.h +++ b/src/common/communication.h @@ -22,6 +22,13 @@ #include #include +/** + * The maximum size in bytes of a string or buffer passed through a void pointer + * in one of the dispatch functions. This is used as a buffer size and also as a + * cutoff for checking if c-style strings behind a `char*` have changed. + */ +constexpr size_t max_string_size = 128; + /** * 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 @@ -34,8 +41,15 @@ struct Event { // dereferenced? intptr_t value; float option; + /** + * The event dispatch function has a void pointer parameter that's used to + * either send string messages to the event (e.g. for `effCanDo`) or to + * write a string back into. This value will contain an (empty) string if + * the void* parameter for the dispatch function was not a null pointer. + */ + std::optional data; - MSGPACK_DEFINE(opcode, parameter, value, option) + MSGPACK_DEFINE(opcode, parameter, value, option, data) }; /** @@ -50,11 +64,11 @@ struct EventResult { * If present, this should get written into the void pointer passed to the * dispatch function. */ - std::optional result; + std::optional data; // TODO: Add missing return value fields; - MSGPACK_DEFINE(return_value, result) + MSGPACK_DEFINE(return_value, data) }; /** @@ -89,9 +103,9 @@ inline void write_object(Socket& socket, const T& object) { */ template inline T read_object(Socket& socket) { - // TODO: Reuse buffers + // TODO: Reuse buffers, also this is way too large right now // TODO: Use boost's buffers directly after switching to bitsery - char buffer[65536]; + char buffer[4096]; auto message_length = socket.receive(boost::asio::buffer(buffer)); return msgpack::unpack(buffer, message_length).get().convert(); diff --git a/src/plugin/bridge.cpp b/src/plugin/bridge.cpp index 7f187b1b..7447c4fb 100644 --- a/src/plugin/bridge.cpp +++ b/src/plugin/bridge.cpp @@ -76,7 +76,7 @@ intptr_t Bridge::dispatch(AEffect* /*plugin*/, int32_t opcode, int32_t parameter, intptr_t value, - void* result, + void* data, float option) { // Some events need some extra handling // TODO: Handle other things such as GUI itneraction @@ -97,13 +97,18 @@ intptr_t Bridge::dispatch(AEffect* /*plugin*/, break; } - const Event event{opcode, parameter, value, option}; + auto payload = + data == nullptr + ? std::nullopt + : std::make_optional(std::string(static_cast(data))); + + const Event event{opcode, parameter, value, option, payload}; write_object(host_vst_dispatch, event); const auto response = read_object(host_vst_dispatch); - if (response.result) { - std::copy(response.result->begin(), response.result->end(), - static_cast(result)); + if (response.data.has_value()) { + std::copy(response.data->begin(), response.data->end(), + static_cast(data)); } return response.return_value; diff --git a/src/plugin/bridge.h b/src/plugin/bridge.h index 5570f269..c46cb35c 100644 --- a/src/plugin/bridge.h +++ b/src/plugin/bridge.h @@ -52,7 +52,7 @@ class Bridge { int32_t opcode, int32_t parameter, intptr_t value, - void* result, + void* data, float option); void process(AEffect* plugin, float** inputs, diff --git a/src/plugin/plugin.cpp b/src/plugin/plugin.cpp index 3e9e2001..f4cedc8e 100644 --- a/src/plugin/plugin.cpp +++ b/src/plugin/plugin.cpp @@ -95,10 +95,10 @@ intptr_t dispatch(AEffect* plugin, int32_t opcode, int32_t parameter, intptr_t value, - void* result, + void* data, float option) { return get_bridge_instance(*plugin).dispatch(plugin, opcode, parameter, - value, result, option); + value, data, option); } void process(AEffect* plugin, diff --git a/src/wine-host/native-includes.h b/src/wine-host/native-includes.h index fa968892..326f4934 100644 --- a/src/wine-host/native-includes.h +++ b/src/wine-host/native-includes.h @@ -34,6 +34,7 @@ #undef __WIN32__ #undef _WIN64 +#include #include #include #include diff --git a/src/wine-host/vst-host.cpp b/src/wine-host/vst-host.cpp index b57cccd1..3fd539ec 100644 --- a/src/wine-host/vst-host.cpp +++ b/src/wine-host/vst-host.cpp @@ -59,12 +59,6 @@ int main(int argc, char* argv[]) { // TODO: Check whether this returned a null pointer AEffect* plugin = vst_entry_point(host_callback); - // TODO: Check the spec, how large should this be? - std::vector buffer(2048, 0); - plugin->dispatcher(plugin, effGetEffectName, 0, 0, buffer.data(), 0.0); - - std::string plugin_title(buffer.data()); - // Connect to the sockets for communication once the plugin has finished // loading // TODO: The program should terminate gracefully when one of the sockets @@ -85,18 +79,41 @@ int main(int argc, char* argv[]) { // TODO: Remove debug, we're just reporting the plugin's name we retrieved // above + std::array buffer; while (true) { auto event = read_object(host_vst_dispatch); - EventResult response; - if (event.opcode == effGetEffectName) { - response.result = plugin_title; - response.return_value = 1; - } else { - response.return_value = 0; + // The void pointer argument for the dispatch function is used for + // either: + // - Not at all, in which case it will be a null pointer + // - For passing strings as input to the event + // - For providing a buffer for the event to write results back into + char* payload = nullptr; + if (event.data.has_value()) { + // If the data parameter was an empty string, then we're going to + // pass a larger buffer to the dispatch function instead.. + if (!event.data->empty()) { + payload = const_cast(event.data->c_str()); + } else { + payload = buffer.data(); + } } - write_object(host_vst_dispatch, response); + const intptr_t return_value = + plugin->dispatcher(plugin, event.opcode, event.option, + event.parameter, payload, event.option); + + // Only write back the value from `payload` if we were passed an empty + // buffer to write into + bool is_updated = event.data.has_value() && event.data->empty(); + + if (is_updated) { + EventResult response{return_value, payload}; + write_object(host_vst_dispatch, response); + } else { + EventResult response{return_value, std::nullopt}; + write_object(host_vst_dispatch, response); + } } } @@ -105,7 +122,7 @@ intptr_t VST_CALL_CONV host_callback(AEffect* plugin, int32_t opcode, int32_t parameter, intptr_t value, - void* result, + void* data, float option) { return 1; }