mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
Add a workaround for Bluecat Audio VST3 plugins
These plugins don't expose `IPluginBase` through the query interface, so we have to do this nasty coercion instead.
This commit is contained in:
@@ -10,6 +10,9 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Added a workaround for a bug present in every Bluecat Audio VST3 plugin where
|
||||||
|
those plugins don't expose the `IPluginBase` interface through their query
|
||||||
|
interface.
|
||||||
- Worked around a regression in Wine 6.5 that would prevent yabridge from
|
- Worked around a regression in Wine 6.5 that would prevent yabridge from
|
||||||
shutting down. With Wine 6.5 terminating a Wine process no longer terminates
|
shutting down. With Wine 6.5 terminating a Wine process no longer terminates
|
||||||
its threads, which would cause yabridge's plugin and host components to wait
|
its threads, which would cause yabridge's plugin and host components to wait
|
||||||
|
|||||||
@@ -35,6 +35,19 @@
|
|||||||
#define __IFileOperation_INTERFACE_DEFINED__
|
#define __IFileOperation_INTERFACE_DEFINED__
|
||||||
#include <public.sdk/source/vst/hosting/module_win32.cpp>
|
#include <public.sdk/source/vst/hosting/module_win32.cpp>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a workaround for Bluecat Audio plugins that don't expose their
|
||||||
|
* `IPluginBase` interface through the query interface. Even though every plugin
|
||||||
|
* object _must_ support `IPlugBase`, these plugins only expose those functions
|
||||||
|
* through `IComponent` (which derives from `IPluginBase`). So if we do
|
||||||
|
* encounter one of those plugins, then we'll just have to coerce an
|
||||||
|
* `IComponent` pointer into an `IPluginBase` smart pointer. This way we can
|
||||||
|
* keep the rest of yabridge's design in tact.
|
||||||
|
*/
|
||||||
|
Steinberg::FUnknownPtr<Steinberg::IPluginBase> hack_init_plugin_base(
|
||||||
|
Steinberg::IPtr<Steinberg::FUnknown> object,
|
||||||
|
Steinberg::IPtr<Steinberg::Vst::IComponent> component);
|
||||||
|
|
||||||
InstancePlugView::InstancePlugView() {}
|
InstancePlugView::InstancePlugView() {}
|
||||||
|
|
||||||
InstancePlugView::InstancePlugView(
|
InstancePlugView::InstancePlugView(
|
||||||
@@ -62,7 +75,7 @@ InstanceInterfaces::InstanceInterfaces(
|
|||||||
midi_mapping(object),
|
midi_mapping(object),
|
||||||
note_expression_controller(object),
|
note_expression_controller(object),
|
||||||
note_expression_physical_ui_mapping(object),
|
note_expression_physical_ui_mapping(object),
|
||||||
plugin_base(object),
|
plugin_base(hack_init_plugin_base(object, component)),
|
||||||
unit_data(object),
|
unit_data(object),
|
||||||
parameter_function_name(object),
|
parameter_function_name(object),
|
||||||
prefetchable_support(object),
|
prefetchable_support(object),
|
||||||
@@ -1297,3 +1310,42 @@ void Vst3Bridge::unregister_object_instance(size_t instance_id) {
|
|||||||
})
|
})
|
||||||
.wait();
|
.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Steinberg::FUnknownPtr<Steinberg::IPluginBase> hack_init_plugin_base(
|
||||||
|
Steinberg::IPtr<Steinberg::FUnknown> object,
|
||||||
|
Steinberg::IPtr<Steinberg::Vst::IComponent> component) {
|
||||||
|
// See the docstring for more information
|
||||||
|
Steinberg::FUnknownPtr<Steinberg::IPluginBase> plugin_base(object);
|
||||||
|
if (plugin_base) {
|
||||||
|
return plugin_base;
|
||||||
|
} else if (component) {
|
||||||
|
// HACK: So this should never be hit, because every object
|
||||||
|
// initializeable from a plugin's factory must inherit from
|
||||||
|
// `IPluginBase`. But, the Bluecat Audio plugins seem to have an
|
||||||
|
// implementation issue where they don't expose this interface. So
|
||||||
|
// instead we'll coerce from `IComponent` instead if this is the
|
||||||
|
// case, since `IComponent` derives from `IPluginBase`. Doing
|
||||||
|
// these manual pointer casts should be perfectly safe, even if
|
||||||
|
// they go against the very idea of having a query interface.
|
||||||
|
static_assert(sizeof(Steinberg::FUnknownPtr<Steinberg::IPluginBase>) ==
|
||||||
|
sizeof(Steinberg::IPtr<Steinberg::IPluginBase>));
|
||||||
|
|
||||||
|
std::cerr << "WARNING: This plugin doesn't expose the IPluginBase"
|
||||||
|
<< std::endl;
|
||||||
|
std::cerr << " interface and is broken. We will attempt an"
|
||||||
|
<< std::endl;
|
||||||
|
std::cerr << " unsafe coercion from IComponent instead."
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
Steinberg::IPtr<Steinberg::IPluginBase> coerced_plugin_base(
|
||||||
|
component.get());
|
||||||
|
|
||||||
|
return *static_cast<Steinberg::FUnknownPtr<Steinberg::IPluginBase>*>(
|
||||||
|
&coerced_plugin_base);
|
||||||
|
} else {
|
||||||
|
// This isn't really needed because the VST3 smart pointers can already
|
||||||
|
// deal with null pointers, but might as well drive the point of this
|
||||||
|
// hack home even further
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user