mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-06-25 05:17:25 +02:00
Move all casted VST3 plugin interfaces to struct
To make Waves plugins happy we're going to have to replace this after calling `IPluginBase::initialize()`.
This commit is contained in:
+218
-191
@@ -48,10 +48,9 @@ Vst3PlugViewInterfaces::Vst3PlugViewInterfaces(
|
||||
parameter_finder(plug_view),
|
||||
plug_view_content_scale_support(plug_view) {}
|
||||
|
||||
Vst3PluginInstance::Vst3PluginInstance(
|
||||
Vst3PluginInterfaces::Vst3PluginInterfaces(
|
||||
Steinberg::IPtr<Steinberg::FUnknown> object) noexcept
|
||||
: object(object),
|
||||
audio_presentation_latency(object),
|
||||
: audio_presentation_latency(object),
|
||||
audio_processor(object),
|
||||
automation_state(object),
|
||||
component(object),
|
||||
@@ -72,11 +71,16 @@ Vst3PluginInstance::Vst3PluginInstance(
|
||||
process_context_requirements(object),
|
||||
program_list_data(object),
|
||||
unit_info(object),
|
||||
xml_representation_controller(object),
|
||||
xml_representation_controller(object) {}
|
||||
|
||||
Vst3PluginInstance::Vst3PluginInstance(
|
||||
Steinberg::IPtr<Steinberg::FUnknown> object) noexcept
|
||||
: object(object),
|
||||
interfaces(object),
|
||||
// If the object doesn't support `IPlugBase` then the object cannot be
|
||||
// uninitialized (this isn't possible right now, but, who knows what the
|
||||
// future might bring)
|
||||
is_initialized(!plugin_base) {}
|
||||
is_initialized(!interfaces.plugin_base) {}
|
||||
|
||||
Vst3Bridge::Vst3Bridge(MainContext& main_context,
|
||||
std::string plugin_dll_path,
|
||||
@@ -221,6 +225,9 @@ void Vst3Bridge::run() {
|
||||
},
|
||||
[&](Vst3PluginProxy::SetState& request)
|
||||
-> Vst3PluginProxy::SetState::Response {
|
||||
const Vst3PluginInterfaces& interfaces =
|
||||
object_instances.at(request.instance_id).interfaces;
|
||||
|
||||
// We need to run `getState()` from the main thread, so we might
|
||||
// as well do the same thing with `setState()`. See below.
|
||||
// NOTE: We also try to handle mutual recursion here, in case
|
||||
@@ -229,17 +236,19 @@ void Vst3Bridge::run() {
|
||||
// This same function is defined in both `IComponent` and
|
||||
// `IEditController`, so the host is calling one or the
|
||||
// other
|
||||
if (object_instances.at(request.instance_id).component) {
|
||||
return object_instances.at(request.instance_id)
|
||||
.component->setState(&request.state);
|
||||
if (interfaces.component) {
|
||||
return interfaces.component->setState(&request.state);
|
||||
} else {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller->setState(&request.state);
|
||||
return interfaces.edit_controller->setState(
|
||||
&request.state);
|
||||
}
|
||||
});
|
||||
},
|
||||
[&](Vst3PluginProxy::GetState& request)
|
||||
-> Vst3PluginProxy::GetState::Response {
|
||||
const Vst3PluginInterfaces& interfaces =
|
||||
object_instances.at(request.instance_id).interfaces;
|
||||
|
||||
// NOTE: The VST3 version of Algonaut Atlas doesn't restore
|
||||
// state unless this function is run from the GUI thread
|
||||
// NOTE: This also requires mutual recursion because REAPER will
|
||||
@@ -249,13 +258,12 @@ void Vst3Bridge::run() {
|
||||
// This same function is defined in both `IComponent`
|
||||
// and `IEditController`, so the host is calling one or
|
||||
// the other
|
||||
if (object_instances.at(request.instance_id)
|
||||
.component) {
|
||||
return object_instances.at(request.instance_id)
|
||||
.component->getState(&request.state);
|
||||
if (interfaces.component) {
|
||||
return interfaces.component->getState(
|
||||
&request.state);
|
||||
} else {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller->getState(&request.state);
|
||||
return interfaces.edit_controller->getState(
|
||||
&request.state);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -267,7 +275,7 @@ void Vst3Bridge::run() {
|
||||
SetAudioPresentationLatencySamples::Response {
|
||||
return object_instances
|
||||
.at(request.instance_id)
|
||||
.audio_presentation_latency
|
||||
.interfaces.audio_presentation_latency
|
||||
->setAudioPresentationLatencySamples(
|
||||
request.dir, request.bus_index,
|
||||
request.latency_in_samples);
|
||||
@@ -275,10 +283,14 @@ void Vst3Bridge::run() {
|
||||
[&](YaAutomationState::SetAutomationState& request)
|
||||
-> YaAutomationState::SetAutomationState::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.automation_state->setAutomationState(request.state);
|
||||
.interfaces.automation_state->setAutomationState(
|
||||
request.state);
|
||||
},
|
||||
[&](YaConnectionPoint::Connect& request)
|
||||
-> YaConnectionPoint::Connect::Response {
|
||||
Vst3PluginInstance& this_instance =
|
||||
object_instances.at(request.instance_id);
|
||||
|
||||
// If the host directly connected the underlying objects then we
|
||||
// can directly connect them as well. Some hosts, like Ardour
|
||||
// and Mixbus, will place a proxy between the two plugins This
|
||||
@@ -292,49 +304,55 @@ void Vst3Bridge::run() {
|
||||
return std::visit(
|
||||
overload{
|
||||
[&](const native_size_t& other_instance_id) -> tresult {
|
||||
return object_instances.at(request.instance_id)
|
||||
.connection_point->connect(
|
||||
object_instances.at(other_instance_id)
|
||||
.connection_point);
|
||||
const Vst3PluginInstance& other_instance =
|
||||
object_instances.at(other_instance_id);
|
||||
|
||||
return this_instance.interfaces.connection_point
|
||||
->connect(
|
||||
other_instance.interfaces.connection_point);
|
||||
},
|
||||
[&](Vst3ConnectionPointProxy::ConstructArgs& args)
|
||||
-> tresult {
|
||||
object_instances.at(request.instance_id)
|
||||
.connection_point_proxy = Steinberg::owned(
|
||||
this_instance.connection_point_proxy =
|
||||
Steinberg::owned(
|
||||
new Vst3ConnectionPointProxyImpl(
|
||||
*this, std::move(args)));
|
||||
|
||||
return object_instances.at(request.instance_id)
|
||||
.connection_point->connect(
|
||||
object_instances.at(request.instance_id)
|
||||
.connection_point_proxy);
|
||||
return this_instance.interfaces.connection_point
|
||||
->connect(this_instance.connection_point_proxy);
|
||||
}},
|
||||
request.other);
|
||||
},
|
||||
[&](const YaConnectionPoint::Disconnect& request)
|
||||
-> YaConnectionPoint::Disconnect::Response {
|
||||
Vst3PluginInstance& this_instance =
|
||||
object_instances.at(request.instance_id);
|
||||
|
||||
// If the objects were connected directly we can also disconnect
|
||||
// them directly. Otherwise we'll disconnect them from our proxy
|
||||
// object and then destroy that proxy object.
|
||||
if (request.other_instance_id) {
|
||||
return object_instances.at(request.instance_id)
|
||||
.connection_point->disconnect(
|
||||
object_instances.at(*request.other_instance_id)
|
||||
.connection_point);
|
||||
const Vst3PluginInstance& other_instance =
|
||||
object_instances.at(*request.other_instance_id);
|
||||
|
||||
return this_instance.interfaces.connection_point
|
||||
->disconnect(
|
||||
other_instance.interfaces.connection_point);
|
||||
} else {
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.connection_point->disconnect(
|
||||
this_instance.interfaces.connection_point->disconnect(
|
||||
object_instances.at(*request.other_instance_id)
|
||||
.connection_point_proxy);
|
||||
object_instances.at(*request.other_instance_id)
|
||||
.connection_point_proxy.reset();
|
||||
this_instance.connection_point_proxy.reset();
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
[&](const YaConnectionPoint::Notify& request)
|
||||
-> YaConnectionPoint::Notify::Response {
|
||||
const Vst3PluginInstance& this_instance =
|
||||
object_instances.at(request.instance_id);
|
||||
|
||||
// NOTE: We're using a few tricks here to pass through a pointer
|
||||
// to the _original_ `IMessage` object passed to a
|
||||
// connection proxy. This is needed because some plugins
|
||||
@@ -351,8 +369,7 @@ void Vst3Bridge::run() {
|
||||
// solution for this (and bypassing Ardour's connection
|
||||
// proxies sort of goes against the idea behind yabridge)
|
||||
return do_mutual_recursion_on_gui_thread([&]() -> tresult {
|
||||
return object_instances.at(request.instance_id)
|
||||
.connection_point->notify(
|
||||
return this_instance.interfaces.connection_point->notify(
|
||||
request.message_ptr.get_original());
|
||||
});
|
||||
},
|
||||
@@ -367,18 +384,20 @@ void Vst3Bridge::run() {
|
||||
[&](YaEditController::SetComponentState& request)
|
||||
-> YaEditController::SetComponentState::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller->setComponentState(&request.state);
|
||||
.interfaces.edit_controller->setComponentState(
|
||||
&request.state);
|
||||
},
|
||||
[&](const YaEditController::GetParameterCount& request)
|
||||
-> YaEditController::GetParameterCount::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller->getParameterCount();
|
||||
.interfaces.edit_controller->getParameterCount();
|
||||
},
|
||||
[&](YaEditController::GetParameterInfo& request)
|
||||
-> YaEditController::GetParameterInfo::Response {
|
||||
Steinberg::Vst::ParameterInfo info{};
|
||||
const tresult result = object_instances.at(request.instance_id)
|
||||
.edit_controller->getParameterInfo(
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.interfaces.edit_controller->getParameterInfo(
|
||||
request.param_index, info);
|
||||
|
||||
return YaEditController::GetParameterInfoResponse{
|
||||
@@ -389,7 +408,7 @@ void Vst3Bridge::run() {
|
||||
Steinberg::Vst::String128 string{0};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.edit_controller->getParamStringByValue(
|
||||
.interfaces.edit_controller->getParamStringByValue(
|
||||
request.id, request.value_normalized, string);
|
||||
|
||||
return YaEditController::GetParamStringByValueResponse{
|
||||
@@ -401,7 +420,7 @@ void Vst3Bridge::run() {
|
||||
Steinberg::Vst::ParamValue value_normalized;
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.edit_controller->getParamValueByString(
|
||||
.interfaces.edit_controller->getParamValueByString(
|
||||
request.id,
|
||||
const_cast<Steinberg::Vst::TChar*>(
|
||||
u16string_to_tchar_pointer(request.string)),
|
||||
@@ -413,19 +432,19 @@ void Vst3Bridge::run() {
|
||||
[&](const YaEditController::NormalizedParamToPlain& request)
|
||||
-> YaEditController::NormalizedParamToPlain::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller->normalizedParamToPlain(
|
||||
.interfaces.edit_controller->normalizedParamToPlain(
|
||||
request.id, request.value_normalized);
|
||||
},
|
||||
[&](const YaEditController::PlainParamToNormalized& request)
|
||||
-> YaEditController::PlainParamToNormalized::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller->plainParamToNormalized(
|
||||
.interfaces.edit_controller->plainParamToNormalized(
|
||||
request.id, request.plain_value);
|
||||
},
|
||||
[&](const YaEditController::GetParamNormalized& request)
|
||||
-> YaEditController::GetParamNormalized::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller->getParamNormalized(request.id);
|
||||
.interfaces.edit_controller->getParamNormalized(request.id);
|
||||
},
|
||||
[&](const YaEditController::SetParamNormalized& request)
|
||||
-> YaEditController::SetParamNormalized::Response {
|
||||
@@ -436,48 +455,48 @@ void Vst3Bridge::run() {
|
||||
// announced.
|
||||
return do_mutual_recursion_on_off_thread([&]() -> tresult {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller->setParamNormalized(request.id,
|
||||
request.value);
|
||||
.interfaces.edit_controller->setParamNormalized(
|
||||
request.id, request.value);
|
||||
});
|
||||
},
|
||||
[&](YaEditController::SetComponentHandler& request)
|
||||
-> YaEditController::SetComponentHandler::Response {
|
||||
Vst3PluginInstance& instance =
|
||||
object_instances.at(request.instance_id);
|
||||
|
||||
// If the host passed a valid component handler, then we'll
|
||||
// create a proxy object for the component handler and pass that
|
||||
// to the initialize function. The lifetime of this object is
|
||||
// tied to that of the actual plugin object we're proxying for.
|
||||
// Otherwise we'll also pass a null pointer. This often happens
|
||||
// just before the host terminates the plugin.
|
||||
object_instances.at(request.instance_id)
|
||||
.component_handler_proxy =
|
||||
instance.component_handler_proxy =
|
||||
request.component_handler_proxy_args
|
||||
? Steinberg::owned(new Vst3ComponentHandlerProxyImpl(
|
||||
*this,
|
||||
std::move(*request.component_handler_proxy_args)))
|
||||
: nullptr;
|
||||
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller->setComponentHandler(
|
||||
object_instances.at(request.instance_id)
|
||||
.component_handler_proxy);
|
||||
return instance.interfaces.edit_controller->setComponentHandler(
|
||||
instance.component_handler_proxy);
|
||||
},
|
||||
[&](const YaEditController::CreateView& request)
|
||||
-> YaEditController::CreateView::Response {
|
||||
Vst3PluginInstance& instance =
|
||||
object_instances.at(request.instance_id);
|
||||
|
||||
// Instantiate the object from the GUI thread
|
||||
main_context
|
||||
.run_in_context([&]() -> void {
|
||||
Steinberg::IPtr<Steinberg::IPlugView> plug_view(
|
||||
Steinberg::owned(
|
||||
object_instances.at(request.instance_id)
|
||||
.edit_controller->createView(
|
||||
instance.interfaces.edit_controller->createView(
|
||||
request.name.c_str())));
|
||||
|
||||
if (plug_view) {
|
||||
object_instances.at(request.instance_id)
|
||||
.plug_view_instance.emplace(plug_view);
|
||||
instance.plug_view_instance.emplace(plug_view);
|
||||
} else {
|
||||
object_instances.at(request.instance_id)
|
||||
.plug_view_instance.reset()
|
||||
instance.plug_view_instance.reset();
|
||||
}
|
||||
})
|
||||
.wait();
|
||||
@@ -486,40 +505,39 @@ void Vst3Bridge::run() {
|
||||
// `IPlugView` object
|
||||
return YaEditController::CreateViewResponse{
|
||||
.plug_view_args =
|
||||
(object_instances.at(request.instance_id)
|
||||
.plug_view_instance
|
||||
(instance.plug_view_instance
|
||||
? std::make_optional<
|
||||
Vst3PlugViewProxy::ConstructArgs>(
|
||||
object_instances.at(request.instance_id)
|
||||
.plug_view_instance->plug_view,
|
||||
instance.plug_view_instance->plug_view,
|
||||
request.instance_id)
|
||||
: std::nullopt)};
|
||||
},
|
||||
[&](const YaEditController2::SetKnobMode& request)
|
||||
-> YaEditController2::SetKnobMode::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller_2->setKnobMode(request.mode);
|
||||
.interfaces.edit_controller_2->setKnobMode(request.mode);
|
||||
},
|
||||
[&](const YaEditController2::OpenHelp& request)
|
||||
-> YaEditController2::OpenHelp::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller_2->openHelp(request.only_check);
|
||||
.interfaces.edit_controller_2->openHelp(request.only_check);
|
||||
},
|
||||
[&](const YaEditController2::OpenAboutBox& request)
|
||||
-> YaEditController2::OpenAboutBox::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller_2->openAboutBox(request.only_check);
|
||||
.interfaces.edit_controller_2->openAboutBox(
|
||||
request.only_check);
|
||||
},
|
||||
[&](const YaEditControllerHostEditing::BeginEditFromHost& request)
|
||||
-> YaEditControllerHostEditing::BeginEditFromHost::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller_host_editing->beginEditFromHost(
|
||||
.interfaces.edit_controller_host_editing->beginEditFromHost(
|
||||
request.param_id);
|
||||
},
|
||||
[&](const YaEditControllerHostEditing::EndEditFromHost& request)
|
||||
-> YaEditControllerHostEditing::EndEditFromHost::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.edit_controller_host_editing->endEditFromHost(
|
||||
.interfaces.edit_controller_host_editing->endEditFromHost(
|
||||
request.param_id);
|
||||
},
|
||||
[&](YaInfoListener::SetChannelContextInfos& request)
|
||||
@@ -530,7 +548,7 @@ void Vst3Bridge::run() {
|
||||
return main_context
|
||||
.run_in_context([&]() -> tresult {
|
||||
return object_instances.at(request.instance_id)
|
||||
.info_listener->setChannelContextInfos(
|
||||
.interfaces.info_listener->setChannelContextInfos(
|
||||
&request.list);
|
||||
})
|
||||
.get();
|
||||
@@ -538,15 +556,15 @@ void Vst3Bridge::run() {
|
||||
[&](const YaKeyswitchController::GetKeyswitchCount& request)
|
||||
-> YaKeyswitchController::GetKeyswitchCount::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.keyswitch_controller->getKeyswitchCount(request.bus_index,
|
||||
request.channel);
|
||||
.interfaces.keyswitch_controller->getKeyswitchCount(
|
||||
request.bus_index, request.channel);
|
||||
},
|
||||
[&](const YaKeyswitchController::GetKeyswitchInfo& request)
|
||||
-> YaKeyswitchController::GetKeyswitchInfo::Response {
|
||||
Steinberg::Vst::KeyswitchInfo info{};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.keyswitch_controller->getKeyswitchInfo(
|
||||
.interfaces.keyswitch_controller->getKeyswitchInfo(
|
||||
request.bus_index, request.channel,
|
||||
request.key_switch_index, info);
|
||||
|
||||
@@ -556,7 +574,7 @@ void Vst3Bridge::run() {
|
||||
[&](const YaMidiLearn::OnLiveMIDIControllerInput& request)
|
||||
-> YaMidiLearn::OnLiveMIDIControllerInput::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.midi_learn->onLiveMIDIControllerInput(
|
||||
.interfaces.midi_learn->onLiveMIDIControllerInput(
|
||||
request.bus_index, request.channel, request.midi_cc);
|
||||
},
|
||||
[&](const YaMidiMapping::GetMidiControllerAssignment& request)
|
||||
@@ -564,7 +582,7 @@ void Vst3Bridge::run() {
|
||||
Steinberg::Vst::ParamID id;
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.midi_mapping->getMidiControllerAssignment(
|
||||
.interfaces.midi_mapping->getMidiControllerAssignment(
|
||||
request.bus_index, request.channel,
|
||||
request.midi_controller_number, id);
|
||||
|
||||
@@ -572,12 +590,14 @@ void Vst3Bridge::run() {
|
||||
.result = result, .id = id};
|
||||
},
|
||||
[&](const YaNoteExpressionController::GetNoteExpressionCount&
|
||||
request)
|
||||
-> YaNoteExpressionController::GetNoteExpressionCount::
|
||||
Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.note_expression_controller->getNoteExpressionCount(
|
||||
request.bus_index, request.channel);
|
||||
request) -> YaNoteExpressionController::
|
||||
GetNoteExpressionCount::Response {
|
||||
return object_instances
|
||||
.at(request.instance_id)
|
||||
.interfaces.note_expression_controller
|
||||
->getNoteExpressionCount(
|
||||
request.bus_index,
|
||||
request.channel);
|
||||
},
|
||||
[&](const YaNoteExpressionController::GetNoteExpressionInfo&
|
||||
request)
|
||||
@@ -585,7 +605,8 @@ void Vst3Bridge::run() {
|
||||
Steinberg::Vst::NoteExpressionTypeInfo info{};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.note_expression_controller->getNoteExpressionInfo(
|
||||
.interfaces.note_expression_controller
|
||||
->getNoteExpressionInfo(
|
||||
request.bus_index, request.channel,
|
||||
request.note_expression_index, info);
|
||||
|
||||
@@ -600,7 +621,7 @@ void Vst3Bridge::run() {
|
||||
Steinberg::Vst::String128 string{0};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.note_expression_controller
|
||||
.interfaces.note_expression_controller
|
||||
->getNoteExpressionStringByValue(
|
||||
request.bus_index, request.channel,
|
||||
request.id, request.value_normalized,
|
||||
@@ -618,7 +639,7 @@ void Vst3Bridge::run() {
|
||||
Steinberg::Vst::NoteExpressionValue value_normalized;
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.note_expression_controller
|
||||
.interfaces.note_expression_controller
|
||||
->getNoteExpressionValueByString(
|
||||
request.bus_index, request.channel,
|
||||
request.id,
|
||||
@@ -638,7 +659,7 @@ void Vst3Bridge::run() {
|
||||
request.list.get();
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.note_expression_physical_ui_mapping
|
||||
.interfaces.note_expression_physical_ui_mapping
|
||||
->getPhysicalUIMapping(request.bus_index,
|
||||
request.channel,
|
||||
reconstructed_list);
|
||||
@@ -660,22 +681,20 @@ void Vst3Bridge::run() {
|
||||
.result = result, .result_tag = result_tag};
|
||||
},
|
||||
[&](const YaParameterFunctionName::GetParameterIDFromFunctionName&
|
||||
request) -> YaParameterFunctionName::
|
||||
GetParameterIDFromFunctionName::Response {
|
||||
request)
|
||||
-> YaParameterFunctionName::GetParameterIDFromFunctionName::
|
||||
Response {
|
||||
Steinberg::Vst::ParamID param_id;
|
||||
const tresult result =
|
||||
object_instances
|
||||
.at(request.instance_id)
|
||||
.parameter_function_name
|
||||
object_instances.at(request.instance_id)
|
||||
.interfaces.parameter_function_name
|
||||
->getParameterIDFromFunctionName(
|
||||
request.unit_id,
|
||||
request.function_name.c_str(),
|
||||
param_id);
|
||||
request.function_name.c_str(), param_id);
|
||||
|
||||
return YaParameterFunctionName::
|
||||
GetParameterIDFromFunctionNameResponse{
|
||||
.result = result,
|
||||
.param_id = param_id};
|
||||
.result = result, .param_id = param_id};
|
||||
},
|
||||
[&](const YaPlugView::IsPlatformTypeSupported& request)
|
||||
-> YaPlugView::IsPlatformTypeSupported::Response {
|
||||
@@ -889,11 +908,14 @@ void Vst3Bridge::run() {
|
||||
},
|
||||
[&](YaPluginBase::Initialize& request)
|
||||
-> YaPluginBase::Initialize::Response {
|
||||
Vst3PluginInstance& instance =
|
||||
object_instances.at(request.instance_id);
|
||||
|
||||
// We'll create a proxy object for the host context passed by
|
||||
// the host and pass that to the initialize function. The
|
||||
// lifetime of this object is tied to that of the actual plugin
|
||||
// object we're proxying for.
|
||||
object_instances.at(request.instance_id).host_context_proxy =
|
||||
instance.host_context_proxy =
|
||||
Steinberg::owned(new Vst3HostContextProxyImpl(
|
||||
*this, std::move(request.host_context_args)));
|
||||
|
||||
@@ -907,18 +929,15 @@ void Vst3Bridge::run() {
|
||||
set_realtime_priority(true);
|
||||
// This static cast is required to upcast to `FUnknown*`
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.plugin_base->initialize(
|
||||
instance.interfaces.plugin_base->initialize(
|
||||
static_cast<YaHostApplication*>(
|
||||
object_instances.at(request.instance_id)
|
||||
.host_context_proxy));
|
||||
instance.host_context_proxy));
|
||||
set_realtime_priority(false);
|
||||
|
||||
// The Win32 message loop will not be run up to this
|
||||
// point to prevent plugins with partially initialized
|
||||
// states from misbehaving
|
||||
object_instances.at(request.instance_id)
|
||||
.is_initialized = true;
|
||||
instance.is_initialized = true;
|
||||
|
||||
return result;
|
||||
})
|
||||
@@ -929,28 +948,29 @@ void Vst3Bridge::run() {
|
||||
return main_context
|
||||
.run_in_context([&]() -> tresult {
|
||||
return object_instances.at(request.instance_id)
|
||||
.plugin_base->terminate();
|
||||
.interfaces.plugin_base->terminate();
|
||||
})
|
||||
.get();
|
||||
},
|
||||
[&](const YaProgramListData::ProgramDataSupported& request)
|
||||
-> YaProgramListData::ProgramDataSupported::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.program_list_data->programDataSupported(request.list_id);
|
||||
.interfaces.program_list_data->programDataSupported(
|
||||
request.list_id);
|
||||
},
|
||||
[&](const YaProcessContextRequirements::
|
||||
GetProcessContextRequirements& request)
|
||||
-> YaProcessContextRequirements::GetProcessContextRequirements::
|
||||
Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.process_context_requirements
|
||||
.interfaces.process_context_requirements
|
||||
->getProcessContextRequirements();
|
||||
},
|
||||
[&](YaProgramListData::GetProgramData& request)
|
||||
-> YaProgramListData::GetProgramData::Response {
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.program_list_data->getProgramData(
|
||||
.interfaces.program_list_data->getProgramData(
|
||||
request.list_id, request.program_index,
|
||||
&request.data);
|
||||
|
||||
@@ -960,19 +980,19 @@ void Vst3Bridge::run() {
|
||||
[&](YaProgramListData::SetProgramData& request)
|
||||
-> YaProgramListData::SetProgramData::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.program_list_data->setProgramData(
|
||||
.interfaces.program_list_data->setProgramData(
|
||||
request.list_id, request.program_index, &request.data);
|
||||
},
|
||||
[&](const YaUnitData::UnitDataSupported& request)
|
||||
-> YaUnitData::UnitDataSupported::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.unit_data->unitDataSupported(request.unit_id);
|
||||
.interfaces.unit_data->unitDataSupported(request.unit_id);
|
||||
},
|
||||
[&](YaUnitData::GetUnitData& request)
|
||||
-> YaUnitData::GetUnitData::Response {
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.unit_data->getUnitData(request.unit_id, &request.data);
|
||||
const tresult result = object_instances.at(request.instance_id)
|
||||
.interfaces.unit_data->getUnitData(
|
||||
request.unit_id, &request.data);
|
||||
|
||||
return YaUnitData::GetUnitDataResponse{
|
||||
.result = result, .data = std::move(request.data)};
|
||||
@@ -980,7 +1000,8 @@ void Vst3Bridge::run() {
|
||||
[&](YaUnitData::SetUnitData& request)
|
||||
-> YaUnitData::SetUnitData::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.unit_data->setUnitData(request.unit_id, &request.data);
|
||||
.interfaces.unit_data->setUnitData(request.unit_id,
|
||||
&request.data);
|
||||
},
|
||||
[&](YaPluginFactory3::SetHostContext& request)
|
||||
-> YaPluginFactory3::SetHostContext::Response {
|
||||
@@ -1000,14 +1021,14 @@ void Vst3Bridge::run() {
|
||||
[&](const YaUnitInfo::GetUnitCount& request)
|
||||
-> YaUnitInfo::GetUnitCount::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.unit_info->getUnitCount();
|
||||
.interfaces.unit_info->getUnitCount();
|
||||
},
|
||||
[&](const YaUnitInfo::GetUnitInfo& request)
|
||||
-> YaUnitInfo::GetUnitInfo::Response {
|
||||
Steinberg::Vst::UnitInfo info{};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.unit_info->getUnitInfo(request.unit_index, info);
|
||||
const tresult result = object_instances.at(request.instance_id)
|
||||
.interfaces.unit_info->getUnitInfo(
|
||||
request.unit_index, info);
|
||||
|
||||
return YaUnitInfo::GetUnitInfoResponse{.result = result,
|
||||
.info = std::move(info)};
|
||||
@@ -1015,13 +1036,14 @@ void Vst3Bridge::run() {
|
||||
[&](const YaUnitInfo::GetProgramListCount& request)
|
||||
-> YaUnitInfo::GetProgramListCount::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.unit_info->getProgramListCount();
|
||||
.interfaces.unit_info->getProgramListCount();
|
||||
},
|
||||
[&](const YaUnitInfo::GetProgramListInfo& request)
|
||||
-> YaUnitInfo::GetProgramListInfo::Response {
|
||||
Steinberg::Vst::ProgramListInfo info{};
|
||||
const tresult result = object_instances.at(request.instance_id)
|
||||
.unit_info->getProgramListInfo(
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.interfaces.unit_info->getProgramListInfo(
|
||||
request.list_index, info);
|
||||
|
||||
return YaUnitInfo::GetProgramListInfoResponse{
|
||||
@@ -1037,7 +1059,7 @@ void Vst3Bridge::run() {
|
||||
const tresult result =
|
||||
do_mutual_recursion_on_off_thread([&]() -> tresult {
|
||||
return object_instances.at(request.instance_id)
|
||||
.unit_info->getProgramName(
|
||||
.interfaces.unit_info->getProgramName(
|
||||
request.list_id, request.program_index, name);
|
||||
});
|
||||
|
||||
@@ -1049,7 +1071,7 @@ void Vst3Bridge::run() {
|
||||
Steinberg::Vst::String128 attribute_value{0};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.unit_info->getProgramInfo(
|
||||
.interfaces.unit_info->getProgramInfo(
|
||||
request.list_id, request.program_index,
|
||||
request.attribute_id.c_str(), attribute_value);
|
||||
|
||||
@@ -1061,15 +1083,15 @@ void Vst3Bridge::run() {
|
||||
[&](const YaUnitInfo::HasProgramPitchNames& request)
|
||||
-> YaUnitInfo::HasProgramPitchNames::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.unit_info->hasProgramPitchNames(request.list_id,
|
||||
request.program_index);
|
||||
.interfaces.unit_info->hasProgramPitchNames(
|
||||
request.list_id, request.program_index);
|
||||
},
|
||||
[&](const YaUnitInfo::GetProgramPitchName& request)
|
||||
-> YaUnitInfo::GetProgramPitchName::Response {
|
||||
Steinberg::Vst::String128 name{0};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.unit_info->getProgramPitchName(
|
||||
.interfaces.unit_info->getProgramPitchName(
|
||||
request.list_id, request.program_index,
|
||||
request.midi_pitch, name);
|
||||
|
||||
@@ -1079,20 +1101,20 @@ void Vst3Bridge::run() {
|
||||
[&](const YaUnitInfo::GetSelectedUnit& request)
|
||||
-> YaUnitInfo::GetSelectedUnit::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.unit_info->getSelectedUnit();
|
||||
.interfaces.unit_info->getSelectedUnit();
|
||||
},
|
||||
[&](const YaUnitInfo::SelectUnit& request)
|
||||
-> YaUnitInfo::SelectUnit::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.unit_info->selectUnit(request.unit_id);
|
||||
.interfaces.unit_info->selectUnit(request.unit_id);
|
||||
},
|
||||
[&](const YaUnitInfo::GetUnitByBus& request)
|
||||
-> YaUnitInfo::GetUnitByBus::Response {
|
||||
Steinberg::Vst::UnitID unit_id;
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.unit_info->getUnitByBus(request.type, request.dir,
|
||||
request.bus_index,
|
||||
.interfaces.unit_info->getUnitByBus(
|
||||
request.type, request.dir, request.bus_index,
|
||||
request.channel, unit_id);
|
||||
|
||||
return YaUnitInfo::GetUnitByBusResponse{.result = result,
|
||||
@@ -1101,25 +1123,24 @@ void Vst3Bridge::run() {
|
||||
[&](YaUnitInfo::SetUnitProgramData& request)
|
||||
-> YaUnitInfo::SetUnitProgramData::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.unit_info->setUnitProgramData(request.list_or_unit_id,
|
||||
request.program_index,
|
||||
.interfaces.unit_info->setUnitProgramData(
|
||||
request.list_or_unit_id, request.program_index,
|
||||
&request.data);
|
||||
},
|
||||
[&](YaXmlRepresentationController::GetXmlRepresentationStream&
|
||||
request) -> YaXmlRepresentationController::
|
||||
GetXmlRepresentationStream::Response {
|
||||
request)
|
||||
-> YaXmlRepresentationController::GetXmlRepresentationStream::
|
||||
Response {
|
||||
const tresult result =
|
||||
object_instances
|
||||
.at(request.instance_id)
|
||||
.xml_representation_controller
|
||||
->getXmlRepresentationStream(
|
||||
request.info, &request.stream);
|
||||
object_instances.at(request.instance_id)
|
||||
.interfaces.xml_representation_controller
|
||||
->getXmlRepresentationStream(request.info,
|
||||
&request.stream);
|
||||
|
||||
return YaXmlRepresentationController::
|
||||
GetXmlRepresentationStreamResponse{
|
||||
.result = result,
|
||||
.stream =
|
||||
std::move(request.stream)};
|
||||
.stream = std::move(request.stream)};
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1164,10 +1185,12 @@ size_t Vst3Bridge::generate_instance_id() noexcept {
|
||||
AudioShmBuffer::Config Vst3Bridge::setup_shared_audio_buffers(
|
||||
size_t instance_id,
|
||||
const Steinberg::Vst::ProcessSetup& setup) {
|
||||
auto& instance = object_instances.at(instance_id);
|
||||
|
||||
const Steinberg::IPtr<Steinberg::Vst::IComponent> component =
|
||||
object_instances.at(instance_id).component;
|
||||
instance.interfaces.component;
|
||||
const Steinberg::IPtr<Steinberg::Vst::IAudioProcessor> audio_processor =
|
||||
object_instances.at(instance_id).audio_processor;
|
||||
instance.interfaces.audio_processor;
|
||||
assert(component && audio_processor);
|
||||
|
||||
// We'll query the plugin for its audio bus layouts, and then create
|
||||
@@ -1225,13 +1248,10 @@ AudioShmBuffer::Config Vst3Bridge::setup_shared_audio_buffers(
|
||||
.size = buffer_size,
|
||||
.input_offsets = std::move(input_bus_offsets),
|
||||
.output_offsets = std::move(output_bus_offsets)};
|
||||
|
||||
std::optional<AudioShmBuffer>& process_buffers =
|
||||
object_instances.at(instance_id).process_buffers;
|
||||
if (!process_buffers) {
|
||||
process_buffers.emplace(buffer_config);
|
||||
if (!instance.process_buffers) {
|
||||
instance.process_buffers.emplace(buffer_config);
|
||||
} else {
|
||||
process_buffers->resize(buffer_config);
|
||||
instance.process_buffers->resize(buffer_config);
|
||||
}
|
||||
|
||||
// After setting up the shared memory buffer, we need to create a vector of
|
||||
@@ -1258,24 +1278,27 @@ AudioShmBuffer::Config Vst3Bridge::setup_shared_audio_buffers(
|
||||
};
|
||||
|
||||
set_bus_pointers(
|
||||
object_instances.at(instance_id).process_buffers_input_pointers,
|
||||
process_buffers->config.input_offsets,
|
||||
instance.process_buffers_input_pointers,
|
||||
instance.process_buffers->config.input_offsets,
|
||||
[&](uint32_t bus, uint32_t channel) -> void* {
|
||||
if (double_precision) {
|
||||
return process_buffers->input_channel_ptr<double>(bus, channel);
|
||||
return instance.process_buffers->input_channel_ptr<double>(
|
||||
bus, channel);
|
||||
} else {
|
||||
return process_buffers->input_channel_ptr<float>(bus, channel);
|
||||
return instance.process_buffers->input_channel_ptr<float>(
|
||||
bus, channel);
|
||||
}
|
||||
});
|
||||
set_bus_pointers(
|
||||
object_instances.at(instance_id).process_buffers_output_pointers,
|
||||
process_buffers->config.output_offsets,
|
||||
instance.process_buffers_output_pointers,
|
||||
instance.process_buffers->config.output_offsets,
|
||||
[&](uint32_t bus, uint32_t channel) -> void* {
|
||||
if (double_precision) {
|
||||
return process_buffers->output_channel_ptr<double>(bus,
|
||||
channel);
|
||||
return instance.process_buffers->output_channel_ptr<double>(
|
||||
bus, channel);
|
||||
} else {
|
||||
return process_buffers->output_channel_ptr<float>(bus, channel);
|
||||
return instance.process_buffers->output_channel_ptr<float>(
|
||||
bus, channel);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1292,8 +1315,8 @@ size_t Vst3Bridge::register_object_instance(
|
||||
// If the object supports `IComponent` or `IAudioProcessor`,
|
||||
// then we'll set up a dedicated thread for function calls for
|
||||
// those interfaces.
|
||||
if (object_instances.at(instance_id).audio_processor ||
|
||||
object_instances.at(instance_id).component) {
|
||||
if (object_instances.at(instance_id).interfaces.audio_processor ||
|
||||
object_instances.at(instance_id).interfaces.component) {
|
||||
std::promise<void> socket_listening_latch;
|
||||
|
||||
object_instances.at(instance_id)
|
||||
@@ -1320,7 +1343,7 @@ size_t Vst3Bridge::register_object_instance(
|
||||
0b00000000;
|
||||
|
||||
return object_instances.at(request.instance_id)
|
||||
.audio_processor->setBusArrangements(
|
||||
.interfaces.audio_processor->setBusArrangements(
|
||||
request.num_ins > 0 ? request.inputs.data()
|
||||
: &empty_arrangement,
|
||||
request.num_ins,
|
||||
@@ -1333,7 +1356,7 @@ size_t Vst3Bridge::register_object_instance(
|
||||
Steinberg::Vst::SpeakerArrangement arr{};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.audio_processor->getBusArrangement(
|
||||
.interfaces.audio_processor->getBusArrangement(
|
||||
request.dir, request.index, arr);
|
||||
|
||||
return YaAudioProcessor::GetBusArrangementResponse{
|
||||
@@ -1342,19 +1365,19 @@ size_t Vst3Bridge::register_object_instance(
|
||||
[&](const YaAudioProcessor::CanProcessSampleSize& request)
|
||||
-> YaAudioProcessor::CanProcessSampleSize::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.audio_processor->canProcessSampleSize(
|
||||
.interfaces.audio_processor->canProcessSampleSize(
|
||||
request.symbolic_sample_size);
|
||||
},
|
||||
[&](const YaAudioProcessor::GetLatencySamples& request)
|
||||
-> YaAudioProcessor::GetLatencySamples::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.audio_processor->getLatencySamples();
|
||||
.interfaces.audio_processor->getLatencySamples();
|
||||
},
|
||||
[&](YaAudioProcessor::SetupProcessing& request)
|
||||
-> YaAudioProcessor::SetupProcessing::Response {
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.audio_processor->setupProcessing(
|
||||
.interfaces.audio_processor->setupProcessing(
|
||||
request.setup);
|
||||
|
||||
// We'll set up the shared audio buffers on the Wine
|
||||
@@ -1374,7 +1397,8 @@ size_t Vst3Bridge::register_object_instance(
|
||||
[&](const YaAudioProcessor::SetProcessing& request)
|
||||
-> YaAudioProcessor::SetProcessing::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.audio_processor->setProcessing(request.state);
|
||||
.interfaces.audio_processor->setProcessing(
|
||||
request.state);
|
||||
},
|
||||
[&](MessageReference<YaAudioProcessor::Process>&
|
||||
request_ref)
|
||||
@@ -1388,12 +1412,6 @@ size_t Vst3Bridge::register_object_instance(
|
||||
// `bitsery::ext::MessageReference`)
|
||||
YaAudioProcessor::Process& request = request_ref.get();
|
||||
|
||||
// Most plugins will already enable FTZ, but there are a
|
||||
// handful of plugins that don't that suffer from
|
||||
// extreme DSP load increases when they start producing
|
||||
// denormals
|
||||
ScopedFlushToZero ftz_guard;
|
||||
|
||||
// As suggested by Jack Winter, we'll synchronize this
|
||||
// thread's audio processing priority with that of the
|
||||
// host's audio thread every once in a while
|
||||
@@ -1402,17 +1420,23 @@ size_t Vst3Bridge::register_object_instance(
|
||||
true, *request.new_realtime_priority);
|
||||
}
|
||||
|
||||
Vst3PluginInstance& instance =
|
||||
object_instances.at(request.instance_id);
|
||||
|
||||
// Most plugins will already enable FTZ, but there are a
|
||||
// handful of plugins that don't that suffer from
|
||||
// extreme DSP load increases when they start producing
|
||||
// denormals
|
||||
ScopedFlushToZero ftz_guard;
|
||||
|
||||
// The actual audio is stored in the shared memory
|
||||
// buffers, so the reconstruction function will need to
|
||||
// know where it should point the `AudioBusBuffers` to
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.audio_processor->process(
|
||||
instance.interfaces.audio_processor->process(
|
||||
request.data.reconstruct(
|
||||
object_instances.at(request.instance_id)
|
||||
.process_buffers_input_pointers,
|
||||
object_instances.at(request.instance_id)
|
||||
.process_buffers_output_pointers));
|
||||
instance.process_buffers_input_pointers,
|
||||
instance.process_buffers_output_pointers));
|
||||
|
||||
return YaAudioProcessor::ProcessResponse{
|
||||
.result = result,
|
||||
@@ -1421,14 +1445,15 @@ size_t Vst3Bridge::register_object_instance(
|
||||
[&](const YaAudioProcessor::GetTailSamples& request)
|
||||
-> YaAudioProcessor::GetTailSamples::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.audio_processor->getTailSamples();
|
||||
.interfaces.audio_processor->getTailSamples();
|
||||
},
|
||||
[&](const YaComponent::GetControllerClassId& request)
|
||||
-> YaComponent::GetControllerClassId::Response {
|
||||
Steinberg::TUID cid{0};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.component->getControllerClassId(cid);
|
||||
.interfaces.component->getControllerClassId(
|
||||
cid);
|
||||
|
||||
return YaComponent::GetControllerClassIdResponse{
|
||||
.result = result, .editor_cid = cid};
|
||||
@@ -1436,21 +1461,22 @@ size_t Vst3Bridge::register_object_instance(
|
||||
[&](const YaComponent::SetIoMode& request)
|
||||
-> YaComponent::SetIoMode::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.component->setIoMode(request.mode);
|
||||
.interfaces.component->setIoMode(request.mode);
|
||||
},
|
||||
[&](const YaComponent::GetBusCount& request)
|
||||
-> YaComponent::GetBusCount::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.component->getBusCount(request.type, request.dir);
|
||||
.interfaces.component->getBusCount(request.type,
|
||||
request.dir);
|
||||
},
|
||||
[&](YaComponent::GetBusInfo& request)
|
||||
-> YaComponent::GetBusInfo::Response {
|
||||
Steinberg::Vst::BusInfo bus{};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.component->getBusInfo(request.type,
|
||||
request.dir,
|
||||
request.index, bus);
|
||||
.interfaces.component->getBusInfo(
|
||||
request.type, request.dir, request.index,
|
||||
bus);
|
||||
|
||||
return YaComponent::GetBusInfoResponse{
|
||||
.result = result, .bus = std::move(bus)};
|
||||
@@ -1460,8 +1486,8 @@ size_t Vst3Bridge::register_object_instance(
|
||||
Steinberg::Vst::RoutingInfo out_info{};
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.component->getRoutingInfo(request.in_info,
|
||||
out_info);
|
||||
.interfaces.component->getRoutingInfo(
|
||||
request.in_info, out_info);
|
||||
|
||||
return YaComponent::GetRoutingInfoResponse{
|
||||
.result = result, .out_info = std::move(out_info)};
|
||||
@@ -1469,8 +1495,8 @@ size_t Vst3Bridge::register_object_instance(
|
||||
[&](const YaComponent::ActivateBus& request)
|
||||
-> YaComponent::ActivateBus::Response {
|
||||
return object_instances.at(request.instance_id)
|
||||
.component->activateBus(request.type, request.dir,
|
||||
request.index,
|
||||
.interfaces.component->activateBus(
|
||||
request.type, request.dir, request.index,
|
||||
request.state);
|
||||
},
|
||||
[&](const YaComponent::SetActive& request)
|
||||
@@ -1486,7 +1512,8 @@ size_t Vst3Bridge::register_object_instance(
|
||||
return do_mutual_recursion_on_off_thread(
|
||||
[&]() -> tresult {
|
||||
return object_instances.at(request.instance_id)
|
||||
.component->setActive(request.state);
|
||||
.interfaces.component->setActive(
|
||||
request.state);
|
||||
});
|
||||
},
|
||||
[&](const YaPrefetchableSupport::GetPrefetchableSupport&
|
||||
@@ -1497,7 +1524,7 @@ size_t Vst3Bridge::register_object_instance(
|
||||
prefetchable;
|
||||
const tresult result =
|
||||
object_instances.at(request.instance_id)
|
||||
.prefetchable_support
|
||||
.interfaces.prefetchable_support
|
||||
->getPrefetchableSupport(prefetchable);
|
||||
|
||||
return YaPrefetchableSupport::
|
||||
@@ -1520,8 +1547,8 @@ size_t Vst3Bridge::register_object_instance(
|
||||
void Vst3Bridge::unregister_object_instance(size_t instance_id) {
|
||||
// Tear the dedicated audio processing socket down again if we
|
||||
// created one while handling `Vst3PluginProxy::Construct`
|
||||
if (object_instances.at(instance_id).audio_processor ||
|
||||
object_instances.at(instance_id).component) {
|
||||
if (object_instances.at(instance_id).interfaces.audio_processor ||
|
||||
object_instances.at(instance_id).interfaces.component) {
|
||||
sockets.remove_audio_processor(instance_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,12 +53,54 @@ struct Vst3PlugViewInterfaces {
|
||||
};
|
||||
|
||||
/**
|
||||
* A holder for plugin object instance created from the factory. This stores all
|
||||
* relevant interface smart pointers to that object so we can handle control
|
||||
* messages sent by the plugin without having to do these expensive casts all
|
||||
* the time. This also stores any additional context data, such as the
|
||||
* `IHostApplication` instance passed to the plugin during
|
||||
* `IPluginBase::initialize()`.
|
||||
* Smart pointers for all interfaces a VST3 plugin object might support.
|
||||
*
|
||||
* @relates Vst3PluginInstance
|
||||
*/
|
||||
struct Vst3PluginInterfaces {
|
||||
Vst3PluginInterfaces(Steinberg::IPtr<Steinberg::FUnknown> object) noexcept;
|
||||
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IAudioPresentationLatency>
|
||||
audio_presentation_latency;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IAudioProcessor> audio_processor;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IAutomationState> automation_state;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IComponent> component;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IConnectionPoint> connection_point;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IEditController> edit_controller;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IEditController2> edit_controller_2;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IEditControllerHostEditing>
|
||||
edit_controller_host_editing;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::ChannelContext::IInfoListener>
|
||||
info_listener;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IKeyswitchController>
|
||||
keyswitch_controller;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IMidiLearn> midi_learn;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IMidiMapping> midi_mapping;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::INoteExpressionController>
|
||||
note_expression_controller;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::INoteExpressionPhysicalUIMapping>
|
||||
note_expression_physical_ui_mapping;
|
||||
Steinberg::FUnknownPtr<Steinberg::IPluginBase> plugin_base;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitData> unit_data;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IParameterFunctionName>
|
||||
parameter_function_name;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IPrefetchableSupport>
|
||||
prefetchable_support;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IProcessContextRequirements>
|
||||
process_context_requirements;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IProgramListData> program_list_data;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitInfo> unit_info;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IXmlRepresentationController>
|
||||
xml_representation_controller;
|
||||
};
|
||||
|
||||
/**
|
||||
* A holder for plugin object instance created from the factory. This contains a
|
||||
* smart pointer to the object's `FUnknown` interface and everything else we
|
||||
* need to proxy for this object, like audio threads and proxy objects for
|
||||
* callbacks. We also store an `interfaces` object that contains smart pointers
|
||||
* to all relevant VST3 interface so we can handle control messages sent by the
|
||||
* plugin without having to do these expensive casts all the time.
|
||||
*/
|
||||
struct Vst3PluginInstance {
|
||||
Vst3PluginInstance(Steinberg::IPtr<Steinberg::FUnknown> object) noexcept;
|
||||
@@ -123,21 +165,6 @@ struct Vst3PluginInstance {
|
||||
registered_context_menus;
|
||||
std::mutex registered_context_menus_mutex;
|
||||
|
||||
/**
|
||||
* The base object we cast from.
|
||||
*/
|
||||
Steinberg::IPtr<Steinberg::FUnknown> object;
|
||||
|
||||
/**
|
||||
* The `IPlugView` object the plugin returned from a call to
|
||||
* `IEditController::createView()`.
|
||||
*
|
||||
* XXX: Technically VST3 supports multiple named views, so we could have
|
||||
* multiple different view for a single plugin. This is not used within
|
||||
* the SDK, so a single pointer should be fine for now.
|
||||
*/
|
||||
std::optional<Vst3PlugViewInterfaces> plug_view_instance;
|
||||
|
||||
/**
|
||||
* A shared memory object we'll write the input audio buffers to on the
|
||||
* native plugin side. We'll then let the plugin write its outputs here on
|
||||
@@ -172,41 +199,28 @@ struct Vst3PluginInstance {
|
||||
*/
|
||||
std::optional<Editor> editor;
|
||||
|
||||
// All smart pointers below are created from `component`. They will be null
|
||||
// pointers if `component` did not implement the interface.
|
||||
/**
|
||||
* The base object we cast from. This is upcasted form the object created by
|
||||
* the factory.
|
||||
*/
|
||||
Steinberg::IPtr<Steinberg::FUnknown> object;
|
||||
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IAudioPresentationLatency>
|
||||
audio_presentation_latency;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IAudioProcessor> audio_processor;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IAutomationState> automation_state;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IComponent> component;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IConnectionPoint> connection_point;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IEditController> edit_controller;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IEditController2> edit_controller_2;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IEditControllerHostEditing>
|
||||
edit_controller_host_editing;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::ChannelContext::IInfoListener>
|
||||
info_listener;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IKeyswitchController>
|
||||
keyswitch_controller;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IMidiLearn> midi_learn;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IMidiMapping> midi_mapping;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::INoteExpressionController>
|
||||
note_expression_controller;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::INoteExpressionPhysicalUIMapping>
|
||||
note_expression_physical_ui_mapping;
|
||||
Steinberg::FUnknownPtr<Steinberg::IPluginBase> plugin_base;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitData> unit_data;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IParameterFunctionName>
|
||||
parameter_function_name;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IPrefetchableSupport>
|
||||
prefetchable_support;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IProcessContextRequirements>
|
||||
process_context_requirements;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IProgramListData> program_list_data;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitInfo> unit_info;
|
||||
Steinberg::FUnknownPtr<Steinberg::Vst::IXmlRepresentationController>
|
||||
xml_representation_controller;
|
||||
/**
|
||||
* The `IPlugView` object the plugin returned from a call to
|
||||
* `IEditController::createView()`. This object can also implement multiple
|
||||
* interfaces.
|
||||
*
|
||||
* XXX: Technically VST3 supports multiple named views, so we could have
|
||||
* multiple different view for a single plugin. This is not used within
|
||||
* the SDK, so a single pointer should be fine for now.
|
||||
*/
|
||||
std::optional<Vst3PlugViewInterfaces> plug_view_instance;
|
||||
|
||||
/**
|
||||
* This contains smart pointers to all VST3 plugin interfaces that can be
|
||||
* casted from `object`.
|
||||
*/
|
||||
Vst3PluginInterfaces interfaces;
|
||||
|
||||
/**
|
||||
* Whether `IPluginBase:initialize()` has already been called for this
|
||||
|
||||
Reference in New Issue
Block a user