mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-13 20:09:59 +02:00
Redesign how interface instantiation works
Transferring some argument pack is much easier than trying to deserialize into an existing object when you also have to transfer more information than just that object.
This commit is contained in:
@@ -3,6 +3,12 @@
|
||||
TODO: Once this is more fleshed out, move this document to `docs/`, and perhaps
|
||||
replace this readme with a link to that document.
|
||||
|
||||
TODO: There are now two approaches in use: the factory takes an interface
|
||||
pointer for serialization and deserializes into an object directly, and the
|
||||
component uses an args struct because the alternative involving pointers is just
|
||||
too unsafe (as we also have to communicate additional payload data). This should
|
||||
probably be unified into only using the latter appraoch.
|
||||
|
||||
The VST3 SDK uses an architecture where every object inherits from an interface,
|
||||
and every interface inherits from `FUnknown` which offers a dynamic casting
|
||||
interface through `queryInterface()`. Every interface gets a unique identifier.
|
||||
|
||||
@@ -16,14 +16,19 @@
|
||||
|
||||
#include "component.h"
|
||||
|
||||
YaComponent::YaComponent(){FUNKNOWN_CTOR}
|
||||
|
||||
YaComponent::YaComponent(
|
||||
Steinberg::IPtr<Steinberg::Vst::IComponent> component) {
|
||||
FUNKNOWN_CTOR
|
||||
|
||||
YaComponent::Arguments::Arguments(
|
||||
Steinberg::IPtr<Steinberg::Vst::IComponent> component,
|
||||
size_t instance_id)
|
||||
: instance_id(instance_id) {
|
||||
// `IComponent::getControllerClassId`
|
||||
component->getControllerClassId(edit_controller_cid);
|
||||
Steinberg::TUID cid;
|
||||
if (component->getControllerClassId(cid) == Steinberg::kResultOk) {
|
||||
edit_controller_cid = std::to_array(cid);
|
||||
}
|
||||
}
|
||||
|
||||
YaComponent::YaComponent(const Arguments&& args) : arguments(std::move(args)) {
|
||||
FUNKNOWN_CTOR
|
||||
|
||||
// Everything else is handled directly through callbacks to minimize the
|
||||
// potential for errors
|
||||
@@ -49,3 +54,13 @@ tresult PLUGIN_API YaComponent::queryInterface(Steinberg::FIDString _iid,
|
||||
*obj = nullptr;
|
||||
return Steinberg::kNoInterface;
|
||||
}
|
||||
|
||||
tresult PLUGIN_API YaComponent::getControllerClassId(Steinberg::TUID classId) {
|
||||
if (arguments.edit_controller_cid) {
|
||||
std::copy(arguments.edit_controller_cid->begin(),
|
||||
arguments.edit_controller_cid->end(), classId);
|
||||
return Steinberg::kResultOk;
|
||||
} else {
|
||||
return Steinberg::kNotImplemented;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include "src/common/serialization/common.h"
|
||||
|
||||
#include <bitsery/ext/pointer.h>
|
||||
#include <bitsery/ext/std_optional.h>
|
||||
#include <bitsery/traits/array.h>
|
||||
#include <pluginterfaces/vst/ivstcomponent.h>
|
||||
|
||||
using Steinberg::TBool, Steinberg::int32, Steinberg::tresult;
|
||||
using Steinberg::TBool, Steinberg::int8, Steinberg::int32, Steinberg::tresult;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
@@ -36,14 +42,44 @@ using Steinberg::TBool, Steinberg::int32, Steinberg::tresult;
|
||||
class YaComponent : public Steinberg::Vst::IComponent {
|
||||
public:
|
||||
/**
|
||||
* Request the Wine plugin host to instantiate a new IComponent to pass
|
||||
* through a call to `IPluginFactory::createInstance(cid, IComponent::iid,
|
||||
* These are the arguments for creating a `YaComponentPluginImpl`.
|
||||
*/
|
||||
struct Arguments {
|
||||
/**
|
||||
* Read arguments from an existing implementation.
|
||||
*/
|
||||
Arguments(Steinberg::IPtr<Steinberg::Vst::IComponent> component,
|
||||
size_t isntance_id);
|
||||
|
||||
/**
|
||||
* The unique identifier for this specific instance.
|
||||
*/
|
||||
native_size_t instance_id;
|
||||
|
||||
/**
|
||||
* The class ID of this component's corresponding editor controller. You
|
||||
* can't use C-style array in `std::optional`s.
|
||||
*/
|
||||
std::optional<std::array<int8, std::extent_v<Steinberg::TUID>>>
|
||||
edit_controller_cid;
|
||||
|
||||
template <typename S>
|
||||
void serialize(S& s) {
|
||||
s.value8b(instance_id);
|
||||
s.ext(edit_controller_cid, bitsery::ext::StdOptional{},
|
||||
[](S& s, auto& cid) { s.container1b(cid); });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Message to request the Wine plugin host to instantiate a new IComponent
|
||||
* to pass through a call to `IPluginFactory::createInstance(cid,
|
||||
* IComponent::iid,
|
||||
* ...)`.
|
||||
*/
|
||||
struct Create {
|
||||
// TODO: This should be `std::optional<YaComponent>`, and we need a way
|
||||
// to deserialize that into an existing YaComponent.
|
||||
using Response = YaComponent&;
|
||||
// TODO: Create a `native_tvalue` wrapper, and then also add them here
|
||||
using Response = std::optional<Arguments>;
|
||||
|
||||
Steinberg::TUID cid;
|
||||
|
||||
@@ -53,12 +89,11 @@ class YaComponent : public Steinberg::Vst::IComponent {
|
||||
}
|
||||
};
|
||||
|
||||
YaComponent();
|
||||
|
||||
/**
|
||||
* Create a copy of an existing component.
|
||||
* Instantiate this instance with arguments read from another interface
|
||||
* implementation.
|
||||
*/
|
||||
explicit YaComponent(Steinberg::IPtr<Steinberg::Vst::IComponent> component);
|
||||
YaComponent(const Arguments&& args);
|
||||
|
||||
/**
|
||||
* @remark The plugin side implementation should send a control message to
|
||||
@@ -97,19 +132,16 @@ class YaComponent : public Steinberg::Vst::IComponent {
|
||||
virtual tresult PLUGIN_API
|
||||
getState(Steinberg::IBStream* state) override = 0;
|
||||
|
||||
template <typename S>
|
||||
void serialize(S& s) {
|
||||
s.container1b(edit_controller_cid);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The class ID of this component's corresponding editor controller.
|
||||
*/
|
||||
Steinberg::TUID edit_controller_cid;
|
||||
Arguments arguments;
|
||||
|
||||
// TODO: As explained in a few other places, `YaComponent` objects should be
|
||||
// assigned a unique ID for identification
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
void serialize(S& s, std::optional<YaComponent::Arguments>& args) {
|
||||
s.ext(args, bitsery::ext::StdOptional{});
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
Reference in New Issue
Block a user