diff --git a/meson.build b/meson.build index 5baeaa02..680cc297 100644 --- a/meson.build +++ b/meson.build @@ -93,6 +93,7 @@ vst3_plugin_sources = [ 'src/common/serialization/vst3/host-context-proxy.cpp', 'src/common/serialization/vst3/param-value-queue.cpp', 'src/common/serialization/vst3/parameter-changes.cpp', + 'src/common/serialization/vst3/plug-frame-proxy.cpp', 'src/common/serialization/vst3/plug-view-proxy.cpp', 'src/common/serialization/vst3/plugin-proxy.cpp', 'src/common/serialization/vst3/plugin-factory.cpp', @@ -145,6 +146,7 @@ if with_vst3 'src/common/serialization/vst3/host-context-proxy.cpp', 'src/common/serialization/vst3/param-value-queue.cpp', 'src/common/serialization/vst3/parameter-changes.cpp', + 'src/common/serialization/vst3/plug-frame-proxy.cpp', 'src/common/serialization/vst3/plug-view-proxy.cpp', 'src/common/serialization/vst3/plugin-proxy.cpp', 'src/common/serialization/vst3/plugin-factory.cpp', diff --git a/src/common/serialization/vst3/component-handler-proxy.h b/src/common/serialization/vst3/component-handler-proxy.h index aa0a944d..eced256b 100644 --- a/src/common/serialization/vst3/component-handler-proxy.h +++ b/src/common/serialization/vst3/component-handler-proxy.h @@ -25,10 +25,10 @@ /** * An abstract class that implements `IComponentHandler`, and optionally also * all other VST3 interfaces an object passed to - * `IEditController::setComponentHandler()`. This works exactly the same as - * `Vst3PluginProxy`, but instead of proxying for an object provided by the - * plugin we are proxying for the `IComponentHandler*` argument passed to plugin - * by the host. + * `IEditController::setComponentHandler()` might implement. This works exactly + * the same as `Vst3PluginProxy`, but instead of proxying for an object provided + * by the plugin we are proxying for the `IComponentHandler*` argument passed to + * plugin by the host. */ class Vst3ComponentHandlerProxy : public YaComponentHandler { public: diff --git a/src/common/serialization/vst3/plug-frame-proxy.cpp b/src/common/serialization/vst3/plug-frame-proxy.cpp new file mode 100644 index 00000000..abf391c7 --- /dev/null +++ b/src/common/serialization/vst3/plug-frame-proxy.cpp @@ -0,0 +1,50 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "plug-frame-proxy.h" + +Vst3PlugFrameProxy::ConstructArgs::ConstructArgs() {} + +Vst3PlugFrameProxy::ConstructArgs::ConstructArgs( + Steinberg::IPtr object, + size_t owner_instance_id) + : owner_instance_id(owner_instance_id), plug_frame_args(object) {} + +Vst3PlugFrameProxy::Vst3PlugFrameProxy(const ConstructArgs&& args) + : YaPlugFrame(std::move(args.plug_frame_args)), + arguments(std::move(args)){FUNKNOWN_CTOR} + + Vst3PlugFrameProxy::~Vst3PlugFrameProxy() { + FUNKNOWN_DTOR +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" +IMPLEMENT_REFCOUNT(Vst3PlugFrameProxy) +#pragma GCC diagnostic pop + +tresult PLUGIN_API Vst3PlugFrameProxy::queryInterface(Steinberg::FIDString _iid, + void** obj) { + if (YaPlugFrame::supported()) { + QUERY_INTERFACE(_iid, obj, Steinberg::FUnknown::iid, + Steinberg::IPlugFrame) + QUERY_INTERFACE(_iid, obj, Steinberg::IPlugFrame::iid, + Steinberg::IPlugFrame) + } + + *obj = nullptr; + return Steinberg::kNoInterface; +} diff --git a/src/common/serialization/vst3/plug-frame-proxy.h b/src/common/serialization/vst3/plug-frame-proxy.h new file mode 100644 index 00000000..0a45bcb3 --- /dev/null +++ b/src/common/serialization/vst3/plug-frame-proxy.h @@ -0,0 +1,97 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include "../common.h" +#include "plug-frame/plug-frame.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" + +/** + * An abstract class that implements `IPlugFrame`, and optionally also all other + * VST3 interfaces an object passed to `IPlugView::setFrame()` might implement. + * This works exactly the same as `Vst3PluginProxy`, but instead of proxying for + * an object provided by the plugin we are proxying for the `IPlugFrame*` + * argument passed to plugin by the host. + */ +class Vst3PlugFrameProxy : public YaPlugFrame { + public: + /** + * These are the arguments for constructing a + * `Vst3PlugFrameProxyImpl`. + */ + struct ConstructArgs { + ConstructArgs(); + + /** + * Read from an existing object. We will try to mimic this object, so + * we'll support any interfaces this object also supports. + */ + ConstructArgs(Steinberg::IPtr object, + size_t owner_instance_id); + + /** + * The unique instance identifier of the proxy object instance this + * component handler has been passed to and thus belongs to. This way we + * can refer to the correct 'actual' `IPlugFrame` instance when the + * plugin does a callback. + */ + native_size_t owner_instance_id; + + YaPlugFrame::ConstructArgs plug_frame_args; + + template + void serialize(S& s) { + s.value8b(owner_instance_id); + s.object(plug_frame_args); + } + }; + + /** + * Instantiate this instance with arguments read from an actual component + * handler. + * + * @note Since this is passed as part of `IEditController::setPlugFrame()`, + * there are no direct `Construct` or `Destruct` messages. This object's + * lifetime is bound to that of the objects they are passed to. If the + * plug view instance gets dropped, this proxy should also be dropped. + */ + Vst3PlugFrameProxy(const ConstructArgs&& args); + + /** + * The lifetime of this object should be bound to the object we created it + * for. When the `Vst3PlugViewProxy` for the object with instance with id + * `n` gets dropped, the corresponding `Vst3PlugFrameProxy` should also be + * dropped. + */ + virtual ~Vst3PlugFrameProxy(); + + DECLARE_FUNKNOWN_METHODS + + /** + * Get the instance ID of the owner of this object. + */ + inline size_t owner_instance_id() const { + return arguments.owner_instance_id; + } + + private: + ConstructArgs arguments; +}; + +#pragma GCC diagnostic pop