Add manual reference counting to GetPluginFactory

Since even though we're passign raw pointers, it's expected that they
are actually `IPtr<T>`s.
This commit is contained in:
Robbert van der Helm
2020-12-07 14:53:55 +01:00
parent 547b11e8ba
commit 9954282065
4 changed files with 46 additions and 37 deletions
+6 -3
View File
@@ -24,11 +24,14 @@ YaPluginFactoryPluginImpl::createInstance(Steinberg::FIDString /*cid*/,
Steinberg::FIDString /*_iid*/, Steinberg::FIDString /*_iid*/,
void** /*obj*/) { void** /*obj*/) {
// TODO: Send a control message // TODO: Send a control message
return 0; return Steinberg::kNotImplemented;
} }
tresult PLUGIN_API tresult PLUGIN_API
YaPluginFactoryPluginImpl::setHostContext(Steinberg::FUnknown* /*context*/) { YaPluginFactoryPluginImpl::setHostContext(Steinberg::FUnknown* /*context*/) {
// TODO: Send a control message // TODO: The docs don't clearly specify what this should be doing, but from
return 0; // what I've seen this is only used to pass a `IHostApplication`
// instance. That's used to allow the plugin to create objects in the
// host.
return Steinberg::kNotImplemented;
} }
+20 -9
View File
@@ -81,13 +81,24 @@ Vst3PluginBridge::Vst3PluginBridge()
overload{[&](const WantsConfiguration&) overload{[&](const WantsConfiguration&)
-> WantsConfiguration::Response { return config; }}); -> WantsConfiguration::Response { return config; }});
}); });
}
// Set up the plugin factory, since this is the first thing the host will
// request after loading the module. Host callback handlers should have Steinberg::IPluginFactory* Vst3PluginBridge::get_plugin_factory() {
// started before this since the Wine plugin host will request a copy of the // Even though we're working with raw pointers here, we should pretend that
// configuration during its initialization. // we're `IPtr<Steinberg::IPluginFactory>` and do the reference counting
plugin_factory = std::make_unique<YaPluginFactoryPluginImpl>(*this); // ourselves because you can't always safely pass those around
sockets.host_vst_control.receive_into( if (plugin_factory) {
WantsPluginFactory{}, *plugin_factory, plugin_factory->addRef();
std::pair<Vst3Logger&, bool>(logger, true)); } else {
// Set up the plugin factory, since this is the first thing the host
// will request after loading the module. Host callback handlers should
// have started before this since the Wine plugin host will request a
// copy of the configuration during its initialization.
plugin_factory = std::make_unique<YaPluginFactoryPluginImpl>(*this);
sockets.host_vst_control.receive_into(
WantsPluginFactory{}, *plugin_factory,
std::pair<Vst3Logger&, bool>(logger, true));
}
return plugin_factory.get();
} }
+19 -8
View File
@@ -52,6 +52,17 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
*/ */
Vst3PluginBridge(); Vst3PluginBridge();
/**
* When the host loads the module it will call `GetPluginFactory()` which
* will in turn call this function. The idea is that we return an
* `IPluginFactory*` while doing all the reference counting that `IPtr<T>`
* would normally do for us ourselves. This means that when the host frees
* its last instance of this factory, `plugin_factory` will also be cleared.
*
* @see plugin_factory
*/
Steinberg::IPluginFactory* get_plugin_factory();
private: private:
/** /**
* Handles callbacks from the plugin to the host over the * Handles callbacks from the plugin to the host over the
@@ -65,16 +76,16 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
*/ */
Vst3Logger logger; Vst3Logger logger;
public:
/** /**
* Our plugin factory. This will be set up directly after initialization. * Our plugin factory. All information about the plugin and its supported
* All information about the plugin and its supported classes are copied * classes are copied directly from the Windows VST3 plugin's factory on the
* directly from the Windows VST3 plugin's factory on the Wine side, and * Wine side, and we'll provide an implementation that can send control
* we'll provide an implementation that can send control messages to the * messages to the Wine plugin host. Even though we're passign plain
* Wine plugin host. * pointers around, we should pretend that they're wrapped in the VST3 SDK's
* reference counting p pointers so we should do the reference counting
* ourselves.
* *
* A pointer to this implementation will be returned to the host in * @related get_plugin_factory
* GetPluginFactory().
*/ */
std::unique_ptr<YaPluginFactory> plugin_factory; std::unique_ptr<YaPluginFactory> plugin_factory;
}; };
+1 -17
View File
@@ -69,21 +69,5 @@ SMTG_EXPORT_SYMBOL Steinberg::IPluginFactory* PLUGIN_API GetPluginFactory() {
// The host should have called `InitModule()` first // The host should have called `InitModule()` first
assert(bridge); assert(bridge);
// TODO: I think there is a flag that indicates that the class configuration return bridge->get_plugin_factory();
// may change, but I don't remember if it's at runtime or every time
// the module is loaded. If it's the former then this will take some
// special handling.
return bridge->plugin_factory.get();
// TODO: In the normal implementation of this function they manually call
// part of the reference counting mechanism. Is this something we also
// have to? And how does the `delete self` in the `removeRef()` play
// with our `std::unique_ptr` (aka, should we also use IPtr here)? The
// normal implementation looks like this:
// if (!gPluginFactory) {
// // Instantiate the factory
// } else {
// gPluginFactory->addRef();
// }
// return gPluginFactory;
} }