diff --git a/src/common/logging/vst3.cpp b/src/common/logging/vst3.cpp index e18f20a6..075609c1 100644 --- a/src/common/logging/vst3.cpp +++ b/src/common/logging/vst3.cpp @@ -151,6 +151,17 @@ void Vst3Logger::log_request(bool is_host_vst, }); } +void Vst3Logger::log_request(bool is_host_vst, + const YaComponent::SetBusArrangements& request) { + log_request_base(is_host_vst, [&](auto& message) { + message << "::setBusArrangements(inputs = [SpeakerArrangement; " + << request.inputs.size() << "], numIns = " << request.num_ins + << ", outputs = [SpeakerArrangement; " << request.outputs.size() + << "], numOuts = " << request.num_outs << ")"; + }); +} + void Vst3Logger::log_request(bool is_host_vst, const YaPluginFactory::Construct&) { log_request_base(is_host_vst, diff --git a/src/common/logging/vst3.h b/src/common/logging/vst3.h index 951466d1..7541abb2 100644 --- a/src/common/logging/vst3.h +++ b/src/common/logging/vst3.h @@ -68,6 +68,7 @@ class Vst3Logger { void log_request(bool is_host_vst, const YaComponent::SetActive&); void log_request(bool is_host_vst, const YaComponent::SetState&); void log_request(bool is_host_vst, const YaComponent::GetState&); + void log_request(bool is_host_vst, const YaComponent::SetBusArrangements&); void log_request(bool is_host_vst, const YaPluginFactory::Construct&); void log_request(bool is_host_vst, const YaPluginFactory::SetHostContext&); void log_request(bool is_host_vst, const WantsConfiguration&); diff --git a/src/common/serialization/vst3.h b/src/common/serialization/vst3.h index 45ded5e4..5a3f01c4 100644 --- a/src/common/serialization/vst3.h +++ b/src/common/serialization/vst3.h @@ -69,6 +69,7 @@ using ControlRequest = std::variant; diff --git a/src/common/serialization/vst3/base.h b/src/common/serialization/vst3/base.h index b70749a0..d1155e35 100644 --- a/src/common/serialization/vst3/base.h +++ b/src/common/serialization/vst3/base.h @@ -39,6 +39,11 @@ using ArrayUID = std::array< std::remove_reference_t()[0])>, std::extent_v>; +/** + * The maximum number of speakers or busses we support. + */ +constexpr size_t max_num_speakers = 16384; + /** * The maximum size for an `IBStream` we can serialize. Allows for up to 50 MB * of preset data. Hopefully no plugin will come anywhere near this limit, but diff --git a/src/common/serialization/vst3/component.h b/src/common/serialization/vst3/component.h index 85326be8..d51cca3d 100644 --- a/src/common/serialization/vst3/component.h +++ b/src/common/serialization/vst3/component.h @@ -192,7 +192,7 @@ class YaComponent : public Steinberg::Vst::IComponent, tresult PLUGIN_API getControllerClassId(Steinberg::TUID classId) override; /** - * Message to pass through a call to `IComponent::setIoMode(IoMode)` to the + * Message to pass through a call to `IComponent::setIoMode(mode)` to the * Wine plugin host. */ struct SetIoMode { @@ -282,7 +282,7 @@ class YaComponent : public Steinberg::Vst::IComponent, /** * The response code and returned routing information for a call to - * `IComponent::getRoutingInfo(inInfo, outInfo )`. + * `IComponent::getRoutingInfo(in_info, out_info )`. */ struct GetRoutingInfoResponse { UniversalTResult result; @@ -298,8 +298,8 @@ class YaComponent : public Steinberg::Vst::IComponent, }; /** - * Message to pass through a call to `IComponent::getRoutingInfo(inInfo, - * outInfo )` to the Wine plugin host. + * Message to pass through a call to `IComponent::getRoutingInfo(in_info, + * out_info )` to the Wine plugin host. */ struct GetRoutingInfo { using Response = GetRoutingInfoResponse; @@ -425,6 +425,33 @@ class YaComponent : public Steinberg::Vst::IComponent, getState(Steinberg::IBStream* state) override = 0; // From `IAudioProcessor` + + /** + * Message to pass through a call to + * `IAudioProcessor::setBusArrangements(inputs, num_ins, outputs, num_outs)` + * to the Wine plugin host. + */ + struct SetBusArrangements { + using Response = UniversalTResult; + + native_size_t instance_id; + + // These are orginally C-style heap arrays, not normal pointers + std::vector inputs; + int32 num_ins; + std::vector outputs; + int32 num_outs; + + template + void serialize(S& s) { + s.value8b(instance_id); + s.container8b(inputs, max_num_speakers); + s.value4b(num_ins); + s.container8b(outputs, max_num_speakers); + s.value4b(num_outs); + } + }; + virtual tresult PLUGIN_API setBusArrangements(Steinberg::Vst::SpeakerArrangement* inputs, int32 numIns, diff --git a/src/plugin/bridges/vst3-impls/component.cpp b/src/plugin/bridges/vst3-impls/component.cpp index b173b19b..34863df9 100644 --- a/src/plugin/bridges/vst3-impls/component.cpp +++ b/src/plugin/bridges/vst3-impls/component.cpp @@ -162,9 +162,18 @@ tresult PLUGIN_API YaComponentPluginImpl::setBusArrangements( int32 numIns, Steinberg::Vst::SpeakerArrangement* outputs, int32 numOuts) { - // TODO: Implement - bridge.logger.log("TODO: IAudioProcessor::setBusArrangements()"); - return Steinberg::kNotImplemented; + assert(inputs && outputs); + return bridge + .send_message(YaComponent::SetBusArrangements{ + .instance_id = arguments.instance_id, + .inputs = std::vector( + inputs, &inputs[numIns]), + .num_ins = numIns, + .outputs = std::vector( + outputs, &outputs[numOuts]), + .num_outs = numOuts, + }) + .native(); } tresult PLUGIN_API YaComponentPluginImpl::getBusArrangement( diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index 2e1c8f85..ef291995 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -167,6 +167,14 @@ void Vst3Bridge::run() { return YaComponent::GetStateResponse{ .result = result, .updated_state = std::move(stream)}; }, + [&](YaComponent::SetBusArrangements& request) + -> YaComponent::SetBusArrangements::Response { + VectorStream stream; + return component_instances[request.instance_id] + .audio_processor->setBusArrangements( + request.inputs.data(), request.num_ins, + request.outputs.data(), request.num_outs); + }, [&](const YaPluginFactory::Construct&) -> YaPluginFactory::Construct::Response { return YaPluginFactory::ConstructArgs(