From bf1dfbcdbfc3c2e25a6a0c00b2063c991ab34d47 Mon Sep 17 00:00:00 2001 From: Alexandre Bique Date: Sat, 4 May 2024 11:35:29 +0200 Subject: [PATCH] Intial glue code for plugin undo --- include/clap/helpers/host-proxy.hh | 16 ++++++++ include/clap/helpers/host-proxy.hxx | 64 +++++++++++++++++++++++++++++ include/clap/helpers/plugin.hh | 26 ++++++++++++ include/clap/helpers/plugin.hxx | 50 ++++++++++++++++++++++ 4 files changed, 156 insertions(+) diff --git a/include/clap/helpers/host-proxy.hh b/include/clap/helpers/host-proxy.hh index 4031251..e5749dc 100644 --- a/include/clap/helpers/host-proxy.hh +++ b/include/clap/helpers/host-proxy.hh @@ -185,6 +185,21 @@ namespace clap { namespace helpers { bool requestDirectory(bool isShared) const noexcept; void releaseDirectory(bool isShared) const noexcept; + //////////////////// + // clap_host_undo // + //////////////////// + bool canUseHostUndo() const noexcept; + void undoBeginChange() const noexcept; + void undoCancelChange() const noexcept; + void undoChangeMade(const char *name, + const void *redo_delta, + size_t redo_delta_size, + const void *undo_delta, + size_t undo_delta_size) const noexcept; + void undoUndo(const clap_host_t *host) const noexcept; + void undoRedo(const clap_host_t *host) const noexcept; + void undoSetWantsContextInfo(const clap_host_t *host, bool wants_info) const noexcept; + protected: void ensureMainThread(const char *method) const noexcept; void ensureAudioThread(const char *method) const noexcept; @@ -211,5 +226,6 @@ namespace clap { namespace helpers { const clap_host_tail *_hostTail = nullptr; const clap_host_context_menu *_hostContextMenu = nullptr; const clap_host_preset_load *_hostPresetLoad = nullptr; + const clap_host_undo *_hostUndo = nullptr; }; }} // namespace clap::helpers diff --git a/include/clap/helpers/host-proxy.hxx b/include/clap/helpers/host-proxy.hxx index c91d5b4..c39ff51 100644 --- a/include/clap/helpers/host-proxy.hxx +++ b/include/clap/helpers/host-proxy.hxx @@ -40,6 +40,7 @@ namespace clap { namespace helpers { getExtension(_hostPresetLoad, CLAP_EXT_PRESET_LOAD); if (!_hostPresetLoad) getExtension(_hostPresetLoad, CLAP_EXT_PRESET_LOAD); + getExtension(_hostUndo, CLAP_EXT_UNDO); } template @@ -681,4 +682,67 @@ namespace clap { namespace helpers { ensureMainThread("resource_directory.release_directory"); _hostResourceDirectory->release_directory(_host, isShared); } + + //////////////////// + // clap_host_undo // + //////////////////// + template + bool HostProxy::canUseHostUndo() const noexcept { + if (!_hostUndo) + return false; + + if (_hostUndo->begin_change && _hostUndo->cancel_change && _hostUndo->change_made && + _hostUndo->undo && _hostUndo->redo && _hostUndo->set_wants_context_info) + return true; + + return false; + } + + template + void HostProxy::undoBeginChange() const noexcept { + assert(canUseUndo()); + ensureMainThread("undo.begin_change"); + _hostUndo->begin_change(_host); + } + + template + void HostProxy::undoCancelChange() const noexcept { + assert(canUseUndo()); + ensureMainThread("undo.cancel_change"); + _hostUndo->cancel_change(_host); + } + + template + void HostProxy::undoChangeMade(const char *name, + const void *redo_delta, + size_t redo_delta_size, + const void *undo_delta, + size_t undo_delta_size) const noexcept { + assert(canUseUndo()); + ensureMainThread("undo.change_made"); + _hostUndo->change_made(_host, name, redo_delta, redo_delta_size, undo_delta, undo_delta_size); + } + + template + void HostProxy::undoUndo(const clap_host_t *host) const noexcept { + assert(canUseUndo()); + ensureMainThread("undo.undo"); + _hostUndo->undo(_host); + } + + template + void HostProxy::undoRedo(const clap_host_t *host) const noexcept { + assert(canUseUndo()); + ensureMainThread("undo.redo"); + _hostUndo->redo(_host); + } + + template + void HostProxy::undoSetWantsContextInfo(const clap_host_t *host, + bool wants_info) const noexcept { + assert(canUseUndo()); + ensureMainThread("undo.set_wants_context_info"); + _hostUndo->set_wants_context_info(_host, wants_info); + } + }} // namespace clap::helpers diff --git a/include/clap/helpers/plugin.hh b/include/clap/helpers/plugin.hh index 2ed3f32..2659f2a 100644 --- a/include/clap/helpers/plugin.hh +++ b/include/clap/helpers/plugin.hh @@ -283,6 +283,17 @@ namespace clap { namespace helpers { virtual bool implementsVoiceInfo() const noexcept { return false; } virtual bool voiceInfoGet(clap_voice_info *info) noexcept { return false; } + //------------------// + // clap_plugin_undo // + //------------------// + virtual bool implementsUndo() const noexcept { return false; } + virtual void undoGetDeltaProperties(clap_undo_delta_properties_t *properties) noexcept; + virtual bool undoCanUseDeltaFormatVersion(clap_id format_version) noexcept; + virtual bool + undoApplyDelta(clap_id format_version, const void *delta, size_t delta_size) noexcept; + virtual void + undoSetContextInfo(uint64_t flags, const char *undo_name, const char *redo_name) noexcept; + ///////////// // Logging // ///////////// @@ -523,6 +534,20 @@ namespace clap { namespace helpers { char *path, uint32_t path_size) noexcept; + // clap_plugin_undo + static void clapUndoGetDeltaProperties(const clap_plugin_t *plugin, + clap_undo_delta_properties_t *properties) noexcept; + static bool clapUndoCanUseDeltaFormatVersion(const clap_plugin_t *plugin, + clap_id format_version) noexcept; + static bool clapUndoApplyDelta(const clap_plugin_t *plugin, + clap_id format_version, + const void *delta, + size_t delta_size) noexcept; + static void clapUndoSetContextInfo(const clap_plugin_t *plugin, + uint64_t flags, + const char *undo_name, + const char *redo_name) noexcept; + // interfaces static const clap_plugin_audio_ports _pluginAudioPorts; static const clap_plugin_audio_ports_config _pluginAudioPortsConfig; @@ -546,6 +571,7 @@ namespace clap { namespace helpers { static const clap_plugin_voice_info _pluginVoiceInfo; static const clap_plugin_context_menu _pluginContextMenu; static const clap_plugin_resource_directory _pluginResourceDirectory; + static const clap_plugin_undo _pluginUndo; // state bool _wasInitialized = false; diff --git a/include/clap/helpers/plugin.hxx b/include/clap/helpers/plugin.hxx index 35d0159..be29ec5 100644 --- a/include/clap/helpers/plugin.hxx +++ b/include/clap/helpers/plugin.hxx @@ -147,6 +147,14 @@ namespace clap { namespace helpers { clapTailGet, }; + template + const clap_plugin_undo Plugin::_pluginUndo = { + clapUndoGetDeltaProperties, + clapUndoCanUseDeltaFormatVersion, + clapUndoApplyDelta, + clapUndoSetContextInfo, + }; + template Plugin::Plugin(const clap_plugin_descriptor *desc, const clap_host *host) : _host(host) { _plugin.plugin_data = this; @@ -496,6 +504,8 @@ namespace clap { namespace helpers { if (self.enableDraftExtensions()) { if (!strcmp(id, CLAP_EXT_RESOURCE_DIRECTORY) && self.implementsResourceDirectory()) return &_pluginResourceDirectory; + if (!strcmp(id, CLAP_EXT_UNDO) && self.implementsUndo()) + return &_pluginUndo; } return self.extension(id); @@ -1645,6 +1655,46 @@ namespace clap { namespace helpers { return self.resourceDirectoryGetFilePath(index, path, path_size); } + //------------------// + // clap_plugin_undo // + //------------------// + template + void + Plugin::clapUndoGetDeltaProperties(const clap_plugin_t *plugin, + clap_undo_delta_properties_t *properties) noexcept { + auto &self = from(plugin); + self.ensureMainThread("clap_undo.get_delta_properties"); + return self.undoGetDeltaProperties(properties); + } + + template + bool Plugin::clapUndoCanUseDeltaFormatVersion(const clap_plugin_t *plugin, + clap_id format_version) noexcept { + auto &self = from(plugin); + self.ensureMainThread("clap_undo.can_use_delta_format_version"); + return self.undoCanUseDeltaFormatVersion(format_version); + } + + template + bool Plugin::clapUndoApplyDelta(const clap_plugin_t *plugin, + clap_id format_version, + const void *delta, + size_t delta_size) noexcept { + auto &self = from(plugin); + self.ensureMainThread("clap_undo.apply_delta"); + return self.undoApplyDelta(format_version, delta, delta_size); + } + + template + void Plugin::clapUndoSetContextInfo(const clap_plugin_t *plugin, + uint64_t flags, + const char *undo_name, + const char *redo_name) noexcept { + auto &self = from(plugin); + self.ensureMainThread("clap_undo.set_context_info"); + return self.undoSetContextInfo(flags, undo_name, redo_name); + } + ///////////// // Logging // /////////////