mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
Add a holder for component contexts and pointers
When implementing the other component interfaces we want to be able to store the `FUnknownPtrs`.
This commit is contained in:
@@ -22,6 +22,12 @@
|
|||||||
|
|
||||||
#include "vst3-impls/host-application.h"
|
#include "vst3-impls/host-application.h"
|
||||||
|
|
||||||
|
ComponentInstance::ComponentInstance() {}
|
||||||
|
|
||||||
|
ComponentInstance::ComponentInstance(
|
||||||
|
Steinberg::IPtr<Steinberg::Vst::IComponent> component)
|
||||||
|
: component(component) {}
|
||||||
|
|
||||||
Vst3Bridge::Vst3Bridge(MainContext& main_context,
|
Vst3Bridge::Vst3Bridge(MainContext& main_context,
|
||||||
std::string plugin_dll_path,
|
std::string plugin_dll_path,
|
||||||
std::string endpoint_base_dir)
|
std::string endpoint_base_dir)
|
||||||
@@ -44,6 +50,11 @@ Vst3Bridge::Vst3Bridge(MainContext& main_context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Vst3Bridge::run() {
|
void Vst3Bridge::run() {
|
||||||
|
// XXX: In theory all of thise should be safe assuming the host doesn't do
|
||||||
|
// anything weird. We're using mutexes when inserting and removing
|
||||||
|
// things, but for correctness we should have a multiple-readers
|
||||||
|
// single-writer style lock since concurrent reads and writes can also
|
||||||
|
// be unsafe.
|
||||||
sockets.host_vst_control.receive_messages(
|
sockets.host_vst_control.receive_messages(
|
||||||
std::nullopt,
|
std::nullopt,
|
||||||
overload{
|
overload{
|
||||||
@@ -61,7 +72,8 @@ void Vst3Bridge::run() {
|
|||||||
component_instances[instance_id] = std::move(component);
|
component_instances[instance_id] = std::move(component);
|
||||||
|
|
||||||
return YaComponent::ConstructArgs(
|
return YaComponent::ConstructArgs(
|
||||||
component_instances[instance_id], instance_id);
|
component_instances[instance_id].component,
|
||||||
|
instance_id);
|
||||||
} else {
|
} else {
|
||||||
// The actual result is lost here
|
// The actual result is lost here
|
||||||
return UniversalTResult(Steinberg::kNotImplemented);
|
return UniversalTResult(Steinberg::kNotImplemented);
|
||||||
@@ -69,15 +81,8 @@ void Vst3Bridge::run() {
|
|||||||
},
|
},
|
||||||
[&](const YaComponent::Destruct& request)
|
[&](const YaComponent::Destruct& request)
|
||||||
-> YaComponent::Destruct::Response {
|
-> YaComponent::Destruct::Response {
|
||||||
std::scoped_lock lock(
|
std::lock_guard lock(component_instances_mutex);
|
||||||
component_instances_mutex,
|
|
||||||
component_host_application_context_instance_mutex);
|
|
||||||
component_instances.erase(request.instance_id);
|
component_instances.erase(request.instance_id);
|
||||||
if (component_host_application_context_instances.contains(
|
|
||||||
request.instance_id)) {
|
|
||||||
component_host_application_context_instances.erase(
|
|
||||||
request.instance_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ack{};
|
return Ack{};
|
||||||
},
|
},
|
||||||
@@ -88,40 +93,39 @@ void Vst3Bridge::run() {
|
|||||||
// be cleaned up again during `YaComponent::Destruct`.
|
// be cleaned up again during `YaComponent::Destruct`.
|
||||||
Steinberg::FUnknown* context = nullptr;
|
Steinberg::FUnknown* context = nullptr;
|
||||||
if (request.host_application_context_args) {
|
if (request.host_application_context_args) {
|
||||||
// TODO: Is this safe? These Steinberg smart pointers are
|
component_instances[request.instance_id]
|
||||||
// scary
|
.hsot_application_context =
|
||||||
component_host_application_context_instances
|
Steinberg::owned(new YaHostApplicationHostImpl(
|
||||||
[request.instance_id] =
|
*this,
|
||||||
Steinberg::owned(new YaHostApplicationHostImpl(
|
std::move(*request.host_application_context_args)));
|
||||||
*this,
|
context = component_instances[request.instance_id]
|
||||||
std::move(
|
.hsot_application_context;
|
||||||
*request.host_application_context_args)));
|
|
||||||
context = component_host_application_context_instances
|
|
||||||
[request.instance_id];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return component_instances[request.instance_id]->initialize(
|
return component_instances[request.instance_id]
|
||||||
context);
|
.component->initialize(context);
|
||||||
},
|
},
|
||||||
[&](const YaComponent::Terminate& request)
|
[&](const YaComponent::Terminate& request)
|
||||||
-> YaComponent::Terminate::Response {
|
-> YaComponent::Terminate::Response {
|
||||||
return component_instances[request.instance_id]->terminate();
|
return component_instances[request.instance_id]
|
||||||
|
.component->terminate();
|
||||||
},
|
},
|
||||||
[&](const YaComponent::SetIoMode& request)
|
[&](const YaComponent::SetIoMode& request)
|
||||||
-> YaComponent::SetIoMode::Response {
|
-> YaComponent::SetIoMode::Response {
|
||||||
return component_instances[request.instance_id]->setIoMode(
|
return component_instances[request.instance_id]
|
||||||
request.mode);
|
.component->setIoMode(request.mode);
|
||||||
},
|
},
|
||||||
[&](const YaComponent::GetBusCount& request)
|
[&](const YaComponent::GetBusCount& request)
|
||||||
-> YaComponent::GetBusCount::Response {
|
-> YaComponent::GetBusCount::Response {
|
||||||
return component_instances[request.instance_id]->getBusCount(
|
return component_instances[request.instance_id]
|
||||||
request.type, request.dir);
|
.component->getBusCount(request.type, request.dir);
|
||||||
},
|
},
|
||||||
[&](YaComponent::GetBusInfo& request)
|
[&](YaComponent::GetBusInfo& request)
|
||||||
-> YaComponent::GetBusInfo::Response {
|
-> YaComponent::GetBusInfo::Response {
|
||||||
const tresult result =
|
const tresult result =
|
||||||
component_instances[request.instance_id]->getBusInfo(
|
component_instances[request.instance_id]
|
||||||
request.type, request.dir, request.index, request.bus);
|
.component->getBusInfo(request.type, request.dir,
|
||||||
|
request.index, request.bus);
|
||||||
|
|
||||||
return YaComponent::GetBusInfoResponse{
|
return YaComponent::GetBusInfoResponse{
|
||||||
.result = result, .updated_bus = request.bus};
|
.result = result, .updated_bus = request.bus};
|
||||||
|
|||||||
@@ -24,6 +24,34 @@
|
|||||||
#include "../../common/configuration.h"
|
#include "../../common/configuration.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A holder for an `IComponent` instance created from the factory along with any
|
||||||
|
* host context proxy objects belonging to it, and several predefined
|
||||||
|
* `FUnknownPtrs` so we don't have to do these dynamic casts all the times..
|
||||||
|
*/
|
||||||
|
struct ComponentInstance {
|
||||||
|
ComponentInstance();
|
||||||
|
|
||||||
|
ComponentInstance(Steinberg::IPtr<Steinberg::Vst::IComponent> component);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the host passes an `IHostApplication` during
|
||||||
|
* `IPluginBase::initialize()`, we'll store a proxy object here and then
|
||||||
|
* pass it to `component->initialize()`.
|
||||||
|
*/
|
||||||
|
Steinberg::IPtr<YaHostApplication> hsot_application_context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `IComponent` instance we created.
|
||||||
|
*/
|
||||||
|
Steinberg::IPtr<Steinberg::Vst::IComponent> component;
|
||||||
|
|
||||||
|
// All smart pointers below are created from `component`. They will be null
|
||||||
|
// pointers if `component` did not implement the interface.
|
||||||
|
|
||||||
|
// TODO: Implement things like `IConnectionPoint` and `IAudioProcessor`
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This hosts a Windows VST3 plugin, forwards messages sent by the Linux VST
|
* This hosts a Windows VST3 plugin, forwards messages sent by the Linux VST
|
||||||
* plugin and provides host callback function for the plugin to talk back.
|
* plugin and provides host callback function for the plugin to talk back.
|
||||||
@@ -112,22 +140,6 @@ class Vst3Bridge : public HostBridge {
|
|||||||
// instances. The mutexes are used for operations that insert or remove
|
// instances. The mutexes are used for operations that insert or remove
|
||||||
// items, and not for regular access.
|
// items, and not for regular access.
|
||||||
|
|
||||||
std::map<size_t, Steinberg::IPtr<Steinberg::Vst::IComponent>>
|
std::map<size_t, ComponentInstance> component_instances;
|
||||||
component_instances;
|
|
||||||
std::mutex component_instances_mutex;
|
std::mutex component_instances_mutex;
|
||||||
|
|
||||||
/**
|
|
||||||
* If an `IHostApplication` was passed during
|
|
||||||
* `{IPluginBase,IComponent}::initialize()`, then we'll store a proxy object
|
|
||||||
* here. The instance ID is the same as the corresponding instance ID in
|
|
||||||
* `component_instances`. When an instance gets removed from
|
|
||||||
* `component_instances`, it should also be removed from here.
|
|
||||||
*
|
|
||||||
* XXX: If it turns out we need to keep track of more of these kinds of
|
|
||||||
* objects, then we should create a wrapper so that everything can stay
|
|
||||||
* in `component_instances`
|
|
||||||
*/
|
|
||||||
std::map<size_t, Steinberg::IPtr<YaHostApplication>>
|
|
||||||
component_host_application_context_instances;
|
|
||||||
std::mutex component_host_application_context_instance_mutex;
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user