-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'next' into track-info-track-index
- Loading branch information
Showing
13 changed files
with
384 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,3 +58,5 @@ cmake-build*/ | |
|
||
# A place to store stuff and get it git ignored | ||
ignore/* | ||
|
||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#pragma once | ||
|
||
#include "../../plugin.h" | ||
|
||
// This extension lets the plugin request "scratch" memory | ||
// from the host. Scratch memory can be accessed during the | ||
// `process()` callback, but its content not persistent | ||
// between callbacks. | ||
// | ||
// The motivation for this extension is to allow the plugin host | ||
// to "share" a single scratch buffer across multiple plugin | ||
// instances. | ||
// | ||
// For example, imagine the host needs to process three plugins | ||
// in sequence, and each plugin requires 10K of scratch memory. | ||
// If each plugin pre-allocates its own scratch memory, then 30K | ||
// of memory is being allocated in total. However, if each plugin | ||
// requests 10K of scratch memory from the host, then the host can | ||
// allocate a single 10K scratch buffer, and make it available to all | ||
// three plugins. | ||
// | ||
// This optimization may allow for reduced memory usage and improved | ||
// CPU cache usage. | ||
|
||
static CLAP_CONSTEXPR const char CLAP_EXT_SCRATCH_MEMORY[] = "clap.scratch-memory/1"; | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
typedef struct clap_host_scratch_memory { | ||
// Asks the host for certain amount of scratch memory. | ||
// If the host is unable to provide the memory, it should | ||
// return "false". | ||
// | ||
// The plugin may call this method multiple times (for | ||
// example, gradually decreasing the amount of scratch | ||
// being asked for until the host returns true), however, | ||
// the plugin should avoid calling this method un-neccesarily | ||
// since the host implementation may be relatively expensive. | ||
// If the plugin calls `reserve()` multiple times, then the | ||
// final call determines the actual amount of scratch memory | ||
// that will be available to the plugin. If the final call | ||
// returns false then no scratch memory will be provided, | ||
// regardless of any previous calls to `reserve()`. | ||
// | ||
// When the plugin is de-activated, the scratch memory | ||
// is invalidated, and the host may free the memory if | ||
// appropriate. The plugin will need to reserve scratch | ||
// memory again the next time it is activated. | ||
// | ||
// In the context of plugins and hosts that implement | ||
// the "thread-pool" extension, scratch memory is assumed | ||
// to be "thread-local". The plugin should request the maximum | ||
// amount of scratch memory that it will need on a single | ||
// thread. Accordingly, the host must ensure that each | ||
// thread can independently provide the requested amount | ||
// of scratch memory. | ||
// | ||
// [main-thread & being-activated] | ||
bool(CLAP_ABI *reserve)(const clap_host_t *host, uint32_t scratch_size_bytes); | ||
|
||
// Asks the host for the previously reserved scratch memory. | ||
// If the host returned "true" when scratch memory was requested, | ||
// then this method must return a pointer to a memory block at least | ||
// as large as the reserved size. If the host returned "false" | ||
// when scratch memory was requested, then this method must not | ||
// be called, and will return NULL. | ||
// | ||
// This method may only be called by the plugin from the audio thread, | ||
// (i.e. during the process() or thread_pool.exec() callback), and | ||
// the provided memory is only valid until the plugin returns from | ||
// that callback. The plugin must not hold any references to data | ||
// that lives in the scratch memory after returning from the callback, | ||
// as that data will likely be over-written by another plugin using | ||
// the same scratch memory. | ||
// | ||
// The provided memory is not initialized, and may have been used | ||
// by other plugin instances, so the plugin must correctly initialize | ||
// the memory when using it. | ||
// | ||
// The provided memory is owned by the host, so the plugin should not | ||
// attempt to free the memory. | ||
// | ||
// [audio-thread] | ||
void*(CLAP_ABI *access)(const clap_host_t *host); | ||
} clap_host_scratch_memory_t; | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
#pragma once | ||
|
||
#include "../../plugin.h" | ||
#include "../../stream.h" | ||
|
||
static CLAP_CONSTEXPR const char CLAP_EXT_UNDO[] = "clap.undo/4"; | ||
static CLAP_CONSTEXPR const char CLAP_EXT_UNDO_CONTEXT[] = "clap.undo_context/4"; | ||
static CLAP_CONSTEXPR const char CLAP_EXT_UNDO_DELTA[] = "clap.undo_delta/4"; | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/// @page Undo | ||
/// | ||
/// This extension enables the plugin to merge its undo history with the host. | ||
/// This leads to a single undo history shared by the host and many plugins. | ||
/// | ||
/// Calling host->undo() or host->redo() is equivalent to clicking undo/redo within the host's GUI. | ||
/// | ||
/// If the plugin uses this interface then its undo and redo should be entirely delegated to | ||
/// the host; clicking in the plugin's UI undo or redo is equivalent to clicking undo or redo in the | ||
/// host's UI. | ||
/// | ||
/// Some changes are long running changes, for example a mouse interaction will begin editing some | ||
/// complex data and it may take multiple events and a long duration to complete the change. | ||
/// In such case the plugin will call host->begin_change() to indicate the beginning of a long | ||
/// running change and complete the change by calling host->change_made(). | ||
/// | ||
/// The host may group changes together: | ||
/// [---------------------------------] | ||
/// ^-T0 ^-T1 ^-T2 ^-T3 | ||
/// Here a long running change C0 begin at T0. | ||
/// A instantaneous change C1 at T1, and another one C2 at T2. | ||
/// Then at T3 the long running change is completed. | ||
/// The host will then create a single undo step that will merge all the changes into C0. | ||
/// | ||
/// This leads to another important consideration: starting a long running change without | ||
/// terminating is **VERY BAD**, because while a change is running it is impossible to call undo or | ||
/// redo. | ||
/// | ||
/// Rationale: multiple designs were considered and this one has the benefit of having a single undo | ||
/// history. This simplifies the host implementation, leading to less bugs, a more robust design | ||
/// and maybe an easier experience for the user because there's a single undo context versus one | ||
/// for the host and one for each plugin instance. | ||
/// | ||
/// This extension tries to make it as easy as possible for the plugin to hook into the host undo | ||
/// and make it efficient when possible by using deltas. The plugin interfaces are all optional, and | ||
/// the plugin can for a minimal implementation, just use the host interface and call | ||
/// host->change_made() without providing a delta. This is enough for the host to know that it can | ||
/// capture a plugin state for the undo step. | ||
|
||
typedef struct clap_undo_delta_properties { | ||
// If true, then the plugin will provide deltas in host->change_made(). | ||
// If false, then all clap_undo_delta_properties's attributes become irrelevant. | ||
bool has_delta; | ||
|
||
// If true, then the deltas can be stored on disk and re-used in the future as long as the plugin | ||
// is compatible with the given format_version. | ||
// | ||
// If false, then format_version must be set to CLAP_INVALID_ID. | ||
bool are_deltas_persistent; | ||
|
||
// This represents the delta format version that the plugin is currently using. | ||
// Use CLAP_INVALID_ID for invalid value. | ||
clap_id format_version; | ||
} clap_undo_delta_properties_t; | ||
|
||
// Use CLAP_EXT_UNDO_DELTA. | ||
// This is an optional interface, using deltas is an optimization versus making a state snapshot. | ||
typedef struct clap_plugin_undo_delta { | ||
// Asks the plugin the delta properties. | ||
// [main-thread] | ||
void(CLAP_ABI *get_delta_properties)(const clap_plugin_t *plugin, | ||
clap_undo_delta_properties_t *properties); | ||
|
||
// Asks the plugin if it can apply a delta using the given format version. | ||
// Returns true if it is possible. | ||
// [main-thread] | ||
bool(CLAP_ABI *can_use_delta_format_version)(const clap_plugin_t *plugin, | ||
clap_id format_version); | ||
|
||
// Undo using the delta. | ||
// Returns true on success. | ||
// | ||
// [main-thread] | ||
bool(CLAP_ABI *undo)(const clap_plugin_t *plugin, | ||
clap_id format_version, | ||
const void *delta, | ||
size_t delta_size); | ||
|
||
// Redo using the delta. | ||
// Returns true on success. | ||
// | ||
// [main-thread] | ||
bool(CLAP_ABI *redo)(const clap_plugin_t *plugin, | ||
clap_id format_version, | ||
const void *delta, | ||
size_t delta_size); | ||
} clap_plugin_undo_delta_t; | ||
|
||
// Use CLAP_EXT_UNDO_CONTEXT. | ||
// This is an optional interface, that the plugin can implement in order to know about | ||
// the current undo context. | ||
typedef struct clap_plugin_undo_context { | ||
// Indicate if it is currently possible to perform an undo or redo operation. | ||
// [main-thread & plugin-subscribed-to-undo-context] | ||
void(CLAP_ABI *set_can_undo)(const clap_plugin_t *plugin, bool can_undo); | ||
void(CLAP_ABI *set_can_redo)(const clap_plugin_t *plugin, bool can_redo); | ||
|
||
// Sets the name of the next undo or redo step. | ||
// name: null terminated string. | ||
// [main-thread & plugin-subscribed-to-undo-context] | ||
void(CLAP_ABI *set_undo_name)(const clap_plugin_t *plugin, const char *name); | ||
void(CLAP_ABI *set_redo_name)(const clap_plugin_t *plugin, const char *name); | ||
} clap_plugin_undo_context_t; | ||
|
||
// Use CLAP_EXT_UNDO. | ||
typedef struct clap_host_undo { | ||
// Begins a long running change. | ||
// The plugin must not call this twice: there must be either a call to cancel_change() or | ||
// change_made() before calling begin_change() again. | ||
// [main-thread] | ||
void(CLAP_ABI *begin_change)(const clap_host_t *host); | ||
|
||
// Cancels a long running change. | ||
// cancel_change() must not be called without a preceding begin_change(). | ||
// [main-thread] | ||
void(CLAP_ABI *cancel_change)(const clap_host_t *host); | ||
|
||
// Completes an undoable change. | ||
// At the moment of this function call, plugin_state->save() would include the current change. | ||
// | ||
// name: mandatory null terminated string describing the change, this is displayed to the user | ||
// | ||
// delta: optional, it is a binary blobs used to perform the undo and redo. When not available | ||
// the host will save the plugin state and use state->load() to perform undo and redo. | ||
// The plugin must be able to perform a redo operation using the delta, though the undo operation | ||
// is only possible if delta_can_undo is true. | ||
// | ||
// Note: the provided delta may be used for incremental state saving and crash recovery. The | ||
// plugin can indicate a format version id and the validity lifetime for the binary blobs. | ||
// The host can use these to verify the compatibility before applying the delta. | ||
// If the plugin is unable to use a delta, a notification should be provided to the user and | ||
// the crash recovery should perform a best effort job, at least restoring the latest saved | ||
// state. | ||
// | ||
// Special case: for objects with shared and synchronized state, changes shouldn't be reported | ||
// as the host already knows about it. | ||
// For example, plugin parameter changes shouldn't produce a call to change_made(). | ||
// | ||
// Note: if the plugin asked for this interface, then host_state->mark_dirty() will not create an | ||
// implicit undo step. | ||
// | ||
// Note: if the plugin did load a preset or did something that leads to a large delta, | ||
// it may consider not producing a delta (pass null) and let the host make a state snapshot | ||
// instead. | ||
// | ||
// Note: if a plugin is producing a lot of changes within a small amount of time, the host | ||
// may merge them into a single undo step. | ||
// | ||
// [main-thread] | ||
void(CLAP_ABI *change_made)(const clap_host_t *host, | ||
const char *name, | ||
const void *delta, | ||
size_t delta_size, | ||
bool delta_can_undo); | ||
|
||
// Asks the host to perform the next undo or redo step. | ||
// | ||
// Note: this maybe a complex and asynchronous operation, which may complete after | ||
// this function returns. | ||
// | ||
// Note: the host may ignore this request if there is no undo/redo step to perform, | ||
// or if the host is unable to perform undo/redo at the time (eg: a long running | ||
// change is going on). | ||
// | ||
// [main-thread] | ||
void(CLAP_ABI *request_undo)(const clap_host_t *host); | ||
void(CLAP_ABI *request_redo)(const clap_host_t *host); | ||
|
||
// Subscribes to or unsubscribes from undo context info. | ||
// | ||
// This method helps reducing the number of calls the host has to perform when updating | ||
// the undo context info. Consider a large project with 1000+ plugins, we don't want to | ||
// call 1000+ times update, while the plugin may only need the context info if its GUI | ||
// is shown and it wants to display undo/redo info. | ||
// | ||
// Initial state is unsubscribed. | ||
// | ||
// is_subscribed: set to true to receive context info | ||
// | ||
// It is mandatory for the plugin to implement CLAP_EXT_UNDO_CONTEXT when using this method. | ||
// | ||
// [main-thread] | ||
void(CLAP_ABI *set_wants_context_updates)(const clap_host_t *host, bool is_subscribed); | ||
} clap_host_undo_t; | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.