Skip to content

Commit

Permalink
Merge pull request #371 from free-audio/next
Browse files Browse the repository at this point in the history
CLAP 1.2.0
  • Loading branch information
abique authored Jan 22, 2024
2 parents e292447 + a470662 commit df8f16c
Show file tree
Hide file tree
Showing 42 changed files with 634 additions and 257 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ add_custom_target(clap-tests)

if (${CLAP_BUILD_TESTS})
message(STATUS "Including CLAP tests, compile tests, and versions")
include(CheckIncludeFile)

macro(clap_compile_cpp SUFFIX EXT STDC STDCPP)
add_executable(clap-compile-${SUFFIX} EXCLUDE_FROM_ALL src/main.${EXT})
Expand Down Expand Up @@ -84,11 +85,17 @@ if (${CLAP_BUILD_TESTS})
clap_compile_cpp(cpp17 cc 17 17)
clap_compile_cpp(cpp20 cc 17 20)

check_include_file(threads.h CLAP_HAS_THREADS_H)

add_library(clap-plugin-template MODULE EXCLUDE_FROM_ALL src/plugin-template.c)
target_link_libraries(clap-plugin-template PRIVATE clap)
set_target_properties(clap-plugin-template PROPERTIES C_STANDARD 11)
add_dependencies(clap-tests clap-plugin-template)

if(CLAP_HAS_THREADS_H)
target_compile_definitions(clap-plugin-template PRIVATE CLAP_HAS_THREADS_H)
endif()

if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(clap-plugin-template PRIVATE -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/linux-my_plug.version)
target_link_libraries(clap-plugin-template PRIVATE -Wl,-z,defs)
Expand Down
74 changes: 74 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,77 @@
# Changes in 1.2.0

## New conventions

* [extension-id](conventions/extension-id.md): introduce some rules about extension ID naming.

## Stabilize extensions

* `CLAP_EXT_AMBISONIC`
* `CLAP_EXT_AUDIO_PORTS_ACTIVATION`
* `CLAP_EXT_CONFIGURABLE_AUDIO_PORTS`
* `CLAP_EXT_CONTEXT_MENU`
* `CLAP_EXT_PARAM_INDICATION`
* `CLAP_EXT_PRESET_LOAD`
* `CLAP_EXT_REMOTE_CONTROLS`
* `CLAP_EXT_STATE_CONTEXT`
* `CLAP_EXT_SURROUND`
* `CLAP_EXT_TRACK_INFO`

### Notes regarding extension ID change after draft stabilization

We changed the extension ID in the process of stabilization which leads to a **break**.

To mitigate this transition, we've provided compatibility extension IDs which can be used to match and use the latest draft extensions as they are 100% compatible.

For example, `CLAP_EXT_CONTEXT_MENU` for the stable ID and `CLAP_EXT_CONTEXT_MENU_COMPAT` for the draft ID.

As you can see in [extension-id](conventions/extension-id.md), we introduced some rules, so this kind of break won't happen again.

We may decide to remove the `*_COMPAT` IDs in the future once their usage becomes antiquated.

## Removed draft extensions

* `CLAP_EXT_CHECK_FOR_UPDATE` wasn't used and it's design needed more thought.
* `CLAP_EXT_MIDI_MAPPING` wasn't used. MIDI2 seems to do it better, and the interface wasn't satisfying.
* `CLAP_EXT_CV` the interface wasn't satisfying.

## Stabilize factory

* `CLAP_PRESET_DISCOVERY_FACTORY_ID`

Note: we kept the last draft factory ID in order to not break plugins already using it.

## Plugin State Converter

* Introduction of a new factory which provides a plugin state convertion mechanism.

## Refactoring

* `clap_plugin_id_t` was renamed to `clap_universal_plugin_id_t` to make it clear that it can describe more than just a CLAP plugin ID.
* `clap_timestamp_t` was renamed to `clap_timestamp` to be consistent with other types, like e.g. `clap_id`. Also it was moved to a separate header as `CLAP_PRESET_DISCOVERY_FACTORY_ID` was stabilized.

## Documentation

* [events.h](include/clap/events.h): Clarify how "Port Channel Key NoteID" matching works
* [events.h](include/clap/events.h): Clarify how `clap_event_note` fields map to MIDI, Host, etc...
* [events.h](include/clap/events.h): Expand clap note expression documentation
* [plugin.h](include/clap/plugin.h): Style cleanup
* [params.h](include/clap/ext/params.h): Fix incorrect function name reference
* [latency.h](include/clap/ext/latency.h): Require the plugin to be activated to get the latency and clarify that the latency can only be fetched when the plugin is activated

## Plugin Template

* [plugin-template.c](src/plugin-template.c): implement thread-safe plugin entry init counter

