commit ed43574b1b026c3d9a4af0da6862b9dcea15b765
parent 40881b7bc288664471ddab5a535840937b80c05d
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date: Tue, 15 Aug 2023 11:08:55 +0200
Merge pull request #336 from abique/undo
Initial take on undo support
Diffstat:
3 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/ChangeLog.md b/ChangeLog.md
@@ -6,6 +6,10 @@
* [gui.h](include/clap/ext/gui.h): documentation clarifications
* [entry.h](include/clap/entry.h): documentation clarifications
+## Draft extensions
+
+* [undo.h](include/clap/ext/draft/undo.h): undo support
+
# Changes in 1.1.9
* [entry.h](include/clap/entry.h): clarify what the `plugin_path` is on macOS
diff --git a/include/clap/clap.h b/include/clap/clap.h
@@ -69,3 +69,4 @@
#include "ext/draft/tuning.h"
#include "ext/draft/configurable-audio-ports.h"
#include "ext/draft/extensible-audio-ports.h"
+#include "ext/draft/undo.h"
diff --git a/include/clap/ext/draft/undo.h b/include/clap/ext/draft/undo.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "../../plugin.h"
+#include "../../string-sizes.h"
+
+static CLAP_CONSTEXPR const char CLAP_EXT_UNDO[] = "clap.undo.draft/0";
+
+// Describes a change which can be undone or redone
+typedef struct clap_undo_change_info {
+ // This is the unique identifier of this undo step.
+ // It is valid until loading a state or destroying the plugin.
+ clap_id change_id;
+
+ // A short string which describes the corresponding change.
+ char description[CLAP_NAME_SIZE];
+} clap_undo_change_info_t;
+
+typedef struct clap_plugin_undo {
+ // returns true if an undo/redo step exists and the info were provided
+ // [main-thread]
+ bool (*get_current_undo_info)(clap_plugin_t *plugin, clap_undo_change_info_t *info);
+ bool (*get_current_redo_info)(clap_plugin_t *plugin, clap_undo_change_info_t *info);
+
+ // Request the plugin to perform an undo operation (async).
+ //
+ // Returns true if the request is being processed, false otherwise.
+ // When returning true, the plugin **must** call clap_host_undo->after_undo_request() once the
+ // request is completed or failed.
+ //
+ // The plugin should only perform the operation if the current undo/redo operation matches the
+ // given id; this is because of the asynchronous nature of the task and to avoid race conditions
+ // if the plugin's undo manager lives in a different thread.
+ //
+ // Call sequence:
+ // 1. plugin->request_undo(change_id=X) -> returns true
+ // 2. later on host->begin_undo(change_id=X)
+ // 3. later on host->end_undo(change_id=X), host->after_undo(change_id=X, true, nullptr)
+ // [main-thread]
+ bool (*request_undo)(clap_plugin_t *plugin, clap_id change_id);
+ bool (*request_redo)(clap_plugin_t *plugin, clap_id change_id);
+} clap_plugin_undo_t;
+
+typedef struct clap_host_undo {
+ // Marks the begining and end of a change which will lead to the creation of an undo step.
+ // [main-thread]
+ void (*begin_change)(clap_host_t *host, const clap_undo_change_info_t *info);
+ void (*end_change)(clap_host_t *host, const clap_undo_change_info_t *info);
+
+ // Marks the beginning and end of processing an undo change.
+ // [main-thread]
+ void (*begin_undo)(clap_host_t *host, const clap_undo_change_info_t *info);
+ void (*end_undo)(clap_host_t *host, const clap_undo_change_info_t *info);
+
+ // Marks the beginning and end of processing a redo change.
+ // [main-thread]
+ void (*begin_redo)(clap_host_t *host, const clap_undo_change_info_t *info);
+ void (*end_redo)(clap_host_t *host, const clap_undo_change_info_t *info);
+
+ // A destructive change happened which makes it impossible to perform an undo.
+ // The entire plugin's undo/redo stack has been cleared.
+ // [main-thread]
+ void (*after_destructive_change)(clap_host_t *host);
+
+ // Callbacks for clap_plugin_undo->request_*()
+ // If succeed is true, then error_msg is ignored and may be null.
+ // [main-thread]
+ void (*after_undo_request)(clap_host_t *host,
+ clap_id change_id,
+ bool succeed,
+ const char *error_msg);
+ void (*after_redo_request)(clap_host_t *host,
+ clap_id change_id,
+ bool succeed,
+ const char *error_msg);
+} clap_host_undo_t;