From 7a68654fa2ac4b1ce28bd1eb10cc37f1449a7f76 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Fri, 7 Feb 2020 15:04:27 +0100 Subject: [PATCH] Handle freeing resources when closing the plugin --- src/plugin/bridge.cpp | 12 +++++++++++- src/plugin/plugin.cpp | 39 ++++++++++++++++++++------------------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/plugin/bridge.cpp b/src/plugin/bridge.cpp index ba50cf82..0fcf3538 100644 --- a/src/plugin/bridge.cpp +++ b/src/plugin/bridge.cpp @@ -17,12 +17,22 @@ intptr_t Bridge::dispatch(AEffect* /*plugin*/, void* result, float /*option*/) { switch (opcode) { + case effClose: + // TODO: Gracefully close the editor? + + // The VST API does not have an explicit function for releasing + // resources, so we'll have to do it here. The actual plugin + // instance gets freed by the host, or at least I think it does. + delete this; + + return 0; + break; case effGetEffectName: const std::string plugin_name("Hello, world!"); std::copy(plugin_name.begin(), plugin_name.end(), static_cast(result)); - // return 1; // TODO: Why? + return 1; // TODO: Why? break; } diff --git a/src/plugin/plugin.cpp b/src/plugin/plugin.cpp index 2613b980..ec65a399 100644 --- a/src/plugin/plugin.cpp +++ b/src/plugin/plugin.cpp @@ -28,27 +28,28 @@ void setParameter(AEffect*, int32_t, float); float getParameter(AEffect*, int32_t); /** - * Retrieve the bridge instance stored in an unused pointer from a VST plugin. - * This is sadly needed as a workaround to avoid using globals since we need - * free function pointers to interface with the VST API. + * Fetch the bridge instance stored in an unused pointer from a VST plugin. This + * is sadly needed as a workaround to avoid using globals since we need free + * function pointers to interface with the VST C API. */ -Bridge* get_bridge_instance(const AEffect& plugin) { - return static_cast(plugin.ptr3); +Bridge& get_bridge_instance(const AEffect& plugin) { + return *static_cast(plugin.ptr3); } /** - * The main VST plugin entry point. This finds the Windows VST plugin that - * should be run, executes it in our VST host inside Wine, and sets up - * communication between the two processes. + * The main VST plugin entry point. We first set up a bridge that connects to a + * Wine process that hosts the Windows VST plugin. We then create and return a + * VST plugin struct that acts as a passthrough to the bridge. * - * This is a bit of a mess since we're interacting with an external C API. To - * keep this somewhat contained this is the only place where we're doing manual - * memory management. + * To keep this somewhat contained this is the only place where we're doing + * manual memory management. Clean up is done when we receive the `effClose` + * opcode from the VST host (i.e. opcode 1).` */ VST_EXPORT AEffect* VSTPluginMain(audioMasterCallback /*audioMaster*/) { - // TODO: Since we are returning raw pointers, how does cleanup work? + Bridge* bridge = new Bridge(); + AEffect* plugin = new AEffect(); - plugin->ptr3 = new Bridge(); + plugin->ptr3 = bridge; plugin->dispatcher = dispatch; plugin->process = process; @@ -73,22 +74,22 @@ intptr_t dispatch(AEffect* plugin, intptr_t value, void* result, float option) { - return get_bridge_instance(*plugin)->dispatch(plugin, opcode, parameter, - value, result, option); + return get_bridge_instance(*plugin).dispatch(plugin, opcode, parameter, + value, result, option); } void process(AEffect* plugin, float** inputs, float** outputs, int32_t sample_frames) { - return get_bridge_instance(*plugin)->process(plugin, inputs, outputs, - sample_frames); + return get_bridge_instance(*plugin).process(plugin, inputs, outputs, + sample_frames); } void setParameter(AEffect* plugin, int32_t index, float value) { - return get_bridge_instance(*plugin)->set_parameter(plugin, index, value); + return get_bridge_instance(*plugin).set_parameter(plugin, index, value); } float getParameter(AEffect* plugin, int32_t index) { - return get_bridge_instance(*plugin)->get_parameter(plugin, index); + return get_bridge_instance(*plugin).get_parameter(plugin, index); }