## Organization

* `clap.h` no longer includes headers from `ext/draft` or `factory/draft`. Draft extension and factory headers must now be explicitly included, either individually or via the `all.h` header.

## Other changes

* [voice-info.h](include/clap/ext/voice-info.h): Make the voice info id `CLAP_CONSTEXPR` like all other ids
* [preset-load.h](include/clap/ext/preset-load.h): Make the preset load id and compat id `CLAP_CONSTEXPR` like all other ids

# Changes in 1.1.10

* [params.h](include/clap/ext/params.h): add `CLAP_PARAM_IS_ENUM` flag.
Expand Down
43 changes: 27 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- [Extensions](#extensions)
- [Fundamental extensions](#fundamental-extensions)
- [Support extensions](#support-extensions)
- [Extra extensions](#extra-extensions)
- [Deeper Host integration](#deeper-host-integration)
- [Third-party extensions](#third-party-extensions)
- [Adapters](#adapters)
- [Resources](#resources)
Expand All @@ -32,6 +32,7 @@ that is, a plugin binary compiled with CLAP 1.x can be loaded by any other
CLAP 1.y.

To work with CLAP, include [clap/clap.h](include/clap/clap.h).
To also include the draft extensions, include [clap/all.h](include/clap/all.h).

The two most important objects are `clap_host` and `clap_plugin`.

Expand Down Expand Up @@ -81,34 +82,44 @@ You can create your own extensions and share them. Make sure that the extension
This is a list of the extensions that you most likely want to implement
and use to get a basic plugin experience:
- [log](include/clap/ext/log.h), lets the host aggregate plugin logs
- [thread-check](include/clap/ext/thread-check.h), check which thread you are currently on, useful for correctness validation
- [audio-ports](include/clap/ext/audio-ports.h), define the audio ports
- [note-ports](include/clap/ext/note-ports.h), define the note ports
- [state](include/clap/ext/state.h), save and load the plugin state
- [state-context](include/clap/ext/state-context.h), same as state but with additional context info (preset, duplicate, project)
- [resource-directory](include/clap/ext/draft/resource-directory.h), host provided folder for the plugin to save extra resource like multi-samples, ... (draft)
- [params](include/clap/ext/params.h), parameters management
- [latency](include/clap/ext/latency.h), report the plugin latency
- [note-ports](include/clap/ext/note-ports.h), define the note ports
- [audio-ports](include/clap/ext/audio-ports.h), define the audio ports
- [surround](include/clap/ext/surround.h), inspect surround channel mapping
- [ambisonic](include/clap/ext/draft/ambisonic.h), inspect ambisonic channel mapping
- [configurable-audio-ports](include/clap/ext/configurable-audio-ports.h), request the plugin to apply a given configuration
- [audio-ports-config](include/clap/ext/audio-ports-config.h), simple list of pre-defined audio ports configurations, meant to be exposed to the user
- [audio-ports-activation](include/clap/ext/audio-ports-activation.h), activate and deactivate a given audio port
- [extensible-audio-ports](include/clap/ext/draft/extensible-audio-ports.h), let the host add audio ports to the plugin, this is useful for dynamic number of audio inputs (draft)
- [render](include/clap/ext/render.h), renders realtime or offline
- [latency](include/clap/ext/latency.h), report the plugin latency
- [tail](include/clap/ext/tail.h), processing tail length
- [state](include/clap/ext/state.h), save and load the plugin state
- [gui](include/clap/ext/gui.h), generic gui controller
- [voice-info](include/clap/ext/voice-info.h), let the host know how many voices the plugin has, this is important for polyphonic modulations
- [track-info](include/clap/ext/track-info.h), give some info to the plugin about the track it belongs to
- [tuning](include/clap/ext/draft/tuning.h), host provided microtuning (draft)
- [triggers](include/clap/ext/draft/triggers.h), plugin's triggers, similar to parameters but stateless
## Support extensions
- [thread-check](include/clap/ext/thread-check.h), check which thread you are currently on, useful for correctness validation
- [thread-pool](include/clap/ext/thread-pool.h), use the host thread pool
- [log](include/clap/ext/log.h), lets the host aggregate plugin logs
- [timer-support](include/clap/ext/timer-support.h), lets the plugin register timer handlers
- [posix-fd-support](include/clap/ext/posix-fd-support.h), lets the plugin register I/O handlers
## Extra extensions
## Deeper Host integration
- [remote-controls](include/clap/ext/remote-controls.h), bank of controls that can be mapped on a controlles with 8 knobs
- [preset-discovery](include/clap/factory/preset-discovery.h), let the host index the plugin's preset in their native file format
- [preset-load](include/clap/ext/preset-load.h), let the host ask the plugin to load a preset
- [param-indication](include/clap/ext/param-indication.h), let the plugin know when a physical control is mapped to a parameter and if there is automation data
- [note-name](include/clap/ext/note-name.h), give a name to notes, useful for drum machines
- [tuning](include/clap/ext/draft/tuning.h), host provided microtuning
- [track-info](include/clap/ext/draft/track-info.h)
- [quick-controls](include/clap/ext/draft/quick-controls.h), bank of controls that can be mapped on a controlles with 8 knobs
- [file-reference](include/clap/ext/draft/file-reference.h), let the host know about the plugin's file reference, and perform "Collect & Save"
- [check-for-update](include/clap/ext/draft/check-for-update.h), check if there is a new version of a plugin
- [audio-ports-config](include/clap/ext/audio-ports-config.h), simple list of possible configurations
- [surround](include/clap/ext/draft/surround.h), inspect surround channel mapping
- [ambisonic](include/clap/ext/draft/ambisonic.h), inspect ambisonic channel mapping
- [transport-control](include/clap/ext/draft/transport-control.h), let the plugin control the host's transport (draft)
- [context-menu](include/clap/ext/context-menu.h), exchange context menu entries between host and plugin, let the plugin ask the host to popup its own context menu
## Third-party extensions
Expand Down
32 changes: 32 additions & 0 deletions conventions/extension-id.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Extension ID

## Naming

The extension shall be named in the form: `clap.$NAME/$REV`.
Where:
- `$NAME` is the name of the exension.
- `$REV` is the revision of the extension. This is an integer that is incremented for each iteration. It should start at 1.

For extensions made by third-parties and not officially published by the CLAP project, please use the following form: `$REVERSE_URI.$NAME/$REV`.
Where:
- `$REVERSE_URI` would be something like `com.bitwig`.

## Draft

An extension is considered a draft extension if it is in the [draft](../include/clap/ext/draft/) folder.
Make sure to also include it in [all.h](../include/clap/all.h).

When the extension is migrating from draft to stable, its extension ID must not change.
Move its inclusion from [all.h](../include/clap/all.h) into [clap.h](../include/clap/clap.h).

All extensions must go though the draft phase first.

## For factory ID

Everything about the extension id symmetrically applies to factory id.

## History

Before version 1.2.0 when this document was written, existing extensions didn't honor these rules.
We wanted to stabilize some draft extensions without breaking compatibility, yet their extension IDs contained the string `draft`.
While these strings weren't user-facing, we still wanted to remove them, so we updated the extension IDs according to this document and introduced IDs with `_COMPAT` suffixes to provide backward compatibility with the draft versions.
12 changes: 12 additions & 0 deletions include/clap/all.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "clap.h"

#include "factory/draft/plugin-invalidation.h"
#include "factory/draft/plugin-state-converter.h"

#include "ext/draft/extensible-audio-ports.h"
#include "ext/draft/resource-directory.h"
#include "ext/draft/transport-control.h"
#include "ext/draft/triggers.h"
#include "ext/draft/tuning.h"
31 changes: 12 additions & 19 deletions include/clap/clap.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,44 +28,37 @@
#include "entry.h"

#include "factory/plugin-factory.h"
#include "factory/draft/plugin-invalidation.h"
#include "factory/draft/preset-discovery.h"
#include "factory/preset-discovery.h"

#include "plugin.h"
#include "plugin-features.h"
#include "host.h"
#include "universal-plugin-id.h"

#include "ext/ambisonic.h"
#include "ext/audio-ports-activation.h"
#include "ext/audio-ports-config.h"
#include "ext/audio-ports.h"
#include "ext/configurable-audio-ports.h"
#include "ext/context-menu.h"
#include "ext/event-registry.h"
#include "ext/gui.h"
#include "ext/latency.h"
#include "ext/log.h"
#include "ext/note-name.h"
#include "ext/note-ports.h"
#include "ext/param-indication.h"
#include "ext/params.h"
#include "ext/posix-fd-support.h"
#include "ext/preset-load.h"
#include "ext/remote-controls.h"
#include "ext/render.h"
#include "ext/state-context.h"
#include "ext/state.h"
#include "ext/surround.h"
#include "ext/tail.h"
#include "ext/thread-check.h"
#include "ext/thread-pool.h"
#include "ext/timer-support.h"
#include "ext/track-info.h"
#include "ext/voice-info.h"

#include "ext/draft/ambisonic.h"
#include "ext/draft/audio-ports-activation.h"
#include "ext/draft/context-menu.h"
#include "ext/draft/cv.h"
#include "ext/draft/midi-mappings.h"
#include "ext/draft/param-indication.h"
#include "ext/draft/preset-load.h"
#include "ext/draft/remote-controls.h"
#include "ext/draft/resource-directory.h"
#include "ext/draft/state-context.h"
#include "ext/draft/surround.h"
#include "ext/draft/track-info.h"
#include "ext/draft/triggers.h"
#include "ext/draft/tuning.h"
#include "ext/draft/configurable-audio-ports.h"
#include "ext/draft/extensible-audio-ports.h"
80 changes: 73 additions & 7 deletions include/clap/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,34 +31,100 @@ extern "C" {
// 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.
// init and deinit in most cases are called once, in a matched pair, when the dso is loaded / unloaded.
// In some rare situations it may be called multiple times in a process, so the functions must be defensive,
// mutex locking and counting calls if undertaking non trivial non idempotent actions.
//
// Rationale:
//
// The intent of the init() and deinit() functions is to provide a "normal" initialization patterh
// which occurs when the shared object is loaded or unloaded. As such, hosts will call each once and
// in matched pairs. In CLAP specifications prior to 1.2.0, this single-call was documented as a
// requirement.
//
// We realized, though, that this is not a requirement hosts can meet. If hosts load a plugin
// which itself wraps another CLAP for instance, while also loading that same clap in its memory
// space, both the host and the wrapper will call init() and deinit() and have no means to communicate
// the state.
//
// With CLAP 1.2.0 and beyond we are changing the spec to indicate that a host should make an
// absolute best effort to call init() and deinit() once, and always in matched pairs (for every
// init() which returns true, one deinit() should be called).
//
// This takes the de-facto burden on plugin writers to deal with multiple calls into a hard requirement.
//
// Most init() / deinit() pairs we have seen are the relatively trivial {return true;} and {}. But
// if your init() function does non-trivial one time work, the plugin author must maintain a counter
// and must manage a mutex lock. The most obvious implementation will maintain a static counter and a
// global mutex, increment the counter on each init, decrement it on each deinit, and only undertake
// the init or deinit action when the counter is zero.
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.
// Initializes the DSO.
//
// This function must be called first, before any-other CLAP-related function or symbol from this
// DSO.
//
// It also must only be called once, until a later call to deinit() is made, after which init()
// can be called once more to re-initialize the DSO.
// This enables hosts to e.g. quickly load and unload a DSO for scanning its plugins, and then
// load it again later to actually use the plugins if needed.
//
// As stated above, even though hosts are forbidden to do so directly, multiple calls before any
// deinit() call may still happen. Implementations *should* take this into account, and *must*
// do so as of CLAP 1.2.0.
//
// 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.
// It is forbidden to display graphical user interfaces in this call.
// It is forbidden to perform any 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.
// Returns true on success. If init() returns false, then the DSO must be considered
// uninitialized, and the host must not call deinit() nor any other CLAP-related symbols from the
// DSO.
// This function also returns true in the case where the DSO is already initialized, and no
// actual initialization work is done in this call, as explain above.
//
// plugin_path is the path to the DSO (Linux, Windows), or the bundle (macOS).
//
// This function may be called on any thread, including a different one from the one a later call
// to deinit() (or a later init()) can be made.
// However, it is forbidden to call this function simultaneously from multiple threads.
// It is also forbidden to call it simultaneously with *any* other CLAP-related symbols from the
// DSO, including (but not limited to) deinit().
bool(CLAP_ABI *init)(const char *plugin_path);

// No more calls into the DSO must be made after calling deinit().
// De-initializes the DSO, freeing any resources allocated or initialized by init().
//
// After this function is called, no more calls into the DSO must be made, except calling init()
// again to re-initialize the DSO.
// This means that after deinit() is called, the DSO can be considered to be in the same state
// as if init() was never called at all yet, enabling it to be re-initialized as needed.
//
// As stated above, even though hosts are forbidden to do so directly, multiple calls before any
// new init() call may still happen. Implementations *should* take this into account, and *must*
// do so as of CLAP 1.2.0.
//
// Just like init(), this function may be called on any thread, including a different one from
// the one init() was called from, or from the one a later init() call can be made.
// However, it is forbidden to call this function simultaneously from multiple threads.
// It is also forbidden to call it simultaneously with *any* other CLAP-related symbols from the
// DSO, including (but not limited to) deinit().
void(CLAP_ABI *deinit)(void);

// Get the pointer to a factory. See factory/plugin-factory.h for an example.
//
// Returns null if the factory is not provided.
// The returned pointer must *not* be freed by the caller.
//
// Unlike init() and deinit(), this function can be called simultaneously by multiple threads.
//
// [thread-safe]
const void *(CLAP_ABI *get_factory)(const char *factory_id);
} clap_plugin_entry_t;

Expand Down
Loading

0 comments on commit df8f16c

Please sign in to comment.