Skip to content

Commit f350abd

Browse files
authored
Merge pull request #405 from free-audio/next
CLAP 1.2.1
2 parents df8f16c + 1dcc744 commit f350abd

File tree

5 files changed

+181
-1
lines changed

5 files changed

+181
-1
lines changed

ChangeLog.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# Changes in 1.2.1
2+
3+
## New draft extensions
4+
5+
* [undo.h](include/clap/ext/draft/undo.h): shared undo stack for the host and plugin.
6+
7+
## Documentation
8+
9+
* [events.h](include/clap/events.h): clarification for note on events.
10+
111
# Changes in 1.2.0
212

313
## New conventions

include/clap/all.h

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@
1010
#include "ext/draft/transport-control.h"
1111
#include "ext/draft/triggers.h"
1212
#include "ext/draft/tuning.h"
13+
#include "ext/draft/undo.h"

include/clap/events.h

+6
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ enum {
144144
// Well constructed plugins will search for voices and notes using
145145
// the entire tuple.
146146
//
147+
// In the case of note on events:
148+
// - The port, channel and key must be specified with a value >= 0
149+
// - A note-on event with a '-1' for port, channel or key is invalid and
150+
// can be rejected or ignored by a plugin or host.
151+
// - A host which does not support note ids should set the note id to -1.
152+
//
147153
// In the case of note choke or end events:
148154
// - the velocity is ignored.
149155
// - key and channel are used to match active notes

include/clap/ext/draft/undo.h

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#pragma once
2+
3+
#include "../../plugin.h"
4+
5+
static CLAP_CONSTEXPR const char CLAP_EXT_UNDO[] = "clap.undo/2";
6+
7+
#ifdef __cplusplus
8+
extern "C" {
9+
#endif
10+
11+
/// @page Undo
12+
///
13+
/// This extension enables the plugin to merge its undo history with the host.
14+
/// This leads to a single undo history shared by the host and many plugins.
15+
///
16+
/// Calling host->undo() or host->redo() is equivalent to clicking undo/redo within the host's GUI.
17+
///
18+
/// If the plugin implements this interface then its undo and redo should be entirely delegated to
19+
/// the host; clicking in the plugin's UI undo or redo is equivalent to clicking undo or redo in the
20+
/// host's UI.
21+
///
22+
/// Some changes are long running changes, for example a mouse interaction will begin editing some
23+
/// complex data and it may take multiple events and a long duration to complete the change.
24+
/// In such case the plugin will call host->begin_change() to indicate the beginning of a long
25+
/// running change and complete the change by calling host->change_made().
26+
///
27+
/// The host may group changes together:
28+
/// [---------------------------------]
29+
/// ^-T0 ^-T1 ^-T2 ^-T3
30+
/// Here a long running change C0 begin at T0.
31+
/// A instantaneous change C1 at T1, and another one C2 at T2.
32+
/// Then at T3 the long running change is completed.
33+
/// The host will then create a single undo step that will merge all the changes into C0.
34+
///
35+
/// This leads to another important consideration: starting a long running change without
36+
/// terminating is **VERY BAD**, because while a change is running it is impossible to call undo or
37+
/// redo.
38+
///
39+
/// Rationale: multiple designs were considered and this one has the benefit of having a single undo
40+
/// history. This simplifies the host implementation, leading to less bugs, a more robust design
41+
/// and maybe an easier experience for the user because there's a single undo context versus one
42+
/// for the host and one for each plugin instance.
43+
44+
enum clap_undo_context_flags {
45+
// While the host is within a change, it is impossible to perform undo or redo.
46+
CLAP_UNDO_IS_WITHIN_CHANGE = 1 << 0,
47+
};
48+
49+
enum clap_undo_delta_properties_flags {
50+
// If not set, then all clap_undo_delta_properties's attributes become irrelevant.
51+
// If set, then the plugin will provide deltas in host->change_made().
52+
CLAP_UNDO_DELTA_PROPERTIES_HAS_DELTA = 1 << 0,
53+
54+
// If set, then the delta will be reusable in the future as long as the plugin is
55+
// compatible with the given format_version.
56+
CLAP_UNDO_DELTA_PROPERTIES_IS_PERSISTENT = 1 << 1,
57+
};
58+
59+
typedef struct clap_undo_delta_properties {
60+
// Bitmask of clap_undo_delta_properties_flags
61+
uint64_t flags;
62+
63+
// This represents the delta format version that the plugin is using.
64+
uint32_t format_version;
65+
} clap_undo_delta_properties_t;
66+
67+
typedef struct clap_plugin_undo {
68+
// Asks the plugin the delta properties.
69+
// [main-thread]
70+
void(CLAP_ABI *get_delta_properties)(const clap_plugin_t *plugin,
71+
clap_undo_delta_properties_t *properties);
72+
73+
// Asks the plugin if it can apply a delta using the given format version.
74+
// Returns true if it is possible.
75+
// [main-thread]
76+
bool(CLAP_ABI *can_use_delta_format_version)(const clap_plugin_t *plugin,
77+
clap_id format_version);
78+
79+
// Applies synchronously a delta.
80+
// Returns true on success.
81+
//
82+
// [main-thread]
83+
bool(CLAP_ABI *apply_delta)(const clap_plugin_t *plugin,
84+
clap_id format_version,
85+
const void *delta,
86+
size_t delta_size);
87+
88+
// Sets the undo context.
89+
// flags: bitmask of clap_undo_context_flags values
90+
// names: null terminated string if an redo/undo step exists, null otherwise.
91+
// [main-thread]
92+
void(CLAP_ABI *set_context_info)(const clap_plugin_t *plugin,
93+
uint64_t flags,
94+
const char *undo_name,
95+
const char *redo_name);
96+
} clap_plugin_undo_t;
97+
98+
typedef struct clap_host_undo {
99+
// Begins a long running change.
100+
// The plugin must not call this twice: there must be either a call to cancel_change() or
101+
// change_made() before calling begin_change() again.
102+
// [main-thread]
103+
void(CLAP_ABI *begin_change)(const clap_host_t *host);
104+
105+
// Cancels a long running change.
106+
// cancel_change() must not be called without a preceding begin_change().
107+
// [main-thread]
108+
void(CLAP_ABI *cancel_change)(const clap_host_t *host);
109+
110+
// Completes an undoable change.
111+
// At the moment of this function call, plugin_state->save() would include the current change.
112+
//
113+
// name: mandatory null terminated string describing the change, this is displayed to the user
114+
//
115+
// deltas: optional, they are binary blobs used to perform the undo and redo. When not available
116+
// the host will save the plugin state and use state->load() to perform undo and redo.
117+
//
118+
// Note: the provided delta may be used for incremental state saving and crash recovery. The
119+
// plugin can indicate a format version id and the validity lifetime for the binary blobs.
120+
// The host can use these to verify the compatibility before applying the delta.
121+
// If the plugin is unable to use a delta, a notification should be provided to the user and
122+
// the crash recovery should perform a best effort job, at least restoring the latest saved state.
123+
//
124+
// Special case: for objects with shared and synchronized state, changes shouldn't be reported
125+
// as the host already knows about it.
126+
// For example, plugin parameter changes shouldn't produce a call to change_made().
127+
//
128+
// [main-thread]
129+
void(CLAP_ABI *change_made)(const clap_host_t *host,
130+
const char *name,
131+
const void *redo_delta,
132+
size_t redo_delta_size,
133+
const void *undo_delta,
134+
size_t undo_delta_size);
135+
136+
// Asks the host to perform the next undo step.
137+
// This operation may be asynchronous.
138+
// [main-thread]
139+
void(CLAP_ABI *undo)(const clap_host_t *host);
140+
141+
// Asks the host to perform the next redo step.
142+
// This operation may be asynchronous.
143+
// [main-thread]
144+
void(CLAP_ABI *redo)(const clap_host_t *host);
145+
146+
// Subscribes to or unsubscribes from undo context info.
147+
//
148+
// This method helps reducing the number of calls the host has to perform when updating
149+
// the undo context info. Consider a large project with 1000+ plugins, we don't want to
150+
// call 1000+ times update, while the plugin may only need the context info if its GUI
151+
// is shown and it wants to display undo/redo info.
152+
//
153+
// Initial state is unsubscribed.
154+
//
155+
// is_subscribed: set to true to receive context info
156+
//
157+
// [main-thread]
158+
void(CLAP_ABI *set_context_info_subscription)(const clap_host_t *host, bool is_subscribed);
159+
} clap_host_undo_t;
160+
161+
#ifdef __cplusplus
162+
}
163+
#endif

include/clap/version.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ typedef struct clap_version {
2222

2323
#define CLAP_VERSION_MAJOR 1
2424
#define CLAP_VERSION_MINOR 2
25-
#define CLAP_VERSION_REVISION 0
25+
#define CLAP_VERSION_REVISION 1
2626

2727
#define CLAP_VERSION_INIT \
2828
{ (uint32_t)CLAP_VERSION_MAJOR, (uint32_t)CLAP_VERSION_MINOR, (uint32_t)CLAP_VERSION_REVISION }

0 commit comments

Comments
 (0)