mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-06-12 15:22:14 +02:00
Implement the plugin side if IComponentHandler3
This commit is contained in:
@@ -179,6 +179,7 @@ using CallbackRequest = std::variant<WantsConfiguration,
|
|||||||
YaComponentHandler2::RequestOpenEditor,
|
YaComponentHandler2::RequestOpenEditor,
|
||||||
YaComponentHandler2::StartGroupEdit,
|
YaComponentHandler2::StartGroupEdit,
|
||||||
YaComponentHandler2::FinishGroupEdit,
|
YaComponentHandler2::FinishGroupEdit,
|
||||||
|
YaComponentHandler3::CreateContextMenu,
|
||||||
// Used when the host uses proxy objects,
|
// Used when the host uses proxy objects,
|
||||||
// and we have to route
|
// and we have to route
|
||||||
// `IConnectionPoint::notify` calls through
|
// `IConnectionPoint::notify` calls through
|
||||||
|
|||||||
@@ -39,6 +39,26 @@ Vst3PluginProxyImpl::queryInterface(const Steinberg::TUID _iid, void** obj) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Vst3PluginProxyImpl::register_context_menu(
|
||||||
|
Steinberg::IPtr<Steinberg::Vst::IContextMenu> menu) {
|
||||||
|
std::lock_guard lock(context_menus_mutex);
|
||||||
|
|
||||||
|
const size_t context_menu_id = current_context_menu_id.fetch_add(1);
|
||||||
|
context_menus.emplace(context_menu_id, std::move(menu));
|
||||||
|
|
||||||
|
return context_menu_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a context menu using the ID generated by a previous call to
|
||||||
|
* `register_context_menu()`. This will release the context menu object
|
||||||
|
* returned by the host.
|
||||||
|
*/
|
||||||
|
bool Vst3PluginProxyImpl::unregister_context_menu(size_t context_menu_id) {
|
||||||
|
std::lock_guard lock(context_menus_mutex);
|
||||||
|
return context_menus.erase(context_menu_id);
|
||||||
|
}
|
||||||
|
|
||||||
tresult PLUGIN_API Vst3PluginProxyImpl::setAudioPresentationLatencySamples(
|
tresult PLUGIN_API Vst3PluginProxyImpl::setAudioPresentationLatencySamples(
|
||||||
Steinberg::Vst::BusDirection dir,
|
Steinberg::Vst::BusDirection dir,
|
||||||
int32 busIndex,
|
int32 busIndex,
|
||||||
@@ -373,6 +393,7 @@ tresult PLUGIN_API Vst3PluginProxyImpl::setComponentHandler(
|
|||||||
// Automatically converted smart pointers for when the plugin performs a
|
// Automatically converted smart pointers for when the plugin performs a
|
||||||
// callback later
|
// callback later
|
||||||
component_handler_2 = component_handler;
|
component_handler_2 = component_handler;
|
||||||
|
component_handler_3 = component_handler;
|
||||||
unit_handler = component_handler;
|
unit_handler = component_handler;
|
||||||
|
|
||||||
return bridge.send_message(YaEditController::SetComponentHandler{
|
return bridge.send_message(YaEditController::SetComponentHandler{
|
||||||
|
|||||||
@@ -38,6 +38,22 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
|
|||||||
tresult PLUGIN_API queryInterface(const Steinberg::TUID _iid,
|
tresult PLUGIN_API queryInterface(const Steinberg::TUID _iid,
|
||||||
void** obj) override;
|
void** obj) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a context menu created by a call to
|
||||||
|
* `IComponentHandler3::createContextMenu` to our list of registered cotnext
|
||||||
|
* menus. This way we can refer to it later when the plugin calls a function
|
||||||
|
* on the proxy object we'll create for it.
|
||||||
|
*/
|
||||||
|
size_t register_context_menu(
|
||||||
|
Steinberg::IPtr<Steinberg::Vst::IContextMenu> menu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a context menu using the ID generated by a previous call to
|
||||||
|
* `register_context_menu()`. This will release the context menu object
|
||||||
|
* returned by the host.
|
||||||
|
*/
|
||||||
|
bool unregister_context_menu(size_t context_menu_id);
|
||||||
|
|
||||||
// From `IAudioPresentationLatency`
|
// From `IAudioPresentationLatency`
|
||||||
tresult PLUGIN_API
|
tresult PLUGIN_API
|
||||||
setAudioPresentationLatencySamples(Steinberg::Vst::BusDirection dir,
|
setAudioPresentationLatencySamples(Steinberg::Vst::BusDirection dir,
|
||||||
@@ -242,6 +258,21 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
|
|||||||
*/
|
*/
|
||||||
Vst3PlugViewProxyImpl* last_created_plug_view = nullptr;
|
Vst3PlugViewProxyImpl* last_created_plug_view = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All context menus created by this object through
|
||||||
|
* `IComponentHandler3::createContextMenu()`. We'll generate a unique
|
||||||
|
* identifier for each context menu just like we do for plugin objects. When
|
||||||
|
* the plugin drops the context menu object, we'll also remove the
|
||||||
|
* corresponding entry for this map causing the original pointer returned by
|
||||||
|
* the host to get dropped a well.
|
||||||
|
*
|
||||||
|
* @see Vst3PluginProxyImpl::register_context_menu
|
||||||
|
* @see Vst3PluginProxyImpl::unregister_context_menu
|
||||||
|
*/
|
||||||
|
std::map<size_t, Steinberg::IPtr<Steinberg::Vst::IContextMenu>>
|
||||||
|
context_menus;
|
||||||
|
std::mutex context_menus_mutex;
|
||||||
|
|
||||||
// The following pointers are cast from `host_context` if
|
// The following pointers are cast from `host_context` if
|
||||||
// `IPluginBase::initialize()` has been called
|
// `IPluginBase::initialize()` has been called
|
||||||
|
|
||||||
@@ -252,6 +283,8 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
|
|||||||
|
|
||||||
Steinberg::FUnknownPtr<Steinberg::Vst::IComponentHandler2>
|
Steinberg::FUnknownPtr<Steinberg::Vst::IComponentHandler2>
|
||||||
component_handler_2;
|
component_handler_2;
|
||||||
|
Steinberg::FUnknownPtr<Steinberg::Vst::IComponentHandler3>
|
||||||
|
component_handler_3;
|
||||||
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitHandler> unit_handler;
|
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitHandler> unit_handler;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -265,4 +298,12 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
|
|||||||
* but for the sake of correctness we will.
|
* but for the sake of correctness we will.
|
||||||
*/
|
*/
|
||||||
Steinberg::IPtr<Steinberg::FUnknown> host_context;
|
Steinberg::IPtr<Steinberg::FUnknown> host_context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to assign unique identifiers to context menus created by
|
||||||
|
* `IComponentHandler3::CreateContextMenu`.
|
||||||
|
*
|
||||||
|
* @related Vst3PluginProxyImpl::register_context_menu
|
||||||
|
*/
|
||||||
|
std::atomic_size_t current_context_menu_id;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -102,6 +102,43 @@ Vst3PluginBridge::Vst3PluginBridge()
|
|||||||
.get()
|
.get()
|
||||||
.component_handler_2->finishGroupEdit();
|
.component_handler_2->finishGroupEdit();
|
||||||
},
|
},
|
||||||
|
[&](const YaComponentHandler3::CreateContextMenu& request)
|
||||||
|
-> YaComponentHandler3::CreateContextMenu::Response {
|
||||||
|
// XXX: As mentioned elsewhere, since VST3 only supports a
|
||||||
|
// single plug view type at the moment we'll just
|
||||||
|
// assume that this function is called from the last
|
||||||
|
// (and only) `IPlugView*` instance returned by the
|
||||||
|
// plugin.
|
||||||
|
Vst3PlugViewProxyImpl* plug_view =
|
||||||
|
plugin_proxies.at(request.owner_instance_id)
|
||||||
|
.get()
|
||||||
|
.last_created_plug_view;
|
||||||
|
|
||||||
|
Steinberg::IPtr<Steinberg::Vst::IContextMenu> context_menu =
|
||||||
|
Steinberg::owned(
|
||||||
|
plugin_proxies.at(request.owner_instance_id)
|
||||||
|
.get()
|
||||||
|
.component_handler_3->createContextMenu(
|
||||||
|
plug_view, request.param_id
|
||||||
|
? &*request.param_id
|
||||||
|
: nullptr));
|
||||||
|
|
||||||
|
if (context_menu) {
|
||||||
|
const size_t context_menu_id =
|
||||||
|
plugin_proxies.at(request.owner_instance_id)
|
||||||
|
.get()
|
||||||
|
.register_context_menu(std::move(context_menu));
|
||||||
|
|
||||||
|
return YaComponentHandler3::CreateContextMenuResponse{
|
||||||
|
.context_menu_args =
|
||||||
|
Vst3ContextMenuProxy::ConstructArgs(
|
||||||
|
context_menu, request.owner_instance_id,
|
||||||
|
context_menu_id)};
|
||||||
|
} else {
|
||||||
|
return YaComponentHandler3::CreateContextMenuResponse{
|
||||||
|
.context_menu_args = std::nullopt};
|
||||||
|
}
|
||||||
|
},
|
||||||
[&](YaConnectionPoint::Notify& request)
|
[&](YaConnectionPoint::Notify& request)
|
||||||
-> YaConnectionPoint::Notify::Response {
|
-> YaConnectionPoint::Notify::Response {
|
||||||
return plugin_proxies.at(request.instance_id)
|
return plugin_proxies.at(request.instance_id)
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ class Vst3Bridge : public HostBridge {
|
|||||||
Vst3Sockets<Win32Thread> sockets;
|
Vst3Sockets<Win32Thread> sockets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to assign unique identifier to instances created for
|
* Used to assign unique identifiers to instances created for
|
||||||
* `IPluginFactory::createInstance()`.
|
* `IPluginFactory::createInstance()`.
|
||||||
*
|
*
|
||||||
* @related enerate_instance_id
|
* @related enerate_instance_id
|
||||||
|
|||||||
Reference in New Issue
Block a user