| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| /* | ||
| * DISTRHO Plugin Framework (DPF) | ||
| * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> | ||
| * | ||
| * Permission to use, copy, modify, and/or distribute this software for any purpose with | ||
| * or without fee is hereby granted, provided that the above copyright notice and this | ||
| * permission notice appear in all copies. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | ||
| * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | ||
| * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | ||
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | ||
| * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| */ | ||
|
|
||
| #include "DistrhoUIInternal.hpp" | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // -------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| #if ! DISTRHO_PLUGIN_WANT_STATE | ||
| static constexpr const setStateFunc setStateCallback = nullptr; | ||
| #endif | ||
| #if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||
| static constexpr const sendNoteFunc sendNoteCallback = nullptr; | ||
| #endif | ||
|
|
||
| // -------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| /** | ||
| * Stub UI class, does nothing but serving as example code for other implementations. | ||
| */ | ||
| class UIStub | ||
| { | ||
| public: | ||
| UIStub(const intptr_t winId, | ||
| const double sampleRate, | ||
| const char* const bundlePath, | ||
| void* const dspPtr, | ||
| const float scaleFactor) | ||
| : fUI(this, winId, sampleRate, | ||
| editParameterCallback, | ||
| setParameterCallback, | ||
| setStateCallback, | ||
| sendNoteCallback, | ||
| setSizeCallback, | ||
| fileRequestCallback, | ||
| bundlePath, dspPtr, scaleFactor) | ||
| { | ||
| } | ||
|
|
||
| // ---------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| private: | ||
| // Stub stuff here | ||
|
|
||
| // Plugin UI (after Stub stuff so the UI can call into us during its constructor) | ||
| UIExporter fUI; | ||
|
|
||
| // ---------------------------------------------------------------------------------------------------------------- | ||
| // DPF callbacks | ||
|
|
||
| void editParameter(uint32_t, bool) const | ||
| { | ||
| } | ||
|
|
||
| static void editParameterCallback(void* const ptr, const uint32_t rindex, const bool started) | ||
| { | ||
| static_cast<UIStub*>(ptr)->editParameter(rindex, started); | ||
| } | ||
|
|
||
| void setParameterValue(uint32_t, float) | ||
| { | ||
| } | ||
|
|
||
| static void setParameterCallback(void* const ptr, const uint32_t rindex, const float value) | ||
| { | ||
| static_cast<UIStub*>(ptr)->setParameterValue(rindex, value); | ||
| } | ||
|
|
||
| void setSize(uint, uint) | ||
| { | ||
| } | ||
|
|
||
| static void setSizeCallback(void* const ptr, const uint width, const uint height) | ||
| { | ||
| static_cast<UIStub*>(ptr)->setSize(width, height); | ||
| } | ||
|
|
||
| #if DISTRHO_PLUGIN_WANT_STATE | ||
| void setState(const char*, const char*) | ||
| { | ||
| } | ||
|
|
||
| static void setStateCallback(void* const ptr, const char* key, const char* value) | ||
| { | ||
| static_cast<UIStub*>(ptr)->setState(key, value); | ||
| } | ||
| #endif | ||
|
|
||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||
| void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) | ||
| { | ||
| } | ||
|
|
||
| static void sendNoteCallback(void* const ptr, const uint8_t channel, const uint8_t note, const uint8_t velocity) | ||
| { | ||
| static_cast<UIStub*>(ptr)->sendNote(channel, note, velocity); | ||
| } | ||
| #endif | ||
|
|
||
| bool fileRequest(const char*) | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| static bool fileRequestCallback(void* const ptr, const char* const key) | ||
| { | ||
| return static_cast<UIStub*>(ptr)->fileRequest(key); | ||
| } | ||
| }; | ||
|
|
||
| // -------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| #pragma once | ||
|
|
||
| #include "private/std.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| // Sample code for reading a stereo buffer: | ||
| // | ||
| // bool isLeftConstant = (buffer->constant_mask & (1 << 0)) != 0; | ||
| // bool isRightConstant = (buffer->constant_mask & (1 << 1)) != 0; | ||
| // | ||
| // for (int i = 0; i < N; ++i) { | ||
| // float l = data32[0][isLeftConstant ? 0 : i]; | ||
| // float r = data32[1][isRightConstant ? 0 : i]; | ||
| // } | ||
| // | ||
| // Note: checking the constant mask is optional, and this implies that | ||
| // the buffer must be filled with the constant value. | ||
| // Rationale: if a buffer reader doesn't check the constant mask, then it may | ||
| // process garbage samples and in result, garbage samples may be transmitted | ||
| // to the audio interface with all the bad consequences it can have. | ||
| // | ||
| // The constant mask is a hint. | ||
| typedef struct clap_audio_buffer { | ||
| // Either data32 or data64 pointer will be set. | ||
| float **data32; | ||
| double **data64; | ||
| uint32_t channel_count; | ||
| uint32_t latency; // latency from/to the audio interface | ||
| uint64_t constant_mask; | ||
| } clap_audio_buffer_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| #pragma once | ||
|
|
||
| #include "version.h" | ||
| #include "private/macros.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| // This interface is the entry point of the dynamic library. | ||
| // | ||
| // CLAP plugins standard search path: | ||
| // | ||
| // Linux | ||
| // - ~/.clap | ||
| // - /usr/lib/clap | ||
| // | ||
| // Windows | ||
| // - %CommonFilesFolder%/CLAP/ | ||
| // - %LOCALAPPDATA%/Programs/Common/CLAP/ | ||
| // | ||
| // MacOS | ||
| // - /Library/Audio/Plug-Ins/CLAP | ||
| // - ~/Library/Audio/Plug-Ins/CLAP | ||
| // | ||
| // In addition to the OS-specific default locations above, a CLAP host must query the environment | ||
| // for a CLAP_PATH variable, which is a list of directories formatted in the same manner as the host | ||
| // OS binary search path (PATH on Unix, separated by `:` and Path on Windows, separated by ';', as | ||
| // of this writing). | ||
| // | ||
| // Each directory should be recursively searched for files and/or bundles as appropriate in your OS | ||
| // ending with the extension `.clap`. | ||
| // | ||
| // Every method must be thread-safe. | ||
| typedef struct clap_plugin_entry { | ||
| clap_version_t clap_version; // initialized to CLAP_VERSION | ||
|
|
||
| // This function must be called first, and can only be called once. | ||
| // | ||
| // It should be as fast as possible, in order to perform a very quick scan of the plugin | ||
| // descriptors. | ||
| // | ||
| // It is forbidden to display graphical user interface in this call. | ||
| // It is forbidden to perform user interaction in this call. | ||
| // | ||
| // If the initialization depends upon expensive computation, maybe try to do them ahead of time | ||
| // and cache the result. | ||
| // | ||
| // If init() returns false, then the host must not call deinit() nor any other clap | ||
| // related symbols from the DSO. | ||
| bool (*init)(const char *plugin_path); | ||
|
|
||
| // No more calls into the DSO must be made after calling deinit(). | ||
| void (*deinit)(void); | ||
|
|
||
| // Get the pointer to a factory. See plugin-factory.h for an example. | ||
| // | ||
| // Returns null if the factory is not provided. | ||
| // The returned pointer must *not* be freed by the caller. | ||
| const void *(*get_factory)(const char *factory_id); | ||
| } clap_plugin_entry_t; | ||
|
|
||
| /* Entry point */ | ||
| CLAP_EXPORT extern const clap_plugin_entry_t clap_entry; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,283 @@ | ||
| #pragma once | ||
|
|
||
| #include "private/std.h" | ||
| #include "fixedpoint.h" | ||
| #include "id.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| // event header | ||
| // must be the first attribute of the event | ||
| typedef struct clap_event_header { | ||
| uint32_t size; // event size including this header, eg: sizeof (clap_event_note) | ||
| uint32_t time; // sample offset within the buffer for this event | ||
| uint16_t space_id; // event space, see clap_host_event_registry | ||
| uint16_t type; // event type | ||
| uint32_t flags; // see clap_event_flags | ||
| } clap_event_header_t; | ||
|
|
||
| // The clap core event space | ||
| static const CLAP_CONSTEXPR uint16_t CLAP_CORE_EVENT_SPACE_ID = 0; | ||
|
|
||
| enum clap_event_flags { | ||
| // Indicate a live user event, for example a user turning a physical knob | ||
| // or playing a physical key. | ||
| CLAP_EVENT_IS_LIVE = 1 << 0, | ||
|
|
||
| // Indicate that the event should not be recorded. | ||
| // For example this is useful when a parameter changes because of a MIDI CC, | ||
| // because if the host records both the MIDI CC automation and the parameter | ||
| // automation there will be a conflict. | ||
| CLAP_EVENT_DONT_RECORD = 1 << 1, | ||
| }; | ||
|
|
||
| // Some of the following events overlap, a note on can be expressed with: | ||
| // - CLAP_EVENT_NOTE_ON | ||
| // - CLAP_EVENT_MIDI | ||
| // - CLAP_EVENT_MIDI2 | ||
| // | ||
| // The preferred way of sending a note event is to use CLAP_EVENT_NOTE_*. | ||
| // | ||
| // The same event must not be sent twice: it is forbidden to send a the same note on | ||
| // encoded with both CLAP_EVENT_NOTE_ON and CLAP_EVENT_MIDI. | ||
| // | ||
| // The plugins are encouraged to be able to handle note events encoded as raw midi or midi2, | ||
| // or implement clap_plugin_event_filter and reject raw midi and midi2 events. | ||
| enum { | ||
| // NOTE_ON and NOTE_OFF represent a key pressed and key released event, respectively. | ||
| // A NOTE_ON with a velocity of 0 is valid and should not be interpreted as a NOTE_OFF. | ||
| // | ||
| // NOTE_CHOKE is meant to choke the voice(s), like in a drum machine when a closed hihat | ||
| // chokes an open hihat. This event can be sent by the host to the plugin. Here are two use cases: | ||
| // - a plugin is inside a drum pad in Bitwig Studio's drum machine, and this pad is choked by | ||
| // another one | ||
| // - the user double clicks the DAW's stop button in the transport which then stops the sound on | ||
| // every tracks | ||
| // | ||
| // NOTE_END is sent by the plugin to the host. The port, channel, key and note_id are those given | ||
| // by the host in the NOTE_ON event. In other words, this event is matched against the | ||
| // plugin's note input port. | ||
| // NOTE_END is useful to help the host to match the plugin's voice life time. | ||
| // | ||
| // When using polyphonic modulations, the host has to allocate and release voices for its | ||
| // polyphonic modulator. Yet only the plugin effectively knows when the host should terminate | ||
| // a voice. NOTE_END solves that issue in a non-intrusive and cooperative way. | ||
| // | ||
| // CLAP assumes that the host will allocate a unique voice on NOTE_ON event for a given port, | ||
| // channel and key. This voice will run until the plugin will instruct the host to terminate | ||
| // it by sending a NOTE_END event. | ||
| // | ||
| // Consider the following sequence: | ||
| // - process() | ||
| // Host->Plugin NoteOn(port:0, channel:0, key:16, time:t0) | ||
| // Host->Plugin NoteOn(port:0, channel:0, key:64, time:t0) | ||
| // Host->Plugin NoteOff(port:0, channel:0, key:16, t1) | ||
| // Host->Plugin NoteOff(port:0, channel:0, key:64, t1) | ||
| // # on t2, both notes did terminate | ||
| // Host->Plugin NoteOn(port:0, channel:0, key:64, t3) | ||
| // # Here the plugin finished processing all the frames and will tell the host | ||
| // # to terminate the voice on key 16 but not 64, because a note has been started at t3 | ||
| // Plugin->Host NoteEnd(port:0, channel:0, key:16, time:ignored) | ||
| // | ||
| // These four events use clap_event_note. | ||
| CLAP_EVENT_NOTE_ON, | ||
| CLAP_EVENT_NOTE_OFF, | ||
| CLAP_EVENT_NOTE_CHOKE, | ||
| CLAP_EVENT_NOTE_END, | ||
|
|
||
| // Represents a note expression. | ||
| // Uses clap_event_note_expression. | ||
| CLAP_EVENT_NOTE_EXPRESSION, | ||
|
|
||
| // PARAM_VALUE sets the parameter's value; uses clap_event_param_value. | ||
| // PARAM_MOD sets the parameter's modulation amount; uses clap_event_param_mod. | ||
| // | ||
| // The value heard is: param_value + param_mod. | ||
| // | ||
| // In case of a concurrent global value/modulation versus a polyphonic one, | ||
| // the voice should only use the polyphonic one and the polyphonic modulation | ||
| // amount will already include the monophonic signal. | ||
| CLAP_EVENT_PARAM_VALUE, | ||
| CLAP_EVENT_PARAM_MOD, | ||
|
|
||
| // Indicates that the user started or finished adjusting a knob. | ||
| // This is not mandatory to wrap parameter changes with gesture events, but this improves | ||
| // the user experience a lot when recording automation or overriding automation playback. | ||
| // Uses clap_event_param_gesture. | ||
| CLAP_EVENT_PARAM_GESTURE_BEGIN, | ||
| CLAP_EVENT_PARAM_GESTURE_END, | ||
|
|
||
| CLAP_EVENT_TRANSPORT, // update the transport info; clap_event_transport | ||
| CLAP_EVENT_MIDI, // raw midi event; clap_event_midi | ||
| CLAP_EVENT_MIDI_SYSEX, // raw midi sysex event; clap_event_midi_sysex | ||
| CLAP_EVENT_MIDI2, // raw midi 2 event; clap_event_midi2 | ||
| }; | ||
|
|
||
| // Note on, off, end and choke events. | ||
| // In the case of note choke or end events: | ||
| // - the velocity is ignored. | ||
| // - key and channel are used to match active notes, a value of -1 matches all. | ||
| typedef struct clap_event_note { | ||
| clap_event_header_t header; | ||
|
|
||
| int32_t note_id; // -1 if unspecified, otherwise >=0 | ||
| int16_t port_index; | ||
| int16_t channel; // 0..15 | ||
| int16_t key; // 0..127 | ||
| double velocity; // 0..1 | ||
| } clap_event_note_t; | ||
|
|
||
| enum { | ||
| // with 0 < x <= 4, plain = 20 * log(x) | ||
| CLAP_NOTE_EXPRESSION_VOLUME, | ||
|
|
||
| // pan, 0 left, 0.5 center, 1 right | ||
| CLAP_NOTE_EXPRESSION_PAN, | ||
|
|
||
| // relative tuning in semitone, from -120 to +120 | ||
| CLAP_NOTE_EXPRESSION_TUNING, | ||
|
|
||
| // 0..1 | ||
| CLAP_NOTE_EXPRESSION_VIBRATO, | ||
| CLAP_NOTE_EXPRESSION_EXPRESSION, | ||
| CLAP_NOTE_EXPRESSION_BRIGHTNESS, | ||
| CLAP_NOTE_EXPRESSION_PRESSURE, | ||
| }; | ||
| typedef int32_t clap_note_expression; | ||
|
|
||
| typedef struct clap_event_note_expression { | ||
| clap_event_header_t header; | ||
|
|
||
| clap_note_expression expression_id; | ||
|
|
||
| // target a specific note_id, port, key and channel, -1 for global | ||
| int32_t note_id; | ||
| int16_t port_index; | ||
| int16_t channel; | ||
| int16_t key; | ||
|
|
||
| double value; // see expression for the range | ||
| } clap_event_note_expression_t; | ||
|
|
||
| typedef struct clap_event_param_value { | ||
| clap_event_header_t header; | ||
|
|
||
| // target parameter | ||
| clap_id param_id; // @ref clap_param_info.id | ||
| void *cookie; // @ref clap_param_info.cookie | ||
|
|
||
| // target a specific note_id, port, key and channel, -1 for global | ||
| int32_t note_id; | ||
| int16_t port_index; | ||
| int16_t channel; | ||
| int16_t key; | ||
|
|
||
| double value; | ||
| } clap_event_param_value_t; | ||
|
|
||
| typedef struct clap_event_param_mod { | ||
| clap_event_header_t header; | ||
|
|
||
| // target parameter | ||
| clap_id param_id; // @ref clap_param_info.id | ||
| void *cookie; // @ref clap_param_info.cookie | ||
|
|
||
| // target a specific note_id, port, key and channel, -1 for global | ||
| int32_t note_id; | ||
| int16_t port_index; | ||
| int16_t channel; | ||
| int16_t key; | ||
|
|
||
| double amount; // modulation amount | ||
| } clap_event_param_mod_t; | ||
|
|
||
| typedef struct clap_event_param_gesture { | ||
| clap_event_header_t header; | ||
|
|
||
| // target parameter | ||
| clap_id param_id; // @ref clap_param_info.id | ||
| } clap_event_param_gesture_t; | ||
|
|
||
| enum clap_transport_flags { | ||
| CLAP_TRANSPORT_HAS_TEMPO = 1 << 0, | ||
| CLAP_TRANSPORT_HAS_BEATS_TIMELINE = 1 << 1, | ||
| CLAP_TRANSPORT_HAS_SECONDS_TIMELINE = 1 << 2, | ||
| CLAP_TRANSPORT_HAS_TIME_SIGNATURE = 1 << 3, | ||
| CLAP_TRANSPORT_IS_PLAYING = 1 << 4, | ||
| CLAP_TRANSPORT_IS_RECORDING = 1 << 5, | ||
| CLAP_TRANSPORT_IS_LOOP_ACTIVE = 1 << 6, | ||
| CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL = 1 << 7, | ||
| }; | ||
|
|
||
| typedef struct clap_event_transport { | ||
| clap_event_header_t header; | ||
|
|
||
| uint32_t flags; // see clap_transport_flags | ||
|
|
||
| clap_beattime song_pos_beats; // position in beats | ||
| clap_sectime song_pos_seconds; // position in seconds | ||
|
|
||
| double tempo; // in bpm | ||
| double tempo_inc; // tempo increment for each samples and until the next | ||
| // time info event | ||
|
|
||
| clap_beattime loop_start_beats; | ||
| clap_beattime loop_end_beats; | ||
| clap_sectime loop_start_seconds; | ||
| clap_sectime loop_end_seconds; | ||
|
|
||
| clap_beattime bar_start; // start pos of the current bar | ||
| int32_t bar_number; // bar at song pos 0 has the number 0 | ||
|
|
||
| uint16_t tsig_num; // time signature numerator | ||
| uint16_t tsig_denom; // time signature denominator | ||
| } clap_event_transport_t; | ||
|
|
||
| typedef struct clap_event_midi { | ||
| clap_event_header_t header; | ||
|
|
||
| uint16_t port_index; | ||
| uint8_t data[3]; | ||
| } clap_event_midi_t; | ||
|
|
||
| typedef struct clap_event_midi_sysex { | ||
| clap_event_header_t header; | ||
|
|
||
| uint16_t port_index; | ||
| const uint8_t *buffer; // midi buffer | ||
| uint32_t size; | ||
| } clap_event_midi_sysex_t; | ||
|
|
||
| // While it is possible to use a series of midi2 event to send a sysex, | ||
| // prefer clap_event_midi_sysex if possible for efficiency. | ||
| typedef struct clap_event_midi2 { | ||
| clap_event_header_t header; | ||
|
|
||
| uint16_t port_index; | ||
| uint32_t data[4]; | ||
| } clap_event_midi2_t; | ||
|
|
||
| // Input event list, events must be sorted by time. | ||
| typedef struct clap_input_events { | ||
| void *ctx; // reserved pointer for the list | ||
|
|
||
| uint32_t (*size)(const struct clap_input_events *list); | ||
|
|
||
| // Don't free the returned event, it belongs to the list | ||
| const clap_event_header_t *(*get)(const struct clap_input_events *list, uint32_t index); | ||
| } clap_input_events_t; | ||
|
|
||
| // Output event list, events must be sorted by time. | ||
| typedef struct clap_output_events { | ||
| void *ctx; // reserved pointer for the list | ||
|
|
||
| // Pushes a copy of the event | ||
| // returns false if the event could not be pushed to the queue (out of memory?) | ||
| bool (*try_push)(const struct clap_output_events *list, const clap_event_header_t *event); | ||
| } clap_output_events_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| #pragma once | ||
|
|
||
| #include "../plugin.h" | ||
| #include "../string-sizes.h" | ||
|
|
||
| /// @page Audio Ports | ||
| /// | ||
| /// This extension provides a way for the plugin to describe its current audio ports. | ||
| /// | ||
| /// If the plugin does not implement this extension, it won't have audio ports. | ||
| /// | ||
| /// 32 bits support is required for both host and plugins. 64 bits audio is optional. | ||
| /// | ||
| /// The plugin is only allowed to change its ports configuration while it is deactivated. | ||
|
|
||
| static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS[] = "clap.audio-ports"; | ||
| static CLAP_CONSTEXPR const char CLAP_PORT_MONO[] = "mono"; | ||
| static CLAP_CONSTEXPR const char CLAP_PORT_STEREO[] = "stereo"; | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| enum { | ||
| // This port is the main audio input or output. | ||
| // There can be only one main input and main output. | ||
| // Main port must be at index 0. | ||
| CLAP_AUDIO_PORT_IS_MAIN = 1 << 0, | ||
|
|
||
| // This port can be used with 64 bits audio | ||
| CLAP_AUDIO_PORT_SUPPORTS_64BITS = 1 << 1, | ||
|
|
||
| // 64 bits audio is preferred with this port | ||
| CLAP_AUDIO_PORT_PREFERS_64BITS = 1 << 2, | ||
|
|
||
| // This port must be used with the same sample size as all the other ports which have this flag. | ||
| // In other words if all ports have this flag then the plugin may either be used entirely with | ||
| // 64 bits audio or 32 bits audio, but it can't be mixed. | ||
| CLAP_AUDIO_PORT_REQUIRES_COMMON_SAMPLE_SIZE = 1 << 3, | ||
| }; | ||
|
|
||
| typedef struct clap_audio_port_info { | ||
| // id identifies a port and must be stable. | ||
| // id may overlap between input and output ports. | ||
| clap_id id; | ||
| char name[CLAP_NAME_SIZE]; // displayable name | ||
|
|
||
| uint32_t flags; | ||
| uint32_t channel_count; | ||
|
|
||
| // If null or empty then it is unspecified (arbitrary audio). | ||
| // This filed can be compared against: | ||
| // - CLAP_PORT_MONO | ||
| // - CLAP_PORT_STEREO | ||
| // - CLAP_PORT_SURROUND (defined in the surround extension) | ||
| // - CLAP_PORT_AMBISONIC (defined in the ambisonic extension) | ||
| // - CLAP_PORT_CV (defined in the cv extension) | ||
| // | ||
| // An extension can provide its own port type and way to inspect the channels. | ||
| const char *port_type; | ||
|
|
||
| // in-place processing: allow the host to use the same buffer for input and output | ||
| // if supported set the pair port id. | ||
| // if not supported set to CLAP_INVALID_ID | ||
| clap_id in_place_pair; | ||
| } clap_audio_port_info_t; | ||
|
|
||
| // The audio ports scan has to be done while the plugin is deactivated. | ||
| typedef struct clap_plugin_audio_ports { | ||
| // number of ports, for either input or output | ||
| // [main-thread] | ||
| uint32_t (*count)(const clap_plugin_t *plugin, bool is_input); | ||
|
|
||
| // get info about about an audio port. | ||
| // [main-thread] | ||
| bool (*get)(const clap_plugin_t *plugin, | ||
| uint32_t index, | ||
| bool is_input, | ||
| clap_audio_port_info_t *info); | ||
| } clap_plugin_audio_ports_t; | ||
|
|
||
| enum { | ||
| // The ports name did change, the host can scan them right away. | ||
| CLAP_AUDIO_PORTS_RESCAN_NAMES = 1 << 0, | ||
|
|
||
| // [!active] The flags did change | ||
| CLAP_AUDIO_PORTS_RESCAN_FLAGS = 1 << 1, | ||
|
|
||
| // [!active] The channel_count did change | ||
| CLAP_AUDIO_PORTS_RESCAN_CHANNEL_COUNT = 1 << 2, | ||
|
|
||
| // [!active] The port type did change | ||
| CLAP_AUDIO_PORTS_RESCAN_PORT_TYPE = 1 << 3, | ||
|
|
||
| // [!active] The in-place pair did change, this requires. | ||
| CLAP_AUDIO_PORTS_RESCAN_IN_PLACE_PAIR = 1 << 4, | ||
|
|
||
| // [!active] The list of ports have changed: entries have been removed/added. | ||
| CLAP_AUDIO_PORTS_RESCAN_LIST = 1 << 5, | ||
| }; | ||
|
|
||
| typedef struct clap_host_audio_ports { | ||
| // Checks if the host allows a plugin to change a given aspect of the audio ports definition. | ||
| // [main-thread] | ||
| bool (*is_rescan_flag_supported)(const clap_host_t *host, uint32_t flag); | ||
|
|
||
| // Rescan the full list of audio ports according to the flags. | ||
| // It is illegal to ask the host to rescan with a flag that is not supported. | ||
| // Certain flags require the plugin to be de-activated. | ||
| // [main-thread] | ||
| void (*rescan)(const clap_host_t *host, uint32_t flags); | ||
| } clap_host_audio_ports_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,219 @@ | ||
| #pragma once | ||
|
|
||
| #include "../plugin.h" | ||
|
|
||
| /// @page GUI | ||
| /// | ||
| /// This extension defines how the plugin will present its GUI. | ||
| /// | ||
| /// There are two approaches: | ||
| /// 1. the plugin creates a window and embeds it into the host's window | ||
| /// 2. the plugin creates a floating window | ||
| /// | ||
| /// Embedding the window gives more control to the host, and feels more integrated. | ||
| /// Floating window are sometimes the only option due to technical limitations. | ||
| /// | ||
| /// Showing the GUI works as follow: | ||
| /// 1. clap_plugin_gui->is_api_supported(), check what can work | ||
| /// 2. clap_plugin_gui->create(), allocates gui resources | ||
| /// 3. if the plugin window is floating | ||
| /// 4. -> clap_plugin_gui->set_transient() | ||
| /// 5. -> clap_plugin_gui->suggest_title() | ||
| /// 6. else | ||
| /// 7. -> clap_plugin_gui->set_scale() | ||
| /// 8. -> clap_plugin_gui->can_resize() | ||
| /// 9. -> if resizable and has known size from previous session, clap_plugin_gui->set_size() | ||
| /// 10. -> else clap_plugin_gui->get_size(), gets initial size | ||
| /// 11. -> clap_plugin_gui->set_parent() | ||
| /// 12. clap_plugin_gui->show() | ||
| /// 13. clap_plugin_gui->hide()/show() ... | ||
| /// 14. clap_plugin_gui->destroy() when done with the gui | ||
| /// | ||
| /// Resizing the window (initiated by the plugin, if embedded): | ||
| /// 1. Plugins calls clap_host_gui->request_resize() | ||
| /// 2. If the host returns true the new size is accepted, | ||
| /// the host doesn't have to call clap_plugin_gui->set_size(). | ||
| /// If the host returns false, the new size is rejected. | ||
| /// | ||
| /// Resizing the window (drag, if embedded)): | ||
| /// 1. Only possible if clap_plugin_gui->can_resize() returns true | ||
| /// 2. Mouse drag -> new_size | ||
| /// 3. clap_plugin_gui->adjust_size(new_size) -> working_size | ||
| /// 4. clap_plugin_gui->set_size(working_size) | ||
|
|
||
| static CLAP_CONSTEXPR const char CLAP_EXT_GUI[] = "clap.gui"; | ||
|
|
||
| // If your windowing API is not listed here, please open an issue and we'll figure it out. | ||
| // https://github.com/free-audio/clap/issues/new | ||
|
|
||
| // uses physical size | ||
| // embed using https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent | ||
| static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WIN32[] = "win32"; | ||
|
|
||
| // uses logical size, don't call clap_plugin_gui->set_scale() | ||
| static const CLAP_CONSTEXPR char CLAP_WINDOW_API_COCOA[] = "cocoa"; | ||
|
|
||
| // uses physical size | ||
| // embed using https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html | ||
| static const CLAP_CONSTEXPR char CLAP_WINDOW_API_X11[] = "x11"; | ||
|
|
||
| // uses physical size | ||
| // embed is currently not supported, use floating windows | ||
| static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WAYLAND[] = "wayland"; | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| typedef void *clap_hwnd; | ||
| typedef void *clap_nsview; | ||
| typedef unsigned long clap_xwnd; | ||
|
|
||
| // Represent a window reference. | ||
| typedef struct clap_window { | ||
| const char *api; // one of CLAP_WINDOW_API_XXX | ||
| union { | ||
| clap_nsview cocoa; | ||
| clap_xwnd x11; | ||
| clap_hwnd win32; | ||
| void *ptr; // for anything defined outside of clap | ||
| uintptr_t uptr; | ||
| }; | ||
| } clap_window_t; | ||
|
|
||
| // Information to improve window resizing when initiated by the host or window manager. | ||
| typedef struct clap_gui_resize_hints { | ||
| bool can_resize_horizontally; | ||
| bool can_resize_vertically; | ||
|
|
||
| // only if can resize horizontally and vertically | ||
| bool preserve_aspect_ratio; | ||
| uint32_t aspect_ratio_width; | ||
| uint32_t aspect_ratio_height; | ||
| } clap_gui_resize_hints_t; | ||
|
|
||
| // Size (width, height) is in pixels; the corresponding windowing system extension is | ||
| // responsible for defining if it is physical pixels or logical pixels. | ||
| typedef struct clap_plugin_gui { | ||
| // Returns true if the requested gui api is supported | ||
| // [main-thread] | ||
| bool (*is_api_supported)(const clap_plugin_t *plugin, const char *api, bool is_floating); | ||
|
|
||
| // Returns true if the plugin has a preferred api. | ||
| // The host has no obligation to honor the plugin preferrence, this is just a hint. | ||
| // [main-thread] | ||
| bool (*get_preferred_api)(const clap_plugin_t *plugin, const char **api, bool *is_floating); | ||
|
|
||
| // Create and allocate all resources necessary for the gui. | ||
| // | ||
| // If is_floating is true, then the window will not be managed by the host. The plugin | ||
| // can set its window to stays above the parent window, see set_transient(). | ||
| // api may be null or blank for floating window. | ||
| // | ||
| // If is_floating is false, then the plugin has to embbed its window into the parent window, see | ||
| // set_parent(). | ||
| // | ||
| // After this call, the GUI may not be visible yet; don't forget to call show(). | ||
| // [main-thread] | ||
| bool (*create)(const clap_plugin_t *plugin, const char *api, bool is_floating); | ||
|
|
||
| // Free all resources associated with the gui. | ||
| // [main-thread] | ||
| void (*destroy)(const clap_plugin_t *plugin); | ||
|
|
||
| // Set the absolute GUI scaling factor, and override any OS info. | ||
| // Should not be used if the windowing api relies upon logical pixels. | ||
| // | ||
| // If the plugin prefers to work out the scaling factor itself by querying the OS directly, | ||
| // then ignore the call. | ||
| // | ||
| // Returns true if the scaling could be applied | ||
| // Returns false if the call was ignored, or the scaling could not be applied. | ||
| // [main-thread] | ||
| bool (*set_scale)(const clap_plugin_t *plugin, double scale); | ||
|
|
||
| // Get the current size of the plugin UI. | ||
| // clap_plugin_gui->create() must have been called prior to asking the size. | ||
| // [main-thread] | ||
| bool (*get_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height); | ||
|
|
||
| // Returns true if the window is resizeable (mouse drag). | ||
| // Only for embedded windows. | ||
| // [main-thread] | ||
| bool (*can_resize)(const clap_plugin_t *plugin); | ||
|
|
||
| // Returns true if the plugin can provide hints on how to resize the window. | ||
| // [main-thread] | ||
| bool (*get_resize_hints)(const clap_plugin_t *plugin, clap_gui_resize_hints_t *hints); | ||
|
|
||
| // If the plugin gui is resizable, then the plugin will calculate the closest | ||
| // usable size which fits in the given size. | ||
| // This method does not change the size. | ||
| // | ||
| // Only for embedded windows. | ||
| // [main-thread] | ||
| bool (*adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height); | ||
|
|
||
| // Sets the window size. Only for embedded windows. | ||
| // [main-thread] | ||
| bool (*set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height); | ||
|
|
||
| // Embbeds the plugin window into the given window. | ||
| // [main-thread & !floating] | ||
| bool (*set_parent)(const clap_plugin_t *plugin, const clap_window_t *window); | ||
|
|
||
| // Set the plugin floating window to stay above the given window. | ||
| // [main-thread & floating] | ||
| bool (*set_transient)(const clap_plugin_t *plugin, const clap_window_t *window); | ||
|
|
||
| // Suggests a window title. Only for floating windows. | ||
| // [main-thread & floating] | ||
| void (*suggest_title)(const clap_plugin_t *plugin, const char *title); | ||
|
|
||
| // Show the window. | ||
| // [main-thread] | ||
| bool (*show)(const clap_plugin_t *plugin); | ||
|
|
||
| // Hide the window, this method does not free the resources, it just hides | ||
| // the window content. Yet it may be a good idea to stop painting timers. | ||
| // [main-thread] | ||
| bool (*hide)(const clap_plugin_t *plugin); | ||
| } clap_plugin_gui_t; | ||
|
|
||
| typedef struct clap_host_gui { | ||
| // The host should call get_resize_hints() again. | ||
| // [thread-safe] | ||
| void (*resize_hints_changed)(const clap_host_t *host); | ||
|
|
||
| /* Request the host to resize the client area to width, height. | ||
| * Return true if the new size is accepted, false otherwise. | ||
| * The host doesn't have to call set_size(). | ||
| * | ||
| * Note: if not called from the main thread, then a return value simply means that the host | ||
| * acknowledged the request and will process it asynchronously. If the request then can't be | ||
| * satisfied then the host will call set_size() to revert the operation. | ||
| * | ||
| * [thread-safe] */ | ||
| bool (*request_resize)(const clap_host_t *host, uint32_t width, uint32_t height); | ||
|
|
||
| /* Request the host to show the plugin gui. | ||
| * Return true on success, false otherwise. | ||
| * [thread-safe] */ | ||
| bool (*request_show)(const clap_host_t *host); | ||
|
|
||
| /* Request the host to hide the plugin gui. | ||
| * Return true on success, false otherwise. | ||
| * [thread-safe] */ | ||
| bool (*request_hide)(const clap_host_t *host); | ||
|
|
||
| // The floating window has been closed, or the connection to the gui has been lost. | ||
| // | ||
| // If was_destroyed is true, then the host must call clap_plugin_gui->destroy() to acknowledge | ||
| // the gui destruction. | ||
| // [thread-safe] | ||
| void (*closed)(const clap_host_t *host, bool was_destroyed); | ||
| } clap_host_gui_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,296 @@ | ||
| #pragma once | ||
|
|
||
| #include "../plugin.h" | ||
| #include "../string-sizes.h" | ||
|
|
||
| /// @page Parameters | ||
| /// @brief parameters management | ||
| /// | ||
| /// Main idea: | ||
| /// | ||
| /// The host sees the plugin as an atomic entity; and acts as a controller on top of its parameters. | ||
| /// The plugin is responsible for keeping its audio processor and its GUI in sync. | ||
| /// | ||
| /// The host can at any time read parameters' value on the [main-thread] using | ||
| /// @ref clap_plugin_params.value(). | ||
| /// | ||
| /// There are two options to communicate parameter value changes, and they are not concurrent. | ||
| /// - send automation points during clap_plugin.process() | ||
| /// - send automation points during clap_plugin_params.flush(), for parameter changes | ||
| /// without processing audio | ||
| /// | ||
| /// When the plugin changes a parameter value, it must inform the host. | ||
| /// It will send @ref CLAP_EVENT_PARAM_VALUE event during process() or flush(). | ||
| /// If the user is adjusting the value, don't forget to mark the begining and end | ||
| /// of the gesture by sending CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END | ||
| /// events. | ||
| /// | ||
| /// @note MIDI CCs are tricky because you may not know when the parameter adjustment ends. | ||
| /// Also if the host records incoming MIDI CC and parameter change automation at the same time, | ||
| /// there will be a conflict at playback: MIDI CC vs Automation. | ||
| /// The parameter automation will always target the same parameter because the param_id is stable. | ||
| /// The MIDI CC may have a different mapping in the future and may result in a different playback. | ||
| /// | ||
| /// When a MIDI CC changes a parameter's value, set the flag CLAP_EVENT_DONT_RECORD in | ||
| /// clap_event_param.header.flags. That way the host may record the MIDI CC automation, but not the | ||
| /// parameter change and there won't be conflict at playback. | ||
| /// | ||
| /// Scenarios: | ||
| /// | ||
| /// I. Loading a preset | ||
| /// - load the preset in a temporary state | ||
| /// - call @ref clap_host_params.rescan() if anything changed | ||
| /// - call @ref clap_host_latency.changed() if latency changed | ||
| /// - invalidate any other info that may be cached by the host | ||
| /// - if the plugin is activated and the preset will introduce breaking changes | ||
| /// (latency, audio ports, new parameters, ...) be sure to wait for the host | ||
| /// to deactivate the plugin to apply those changes. | ||
| /// If there are no breaking changes, the plugin can apply them them right away. | ||
| /// The plugin is resonsible for updating both its audio processor and its gui. | ||
| /// | ||
| /// II. Turning a knob on the DAW interface | ||
| /// - the host will send an automation event to the plugin via a process() or flush() | ||
| /// | ||
| /// III. Turning a knob on the Plugin interface | ||
| /// - the plugin is responsible for sending the parameter value to its audio processor | ||
| /// - call clap_host_params->request_flush() or clap_host->request_process(). | ||
| /// - when the host calls either clap_plugin->process() or clap_plugin_params->flush(), | ||
| /// send an automation event and don't forget to set begin_adjust, | ||
| /// end_adjust and should_record flags | ||
| /// | ||
| /// IV. Turning a knob via automation | ||
| /// - host sends an automation point during clap_plugin->process() or clap_plugin_params->flush(). | ||
| /// - the plugin is responsible for updating its GUI | ||
| /// | ||
| /// V. Turning a knob via plugin's internal MIDI mapping | ||
| /// - the plugin sends a CLAP_EVENT_PARAM_SET output event, set should_record to false | ||
| /// - the plugin is responsible to update its GUI | ||
| /// | ||
| /// VI. Adding or removing parameters | ||
| /// - if the plugin is activated call clap_host->restart() | ||
| /// - once the plugin isn't active: | ||
| /// - apply the new state | ||
| /// - if a parameter is gone or is created with an id that may have been used before, | ||
| /// call clap_host_params.clear(host, param_id, CLAP_PARAM_CLEAR_ALL) | ||
| /// - call clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) | ||
|
|
||
| static CLAP_CONSTEXPR const char CLAP_EXT_PARAMS[] = "clap.params"; | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| enum { | ||
| // Is this param stepped? (integer values only) | ||
| // if so the double value is converted to integer using a cast (equivalent to trunc). | ||
| CLAP_PARAM_IS_STEPPED = 1 << 0, | ||
|
|
||
| // Useful for for periodic parameters like a phase | ||
| CLAP_PARAM_IS_PERIODIC = 1 << 1, | ||
|
|
||
| // The parameter should not be shown to the user, because it is currently not used. | ||
| // It is not necessary to process automation for this parameter. | ||
| CLAP_PARAM_IS_HIDDEN = 1 << 2, | ||
|
|
||
| // The parameter can't be changed by the host. | ||
| CLAP_PARAM_IS_READONLY = 1 << 3, | ||
|
|
||
| // This parameter is used to merge the plugin and host bypass button. | ||
| // It implies that the parameter is stepped. | ||
| // min: 0 -> bypass off | ||
| // max: 1 -> bypass on | ||
| CLAP_PARAM_IS_BYPASS = 1 << 4, | ||
|
|
||
| // When set: | ||
| // - automation can be recorded | ||
| // - automation can be played back | ||
| // | ||
| // The host can send live user changes for this parameter regardless of this flag. | ||
| // | ||
| // If this parameters affect the internal processing structure of the plugin, ie: max delay, fft | ||
| // size, ... and the plugins needs to re-allocate its working buffers, then it should call | ||
| // host->request_restart(), and perform the change once the plugin is re-activated. | ||
| CLAP_PARAM_IS_AUTOMATABLE = 1 << 5, | ||
|
|
||
| // Does this parameter support per note automations? | ||
| CLAP_PARAM_IS_AUTOMATABLE_PER_NOTE_ID = 1 << 6, | ||
|
|
||
| // Does this parameter support per key automations? | ||
| CLAP_PARAM_IS_AUTOMATABLE_PER_KEY = 1 << 7, | ||
|
|
||
| // Does this parameter support per channel automations? | ||
| CLAP_PARAM_IS_AUTOMATABLE_PER_CHANNEL = 1 << 8, | ||
|
|
||
| // Does this parameter support per port automations? | ||
| CLAP_PARAM_IS_AUTOMATABLE_PER_PORT = 1 << 9, | ||
|
|
||
| // Does this parameter support the modulation signal? | ||
| CLAP_PARAM_IS_MODULATABLE = 1 << 10, | ||
|
|
||
| // Does this parameter support per note modulations? | ||
| CLAP_PARAM_IS_MODULATABLE_PER_NOTE_ID = 1 << 11, | ||
|
|
||
| // Does this parameter support per key modulations? | ||
| CLAP_PARAM_IS_MODULATABLE_PER_KEY = 1 << 12, | ||
|
|
||
| // Does this parameter support per channel modulations? | ||
| CLAP_PARAM_IS_MODULATABLE_PER_CHANNEL = 1 << 13, | ||
|
|
||
| // Does this parameter support per port modulations? | ||
| CLAP_PARAM_IS_MODULATABLE_PER_PORT = 1 << 14, | ||
|
|
||
| // Any change to this parameter will affect the plugin output and requires to be done via | ||
| // process() if the plugin is active. | ||
| // | ||
| // A simple example would be a DC Offset, changing it will change the output signal and must be | ||
| // processed. | ||
| CLAP_PARAM_REQUIRES_PROCESS = 1 << 15, | ||
| }; | ||
| typedef uint32_t clap_param_info_flags; | ||
|
|
||
| /* This describes a parameter */ | ||
| typedef struct clap_param_info { | ||
| // stable parameter identifier, it must never change. | ||
| clap_id id; | ||
|
|
||
| clap_param_info_flags flags; | ||
|
|
||
| // This value is optional and set by the plugin. | ||
| // Its purpose is to provide a fast access to the plugin parameter: | ||
| // | ||
| // Parameter *p = findParameter(param_id); | ||
| // param_info->cookie = p; | ||
| // | ||
| // /* and later on */ | ||
| // Parameter *p = (Parameter *)cookie; | ||
| // | ||
| // It is invalidated on clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) and when the plugin is | ||
| // destroyed. | ||
| void *cookie; | ||
|
|
||
| // the display name | ||
| char name[CLAP_NAME_SIZE]; | ||
|
|
||
| // the module path containing the param, eg:"oscillators/wt1" | ||
| // '/' will be used as a separator to show a tree like structure. | ||
| char module[CLAP_PATH_SIZE]; | ||
|
|
||
| double min_value; // minimum plain value | ||
| double max_value; // maximum plain value | ||
| double default_value; // default plain value | ||
| } clap_param_info_t; | ||
|
|
||
| typedef struct clap_plugin_params { | ||
| // Returns the number of parameters. | ||
| // [main-thread] | ||
| uint32_t (*count)(const clap_plugin_t *plugin); | ||
|
|
||
| // Copies the parameter's info to param_info and returns true on success. | ||
| // [main-thread] | ||
| bool (*get_info)(const clap_plugin_t *plugin, | ||
| uint32_t param_index, | ||
| clap_param_info_t *param_info); | ||
|
|
||
| // Gets the parameter plain value. | ||
| // [main-thread] | ||
| bool (*get_value)(const clap_plugin_t *plugin, clap_id param_id, double *value); | ||
|
|
||
| // Formats the display text for the given parameter value. | ||
| // The host should always format the parameter value to text using this function | ||
| // before displaying it to the user. | ||
| // [main-thread] | ||
| bool (*value_to_text)( | ||
| const clap_plugin_t *plugin, clap_id param_id, double value, char *display, uint32_t size); | ||
|
|
||
| // Converts the display text to a parameter value. | ||
| // [main-thread] | ||
| bool (*text_to_value)(const clap_plugin_t *plugin, | ||
| clap_id param_id, | ||
| const char *display, | ||
| double *value); | ||
|
|
||
| // Flushes a set of parameter changes. | ||
| // This method must not be called concurrently to clap_plugin->process(). | ||
| // | ||
| // [active ? audio-thread : main-thread] | ||
| void (*flush)(const clap_plugin_t *plugin, | ||
| const clap_input_events_t *in, | ||
| const clap_output_events_t *out); | ||
| } clap_plugin_params_t; | ||
|
|
||
| enum { | ||
| // The parameter values did change, eg. after loading a preset. | ||
| // The host will scan all the parameters value. | ||
| // The host will not record those changes as automation points. | ||
| // New values takes effect immediately. | ||
| CLAP_PARAM_RESCAN_VALUES = 1 << 0, | ||
|
|
||
| // The value to text conversion changed, and the text needs to be rendered again. | ||
| CLAP_PARAM_RESCAN_TEXT = 1 << 1, | ||
|
|
||
| // The parameter info did change, use this flag for: | ||
| // - name change | ||
| // - module change | ||
| // - is_periodic (flag) | ||
| // - is_hidden (flag) | ||
| // New info takes effect immediately. | ||
| CLAP_PARAM_RESCAN_INFO = 1 << 2, | ||
|
|
||
| // Invalidates everything the host knows about parameters. | ||
| // It can only be used while the plugin is deactivated. | ||
| // If the plugin is activated use clap_host->restart() and delay any change until the host calls | ||
| // clap_plugin->deactivate(). | ||
| // | ||
| // You must use this flag if: | ||
| // - some parameters were added or removed. | ||
| // - some parameters had critical changes: | ||
| // - is_per_note (flag) | ||
| // - is_per_channel (flag) | ||
| // - is_readonly (flag) | ||
| // - is_bypass (flag) | ||
| // - is_stepped (flag) | ||
| // - is_modulatable (flag) | ||
| // - min_value | ||
| // - max_value | ||
| // - cookie | ||
| CLAP_PARAM_RESCAN_ALL = 1 << 3, | ||
| }; | ||
| typedef uint32_t clap_param_rescan_flags; | ||
|
|
||
| enum { | ||
| // Clears all possible references to a parameter | ||
| CLAP_PARAM_CLEAR_ALL = 1 << 0, | ||
|
|
||
| // Clears all automations to a parameter | ||
| CLAP_PARAM_CLEAR_AUTOMATIONS = 1 << 1, | ||
|
|
||
| // Clears all modulations to a parameter | ||
| CLAP_PARAM_CLEAR_MODULATIONS = 1 << 2, | ||
| }; | ||
| typedef uint32_t clap_param_clear_flags; | ||
|
|
||
| typedef struct clap_host_params { | ||
| // Rescan the full list of parameters according to the flags. | ||
| // [main-thread] | ||
| void (*rescan)(const clap_host_t *host, clap_param_rescan_flags flags); | ||
|
|
||
| // Clears references to a parameter. | ||
| // [main-thread] | ||
| void (*clear)(const clap_host_t *host, clap_id param_id, clap_param_clear_flags flags); | ||
|
|
||
| // Request a parameter flush. | ||
| // | ||
| // The host will then schedule a call to either: | ||
| // - clap_plugin.process() | ||
| // - clap_plugin_params->flush() | ||
| // | ||
| // This function is always safe to use and should not be called from an [audio-thread] as the | ||
| // plugin would already be within process() or flush(). | ||
| // | ||
| // [thread-safe,!audio-thread] | ||
| void (*request_flush)(const clap_host_t *host); | ||
| } clap_host_params_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #pragma once | ||
|
|
||
| #include "private/std.h" | ||
| #include "private/macros.h" | ||
|
|
||
| /// We use fixed point representation of beat time and seconds time | ||
| /// Usage: | ||
| /// double x = ...; // in beats | ||
| /// clap_beattime y = round(CLAP_BEATTIME_FACTOR * x); | ||
|
|
||
| // This will never change | ||
| static const CLAP_CONSTEXPR int64_t CLAP_BEATTIME_FACTOR = 1LL << 31; | ||
| static const CLAP_CONSTEXPR int64_t CLAP_SECTIME_FACTOR = 1LL << 31; | ||
|
|
||
| typedef int64_t clap_beattime; | ||
| typedef int64_t clap_sectime; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| #pragma once | ||
|
|
||
| #include "version.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| typedef struct clap_host { | ||
| clap_version_t clap_version; // initialized to CLAP_VERSION | ||
|
|
||
| void *host_data; // reserved pointer for the host | ||
|
|
||
| // name and version are mandatory. | ||
| const char *name; // eg: "Bitwig Studio" | ||
| const char *vendor; // eg: "Bitwig GmbH" | ||
| const char *url; // eg: "https://bitwig.com" | ||
| const char *version; // eg: "4.3" | ||
|
|
||
| // Query an extension. | ||
| // [thread-safe] | ||
| const void *(*get_extension)(const struct clap_host *host, const char *extension_id); | ||
|
|
||
| // Request the host to deactivate and then reactivate the plugin. | ||
| // The operation may be delayed by the host. | ||
| // [thread-safe] | ||
| void (*request_restart)(const struct clap_host *host); | ||
|
|
||
| // Request the host to activate and start processing the plugin. | ||
| // This is useful if you have external IO and need to wake up the plugin from "sleep". | ||
| // [thread-safe] | ||
| void (*request_process)(const struct clap_host *host); | ||
|
|
||
| // Request the host to schedule a call to plugin->on_main_thread(plugin) on the main thread. | ||
| // [thread-safe] | ||
| void (*request_callback)(const struct clap_host *host); | ||
| } clap_host_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| #pragma once | ||
|
|
||
| #include "private/std.h" | ||
| #include "private/macros.h" | ||
|
|
||
| typedef uint32_t clap_id; | ||
|
|
||
| static const CLAP_CONSTEXPR clap_id CLAP_INVALID_ID = UINT32_MAX; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| #pragma once | ||
|
|
||
| #include "plugin.h" | ||
|
|
||
| static const CLAP_CONSTEXPR char CLAP_PLUGIN_FACTORY_ID[] = "clap.plugin-factory"; | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| // Every method must be thread-safe. | ||
| // It is very important to be able to scan the plugin as quickly as possible. | ||
| // | ||
| // If the content of the factory may change due to external events, like the user installed | ||
| typedef struct clap_plugin_factory { | ||
| // Get the number of plugins available. | ||
| // [thread-safe] | ||
| uint32_t (*get_plugin_count)(const struct clap_plugin_factory *factory); | ||
|
|
||
| // Retrieves a plugin descriptor by its index. | ||
| // Returns null in case of error. | ||
| // The descriptor must not be freed. | ||
| // [thread-safe] | ||
| const clap_plugin_descriptor_t *(*get_plugin_descriptor)( | ||
| const struct clap_plugin_factory *factory, uint32_t index); | ||
|
|
||
| // Create a clap_plugin by its plugin_id. | ||
| // The returned pointer must be freed by calling plugin->destroy(plugin); | ||
| // The plugin is not allowed to use the host callbacks in the create method. | ||
| // Returns null in case of error. | ||
| // [thread-safe] | ||
| const clap_plugin_t *(*create_plugin)(const struct clap_plugin_factory *factory, | ||
| const clap_host_t *host, | ||
| const char *plugin_id); | ||
| } clap_plugin_factory_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| #pragma once | ||
|
|
||
| #include "private/macros.h" | ||
|
|
||
| // This file provides a set of standard plugin features meant to be used | ||
| // within clap_plugin_descriptor.features. | ||
| // | ||
| // For practical reasons we'll avoid spaces and use `-` instead to facilitate | ||
| // scripts that generate the feature array. | ||
| // | ||
| // Non-standard features should be formated as follow: "$namespace:$feature" | ||
|
|
||
| ///////////////////// | ||
| // Plugin category // | ||
| ///////////////////// | ||
|
|
||
| // Add this feature if your plugin can process note events and then produce audio | ||
| #define CLAP_PLUGIN_FEATURE_INSTRUMENT "instrument" | ||
|
|
||
| // Add this feature if your plugin is an audio effect | ||
| #define CLAP_PLUGIN_FEATURE_AUDIO_EFFECT "audio-effect" | ||
|
|
||
| // Add this feature if your plugin is a note effect or a note generator/sequencer | ||
| #define CLAP_PLUGIN_FEATURE_NOTE_EFFECT "note-effect" | ||
|
|
||
| // Add this feature if your plugin is an analyzer | ||
| #define CLAP_PLUGIN_FEATURE_ANALYZER "analyzer" | ||
|
|
||
| ///////////////////////// | ||
| // Plugin sub-category // | ||
| ///////////////////////// | ||
|
|
||
| #define CLAP_PLUGIN_FEATURE_SYNTHESIZER "synthesizer" | ||
| #define CLAP_PLUGIN_FEATURE_SAMPLER "sampler" | ||
| #define CLAP_PLUGIN_FEATURE_DRUM "drum" // For single drum | ||
| #define CLAP_PLUGIN_FEATURE_DRUM_MACHINE "drum-machine" | ||
|
|
||
| #define CLAP_PLUGIN_FEATURE_FILTER "filter" | ||
| #define CLAP_PLUGIN_FEATURE_PHASER "phaser" | ||
| #define CLAP_PLUGIN_FEATURE_EQUALIZER "equalizer" | ||
| #define CLAP_PLUGIN_FEATURE_DEESSER "de-esser" | ||
| #define CLAP_PLUGIN_FEATURE_PHASE_VOCODER "phase-vocoder" | ||
| #define CLAP_PLUGIN_FEATURE_GRANULAR "granular" | ||
| #define CLAP_PLUGIN_FEATURE_FREQUENCY_SHIFTER "frequency-shifter" | ||
| #define CLAP_PLUGIN_FEATURE_PITCH_SHIFTER "pitch-shifter" | ||
|
|
||
| #define CLAP_PLUGIN_FEATURE_DISTORTION "distortion" | ||
| #define CLAP_PLUGIN_FEATURE_TRANSIENT_SHAPER "transient-shaper" | ||
| #define CLAP_PLUGIN_FEATURE_COMPRESSOR "compressor" | ||
| #define CLAP_PLUGIN_FEATURE_LIMITER "limiter" | ||
|
|
||
| #define CLAP_PLUGIN_FEATURE_FLANGER "flanger" | ||
| #define CLAP_PLUGIN_FEATURE_CHORUS "chorus" | ||
| #define CLAP_PLUGIN_FEATURE_DELAY "delay" | ||
| #define CLAP_PLUGIN_FEATURE_REVERB "reverb" | ||
|
|
||
| #define CLAP_PLUGIN_FEATURE_TREMOLO "tremolo" | ||
| #define CLAP_PLUGIN_FEATURE_GLITCH "glitch" | ||
|
|
||
| #define CLAP_PLUGIN_FEATURE_UTILITY "utility" | ||
| #define CLAP_PLUGIN_FEATURE_PITCH_CORRECTION "pitch-correction" | ||
| #define CLAP_PLUGIN_FEATURE_RESTORATION "restoration" // repair the sound | ||
|
|
||
| #define CLAP_PLUGIN_FEATURE_MULTI_EFFECTS "multi-effects" | ||
|
|
||
| #define CLAP_PLUGIN_FEATURE_MIXING "mixing" | ||
| #define CLAP_PLUGIN_FEATURE_MASTERING "mastering" | ||
|
|
||
| //////////////////////// | ||
| // Audio Capabilities // | ||
| //////////////////////// | ||
|
|
||
| #define CLAP_PLUGIN_FEATURE_MONO "mono" | ||
| #define CLAP_PLUGIN_FEATURE_STEREO "stereo" | ||
| #define CLAP_PLUGIN_FEATURE_SURROUND "surround" | ||
| #define CLAP_PLUGIN_FEATURE_AMBISONIC "ambisonic" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| #pragma once | ||
|
|
||
| #include "private/macros.h" | ||
| #include "host.h" | ||
| #include "process.h" | ||
| #include "plugin-features.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| typedef struct clap_plugin_descriptor { | ||
| clap_version_t clap_version; // initialized to CLAP_VERSION | ||
|
|
||
| // Mandatory fields must be set and must not be blank. | ||
| // Otherwise the fields can be null or blank, though it is safer to make them blank. | ||
| const char *id; // eg: "com.u-he.diva", mandatory | ||
| const char *name; // eg: "Diva", mandatory | ||
| const char *vendor; // eg: "u-he" | ||
| const char *url; // eg: "https://u-he.com/products/diva/" | ||
| const char *manual_url; // eg: "https://dl.u-he.com/manuals/plugins/diva/Diva-user-guide.pdf" | ||
| const char *support_url; // eg: "https://u-he.com/support/" | ||
| const char *version; // eg: "1.4.4" | ||
| const char *description; // eg: "The spirit of analogue" | ||
|
|
||
| // Arbitrary list of keywords. | ||
| // They can be matched by the host indexer and used to classify the plugin. | ||
| // The array of pointers must be null terminated. | ||
| // For some standard features see plugin-features.h | ||
| const char **features; | ||
| } clap_plugin_descriptor_t; | ||
|
|
||
| typedef struct clap_plugin { | ||
| const clap_plugin_descriptor_t *desc; | ||
|
|
||
| void *plugin_data; // reserved pointer for the plugin | ||
|
|
||
| // Must be called after creating the plugin. | ||
| // If init returns false, the host must destroy the plugin instance. | ||
| // [main-thread] | ||
| bool (*init)(const struct clap_plugin *plugin); | ||
|
|
||
| // Free the plugin and its resources. | ||
| // It is required to deactivate the plugin prior to this call. | ||
| // [main-thread & !active] | ||
| void (*destroy)(const struct clap_plugin *plugin); | ||
|
|
||
| // Activate and deactivate the plugin. | ||
| // In this call the plugin may allocate memory and prepare everything needed for the process | ||
| // call. The process's sample rate will be constant and process's frame count will included in | ||
| // the [min, max] range, which is bounded by [1, INT32_MAX]. | ||
| // Once activated the latency and port configuration must remain constant, until deactivation. | ||
| // | ||
| // [main-thread & !active_state] | ||
| bool (*activate)(const struct clap_plugin *plugin, | ||
| double sample_rate, | ||
| uint32_t min_frames_count, | ||
| uint32_t max_frames_count); | ||
|
|
||
| // [main-thread & active_state] | ||
| void (*deactivate)(const struct clap_plugin *plugin); | ||
|
|
||
| // Call start processing before processing. | ||
| // [audio-thread & active_state & !processing_state] | ||
| bool (*start_processing)(const struct clap_plugin *plugin); | ||
|
|
||
| // Call stop processing before sending the plugin to sleep. | ||
| // [audio-thread & active_state & processing_state] | ||
| void (*stop_processing)(const struct clap_plugin *plugin); | ||
|
|
||
| // - Clears all buffers, performs a full reset of the processing state (filters, oscillators, | ||
| // enveloppes, lfo, ...) and kills all voices. | ||
| // - The parameter's value remain unchanged. | ||
| // - clap_process.steady_time may jump backward. | ||
| // | ||
| // [audio-thread & active_state] | ||
| void (*reset)(const struct clap_plugin *plugin); | ||
|
|
||
| // process audio, events, ... | ||
| // [audio-thread & active_state & processing_state] | ||
| clap_process_status (*process)(const struct clap_plugin *plugin, const clap_process_t *process); | ||
|
|
||
| // Query an extension. | ||
| // The returned pointer is owned by the plugin. | ||
| // [thread-safe] | ||
| const void *(*get_extension)(const struct clap_plugin *plugin, const char *id); | ||
|
|
||
| // Called by the host on the main thread in response to a previous call to: | ||
| // host->request_callback(host); | ||
| // [main-thread] | ||
| void (*on_main_thread)(const struct clap_plugin *plugin); | ||
| } clap_plugin_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #pragma once | ||
|
|
||
| // Define CLAP_EXPORT | ||
| #if !defined(CLAP_EXPORT) | ||
| # if defined _WIN32 || defined __CYGWIN__ | ||
| # ifdef __GNUC__ | ||
| # define CLAP_EXPORT __attribute__((dllexport)) | ||
| # else | ||
| # define CLAP_EXPORT __declspec(dllexport) | ||
| # endif | ||
| # else | ||
| # if __GNUC__ >= 4 || defined(__clang__) | ||
| # define CLAP_EXPORT __attribute__((visibility("default"))) | ||
| # else | ||
| # define CLAP_EXPORT | ||
| # endif | ||
| # endif | ||
| #endif | ||
|
|
||
| #if defined(__cplusplus) && __cplusplus >= 201103L | ||
| # define CLAP_HAS_CXX11 | ||
| # define CLAP_CONSTEXPR constexpr | ||
| #else | ||
| # define CLAP_CONSTEXPR | ||
| #endif | ||
|
|
||
| #if defined(__cplusplus) && __cplusplus >= 201703L | ||
| # define CLAP_HAS_CXX17 | ||
| # define CLAP_NODISCARD [[nodiscard]] | ||
| #else | ||
| # define CLAP_NODISCARD | ||
| #endif | ||
|
|
||
| #if defined(__cplusplus) && __cplusplus >= 202002L | ||
| # define CLAP_HAS_CXX20 | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #pragma once | ||
|
|
||
| #include "macros.h" | ||
|
|
||
| #ifdef CLAP_HAS_CXX11 | ||
| # include <cstdint> | ||
| #else | ||
| # include <stdint.h> | ||
| #endif | ||
|
|
||
| #ifdef __cplusplus | ||
| # include <cstddef> | ||
| #else | ||
| # include <stddef.h> | ||
| # include <stdbool.h> | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| #pragma once | ||
|
|
||
| #include "events.h" | ||
| #include "audio-buffer.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| enum { | ||
| // Processing failed. The output buffer must be discarded. | ||
| CLAP_PROCESS_ERROR = 0, | ||
|
|
||
| // Processing succeeded, keep processing. | ||
| CLAP_PROCESS_CONTINUE = 1, | ||
|
|
||
| // Processing succeeded, keep processing if the output is not quiet. | ||
| CLAP_PROCESS_CONTINUE_IF_NOT_QUIET = 2, | ||
|
|
||
| // Rely upon the plugin's tail to determine if the plugin should continue to process. | ||
| // see clap_plugin_tail | ||
| CLAP_PROCESS_TAIL = 3, | ||
|
|
||
| // Processing succeeded, but no more processing is required, | ||
| // until the next event or variation in audio input. | ||
| CLAP_PROCESS_SLEEP = 4, | ||
| }; | ||
| typedef int32_t clap_process_status; | ||
|
|
||
| typedef struct clap_process { | ||
| // A steady sample time counter. | ||
| // This field can be used to calculate the sleep duration between two process calls. | ||
| // This value may be specific to this plugin instance and have no relation to what | ||
| // other plugin instances may receive. | ||
| // | ||
| // Set to -1 if not available, otherwise the value must be greater or equal to 0, | ||
| // and must be increased by at least `frames_count` for the next call to process. | ||
| int64_t steady_time; | ||
|
|
||
| // Number of frames to process | ||
| uint32_t frames_count; | ||
|
|
||
| // time info at sample 0 | ||
| // If null, then this is a free running host, no transport events will be provided | ||
| const clap_event_transport_t *transport; | ||
|
|
||
| // Audio buffers, they must have the same count as specified | ||
| // by clap_plugin_audio_ports->get_count(). | ||
| // The index maps to clap_plugin_audio_ports->get_info(). | ||
| const clap_audio_buffer_t *audio_inputs; | ||
| clap_audio_buffer_t *audio_outputs; | ||
| uint32_t audio_inputs_count; | ||
| uint32_t audio_outputs_count; | ||
|
|
||
| // Input and output events. | ||
| // | ||
| // Events must be sorted by time. | ||
| // The input event list can't be modified. | ||
| const clap_input_events_t *in_events; | ||
| const clap_output_events_t *out_events; | ||
| } clap_process_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| #pragma once | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| enum { | ||
| // String capacity for names that can be displayed to the user. | ||
| CLAP_NAME_SIZE = 256, | ||
|
|
||
| // String capacity for describing a path, like a parameter in a module hierarchy or path within a | ||
| // set of nested track groups. | ||
| // | ||
| // This is not suited for describing a file path on the disk, as NTFS allows up to 32K long | ||
| // paths. | ||
| CLAP_PATH_SIZE = 1024, | ||
| }; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #pragma once | ||
|
|
||
| #include "private/macros.h" | ||
| #include "private/std.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| typedef struct clap_version { | ||
| // This is the major ABI and API design | ||
| // Version 0.X.Y correspond to the development stage, API and ABI are not stable | ||
| // Version 1.X.Y correspont to the release stage, API and ABI are stable | ||
| uint32_t major; | ||
| uint32_t minor; | ||
| uint32_t revision; | ||
| } clap_version_t; | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #define CLAP_VERSION_MAJOR ((uint32_t)1) | ||
| #define CLAP_VERSION_MINOR ((uint32_t)1) | ||
| #define CLAP_VERSION_REVISION ((uint32_t)1) | ||
| #define CLAP_VERSION_INIT {CLAP_VERSION_MAJOR, CLAP_VERSION_MINOR, CLAP_VERSION_REVISION} | ||
|
|
||
| static const CLAP_CONSTEXPR clap_version_t CLAP_VERSION = CLAP_VERSION_INIT; | ||
|
|
||
| CLAP_NODISCARD static inline CLAP_CONSTEXPR bool | ||
| clap_version_is_compatible(const clap_version_t v) { | ||
| // versions 0.x.y were used during development stage and aren't compatible | ||
| return v.major >= 1; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| EXPORTS | ||
| clap_entry |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| _clap_entry |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| global: clap_entry; | ||
| local: *; | ||
| }; |