mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-08 20:40:11 +02:00
Add dedicated IAudioProcessor/IComponent sockets
This way every relevant object instance will get its own thread for handling these calls. The alternative would be creating a full fat Vst3MessageHandler pair for all object instances, but that would be a huge waste.
This commit is contained in:
@@ -27,7 +27,7 @@ Vst3PluginProxyImpl::Vst3PluginProxyImpl(Vst3PluginBridge& bridge,
|
||||
Vst3PluginProxyImpl::~Vst3PluginProxyImpl() {
|
||||
bridge.send_message(
|
||||
Vst3PluginProxy::Destruct{.instance_id = instance_id()});
|
||||
bridge.unregister_plugin_proxy(instance_id());
|
||||
bridge.unregister_plugin_proxy(*this);
|
||||
}
|
||||
|
||||
tresult PLUGIN_API
|
||||
@@ -49,29 +49,32 @@ tresult PLUGIN_API Vst3PluginProxyImpl::setBusArrangements(
|
||||
int32 numOuts) {
|
||||
// NOTE: Ardour passes a null pointer when `numIns` or `numOuts` is 0, so we
|
||||
// need to work around that
|
||||
return bridge.send_message(YaAudioProcessor::SetBusArrangements{
|
||||
.instance_id = instance_id(),
|
||||
.inputs = (inputs ? std::vector<Steinberg::Vst::SpeakerArrangement>(
|
||||
inputs, &inputs[numIns])
|
||||
: std::vector<Steinberg::Vst::SpeakerArrangement>()),
|
||||
.num_ins = numIns,
|
||||
.outputs =
|
||||
(outputs ? std::vector<Steinberg::Vst::SpeakerArrangement>(
|
||||
outputs, &outputs[numOuts])
|
||||
: std::vector<Steinberg::Vst::SpeakerArrangement>()),
|
||||
.num_outs = numOuts,
|
||||
});
|
||||
return bridge.send_audio_processor_message(
|
||||
YaAudioProcessor::SetBusArrangements{
|
||||
.instance_id = instance_id(),
|
||||
.inputs =
|
||||
(inputs ? std::vector<Steinberg::Vst::SpeakerArrangement>(
|
||||
inputs, &inputs[numIns])
|
||||
: std::vector<Steinberg::Vst::SpeakerArrangement>()),
|
||||
.num_ins = numIns,
|
||||
.outputs =
|
||||
(outputs ? std::vector<Steinberg::Vst::SpeakerArrangement>(
|
||||
outputs, &outputs[numOuts])
|
||||
: std::vector<Steinberg::Vst::SpeakerArrangement>()),
|
||||
.num_outs = numOuts,
|
||||
});
|
||||
}
|
||||
|
||||
tresult PLUGIN_API Vst3PluginProxyImpl::getBusArrangement(
|
||||
Steinberg::Vst::BusDirection dir,
|
||||
int32 index,
|
||||
Steinberg::Vst::SpeakerArrangement& arr) {
|
||||
const GetBusArrangementResponse response = bridge.send_message(
|
||||
YaAudioProcessor::GetBusArrangement{.instance_id = instance_id(),
|
||||
.dir = dir,
|
||||
.index = index,
|
||||
.arr = arr});
|
||||
const GetBusArrangementResponse response =
|
||||
bridge.send_audio_processor_message(
|
||||
YaAudioProcessor::GetBusArrangement{.instance_id = instance_id(),
|
||||
.dir = dir,
|
||||
.index = index,
|
||||
.arr = arr});
|
||||
|
||||
arr = response.updated_arr;
|
||||
|
||||
@@ -80,24 +83,26 @@ tresult PLUGIN_API Vst3PluginProxyImpl::getBusArrangement(
|
||||
|
||||
tresult PLUGIN_API
|
||||
Vst3PluginProxyImpl::canProcessSampleSize(int32 symbolicSampleSize) {
|
||||
return bridge.send_message(YaAudioProcessor::CanProcessSampleSize{
|
||||
.instance_id = instance_id(),
|
||||
.symbolic_sample_size = symbolicSampleSize});
|
||||
return bridge.send_audio_processor_message(
|
||||
YaAudioProcessor::CanProcessSampleSize{
|
||||
.instance_id = instance_id(),
|
||||
.symbolic_sample_size = symbolicSampleSize});
|
||||
}
|
||||
|
||||
uint32 PLUGIN_API Vst3PluginProxyImpl::getLatencySamples() {
|
||||
return bridge.send_message(
|
||||
return bridge.send_audio_processor_message(
|
||||
YaAudioProcessor::GetLatencySamples{.instance_id = instance_id()});
|
||||
}
|
||||
|
||||
tresult PLUGIN_API
|
||||
Vst3PluginProxyImpl::setupProcessing(Steinberg::Vst::ProcessSetup& setup) {
|
||||
return bridge.send_message(YaAudioProcessor::SetupProcessing{
|
||||
.instance_id = instance_id(), .setup = setup});
|
||||
return bridge.send_audio_processor_message(
|
||||
YaAudioProcessor::SetupProcessing{.instance_id = instance_id(),
|
||||
.setup = setup});
|
||||
}
|
||||
|
||||
tresult PLUGIN_API Vst3PluginProxyImpl::setProcessing(TBool state) {
|
||||
return bridge.send_message(YaAudioProcessor::SetProcessing{
|
||||
return bridge.send_audio_processor_message(YaAudioProcessor::SetProcessing{
|
||||
.instance_id = instance_id(), .state = state});
|
||||
}
|
||||
|
||||
@@ -105,7 +110,7 @@ tresult PLUGIN_API
|
||||
Vst3PluginProxyImpl::process(Steinberg::Vst::ProcessData& data) {
|
||||
// TODO: Check whether reusing a `YaProcessData` object make a difference in
|
||||
// terms of performance
|
||||
ProcessResponse response = bridge.send_message(
|
||||
ProcessResponse response = bridge.send_audio_processor_message(
|
||||
YaAudioProcessor::Process{.instance_id = instance_id(), .data = data});
|
||||
|
||||
response.output_data.write_back_outputs(data);
|
||||
@@ -114,14 +119,15 @@ Vst3PluginProxyImpl::process(Steinberg::Vst::ProcessData& data) {
|
||||
}
|
||||
|
||||
uint32 PLUGIN_API Vst3PluginProxyImpl::getTailSamples() {
|
||||
return bridge.send_message(
|
||||
return bridge.send_audio_processor_message(
|
||||
YaAudioProcessor::GetTailSamples{.instance_id = instance_id()});
|
||||
}
|
||||
|
||||
tresult PLUGIN_API
|
||||
Vst3PluginProxyImpl::getControllerClassId(Steinberg::TUID classId) {
|
||||
const GetControllerClassIdResponse response = bridge.send_message(
|
||||
YaComponent::GetControllerClassId{.instance_id = instance_id()});
|
||||
const GetControllerClassIdResponse response =
|
||||
bridge.send_audio_processor_message(
|
||||
YaComponent::GetControllerClassId{.instance_id = instance_id()});
|
||||
|
||||
std::copy(response.editor_cid.begin(), response.editor_cid.end(), classId);
|
||||
|
||||
@@ -129,14 +135,14 @@ Vst3PluginProxyImpl::getControllerClassId(Steinberg::TUID classId) {
|
||||
}
|
||||
|
||||
tresult PLUGIN_API Vst3PluginProxyImpl::setIoMode(Steinberg::Vst::IoMode mode) {
|
||||
return bridge.send_message(
|
||||
return bridge.send_audio_processor_message(
|
||||
YaComponent::SetIoMode{.instance_id = instance_id(), .mode = mode});
|
||||
}
|
||||
|
||||
int32 PLUGIN_API
|
||||
Vst3PluginProxyImpl::getBusCount(Steinberg::Vst::MediaType type,
|
||||
Steinberg::Vst::BusDirection dir) {
|
||||
return bridge.send_message(YaComponent::GetBusCount{
|
||||
return bridge.send_audio_processor_message(YaComponent::GetBusCount{
|
||||
.instance_id = instance_id(), .type = type, .dir = dir});
|
||||
}
|
||||
|
||||
@@ -145,7 +151,7 @@ Vst3PluginProxyImpl::getBusInfo(Steinberg::Vst::MediaType type,
|
||||
Steinberg::Vst::BusDirection dir,
|
||||
int32 index,
|
||||
Steinberg::Vst::BusInfo& bus /*out*/) {
|
||||
const GetBusInfoResponse response = bridge.send_message(
|
||||
const GetBusInfoResponse response = bridge.send_audio_processor_message(
|
||||
YaComponent::GetBusInfo{.instance_id = instance_id(),
|
||||
.type = type,
|
||||
.dir = dir,
|
||||
@@ -159,7 +165,7 @@ Vst3PluginProxyImpl::getBusInfo(Steinberg::Vst::MediaType type,
|
||||
tresult PLUGIN_API Vst3PluginProxyImpl::getRoutingInfo(
|
||||
Steinberg::Vst::RoutingInfo& inInfo,
|
||||
Steinberg::Vst::RoutingInfo& outInfo /*out*/) {
|
||||
const GetRoutingInfoResponse response = bridge.send_message(
|
||||
const GetRoutingInfoResponse response = bridge.send_audio_processor_message(
|
||||
YaComponent::GetRoutingInfo{.instance_id = instance_id(),
|
||||
.in_info = inInfo,
|
||||
.out_info = outInfo});
|
||||
@@ -174,7 +180,7 @@ Vst3PluginProxyImpl::activateBus(Steinberg::Vst::MediaType type,
|
||||
Steinberg::Vst::BusDirection dir,
|
||||
int32 index,
|
||||
TBool state) {
|
||||
return bridge.send_message(
|
||||
return bridge.send_audio_processor_message(
|
||||
YaComponent::ActivateBus{.instance_id = instance_id(),
|
||||
.type = type,
|
||||
.dir = dir,
|
||||
@@ -183,7 +189,7 @@ Vst3PluginProxyImpl::activateBus(Steinberg::Vst::MediaType type,
|
||||
}
|
||||
|
||||
tresult PLUGIN_API Vst3PluginProxyImpl::setActive(TBool state) {
|
||||
return bridge.send_message(
|
||||
return bridge.send_audio_processor_message(
|
||||
YaComponent::SetActive{.instance_id = instance_id(), .state = state});
|
||||
}
|
||||
|
||||
|
||||
@@ -161,13 +161,28 @@ Steinberg::IPluginFactory* Vst3PluginBridge::get_plugin_factory() {
|
||||
return plugin_factory;
|
||||
}
|
||||
|
||||
void Vst3PluginBridge::register_plugin_proxy(Vst3PluginProxyImpl& component) {
|
||||
void Vst3PluginBridge::register_plugin_proxy(
|
||||
Vst3PluginProxyImpl& proxy_object) {
|
||||
std::lock_guard lock(plugin_proxies_mutex);
|
||||
plugin_proxies.emplace(component.instance_id(),
|
||||
std::ref<Vst3PluginProxyImpl>(component));
|
||||
|
||||
plugin_proxies.emplace(proxy_object.instance_id(),
|
||||
std::ref<Vst3PluginProxyImpl>(proxy_object));
|
||||
|
||||
// For optimization reaons we use dedicated sockets for functions that will
|
||||
// be run in the audio processing loop
|
||||
if (proxy_object.YaAudioProcessor::supported() ||
|
||||
proxy_object.YaComponent::supported()) {
|
||||
sockets.add_audio_processor_and_connect(proxy_object.instance_id());
|
||||
}
|
||||
}
|
||||
|
||||
void Vst3PluginBridge::unregister_plugin_proxy(size_t instance_id) {
|
||||
void Vst3PluginBridge::unregister_plugin_proxy(
|
||||
Vst3PluginProxyImpl& proxy_object) {
|
||||
std::lock_guard lock(plugin_proxies_mutex);
|
||||
plugin_proxies.erase(instance_id);
|
||||
|
||||
plugin_proxies.erase(proxy_object.instance_id());
|
||||
if (proxy_object.YaAudioProcessor::supported() ||
|
||||
proxy_object.YaComponent::supported()) {
|
||||
sockets.remove_audio_processor(proxy_object.instance_id());
|
||||
}
|
||||
}
|
||||
|
||||
+20
-10
@@ -76,13 +76,12 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
|
||||
/**
|
||||
* Add a `Vst3PluginProxyImpl` to the list of registered proxy objects so we
|
||||
* can handle host callbacks. This function is called in
|
||||
* `Vst3PluginProxyImpl`'s constructor.
|
||||
* `Vst3PluginProxyImpl`'s constructor. If the plugin supports the
|
||||
* `IAudioProcessor` or `IComponent` interfaces, then we'll also connect to
|
||||
* a dedicated audio processing socket.
|
||||
*
|
||||
* @param instance_id The instance ID generated by the plugin host when
|
||||
* instantiating the `IComponent`. Used as a stable name to refer to
|
||||
* these.
|
||||
* @param plugin_proxy The actual proxy object we can access its host
|
||||
* context.
|
||||
* @param proxy_object The proxy object so we can access its host context
|
||||
* and unique instance identifier.
|
||||
*
|
||||
* @see plugin_proxies
|
||||
*/
|
||||
@@ -93,13 +92,12 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
|
||||
* registered proxy objects. Called during the object's destructor after
|
||||
* asking the Wine plugin host to destroy the component on its side.
|
||||
*
|
||||
* @param instance_id The instance ID generated by the plugin host when
|
||||
* instantiating the `IComponent`. Used as a stable name to refer to
|
||||
* these.
|
||||
* @param proxy_object The proxy object so we can access its unique instance
|
||||
* identifier.
|
||||
*
|
||||
* @see plugin_proxies
|
||||
*/
|
||||
void unregister_plugin_proxy(size_t instance_id);
|
||||
void unregister_plugin_proxy(Vst3PluginProxyImpl& proxy_object);
|
||||
|
||||
/**
|
||||
* Send a control message to the Wine plugin host return the response. This
|
||||
@@ -112,6 +110,18 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
|
||||
object, std::pair<Vst3Logger&, bool>(logger, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an `IAudioProcessor` or `IComponent` control message to a specific
|
||||
* plugin instance. This is separated from the above `send_message()` for
|
||||
* performance reasons, as this way every instance has its own dedicated
|
||||
* socket and thread.
|
||||
*/
|
||||
template <typename T>
|
||||
typename T::Response send_audio_processor_message(const T& object) {
|
||||
return sockets.send_audio_processor_message(
|
||||
object, std::pair<Vst3Logger&, bool>(logger, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* The logging facility used for this instance of yabridge. Wraps around
|
||||
* `PluginBridge::generic_logger`.
|
||||
|
||||
Reference in New Issue
Block a user