Implement the plugin side of IContextMenu

This commit is contained in:
Robbert van der Helm
2021-01-07 16:19:41 +01:00
parent 0617bfb565
commit 83d45eef27
6 changed files with 92 additions and 9 deletions
@@ -18,6 +18,10 @@
#include "plug-view-proxy.h"
Vst3PluginProxyImpl::ContextMenu::ContextMenu(
Steinberg::IPtr<Steinberg::Vst::IContextMenu> menu)
: menu(menu) {}
Vst3PluginProxyImpl::Vst3PluginProxyImpl(Vst3PluginBridge& bridge,
Vst3PluginProxy::ConstructArgs&& args)
: Vst3PluginProxy(std::move(args)), bridge(bridge) {
+21 -2
View File
@@ -258,6 +258,26 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
*/
Vst3PlugViewProxyImpl* last_created_plug_view = nullptr;
/**
* A pointer to a context menu returned by the host as a response to a call
* to `IComponentHandler3::createContextMenu`, as well as all targets we've
* created for it. This way we can drop both all at once.
*/
struct ContextMenu {
ContextMenu(Steinberg::IPtr<Steinberg::Vst::IContextMenu> menu);
Steinberg::IPtr<Steinberg::Vst::IContextMenu> menu;
/**
* All targets we pass to `IContextMenu::addItem`. We'll store them per
* item tag, so we can drop them together with the menu. We probably
* don't have to use smart pointers for this, but the docs are missing a
* lot of details o how this should be implemented and there's no
* example implementation around.
*/
std::map<int32, Steinberg::IPtr<YaContextMenuTarget>> targets;
};
/**
* All context menus created by this object through
* `IComponentHandler3::createContextMenu()`. We'll generate a unique
@@ -269,8 +289,7 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* @see Vst3PluginProxyImpl::register_context_menu
* @see Vst3PluginProxyImpl::unregister_context_menu
*/
std::map<size_t, Steinberg::IPtr<Steinberg::Vst::IContextMenu>>
context_menus;
std::map<size_t, ContextMenu> context_menus;
std::mutex context_menus_mutex;
// The following pointers are cast from `host_context` if
+52
View File
@@ -17,6 +17,7 @@
#include "vst3.h"
#include "src/common/serialization/vst3.h"
#include "vst3-impls/context-menu-target.h"
#include "vst3-impls/plugin-factory.h"
#include "vst3-impls/plugin-proxy.h"
@@ -148,6 +149,57 @@ Vst3PluginBridge::Vst3PluginBridge()
.context_menu_args = std::nullopt};
}
},
[&](const YaContextMenu::GetItemCount& request)
-> YaContextMenu::GetItemCount::Response {
return plugin_proxies.at(request.owner_instance_id)
.get()
.context_menus.at(request.context_menu_id)
.menu->getItemCount();
},
[&](YaContextMenu::AddItem& request)
-> YaContextMenu::AddItem::Response {
Vst3PluginProxyImpl::ContextMenu& context_menu =
plugin_proxies.at(request.owner_instance_id)
.get()
.context_menus.at(request.context_menu_id);
if (request.target) {
context_menu.targets[request.item.tag] =
Steinberg::owned(new YaContextMenuTargetImpl(
*this, std::move(*request.target)));
return context_menu.menu->addItem(
request.item,
context_menu.targets[request.item.tag]);
} else {
return context_menu.menu->addItem(request.item,
nullptr);
}
},
[&](const YaContextMenu::RemoveItem& request)
-> YaContextMenu::RemoveItem::Response {
Vst3PluginProxyImpl::ContextMenu& context_menu =
plugin_proxies.at(request.owner_instance_id)
.get()
.context_menus.at(request.context_menu_id);
if (const auto it =
context_menu.targets.find(request.item.tag);
it != context_menu.targets.end()) {
return context_menu.menu->removeItem(request.item,
it->second);
} else {
return context_menu.menu->removeItem(request.item,
nullptr);
}
},
[&](const YaContextMenu::Popup& request)
-> YaContextMenu::Popup::Response {
return plugin_proxies.at(request.owner_instance_id)
.get()
.context_menus.at(request.context_menu_id)
.menu->popup(request.x, request.y);
},
[&](YaConnectionPoint::Notify& request)
-> YaConnectionPoint::Notify::Response {
return plugin_proxies.at(request.instance_id)