Split IPluginBase from IComponent

We're also going to need this for `IEditController`. Separating all of
these classes will also keep everything much more maintainable with all
of these associated structs.
This commit is contained in:
Robbert van der Helm
2020-12-16 23:46:47 +01:00
parent 97570a47ba
commit 6809e73d6b
14 changed files with 257 additions and 150 deletions
+2
View File
@@ -2,6 +2,8 @@
TODO: Flesh this out further TODO: Flesh this out further
TODO: Link to `src/common/serialization/vst3/README.md`
The VST3 SDK uses an architecture where every concrete object inherits from an The VST3 SDK uses an architecture where every concrete object inherits from an
interface, and every interface inherits from `FUnknown`. `FUnkonwn` offers a interface, and every interface inherits from `FUnknown`. `FUnkonwn` offers a
dynamic casting interface through `queryInterface()` and a reference counting dynamic casting interface through `queryInterface()` and a reference counting
+2
View File
@@ -83,6 +83,7 @@ vst3_plugin_sources = [
'src/common/serialization/vst3/host-application.cpp', 'src/common/serialization/vst3/host-application.cpp',
'src/common/serialization/vst3/param-value-queue.cpp', 'src/common/serialization/vst3/param-value-queue.cpp',
'src/common/serialization/vst3/parameter-changes.cpp', 'src/common/serialization/vst3/parameter-changes.cpp',
'src/common/serialization/vst3/plugin-base.cpp',
'src/common/serialization/vst3/plugin-factory.cpp', 'src/common/serialization/vst3/plugin-factory.cpp',
'src/common/serialization/vst3/process-data.cpp', 'src/common/serialization/vst3/process-data.cpp',
'src/common/configuration.cpp', 'src/common/configuration.cpp',
@@ -122,6 +123,7 @@ if with_vst3
'src/common/serialization/vst3/host-application.cpp', 'src/common/serialization/vst3/host-application.cpp',
'src/common/serialization/vst3/param-value-queue.cpp', 'src/common/serialization/vst3/param-value-queue.cpp',
'src/common/serialization/vst3/parameter-changes.cpp', 'src/common/serialization/vst3/parameter-changes.cpp',
'src/common/serialization/vst3/plugin-base.cpp',
'src/common/serialization/vst3/plugin-factory.cpp', 'src/common/serialization/vst3/plugin-factory.cpp',
'src/common/serialization/vst3/process-data.cpp', 'src/common/serialization/vst3/process-data.cpp',
'src/wine-host/bridges/vst3-impls/host-application.cpp', 'src/wine-host/bridges/vst3-impls/host-application.cpp',
+21 -21
View File
@@ -54,27 +54,6 @@ void Vst3Logger::log_request(bool is_host_vst,
}); });
} }
void Vst3Logger::log_request(bool is_host_vst,
const YaComponent::Initialize& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "<IComponent* #" << request.instance_id
<< ">::initialize(context = ";
if (request.host_application_context_args) {
message << "<IHostApplication*>";
} else {
message << "<nullptr>";
}
message << ")";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaComponent::Terminate& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "<IComponent* #" << request.instance_id << ">::terminate()";
});
}
void Vst3Logger::log_request(bool is_host_vst, void Vst3Logger::log_request(bool is_host_vst,
const YaComponent::SetIoMode& request) { const YaComponent::SetIoMode& request) {
log_request_base(is_host_vst, [&](auto& message) { log_request_base(is_host_vst, [&](auto& message) {
@@ -227,6 +206,27 @@ void Vst3Logger::log_request(bool is_host_vst,
}); });
} }
void Vst3Logger::log_request(bool is_host_vst,
const YaPluginBase::Initialize& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "<IPluginBase* #" << request.instance_id
<< ">::initialize(context = ";
if (request.host_application_context_args) {
message << "<IHostApplication*>";
} else {
message << "<nullptr>";
}
message << ")";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaPluginBase::Terminate& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "<IPluginBase* #" << request.instance_id << ">::terminate()";
});
}
void Vst3Logger::log_request(bool is_host_vst, void Vst3Logger::log_request(bool is_host_vst,
const YaPluginFactory::Construct&) { const YaPluginFactory::Construct&) {
log_request_base(is_host_vst, log_request_base(is_host_vst,
+2 -2
View File
@@ -58,8 +58,6 @@ class Vst3Logger {
void log_request(bool is_host_vst, const YaComponent::Construct&); void log_request(bool is_host_vst, const YaComponent::Construct&);
void log_request(bool is_host_vst, const YaComponent::Destruct&); void log_request(bool is_host_vst, const YaComponent::Destruct&);
void log_request(bool is_host_vst, const YaComponent::Initialize&);
void log_request(bool is_host_vst, const YaComponent::Terminate&);
void log_request(bool is_host_vst, const YaComponent::SetIoMode&); void log_request(bool is_host_vst, const YaComponent::SetIoMode&);
void log_request(bool is_host_vst, const YaComponent::GetBusCount&); void log_request(bool is_host_vst, const YaComponent::GetBusCount&);
void log_request(bool is_host_vst, const YaComponent::GetBusInfo&); void log_request(bool is_host_vst, const YaComponent::GetBusInfo&);
@@ -77,6 +75,8 @@ class Vst3Logger {
void log_request(bool is_host_vst, const YaComponent::SetProcessing&); void log_request(bool is_host_vst, const YaComponent::SetProcessing&);
void log_request(bool is_host_vst, const YaComponent::Process&); void log_request(bool is_host_vst, const YaComponent::Process&);
void log_request(bool is_host_vst, const YaComponent::GetTailSamples&); void log_request(bool is_host_vst, const YaComponent::GetTailSamples&);
void log_request(bool is_host_vst, const YaPluginBase::Initialize&);
void log_request(bool is_host_vst, const YaPluginBase::Terminate&);
void log_request(bool is_host_vst, const YaPluginFactory::Construct&); void log_request(bool is_host_vst, const YaPluginFactory::Construct&);
void log_request(bool is_host_vst, const YaPluginFactory::SetHostContext&); void log_request(bool is_host_vst, const YaPluginFactory::SetHostContext&);
void log_request(bool is_host_vst, const WantsConfiguration&); void log_request(bool is_host_vst, const WantsConfiguration&);
+2 -2
View File
@@ -59,8 +59,6 @@ struct WantsConfiguration {
*/ */
using ControlRequest = std::variant<YaComponent::Construct, using ControlRequest = std::variant<YaComponent::Construct,
YaComponent::Destruct, YaComponent::Destruct,
YaComponent::Initialize,
YaComponent::Terminate,
YaComponent::SetIoMode, YaComponent::SetIoMode,
YaComponent::GetBusCount, YaComponent::GetBusCount,
YaComponent::GetBusInfo, YaComponent::GetBusInfo,
@@ -77,6 +75,8 @@ using ControlRequest = std::variant<YaComponent::Construct,
YaComponent::SetProcessing, YaComponent::SetProcessing,
YaComponent::Process, YaComponent::Process,
YaComponent::GetTailSamples, YaComponent::GetTailSamples,
YaPluginBase::Initialize,
YaPluginBase::Terminate,
YaPluginFactory::Construct, YaPluginFactory::Construct,
YaPluginFactory::SetHostContext>; YaPluginFactory::SetHostContext>;
+6 -5
View File
@@ -7,11 +7,12 @@ serialization works.
VST3 interfaces are implemented as follows: VST3 interfaces are implemented as follows:
| Yabridge class | Interfaces | Notes | | Yabridge class | Included in | Interfaces |
| ------------------- | ------------------------------------------------------ | ---------------------------------------------------------- | | ------------------- | ------------- | ------------------------------------------------------ |
| `YaComponent` | `IComponent`, `IPluginBase`, `IAudioProcessor` | | | `YaComponent` | | `IComponent`, `IAudioProcessor` |
| `YaHostApplication` | `iHostAPplication` | Used as a 'context' to allow the plugin to maek callbacks. | | `YaHostApplication` | | `iHostAPplication` |
| `YaPluginFactory` | `IPluginFactory`, `IPluginFactory2`, `IPluginFactory3` | | | `YaPluginBase` | `YaComponent` | `IPluginBase` |
| `YaPluginFactory` | | `IPluginFactory`, `IPluginFactory2`, `IPluginFactory3` |
The following interfaces are implemented purely fur serialization purposes: The following interfaces are implemented purely fur serialization purposes:
+22 -23
View File
@@ -21,30 +21,21 @@ YaComponent::ConstructArgs::ConstructArgs() {}
YaComponent::ConstructArgs::ConstructArgs( YaComponent::ConstructArgs::ConstructArgs(
Steinberg::IPtr<Steinberg::Vst::IComponent> component, Steinberg::IPtr<Steinberg::Vst::IComponent> component,
size_t instance_id) size_t instance_id)
: instance_id(instance_id) { : instance_id(instance_id),
known_iids.insert(component->iid); audio_processor_supported(
Steinberg::FUnknownPtr<Steinberg::Vst::IAudioProcessor>(component)) {
// `IComponent::getControllerClassId` // `IComponent::getControllerClassId`
Steinberg::TUID cid; Steinberg::TUID cid;
if (component->getControllerClassId(cid) == Steinberg::kResultOk) { if (component->getControllerClassId(cid) == Steinberg::kResultOk) {
edit_controller_cid = std::to_array(cid); edit_controller_cid = std::to_array(cid);
} }
// There's no static data we can copy from the audio processor
if (auto audio_processor =
Steinberg::FUnknownPtr<Steinberg::Vst::IAudioProcessor>(
component)) {
known_iids.insert(Steinberg::Vst::IAudioProcessor::iid);
}
} }
YaComponent::YaComponent(const ConstructArgs&& args) : arguments(std::move(args)) { YaComponent::YaComponent(const ConstructArgs&& args)
FUNKNOWN_CTOR : YaPluginBase(std::move(args.plugin_base_args)),
arguments(std::move(args)){FUNKNOWN_CTOR}
// Everything else is handled directly through callbacks to minimize the YaComponent::~YaComponent() {
// potential for errors
}
YaComponent::~YaComponent() {
FUNKNOWN_DTOR FUNKNOWN_DTOR
} }
@@ -55,14 +46,22 @@ IMPLEMENT_REFCOUNT(YaComponent)
tresult PLUGIN_API YaComponent::queryInterface(Steinberg::FIDString _iid, tresult PLUGIN_API YaComponent::queryInterface(Steinberg::FIDString _iid,
void** obj) { void** obj) {
QUERY_INTERFACE(_iid, obj, Steinberg::FUnknown::iid, Steinberg::IPluginBase) QUERY_INTERFACE(_iid, obj, Steinberg::FUnknown::iid,
if (arguments.known_iids.contains(Steinberg::Vst::IComponent::iid)) { Steinberg::Vst::IComponent)
QUERY_INTERFACE(_iid, obj, Steinberg::IPluginBase::iid, if (YaPluginBase::supported()) {
Steinberg::IPluginBase) // We had to expand the macro here because we need to cast through
QUERY_INTERFACE(_iid, obj, Steinberg::Vst::IComponent::iid, // `YaPluginBase`, since `IpluginBase` is also a base of `IComponent`
Steinberg::Vst::IComponent) if (Steinberg::FUnknownPrivate ::iidEqual(
_iid, Steinberg::IPluginBase::iid)) {
addRef();
*obj = static_cast<Steinberg ::IPluginBase*>(
static_cast<YaPluginBase*>(this));
return ::Steinberg ::kResultOk;
}
} }
if (arguments.known_iids.contains(Steinberg::Vst::IAudioProcessor::iid)) { QUERY_INTERFACE(_iid, obj, Steinberg::Vst::IComponent::iid,
Steinberg::Vst::IComponent)
if (arguments.audio_processor_supported) {
QUERY_INTERFACE(_iid, obj, Steinberg::Vst::IAudioProcessor::iid, QUERY_INTERFACE(_iid, obj, Steinberg::Vst::IAudioProcessor::iid,
Steinberg::Vst::IAudioProcessor) Steinberg::Vst::IAudioProcessor)
} }
+13 -57
View File
@@ -32,6 +32,7 @@
#include "../common.h" #include "../common.h"
#include "base.h" #include "base.h"
#include "host-application.h" #include "host-application.h"
#include "plugin-base.h"
#include "process-data.h" #include "process-data.h"
#pragma GCC diagnostic push #pragma GCC diagnostic push
@@ -43,18 +44,18 @@
* used for serialization, and on the plugin side have an implementation that * used for serialization, and on the plugin side have an implementation that
* can send control messages. * can send control messages.
* *
* This implements all interfaces that an `IComponent` might also implement.
*
* We might be able to do some caching here with the buss infos, but since that * We might be able to do some caching here with the buss infos, but since that
* sounds like a huge potential source of errors we'll just do pure callbacks * sounds like a huge potential source of errors we'll just do pure callbacks
* for everything other than the edit controller's class ID. * for everything other than the edit controller's class ID.
* *
* TODO: Amplement IConnectionPoint * TODO: Rework this into `YaPluginMonolith`
* TODO: How should we support IComponents without a seperate edit controller? * TODO: Eventually this should (optionally) implement everything supported by
* Can we just use a separate `YaEditController` that just points to the * the SDK's `AudioEffect` component.
* same implementation (with the same CID)? Check the reference
* implementation in the framework to see how this is initialized, make
* sure we support the reference w workflow.
*/ */
class YaComponent : public Steinberg::Vst::IComponent, class YaComponent : public Steinberg::Vst::IComponent,
public YaPluginBase,
public Steinberg::Vst::IAudioProcessor { public Steinberg::Vst::IAudioProcessor {
public: public:
/** /**
@@ -76,10 +77,10 @@ class YaComponent : public Steinberg::Vst::IComponent,
*/ */
native_size_t instance_id; native_size_t instance_id;
/** YaPluginBase::ConstructArgs plugin_base_args;
* The IIDs that the interface we serialized supports.
*/ // TODO: Remove, transitional
std::set<Steinberg::FUID> known_iids; bool audio_processor_supported;
/** /**
* The class ID of this component's corresponding editor controller. You * The class ID of this component's corresponding editor controller. You
@@ -90,10 +91,8 @@ class YaComponent : public Steinberg::Vst::IComponent,
template <typename S> template <typename S>
void serialize(S& s) { void serialize(S& s) {
s.value8b(instance_id); s.value8b(instance_id);
s.ext(known_iids, bitsery::ext::StdSet{32}, s.object(plugin_base_args);
[](S& s, Steinberg::FUID& iid) { s.value1b(audio_processor_supported);
s.ext(iid, bitsery::ext::FUID{});
});
s.ext(edit_controller_cid, bitsery::ext::StdOptional{}, s.ext(edit_controller_cid, bitsery::ext::StdOptional{},
[](S& s, auto& cid) { s.container1b(cid); }); [](S& s, auto& cid) { s.container1b(cid); });
} }
@@ -146,49 +145,6 @@ class YaComponent : public Steinberg::Vst::IComponent,
DECLARE_FUNKNOWN_METHODS DECLARE_FUNKNOWN_METHODS
// From `IPluginBase`
/**
* Message to pass through a call to `IPluginBase::initialize()` to the Wine
* plugin host. if we pass an `IHostApplication` instance, then a proxy
* `YaHostApplication` should be created and passed as an argument to
* `IPluginBase::initialize()`. If this is absent a null pointer should be
* passed. The lifetime of this `YaHostApplication` object should be bound
* to the `IComponent` we are proxying.
*/
struct Initialize {
using Response = UniversalTResult;
native_size_t instance_id;
std::optional<YaHostApplication::ConstructArgs>
host_application_context_args;
template <typename S>
void serialize(S& s) {
s.value8b(instance_id);
s.ext(host_application_context_args, bitsery::ext::StdOptional{});
}
};
virtual tresult PLUGIN_API initialize(FUnknown* context) override = 0;
/**
* Message to pass through a call to `IPluginBase::terminate()` to the Wine
* plugin host.
*/
struct Terminate {
using Response = UniversalTResult;
native_size_t instance_id;
template <typename S>
void serialize(S& s) {
s.value8b(instance_id);
}
};
virtual tresult PLUGIN_API terminate() override = 0;
// From `IComponent` // From `IComponent`
tresult PLUGIN_API getControllerClassId(Steinberg::TUID classId) override; tresult PLUGIN_API getControllerClassId(Steinberg::TUID classId) override;
@@ -0,0 +1,26 @@
// 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 <https://www.gnu.org/licenses/>.
#include "plugin-base.h"
YaPluginBase::ConstructArgs::ConstructArgs() {}
YaPluginBase::ConstructArgs::ConstructArgs(
Steinberg::IPtr<Steinberg::FUnknown> component)
: supported(Steinberg::FUnknownPtr<Steinberg::IPluginBase>(component)) {}
YaPluginBase::YaPluginBase(const ConstructArgs&& args)
: arguments(std::move(args)) {}
+113
View File
@@ -0,0 +1,113 @@
// 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 <https://www.gnu.org/licenses/>.
#pragma once
#include <bitsery/ext/std_optional.h>
#include <pluginterfaces/base/ipluginbase.h>
#include "../common.h"
#include "base.h"
#include "host-application.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
/**
* Wraps around `IPluginBase` for serialization purposes. Both components and
* edit controllers inherit from this. This is instantiated as part of
* `YaComponent` or `YaEditController`.
*/
class YaPluginBase : public Steinberg::IPluginBase {
public:
/**
* These are the arguments for creating a `YaPluginBase`.
*/
struct ConstructArgs {
ConstructArgs();
/**
* Read arguments from an existing implementation. Depending on the
* supported interface function more or less of this struct will be left
* empty, and `known_iids` will be set accordingly.
*/
ConstructArgs(Steinberg::IPtr<Steinberg::FUnknown> object);
/**
* Whether the object supported this interface.
*/
bool supported;
template <typename S>
void serialize(S& s) {
s.value1b(supported);
}
};
/**
* Instantiate this instance with arguments read from another interface
* implementation.
*/
YaPluginBase(const ConstructArgs&& args);
inline bool supported() { return arguments.supported; }
/**
* Message to pass through a call to `IPluginBase::initialize()` to the Wine
* plugin host. if we pass an `IHostApplication` instance, then a proxy
* `YaHostApplication` should be created and passed as an argument to
* `IPluginBase::initialize()`. If this is absent a null pointer should be
* passed. The lifetime of this `YaHostApplication` object should be bound
* to the `IComponent` we are proxying.
*/
struct Initialize {
using Response = UniversalTResult;
native_size_t instance_id;
std::optional<YaHostApplication::ConstructArgs>
host_application_context_args;
template <typename S>
void serialize(S& s) {
s.value8b(instance_id);
s.ext(host_application_context_args, bitsery::ext::StdOptional{});
}
};
virtual tresult PLUGIN_API initialize(FUnknown* context) override = 0;
/**
* Message to pass through a call to `IPluginBase::terminate()` to the Wine
* plugin host.
*/
struct Terminate {
using Response = UniversalTResult;
native_size_t instance_id;
template <typename S>
void serialize(S& s) {
s.value8b(instance_id);
}
};
virtual tresult PLUGIN_API terminate() override = 0;
protected:
ConstructArgs arguments;
};
#pragma GCC diagnostic pop
+29 -29
View File
@@ -40,35 +40,6 @@ YaComponentPluginImpl::queryInterface(const Steinberg::TUID _iid, void** obj) {
return result; return result;
} }
tresult PLUGIN_API YaComponentPluginImpl::initialize(FUnknown* context) {
// This `context` will likely be an `IHostApplication`. If it is, we will
// store it here, and we'll proxy through all calls to it made from the Wine
// side. Otherwise we'll still call `IPluginBase::initialize()` but with a
// null pointer instead.
host_application_context = context;
std::optional<YaHostApplication::ConstructArgs>
host_application_context_args = std::nullopt;
if (host_application_context) {
host_application_context_args = YaHostApplication::ConstructArgs(
host_application_context, arguments.instance_id);
} else {
bridge.logger.log_unknown_interface(
"In IPluginBase::initialize()",
context ? std::optional(context->iid) : std::nullopt);
}
return bridge.send_message(
YaComponent::Initialize{.instance_id = arguments.instance_id,
.host_application_context_args =
std::move(host_application_context_args)});
}
tresult PLUGIN_API YaComponentPluginImpl::terminate() {
return bridge.send_message(
YaComponent::Terminate{.instance_id = arguments.instance_id});
}
tresult PLUGIN_API tresult PLUGIN_API
YaComponentPluginImpl::setIoMode(Steinberg::Vst::IoMode mode) { YaComponentPluginImpl::setIoMode(Steinberg::Vst::IoMode mode) {
return bridge.send_message(YaComponent::SetIoMode{ return bridge.send_message(YaComponent::SetIoMode{
@@ -143,6 +114,35 @@ tresult PLUGIN_API YaComponentPluginImpl::getState(Steinberg::IBStream* state) {
return response.result; return response.result;
} }
tresult PLUGIN_API YaComponentPluginImpl::initialize(FUnknown* context) {
// This `context` will likely be an `IHostApplication`. If it is, we will
// store it here, and we'll proxy through all calls to it made from the Wine
// side. Otherwise we'll still call `IPluginBase::initialize()` but with a
// null pointer instead.
host_application_context = context;
std::optional<YaHostApplication::ConstructArgs>
host_application_context_args = std::nullopt;
if (host_application_context) {
host_application_context_args = YaHostApplication::ConstructArgs(
host_application_context, arguments.instance_id);
} else {
bridge.logger.log_unknown_interface(
"In IPluginBase::initialize()",
context ? std::optional(context->iid) : std::nullopt);
}
return bridge.send_message(
YaPluginBase::Initialize{.instance_id = arguments.instance_id,
.host_application_context_args =
std::move(host_application_context_args)});
}
tresult PLUGIN_API YaComponentPluginImpl::terminate() {
return bridge.send_message(
YaPluginBase::Terminate{.instance_id = arguments.instance_id});
}
tresult PLUGIN_API YaComponentPluginImpl::setBusArrangements( tresult PLUGIN_API YaComponentPluginImpl::setBusArrangements(
Steinberg::Vst::SpeakerArrangement* inputs, Steinberg::Vst::SpeakerArrangement* inputs,
int32 numIns, int32 numIns,
+5 -3
View File
@@ -39,9 +39,7 @@ class YaComponentPluginImpl : public YaComponent {
tresult PLUGIN_API queryInterface(const Steinberg::TUID _iid, tresult PLUGIN_API queryInterface(const Steinberg::TUID _iid,
void** obj) override; void** obj) override;
tresult PLUGIN_API initialize(FUnknown* context) override; // From `IComponent`
tresult PLUGIN_API terminate() override;
tresult PLUGIN_API setIoMode(Steinberg::Vst::IoMode mode) override; tresult PLUGIN_API setIoMode(Steinberg::Vst::IoMode mode) override;
int32 PLUGIN_API getBusCount(Steinberg::Vst::MediaType type, int32 PLUGIN_API getBusCount(Steinberg::Vst::MediaType type,
Steinberg::Vst::BusDirection dir) override; Steinberg::Vst::BusDirection dir) override;
@@ -61,6 +59,10 @@ class YaComponentPluginImpl : public YaComponent {
tresult PLUGIN_API setState(Steinberg::IBStream* state) override; tresult PLUGIN_API setState(Steinberg::IBStream* state) override;
tresult PLUGIN_API getState(Steinberg::IBStream* state) override; tresult PLUGIN_API getState(Steinberg::IBStream* state) override;
// From `IPluginBase`
tresult PLUGIN_API initialize(FUnknown* context) override;
tresult PLUGIN_API terminate() override;
tresult PLUGIN_API tresult PLUGIN_API
setBusArrangements(Steinberg::Vst::SpeakerArrangement* inputs, setBusArrangements(Steinberg::Vst::SpeakerArrangement* inputs,
int32 numIns, int32 numIns,
+9 -7
View File
@@ -26,7 +26,9 @@ ComponentInstance::ComponentInstance() {}
ComponentInstance::ComponentInstance( ComponentInstance::ComponentInstance(
Steinberg::IPtr<Steinberg::Vst::IComponent> component) Steinberg::IPtr<Steinberg::Vst::IComponent> component)
: component(component), audio_processor(component) {} : component(component),
plugin_base(component),
audio_processor(component) {}
Vst3Bridge::Vst3Bridge(MainContext& main_context, Vst3Bridge::Vst3Bridge(MainContext& main_context,
std::string plugin_dll_path, std::string plugin_dll_path,
@@ -86,8 +88,8 @@ void Vst3Bridge::run() {
return Ack{}; return Ack{};
}, },
[&](YaComponent::Initialize& request) [&](YaPluginBase::Initialize& request)
-> YaComponent::Initialize::Response { -> YaPluginBase::Initialize::Response {
// If we got passed a host context, we'll create a proxy object // If we got passed a host context, we'll create a proxy object
// and pass that to the initialize function. This object should // and pass that to the initialize function. This object should
// be cleaned up again during `YaComponent::Destruct`. // be cleaned up again during `YaComponent::Destruct`.
@@ -103,12 +105,12 @@ void Vst3Bridge::run() {
} }
return component_instances[request.instance_id] return component_instances[request.instance_id]
.component->initialize(context); .plugin_base->initialize(context);
}, },
[&](const YaComponent::Terminate& request) [&](const YaPluginBase::Terminate& request)
-> YaComponent::Terminate::Response { -> YaPluginBase::Terminate::Response {
return component_instances[request.instance_id] return component_instances[request.instance_id]
.component->terminate(); .plugin_base->terminate();
}, },
[&](const YaComponent::SetIoMode& request) [&](const YaComponent::SetIoMode& request)
-> YaComponent::SetIoMode::Response { -> YaComponent::SetIoMode::Response {
+5 -1
View File
@@ -28,6 +28,9 @@
* A holder for an `IComponent` instance created from the factory along with any * A holder for an `IComponent` instance created from the factory along with any
* host context proxy objects belonging to it, and several predefined * host context proxy objects belonging to it, and several predefined
* `FUnknownPtrs` so we don't have to do these dynamic casts all the times.. * `FUnknownPtrs` so we don't have to do these dynamic casts all the times..
*
* TODO: When implementing `IEditController`, change this to use `IPluginBase`
* as the base interface.
*/ */
struct ComponentInstance { struct ComponentInstance {
ComponentInstance(); ComponentInstance();
@@ -37,7 +40,7 @@ struct ComponentInstance {
/** /**
* If the host passes an `IHostApplication` during * If the host passes an `IHostApplication` during
* `IPluginBase::initialize()`, we'll store a proxy object here and then * `IPluginBase::initialize()`, we'll store a proxy object here and then
* pass it to `component->initialize()`. * pass it to `plugin_base->initialize()`.
*/ */
Steinberg::IPtr<YaHostApplication> hsot_application_context; Steinberg::IPtr<YaHostApplication> hsot_application_context;
@@ -49,6 +52,7 @@ struct ComponentInstance {
// All smart pointers below are created from `component`. They will be null // All smart pointers below are created from `component`. They will be null
// pointers if `component` did not implement the interface. // pointers if `component` did not implement the interface.
Steinberg::FUnknownPtr<Steinberg::IPluginBase> plugin_base;
Steinberg::FUnknownPtr<Steinberg::Vst::IAudioProcessor> audio_processor; Steinberg::FUnknownPtr<Steinberg::Vst::IAudioProcessor> audio_processor;
}; };