Add CLAP plugin destroying

Everything else is still a stub, but at least the lifecycle now works
correctly.
This commit is contained in:
Robbert van der Helm
2022-09-09 15:32:19 +02:00
parent 54dd4c583f
commit d2fb84e529
6 changed files with 51 additions and 14 deletions
+10 -4
View File
@@ -38,16 +38,22 @@ bool ClapLogger::log_request(bool is_host_plugin,
}); });
} }
bool ClapLogger::log_request(bool is_host_plugin,
const clap::plugin::Destroy& request) {
return log_request_base(is_host_plugin, [&](auto& message) {
message << request.instance_id << ": clap_plugin::destroy()";
});
}
bool ClapLogger::log_request(bool is_host_plugin, const WantsConfiguration&) { bool ClapLogger::log_request(bool is_host_plugin, const WantsConfiguration&) {
return log_request_base(is_host_plugin, [&](auto& message) { return log_request_base(is_host_plugin, [&](auto& message) {
message << "Requesting <Configuration>"; message << "Requesting <Configuration>";
}); });
} }
// void ClapLogger::log_response(bool is_host_plugin, const Ack&) { void ClapLogger::log_response(bool is_host_plugin, const Ack&) {
// log_response_base(is_host_plugin, [&](auto& message) { message << "ACK"; log_response_base(is_host_plugin, [&](auto& message) { message << "ACK"; });
// }); }
// }
void ClapLogger::log_response( void ClapLogger::log_response(
bool is_host_plugin, bool is_host_plugin,
+2 -1
View File
@@ -47,6 +47,7 @@ class ClapLogger {
bool log_request(bool is_host_plugin, const clap::plugin_factory::List&); bool log_request(bool is_host_plugin, const clap::plugin_factory::List&);
bool log_request(bool is_host_plugin, const clap::plugin_factory::Create&); bool log_request(bool is_host_plugin, const clap::plugin_factory::Create&);
bool log_request(bool is_host_plugin, const clap::plugin::Destroy&);
// TODO: Audio thread requests // TODO: Audio thread requests
// bool log_request(bool is_host_plugin, // bool log_request(bool is_host_plugin,
@@ -54,7 +55,7 @@ class ClapLogger {
bool log_request(bool is_host_plugin, const WantsConfiguration&); bool log_request(bool is_host_plugin, const WantsConfiguration&);
// void log_response(bool is_host_plugin, const Ack&); void log_response(bool is_host_plugin, const Ack&);
void log_response(bool is_host_plugin, void log_response(bool is_host_plugin,
const clap::plugin_factory::ListResponse&); const clap::plugin_factory::ListResponse&);
void log_response(bool is_host_plugin, void log_response(bool is_host_plugin,
+2 -1
View File
@@ -41,7 +41,8 @@
// serialize this without it. // serialize this without it.
using ClapMainThreadControlRequest = std::variant<WantsConfiguration, using ClapMainThreadControlRequest = std::variant<WantsConfiguration,
clap::plugin_factory::List, clap::plugin_factory::List,
clap::plugin_factory::Create>; clap::plugin_factory::Create,
clap::plugin::Destroy>;
template <typename S> template <typename S>
void serialize(S& s, ClapMainThreadControlRequest& payload) { void serialize(S& s, ClapMainThreadControlRequest& payload) {
+17
View File
@@ -24,6 +24,7 @@
#include <clap/plugin.h> #include <clap/plugin.h>
#include "../../bitsery/ext/in-place-optional.h" #include "../../bitsery/ext/in-place-optional.h"
#include "../common.h"
// Serialization messages for `clap/plugin.h` // Serialization messages for `clap/plugin.h`
@@ -104,6 +105,22 @@ struct Descriptor {
mutable clap_plugin_descriptor_t clap_descriptor; mutable clap_plugin_descriptor_t clap_descriptor;
}; };
/**
* Message struct for `clap_plugin::destroy()`. The Wine plugin host should
* clean up the plugin, and everything is also cleaned up on the plugin side
* after receiving acknowledgement
*/
struct Destroy {
using Response = Ack;
native_size_t instance_id;
template <typename S>
void serialize(S& s) {
s.value8b(instance_id);
}
};
} // namespace plugin } // namespace plugin
} // namespace clap } // namespace clap
@@ -54,9 +54,12 @@ clap_plugin_proxy::plugin_destroy(const struct clap_plugin* plugin) {
assert(plugin && plugin->plugin_data); assert(plugin && plugin->plugin_data);
auto self = static_cast<const clap_plugin_proxy*>(plugin->plugin_data); auto self = static_cast<const clap_plugin_proxy*>(plugin->plugin_data);
// TODO: Destroy on the Wine side // This will clean everything related to this instance up on the Wine plugin
// host side
self->bridge_.send_main_thread_message(
clap::plugin::Destroy{.instance_id = self->instance_id()});
// This deallocates and destroys `self` // And this deallocates and destroys `self`
self->bridge_.unregister_plugin_proxy(self->instance_id()); self->bridge_.unregister_plugin_proxy(self->instance_id());
} }
+15 -6
View File
@@ -209,6 +209,19 @@ void ClapBridge::run() {
}) })
.get(); .get();
}, },
[&](clap::plugin::Destroy& request)
-> clap::plugin::Destroy::Response {
return main_context_
.run_in_context([&]() {
// This calls `clap_plugin::destroy()` as part of
// cleaning up the `unique_ptr` holding the plugin
// instance pointer
unregister_plugin_instance(request.instance_id);
return Ack{};
})
.get();
},
}); });
} }
@@ -446,12 +459,8 @@ void ClapBridge::unregister_plugin_instance(size_t instance_id) {
// Remove the instance from within the main IO context so // Remove the instance from within the main IO context so
// removing it doesn't interfere with the Win32 message loop // removing it doesn't interfere with the Win32 message loop
// XXX: I don't think we have to wait for the object to be // NOTE: This will implicitly run `clap_plugin::destroy()` as part of the
// deleted most of the time, but I can imagine a situation // `unique_ptr`'s cleanup
// where the plugin does a host callback triggered by a
// Win32 timer in between where the above closure is being
// executed and when the actual host application context on
// the plugin side gets deallocated.
main_context_ main_context_
.run_in_context([&, instance_id]() -> void { .run_in_context([&, instance_id]() -> void {
std::unique_lock lock(object_instances_mutex_); std::unique_lock lock(object_instances_mutex_);