clap

CLAP Audio Plugin API
Log | Files | Refs | README | LICENSE

commit 336eb2fdc0df58be80fc7885a1049376fa249310
parent 3ac3716a1716f3238c7cf91d89710b68597f8be2
Author: Alexandre BIQUE <bique.alexandre@gmail.com>
Date:   Fri, 30 Jul 2021 17:34:27 +0200

More work on the examples and rpc between the dsp and gui

Diffstat:
Aexamples/io/messages.hh | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mexamples/io/remote-channel.cc | 34+++++++++++++++++++++++++++++++---
Mexamples/io/remote-channel.hh | 71++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mexamples/plugins/abstract-gui.hh | 2+-
Mexamples/plugins/plugin-helper.cc | 26++++++++++++++++++++++----
Mexamples/plugins/plugin-helper.hh | 8++++----
Mexamples/plugins/remote-gui.cc | 16+++++++++++++++-
Mexamples/plugins/remote-gui.hh | 12+++++-------
8 files changed, 210 insertions(+), 49 deletions(-)

diff --git a/examples/io/messages.hh b/examples/io/messages.hh @@ -0,0 +1,89 @@ +#include <stdint.h> + +namespace clap::messages { + + enum Type : uint32_t { + // DSP->GUI + kDefineParameterRequest, + + // GUI->DSP + kBeginAdjustRequest, + kAdjustRequest, + kEndAdjustRequest, + + // Gui, Host->Plugin + kSetScaleRequest, + kSizeRequest, + kSizeResponse, + kRoundSizeRequest, + kRoundSizeResponse, + kSetSizeRequest, + kSetSizeResponse, + kShowRequest, + kHideRequest, + kCloseRequest, + + // Gui, Plugin->Host + kResizeRequest, + kResizeResponse, + }; + + struct SetScaleRequest final { + static const constexpr Type type = kSetScaleRequest; + double scale; + }; + + struct SizeRequest final { + static const constexpr Type type = kSizeRequest; + }; + + struct SizeResponse final { + static const constexpr Type type = kSizeResponse; + uint32_t width; + uint32_t height; + }; + + struct RoundSizeRequest final { + static const constexpr Type type = kRoundSizeRequest; + uint32_t width; + uint32_t height; + }; + + struct RoundSizeResponse final { + static const constexpr Type type = kRoundSizeResponse; + uint32_t width; + uint32_t height; + }; + + struct SetSizeRequest final { + static const constexpr Type type = kSetSizeRequest; + uint32_t width; + uint32_t height; + }; + + struct SetSizeResponse final { + static const constexpr Type type = kSetSizeResponse; + }; + + struct ShowRequest final { + static const constexpr Type type = kShowRequest; + }; + + struct HideRequest final { + static const constexpr Type type = kHideRequest; + }; + + struct CloseRequest final { + static const constexpr Type type = kCloseRequest; + }; + + struct ResizeRequest final { + static const constexpr Type type = kResizeRequest; + uint32_t width; + uint32_t height; + }; + + struct ResizeResponse final { + static const constexpr Type type = kResizeResponse; + }; +} // namespace clap::messages +\ No newline at end of file diff --git a/examples/io/remote-channel.cc b/examples/io/remote-channel.cc @@ -7,8 +7,11 @@ namespace clap { - RemoteChannel::RemoteChannel(Handler &handler, EventControl &evControl, int socket) - : handler_(handler), evControl_(evControl), socket_(socket) {} + RemoteChannel::RemoteChannel(const MessageHandler &handler, + EventControl &evControl, + int socket, + bool cookieHalf) + : cookieHalf_(cookieHalf), handler_(handler), evControl_(evControl), socket_(socket) {} RemoteChannel::~RemoteChannel() { close(); } @@ -27,7 +30,8 @@ namespace clap { inputBuffer_.rewind(); } - void RemoteChannel::write(const uint8_t *data, size_t size) { + void RemoteChannel::write(const void *_data, size_t size) { + const uint8_t *data = static_cast<const uint8_t *>(_data); while (size > 0) { auto &buffer = nextWriteBuffer(); buffer.write(data, size); @@ -85,4 +89,28 @@ namespace clap { ::close(socket_); socket_ = -1; } + + uint32_t RemoteChannel::computeNextCookie() noexcept { + uint32_t cookie = nextCookie_; + if (cookieHalf_) + cookie |= (1ULL << 31); + else + cookie &= ~(1ULL << 31); + + ++nextCookie_; // overflow is fine + return cookie; + } + + bool RemoteChannel::sendMessageAsync(const Message &msg) { + write(&msg.type, sizeof(msg.type)); + write(&msg.cookie, sizeof(msg.cookie)); + write(&msg.size, sizeof(msg.size)); + write(msg.data, msg.size); + onWrite(); + return true; + } + + bool RemoteChannel::sendMessageSync(const Message &msg, const MessageHandler &handler) { + return true; + } } // namespace clap \ No newline at end of file diff --git a/examples/io/remote-channel.hh b/examples/io/remote-channel.hh @@ -1,7 +1,10 @@ #pragma once -#include <queue> +#include <cstring> +#include <functional> #include <memory> +#include <queue> +#include <unordered_map> #include <clap/all.h> @@ -15,31 +18,35 @@ namespace clap { virtual void modifyFd(clap_fd_flags flags) = 0; }; - class Handler { - public: - virtual ~Handler() = default; - - // GUI callbacks - virtual void defineParameter(const clap_param_info &info) {} - virtual bool attachCocoa(void *nsView) { return false; } - virtual bool attachWin32(clap_hwnd window) { return false; } - virtual bool attachX11(const char *display_name, unsigned long window) { return false; } - - virtual void size(int32_t *width, int32_t *height) {} - virtual void setScale(double scale) {} - - virtual bool show() { return false; } - virtual bool hide() { return false; } - - virtual void close() {} - - // Plugin callbacks - virtual void beginAdjust(clap_id paramId) {} - virtual void adjust(clap_id paramId, double value) {} - virtual void endAdjust(clap_id paramId) {} + struct Message final { + uint32_t type; + uint32_t cookie; + uint32_t size; + const void *data; + + template <typename T> + Message(const T &msg, uint32_t c) : cookie(c) { + set(msg); + } + + template <typename T> + const T &get() const noexcept { + return *reinterpret_cast<const T *>(data); + } + + template <typename T> + void set(const T &msg) noexcept { + type = T::type; + data = &msg; + } }; - RemoteChannel(Handler &handler, EventControl &evControl, clap_fd socket); + using MessageHandler = std::function<void(const Message &response)>; + + RemoteChannel(const MessageHandler &handler, + EventControl &evControl, + clap_fd socket, + bool cookieHalf); ~RemoteChannel(); RemoteChannel(const RemoteChannel &) = delete; @@ -47,8 +54,10 @@ namespace clap { RemoteChannel &operator=(const RemoteChannel &) = delete; RemoteChannel &operator=(RemoteChannel &&) = delete; - void defineParameter(const clap_param_info &info); - void setParameterValue(clap_id paramId, double value); + uint32_t computeNextCookie() noexcept; + + bool sendMessageAsync(const Message &msg); + bool sendMessageSync(const Message &msg, const MessageHandler &handler); void close(); @@ -62,12 +71,16 @@ namespace clap { using ReadBuffer = Buffer<uint8_t, 128 * 1024>; using WriteBuffer = Buffer<uint8_t, 32 * 1024>; - void write(const uint8_t *data, size_t size); - WriteBuffer& nextWriteBuffer(); + void write(const void *data, size_t size); + WriteBuffer &nextWriteBuffer(); void parseInput(); - Handler &handler_; + const bool cookieHalf_; + uint32_t nextCookie_ = 0; + + const MessageHandler &handler_; + std::unordered_map<uint32_t /* cookie */, MessageHandler &> syncHandlers_; EventControl &evControl_; clap_fd socket_; diff --git a/examples/plugins/abstract-gui.hh b/examples/plugins/abstract-gui.hh @@ -14,7 +14,7 @@ namespace clap { virtual bool attachWin32(clap_hwnd window) noexcept = 0; virtual bool attachX11(const char *display_name, unsigned long window) noexcept = 0; - virtual void size(int32_t *width, int32_t *height) noexcept = 0; + virtual bool size(uint32_t *width, uint32_t *height) noexcept = 0; virtual void setScale(double scale) noexcept = 0; virtual bool show() noexcept = 0; diff --git a/examples/plugins/plugin-helper.cc b/examples/plugins/plugin-helper.cc @@ -80,12 +80,30 @@ namespace clap { return true; } - bool PluginHelper::guiSize(uint32_t *width, uint32_t *height) noexcept - { + bool PluginHelper::guiSize(uint32_t *width, uint32_t *height) noexcept { if (!remoteGui_) return false; - // TODO: synchronous call - return false; + return remoteGui_->size(width, height); + } + + void PluginHelper::guiSetScale(double scale) noexcept { + if (remoteGui_) + remoteGui_->setScale(scale); + } + + void PluginHelper::guiShow() noexcept { + if (remoteGui_) + remoteGui_->show(); + } + + void PluginHelper::guiHide() noexcept { + if (remoteGui_) + remoteGui_->hide(); + } + + void PluginHelper::guiClose() noexcept { + if (remoteGui_) + remoteGui_->close(); } } // namespace clap \ No newline at end of file diff --git a/examples/plugins/plugin-helper.hh b/examples/plugins/plugin-helper.hh @@ -84,10 +84,10 @@ namespace clap { void guiRoundSize(uint32_t *width, uint32_t *height) noexcept override { guiSize(width, height); } - void guiSetScale(double scale) noexcept override {} - void guiShow() noexcept override {} - void guiHide() noexcept override {} - void guiClose() noexcept override {} + void guiSetScale(double scale) noexcept override; + void guiShow() noexcept override; + void guiHide() noexcept override; + void guiClose() noexcept override; //---------------------// // clap_plugin_gui_x11 // diff --git a/examples/plugins/remote-gui.cc b/examples/plugins/remote-gui.cc @@ -6,6 +6,7 @@ #include <cassert> #include "remote-gui.hh" +#include <messages.hh> namespace clap { @@ -40,7 +41,8 @@ namespace clap { ::close(sockets[1]); } - channel_.reset(new RemoteChannel(*this, *this, sockets[0])); + channel_.reset(new RemoteChannel( + [this](const RemoteChannel::Message &msg) { onMessage(msg); }, *this, sockets[0], true)); return true; #else @@ -48,4 +50,16 @@ namespace clap { #endif } + bool RemoteGui::size(uint32_t *width, uint32_t *height) noexcept { + channel_->sendMessageSync( + RemoteChannel::Message(messages::SizeRequest{}, channel_->computeNextCookie()), + [width, height](const RemoteChannel::Message &m) { + auto &response = m.get<messages::SizeResponse>(); + *width = response.width; + *height = response.height; + }); + + return true; + } + } // namespace clap \ No newline at end of file diff --git a/examples/plugins/remote-gui.hh b/examples/plugins/remote-gui.hh @@ -10,7 +10,8 @@ #include "remote-channel.hh" namespace clap { - class RemoteGui : public AbstractGui, public RemoteChannel::Handler, public RemoteChannel::EventControl { + class RemoteGui : public AbstractGui, public RemoteChannel::EventControl { + public: RemoteGui(PluginHelper &plugin) : AbstractGui(plugin) {} bool spawn(); @@ -19,7 +20,7 @@ namespace clap { bool attachWin32(clap_hwnd window) noexcept override; bool attachX11(const char *display_name, unsigned long window) noexcept override; - void size(int32_t *width, int32_t *height) noexcept override; + bool size(uint32_t *width, uint32_t *height) noexcept override; void setScale(double scale) noexcept override; bool show() noexcept override; @@ -27,15 +28,12 @@ namespace clap { void close() noexcept override; - // RemoteChannel::Handler - void beginAdjust(clap_id paramId) override; - void adjust(clap_id paramId, double value) override; - void endAdjust(clap_id paramId) override; - // RemoteChannel::EventControl void modifyFd(clap_fd_flags flags) override; private: + void onMessage(const RemoteChannel::Message& msg); + std::unique_ptr<RemoteChannel> channel_; #ifdef __unix__