mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
Document the plugin factory approach
This commit is contained in:
@@ -50,7 +50,37 @@ instantiated and managed by the host. The model works as follows:
|
|||||||
|
|
||||||
## Plugin Factory
|
## Plugin Factory
|
||||||
|
|
||||||
TODO: Explain how we implement `createInstance()`, based on the todo comment there.
|
Creating a new instance of an interface using the plugin factory wroks as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
1. The host calls `createInterface(cid, _iid, obj)` on an IPluginFactory
|
||||||
|
implementation exposed to the host as described above.
|
||||||
|
2. We check which interface we support matches the `_iid`. If we don't support
|
||||||
|
the interface, we'll log a message about it and return that we do not support
|
||||||
|
the itnerface.
|
||||||
|
3. If we determine that `_iid` matches `IFoo`, then we'll send a
|
||||||
|
`YaFoo::Create{cid}` to the Wine plugin host process.
|
||||||
|
4. The Wine plugin host will then call
|
||||||
|
`module->getFactory().createInstance<IFoo>(cid)` using the Windows VST3
|
||||||
|
plugin's plugin factory to ask it to create an instance of that interface. If
|
||||||
|
this operation fails and returns a null pointer, we'll send an `std::nullopt`
|
||||||
|
back to indicate that the instantiation was not successful and we relay this
|
||||||
|
on the plugin side.
|
||||||
|
5. Using the newly created instance (which will be returned by the factory as an
|
||||||
|
`IPtr<IFoo>`), we will instantiate a `YaFoo` object using `YaFooHostImpl`.
|
||||||
|
This will read all simple data members from the `IFoo` smart pointer just
|
||||||
|
like described in the above section. The `YaFoo` object will also gen a
|
||||||
|
unique identifier which we generate on the Wine side using an atomic
|
||||||
|
fetch-and-add on a counter. This way we can refer to this specific isntance
|
||||||
|
when doing callbacks.
|
||||||
|
6. Still on the Wine side of things, the `IPtr<IFoo>` will be moved to an
|
||||||
|
`std::map<size_t, IPtr<IFoo>>` with that unique identifier we generated
|
||||||
|
earlier as a key so we can refer to it later.
|
||||||
|
7. Finally on the plugin side we will create an `YaFooPluginImpl` object that
|
||||||
|
can send control messages to the Wine plugin host, and then we'll deserialize
|
||||||
|
the `YaFoo` object we receive into that.
|
||||||
|
8. A pointer to this `YaFooPluginImpl` then gets returned as the final step of
|
||||||
|
the initialization process.
|
||||||
|
|
||||||
## Safety notes
|
## Safety notes
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ class YaComponent : public Steinberg::Vst::IComponent {
|
|||||||
* ...)`.
|
* ...)`.
|
||||||
*/
|
*/
|
||||||
struct Create {
|
struct Create {
|
||||||
|
// TODO: This should be `std::optional<YaComponent>`, and we need a way
|
||||||
|
// to deserialize that into an existing YaComponent.
|
||||||
using Response = YaComponent&;
|
using Response = YaComponent&;
|
||||||
|
|
||||||
Steinberg::TUID cid;
|
Steinberg::TUID cid;
|
||||||
@@ -58,7 +60,11 @@ class YaComponent : public Steinberg::Vst::IComponent {
|
|||||||
*/
|
*/
|
||||||
explicit YaComponent(Steinberg::IPtr<Steinberg::Vst::IComponent> component);
|
explicit YaComponent(Steinberg::IPtr<Steinberg::Vst::IComponent> component);
|
||||||
|
|
||||||
virtual ~YaComponent();
|
/**
|
||||||
|
* @remark The plugin side implementation should send a control message to
|
||||||
|
* clean up the instance on the Wine side in its destructor.
|
||||||
|
*/
|
||||||
|
virtual ~YaComponent() = 0;
|
||||||
|
|
||||||
DECLARE_FUNKNOWN_METHODS
|
DECLARE_FUNKNOWN_METHODS
|
||||||
|
|
||||||
|
|||||||
@@ -25,32 +25,7 @@ tresult PLUGIN_API
|
|||||||
YaPluginFactoryPluginImpl::createInstance(Steinberg::FIDString cid,
|
YaPluginFactoryPluginImpl::createInstance(Steinberg::FIDString cid,
|
||||||
Steinberg::FIDString _iid,
|
Steinberg::FIDString _iid,
|
||||||
void** obj) {
|
void** obj) {
|
||||||
// TODO: This should:
|
// TODO: Implement as specified in `src/common/serialization/vst3/README.md`
|
||||||
// 1. Check which interface `_iid` belongs to. Let's call this
|
|
||||||
// interface `T`. If we do not (yet) support it, then we should log
|
|
||||||
// it and return `Steinberg::kNotImplemented`.
|
|
||||||
// 2. Send a control message to the Wine plugin host to instantiate a
|
|
||||||
// new object of type `T` with `cid` and `_iid` as parameters.
|
|
||||||
// 3. On the Wine side this calls `createIntance()` on the module's
|
|
||||||
// factory with thsoe same `cid` and `_iid` arguments.
|
|
||||||
// 4. It this was successful, we'll assign this object a unique number
|
|
||||||
// (by just doing a fetch-and-add on an atomic size_t) so we can
|
|
||||||
// refer to it and add it to an `std::map<size_t, IP tr<T>`, where
|
|
||||||
// `T` is the _original_ object (we don't have to and shouldn't
|
|
||||||
// wrap it).
|
|
||||||
// 5. We'll copy over any payload data into a `YaT` **which includes
|
|
||||||
// that unique identifier we generated** and send it back to the
|
|
||||||
// plugin.
|
|
||||||
// 6. On the plugin's side we'll create a new `YaTPluginImpl` inside
|
|
||||||
// of a VST smart pointer and deserialize the `YaT` we got sent
|
|
||||||
// into that. We then write that smart pointer into `obj`. We don't
|
|
||||||
// have to keep track of these objects on the plugin side and the
|
|
||||||
// reference counting pointers will cause everything to clean up
|
|
||||||
// after itself.
|
|
||||||
// 7. Since those `YaTPluginImpl` objects we'll return from
|
|
||||||
// `createInstance()` will have a reference to `Vst3PluginBridge`,
|
|
||||||
// they can also send control messages themselves.
|
|
||||||
|
|
||||||
if (Steinberg::FIDStringsEqual(_iid, Steinberg::Vst::IComponent::iid)) {
|
if (Steinberg::FIDStringsEqual(_iid, Steinberg::Vst::IComponent::iid)) {
|
||||||
// TODO: Instantiate an IComponent as described above
|
// TODO: Instantiate an IComponent as described above
|
||||||
return Steinberg::kNotImplemented;
|
return Steinberg::kNotImplemented;
|
||||||
|
|||||||
Reference in New Issue
Block a user