diff --git a/src/wine-host/bridges/vst3-impls/context-menu-proxy.cpp b/src/wine-host/bridges/vst3-impls/context-menu-proxy.cpp index eeeae52d..fc28d22a 100644 --- a/src/wine-host/bridges/vst3-impls/context-menu-proxy.cpp +++ b/src/wine-host/bridges/vst3-impls/context-menu-proxy.cpp @@ -21,7 +21,9 @@ Vst3ContextMenuProxyImpl::Vst3ContextMenuProxyImpl( Vst3Bridge& bridge, Vst3ContextMenuProxy::ConstructArgs&& args) - : Vst3ContextMenuProxy(std::move(args)), bridge(bridge) {} + : Vst3ContextMenuProxy(std::move(args)), bridge(bridge) { + bridge.register_context_menu(*this); +} Vst3ContextMenuProxyImpl::~Vst3ContextMenuProxyImpl() { // Also drop the context menu smart pointer on plugin side when this gets @@ -29,6 +31,7 @@ Vst3ContextMenuProxyImpl::~Vst3ContextMenuProxyImpl() { bridge.send_message( Vst3ContextMenuProxy::Destruct{.owner_instance_id = owner_instance_id(), .context_menu_id = context_menu_id()}); + bridge.unregister_context_menu(owner_instance_id(), context_menu_id()); } tresult PLUGIN_API diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index de99d18d..4686620a 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -858,6 +858,25 @@ void Vst3Bridge::handle_win32_events() { } } +void Vst3Bridge::register_context_menu(Vst3ContextMenuProxy& context_menu) { + std::lock_guard lock(object_instances[context_menu.owner_instance_id()] + .registered_context_menus_mutex); + + object_instances[context_menu.owner_instance_id()] + .registered_context_menus.emplace( + context_menu.context_menu_id(), + std::ref(context_menu)); +} + +void Vst3Bridge::unregister_context_menu(size_t object_instance_id, + size_t context_menu_id) { + std::lock_guard lock( + object_instances[object_instance_id].registered_context_menus_mutex); + + object_instances[object_instance_id].registered_context_menus.erase( + context_menu_id); +} + size_t Vst3Bridge::generate_instance_id() { return current_instance_id.fetch_add(1); } diff --git a/src/wine-host/bridges/vst3.h b/src/wine-host/bridges/vst3.h index 53e01c7e..b4bd56a6 100644 --- a/src/wine-host/bridges/vst3.h +++ b/src/wine-host/bridges/vst3.h @@ -104,6 +104,20 @@ struct InstanceInterfaces { */ Steinberg::IPtr plug_frame_proxy; + /** + * Currently active context menu proxy instances. A call to + * `IComponentHandler3::createContextMenu` by the plugin will create a proxy + * object for the actual context menu returned by the host. We'll use this + * map to refer to a specific context menu later when the host wants to + * execute a specific menu item. + * + * @relates Vst3Bridge::register_context_menu + * @relates Vst3Bridge::unregister_context_menu + */ + std::map> + registered_context_menus; + std::mutex registered_context_menus_mutex; + /** * The base object we cast from. */ @@ -291,6 +305,21 @@ class Vst3Bridge : public HostBridge { return do_call_response.get(); } + /** + * Register a context with with `context_menu`'s ID and owner in + * `object_instances`. This will be called during the constructor of + * `Vst3ContextMenuProxyImpl` so we can refer to the exact instance later. + */ + void register_context_menu(Vst3ContextMenuProxy& context_menu); + + /** + * Remove a previously registered context menu from `object_instances`. This + * is called from the destructor of `Vst3ContextMenuProxyImpl` just before + * the object gets freed. + */ + void unregister_context_menu(size_t object_instance_id, + size_t context_menu_id); + private: Logger generic_logger;