diff --git a/src/common/serialization/vst3/README.md b/src/common/serialization/vst3/README.md index 2554f0b1..0757e74e 100644 --- a/src/common/serialization/vst3/README.md +++ b/src/common/serialization/vst3/README.md @@ -50,7 +50,37 @@ instantiated and managed by the host. The model works as follows: ## 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(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`), 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` will be moved to an + `std::map>` 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 diff --git a/src/common/serialization/vst3/component.h b/src/common/serialization/vst3/component.h index 9a966587..41f6718a 100644 --- a/src/common/serialization/vst3/component.h +++ b/src/common/serialization/vst3/component.h @@ -41,6 +41,8 @@ class YaComponent : public Steinberg::Vst::IComponent { * ...)`. */ struct Create { + // TODO: This should be `std::optional`, and we need a way + // to deserialize that into an existing YaComponent. using Response = YaComponent&; Steinberg::TUID cid; @@ -58,7 +60,11 @@ class YaComponent : public Steinberg::Vst::IComponent { */ explicit YaComponent(Steinberg::IPtr 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 diff --git a/src/plugin/bridges/vst3-impls.cpp b/src/plugin/bridges/vst3-impls.cpp index 971264c5..e8c78bc6 100644 --- a/src/plugin/bridges/vst3-impls.cpp +++ b/src/plugin/bridges/vst3-impls.cpp @@ -25,32 +25,7 @@ tresult PLUGIN_API YaPluginFactoryPluginImpl::createInstance(Steinberg::FIDString cid, Steinberg::FIDString _iid, void** obj) { - // TODO: This should: - // 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`, 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. - + // TODO: Implement as specified in `src/common/serialization/vst3/README.md` if (Steinberg::FIDStringsEqual(_iid, Steinberg::Vst::IComponent::iid)) { // TODO: Instantiate an IComponent as described above return Steinberg::kNotImplemented;