git subrepo clone (merge) https://github.com/free-audio/clap deps/clap-juce-extensions/clap-libs/clap

subrepo:
  subdir:   "deps/clap-juce-extensions/clap-libs/clap"
  merged:   "3189bdfaf"
upstream:
  origin:   "https://github.com/free-audio/clap"
  branch:   "main"
  commit:   "3189bdfaf"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/ingydotnet/git-subrepo.git"
  commit:   "2f68596"
This commit is contained in:
essej 2022-06-14 21:34:50 -04:00
parent 1b74370003
commit 8bbddf66e9
77 changed files with 8684 additions and 1 deletions

@ -1 +0,0 @@
Subproject commit 84ad6fe9739d3070ed0eb05c24be303a899ab813

View File

@ -0,0 +1,137 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -3
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 3
ContinuationIndentWidth: 3
Cpp11BracedListStyle: true
DeriveLineEnding: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
- Regex: '.*'
Priority: 1
SortPriority: 0
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentGotoLabels: true
IndentPPDirectives: AfterHash
IndentWidth: 3
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 3
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Latest
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
...

View File

@ -0,0 +1,45 @@
# Copyright (c) 2021 Luca Cappa
# Released under the term specified in file LICENSE.txt
# SPDX short identifier: MIT
#
# The peculiarity of this workflow is that assumes vcpkg stored as a submodule of this repository.
# This workflow does the following:
# - Restores vcpkg artifacts from cache.
# - Sets up vcpkg if needed, then run CMake with CMakePreset.json using a configuration
# that leverages the vcpkg's toolchain file. This will automatically run vcpkg to install dependencies
# described by the vcpkg.json manifest file. It will be a no-op if those are restored from cache.
# - Finally builds the sources with Ninja.
name: build
on: [push, workflow_dispatch]
jobs:
VCPKG:
name: ${{ matrix.os }}-${{ github.workflow }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v2
with:
submodules: true
- uses: lukka/get-cmake@latest
- name: Setup MacOS
if: startsWith(matrix.os, 'macOS')
run: brew install automake autoconf ninja cmake
- name: Setup Ubuntu
if: startsWith(matrix.os, 'ubuntu')
run: sudo apt install ninja-build cmake
- name: Run CMake+Ninja+CTest to generate/build/test.
uses: lukka/run-cmake@v10
id: runcmake
with:
configurePreset: 'ninja'
buildPreset: 'ninja-release'
testPreset: 'ninja-release'

View File

@ -0,0 +1,6 @@
{
"name": "clap",
"description": "Build C/C++ code with CMake and Ninja.",
"iconName": "cmake",
"categories": ["CMake", "cpp", "cplusplus", "Ninja"]
}

View File

@ -0,0 +1,60 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Visual Studio
obj/
*.sln
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
.vs/
packages/
target/
*.pdb
packages.config
CMakeSettings.json
.vscode
.cache
# C++ IDE helpers
compile_commands.json
# IntelliJ IDEA
.idea
# CMake common patterns
build*/
cmake-build*/
# A place to store stuff and get it git ignored
ignore/*

View File

@ -0,0 +1,12 @@
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
;
[subrepo]
remote = https://github.com/free-audio/clap
branch = main
commit = 3189bdfaf849eadeb5a0149bf3e2cb9fd0690518
parent = 1b743700030422251f8e1b50f094c7a50ffff8fd
method = merge
cmdver = 0.4.3

View File

@ -0,0 +1,64 @@
cmake_minimum_required(VERSION 3.17)
enable_testing()
project(CLAP C CXX)
add_custom_target(clap-tests)
# If you use clap as a submodule of your plugin you need some interface projects
# to allow you to link. clap-core gives you the include directory and clap-plugin-core
# gives you the core + plugin-glue.
add_library(clap-core INTERFACE)
target_include_directories(clap-core INTERFACE include)
install(DIRECTORY include DESTINATION "." OPTIONAL EXCLUDE_FROM_ALL)
add_executable(clap-compile-c EXCLUDE_FROM_ALL src/main.c)
macro(clap_compile_cpp SUFFIX EXT STDC STDCPP)
add_executable(clap-compile-${SUFFIX} EXCLUDE_FROM_ALL src/main.${EXT})
target_link_libraries(clap-compile-${SUFFIX} clap-core)
set_target_properties(clap-compile-${SUFFIX} PROPERTIES
C_STANDARD ${STDC}
CXX_STANDARD ${STDCPP})
add_test(NAME test-clap-compile-${SUFFIX} COMMAND clap-compile-${SUFFIX})
add_dependencies(clap-tests clap-compile-${SUFFIX})
if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
target_compile_options(clap-compile-${SUFFIX} PRIVATE -Wall -Wextra -pedantic)
endif()
if (${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
target_compile_options(clap-compile-${SUFFIX} PRIVATE -Werror=pragma-pack)
endif()
endmacro()
clap_compile_cpp(c11 c 11 11)
clap_compile_cpp(cpp11 cc 11 11)
clap_compile_cpp(cpp14 cc 11 14)
clap_compile_cpp(c17 c 17 17)
clap_compile_cpp(cpp17 cc 17 17)
clap_compile_cpp(cpp20 cc 17 20)
add_library(clap-plugin-template MODULE EXCLUDE_FROM_ALL src/plugin-template.c)
target_link_libraries(clap-plugin-template PRIVATE clap-core)
set_target_properties(clap-plugin-template PROPERTIES C_STANDARD 11)
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)
set_target_properties(clap-plugin-template PROPERTIES SUFFIX ".clap" PREFIX "")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_link_options(clap-plugin-template PRIVATE -exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/src/macos-symbols.txt)
set_target_properties(clap-plugin-template PROPERTIES
BUNDLE True
BUNDLE_EXTENSION clap
MACOSX_BUNDLE_GUI_IDENTIFIER com.my_company.my_plug
MACOSX_BUNDLE_BUNDLE_NAME my_plug
MACOSX_BUNDLE_BUNDLE_VERSION "1"
MACOSX_BUNDLE_SHORT_VERSION_STRING "1"
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/src/plugins.plist.in
)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set_target_properties(clap-plugin-template PROPERTIES SUFFIX ".clap" PREFIX "")
endif()

View File

@ -0,0 +1,40 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 17,
"patch": 0
},
"configurePresets": [
{
"name": "ninja",
"displayName": "Ninja",
"description": "Configure and generate Ninja project files for all configurations",
"binaryDir": "${sourceDir}/builds/${presetName}",
"generator": "Ninja Multi-Config",
"cacheVariables": {
"CMAKE_EXPORT_COMPILE_COMMANDS": {
"type": "boolean",
"value": true
}
}
}
],
"buildPresets": [
{
"name": "ninja-release",
"configurePreset": "ninja",
"displayName": "Build ninja-release",
"description": "Build ninja Release configuration",
"configuration": "RelWithDebInfo",
"targets": ["clap-tests"]
}
],
"testPresets": [
{
"name": "ninja-release",
"configurePreset": "ninja",
"configuration": "RelWithDebInfo"
}
]
}

View File

@ -0,0 +1,43 @@
## Changes in 1.0.1
* [gui.h](include/clap/ext/gui.h): fix doc: set_scale must be provided
* [events.h](include/clap/events.h): remove `clap_event_type` which was never used
* [draft/transport-control.h](include/clap/ext/draft/transport-control.h): rename from `CLAP_EXT_CV` to `CLAP_EXT_TRANSPORT_CONTROL`
* [draft/tuning.h](include/clap/ext/draft/tuning.h): rename `clap_client_tuning` to `clap_plugin_tuning`
* [macros.h](include/clap/private/macros.h): fix compatibility with C17
## Changes in 1.0.0
# New stable interfaces
* [audio-ports-config.h](include/clap/ext/audio-ports-config.h)
* [audio-ports.h](include/clap/ext/audio-ports.h)
* [event-registry.h](include/clap/ext/event-registry.h)
* [gui.h](include/clap/ext/gui.h)
* [latency.h](include/clap/ext/latency.h)
* [log.h](include/clap/ext/log.h)
* [note-name.h](include/clap/ext/note-name.h)
* [note-ports.h](include/clap/ext/note-ports.h)
* [params.h](include/clap/ext/params.h)
* [posix-fd-support.h](include/clap/ext/posix-fd-support.h)
* [render.h](include/clap/ext/render.h)
* [state.h](include/clap/ext/state.h)
* [tail.h](include/clap/ext/tail.h)
* [thread-check.h](include/clap/ext/thread-check.h)
* [thread-pool.h](include/clap/ext/thread-pool.h)
* [timer-support.h](include/clap/ext/time-support.h)
# New draft interfaces
* [ambisonic.h](include/clap/ext/draft/ambisonic.h)
* [check-for-update.h](include/clap/ext/draft/check-for-update.h)
* [cv.h](include/clap/ext/draft/cv.h)
* [file-reference.h](include/clap/ext/draft/file-reference.h)
* [midi-mappings.h](include/clap/ext/draft/midi-mappings.h)
* [preset-load.h](include/clap/ext/draft/preset-load.h)
* [quick-controls.h](include/clap/ext/draft/quick-controls.h)
* [surround.h](include/clap/ext/draft/surround.h)
* [track-info.h](include/clap/ext/draft/track-info.h)
* [transport-control.h](include/clap/ext/draft/transport-control.h)
* [tuning.h](include/clap/ext/draft/tuning.h)
* [voice-info.h](include/clap/ext/draft/voice-info.h)

View File

@ -0,0 +1,25 @@
CLAP is the result of countless conversations, brainstorms, reviews, tests,
and iterations. A legion of developers with different backgrounds and points
of view worked together and converged on a, well, clever solution.
All of the contributors cannot be listed. But here are a few, along with a
thank you to all involved:
- Alexandre Bique (Bitwig and u-he/linux)
- Claes Johanson (Bitwig)
- David Schornsheim (Schroedingers-Cat, u-he)
- Frank Hoffmann (u-he)
- Giel Bremmers (MultitrackStudio)
- Jan Storm (u-he)
- John Schwartz (Cockos)
- Nicholas Allen (Bitwig)
- Paul Walker (BaconPaul, Surge)
- Placidus Schelbert (Bitwig)
- Robbert van der Helm (yabridge)
- Robin Gareus (Ardour)
- Thomas Binek (tas, u-he)
- Timo Kaluza
- Tor-Helge Skei (MIP2)
- Urs Heckmann (u-he)
- Vadim Zavalishin
- William Light (LHI Audio)

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Alexandre BIQUE
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,138 @@
<p align=center>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/free-audio/clap/main/artwork/clap-full-logo-white.png">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/free-audio/clap/main/artwork/clap-full-logo-black.png">
<img alt="CLAP" title="Clever Audio Plugin" src="https://raw.githubusercontent.com/free-audio/clap/main/artwork/clap-full-logo-black.png" width=200>
</picture>
</p>
- [Learn about CLAP](#learn-about-clap)
- [Entry point](#entry-point)
- [Extensions](#extensions)
- [Fundamental extensions](#fundamental-extensions)
- [Support extensions](#support-extensions)
- [Extra extensions](#extra-extensions)
- [Resources](#resources)
- [Plugins](#plugins)
- [Hosts](#hosts)
- [Examples](#examples)
- [Community related projects](#community-related-projects)
- [Programming Language Bindings](#programming-language-bindings)
- [Artwork](#artwork)
# Learn about CLAP
CLAP stands for **CL**ever **A**udio **P**lugin.
It is an audio plugin ABI which defines a standard for *Digital Audio Workstations* and audio plugins (synthesizers, audio effects, ...) to work together.
To work with CLAP, include [clap/clap.h](include/clap/clap.h).
The two most important objects are `clap_host` and `clap_plugin`.
[src/plugin-template.c](src/plugin-template.c) is a very minimal example which demonstrates how to wire a CLAP plugin.
## Entry point
The entry point is declared in [entry.h](include/clap/entry.h).
## Extensions
Most features comes from extensions, which are in fact C interfaces.
```C
// host extension
const clap_host_log *log = host->extension(host, CLAP_EXT_LOG);
if (log)
log->log(host, CLAP_LOG_INFO, "Hello World! ;^)");
// plugin extension
const clap_plugin_params *params = plugin->extension(plugin, CLAP_EXT_PARAMS);
if (params)
{
uint32_t paramsCount = params->count(plugin);
// ...
}
```
The extensions are defined in [ext](include/clap/ext) folder.
Some extensions are still in the progress of being designed and they are in
the [draft](include/clap/ext/draft) folder.
An extension comes with:
- an header `#include <clap/ext/xxx.h>`
- an extension identifier: `#define CLAP_EXT_XXX "clap/XXX"`
- host interfaces are named like: `struct clap_host_xxx`
- plugin interfaces are named like: `struct clap_plugin_xxx`
- each methods must have a clear thread specification
You can create your own extensions and share them, make sure that the extension identifier
- includes versioning in case the ABI breaks
- a unique identifier
**All strings are valid UTF-8**.
## Fundamental extensions
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
- [params](include/clap/ext/params.h), parameters management
- [latency](include/clap/ext/latency.h), report the plugin latency
- [render](include/clap/ext/render.h), renders realtime or offline
- [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
## Support extensions
- [thread-pool](include/clap/ext/thread-pool.h), use the host thread pool
- [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
- [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
# Resources
## Plugins
- [u-he](https://u-he.com/fwd/clap/), synthesizers and effects
- [Surge](https://surge-synthesizer.github.io/), open source synthesizer and effect
- CLAP is enabled in [nightly builds](https://github.com/surge-synthesizer/releases-xt/releases/tag/Nightly)
## Hosts
- [Bitwig](https://bitwig.com), you need at least _Bitwig Studio 4.3 Beta 5_
## Examples
- [clap-host](https://github.com/free-audio/clap-host), very simple host
- [clap-plugins](https://github.com/free-audio/clap-plugins), very simple plugins
- [schwaaa's plugin](https://github.com/schwaaa/clap-plugin), basic example for prototyping CLAP audio plugins using Dear ImGui as the user interface
## Community related projects
- [clap-juce-extension](https://github.com/free-audio/clap-juce-extension), juce add-on
- [MIP2](https://github.com/skei/MIP2), host and plugins
- [Avendish](https://github.com/celtera/avendish), a reflection-based API for media plug-ins in C++ which supports Clap
- [nih-plug](https://github.com/robbert-vdh/nih-plug), an API-agnostic, Rust-based plugin framework aiming to reduce boilerplate without getting in your way
## Programming Language Bindings
- [clap-sys](https://github.com/glowcoil/clap-sys), rust binding
- [CLAP-for-Delphi](https://github.com/Bremmers/CLAP-for-Delphi), Delphi binding
## Artwork
- [CLAP Logo Pack.zip](https://github.com/free-audio/clap/files/8805281/CLAP.Logo.Pack.zip)

Binary file not shown.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.2" baseProfile="tiny" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 255.1 269.3" overflow="visible" xml:space="preserve">
<path d="M91.2,158.4c9.1,0,16.5-7.4,16.5-16.5v-28.3c0-22.1,18-40.1,40.1-40.1c1.2,0,2.4,0.1,3.5,0.2l-23.7-41l-40.1,69.4
c1.2-0.1,2.3-0.2,3.5-0.2h9.8c-1,3.8-1.6,7.7-1.6,11.8v11.8h-8.3c-9.1,0-16.5,7.4-16.5,16.5C74.6,151,82,158.4,91.2,158.4z"/>
<path d="M184.2,130.5c-6.4,13.7-20.3,23.2-36.4,23.2H138c1-3.8,1.6-7.7,1.6-11.8v-11.8h8.3c9.1,0,16.5-7.4,16.5-16.5
c0-9.1-7.4-16.5-16.5-16.5c-9.1,0-16.5,7.4-16.5,16.5l0,28.3c0,22.1-18,40.1-40.1,40.1c-16.1,0-30-9.5-36.4-23.2l-19.9,34.5h185.7
L184.2,130.5z"/>
<path d="M159.3,209h-6.5c-3.6,0-6.5,2.9-6.5,6.5V235h6.5v-6.5h6.5v6.5h6.5v-19.5C165.8,211.9,162.9,209,159.3,209z M159.3,222h-6.5
c0,0-0.1-1.4-0.1-3.2c0-1.8,0.1-3.2,0.1-3.2s1-0.1,3.2-0.1s3.2,0.1,3.2,0.1s0.1,1.1,0.1,3.2S159.3,222,159.3,222z"/>
<path d="M216,208.9h-13v26h6.5v-6.5h6.5c3.6,0,6.5-2.9,6.5-6.5v-6.5C222.5,211.9,219.6,208.9,216,208.9z M216,221.9
c0,0-1.1,0.1-3.2,0.1c-2.1,0-3.2-0.1-3.2-0.1v-6.5c0,0,1.4-0.1,3.2-0.1c1.8,0,3.2,0.1,3.2,0.1s0.1,1,0.1,3.2S216,221.9,216,221.9z"
/>
<path d="M32.9,215.5v13c0,3.6,2.9,6.5,6.5,6.5l13,0v-6.5h-13v-13h13V209h-13C35.8,209,32.9,211.9,32.9,215.5z"/>
<path d="M97.4,209h-6.5v19.5c0,3.6,2.9,6.5,6.5,6.5l10.4,0v-6.5H97.4V209z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.2" baseProfile="tiny" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 16 16" overflow="visible" xml:space="preserve">
<g>
<path d="M10.5,1.8c-1.8,0-3.4,1-4.3,2.5H6H5.5c-2.7,0-4.9,2.2-4.9,4.9s2.2,4.9,4.9,4.9c1.8,0,3.4-1,4.3-2.5H10h0.5
c2.7,0,4.9-2.2,4.9-4.9C15.4,4,13.2,1.8,10.5,1.8L10.5,1.8z"/>
</g>
<path fill="#F0F2F4" d="M10.5,10.3H10V8.2h0.5c0.8,0,1.4-0.7,1.4-1.4c0-0.8-0.7-1.4-1.4-1.4C9.7,5.3,9,6,9,6.8l0,2.5
c0,1.9-1.6,3.5-3.5,3.5S2,11.2,2,9.2s1.6-3.5,3.5-3.5H6v2.1H5.5c-0.8,0-1.4,0.7-1.4,1.4c0,0.8,0.7,1.4,1.4,1.4S7,10,7,9.2V6.8
c0-1.9,1.6-3.5,3.5-3.5S14,4.8,14,6.8S12.4,10.3,10.5,10.3z"/>
</svg>

After

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.2" baseProfile="tiny" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 32 32" overflow="visible" xml:space="preserve">
<path fill="#1D1D1B" d="M11.3,14.2h1.1c-0.1,0.5-0.2,1-0.2,1.5v1.5h-0.9c-1.2,0-2.1,1-2.1,2.1c0,1.2,1,2.1,2.1,2.1s2.1-1,2.1-2.1
v-3.7c0-2.9,2.3-5.2,5.2-5.2c0.2,0,0.3,0,0.5,0L16,5.2l-5.2,9C11,14.2,11.1,14.2,11.3,14.2z"/>
<path fill="#1D1D1B" d="M23.3,17.9c-0.8,1.8-2.6,3-4.7,3h-1.1c0.1-0.5,0.2-1,0.2-1.5v-1.5h0.9c1.2,0,2.1-1,2.1-2.1
c0-1.2-1-2.1-2.1-2.1c-1.2,0-2.1,1-2.1,2.1l0,3.7c0,2.9-2.3,5.2-5.2,5.2c-2.1,0-3.9-1.2-4.7-3L4,26h24L23.3,17.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 794 B

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.2" baseProfile="tiny" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 255.1 255.1" overflow="visible" xml:space="preserve">
<path fill="#1D1D1B" d="M91.1,172.5c9.1,0,16.5-7.4,16.5-16.5v-28.3c0-22.1,18-40.1,40.1-40.1c1.2,0,2.4,0.1,3.5,0.2l-23.7-41
l-40,69.3c1.2-0.1,2.3-0.2,3.5-0.2h9.8c-1,3.8-1.6,7.7-1.6,11.8v11.8h-8.2c-9.1,0-16.5,7.4-16.5,16.5
C74.6,165.1,82,172.5,91.1,172.5z"/>
<path fill="#1D1D1B" d="M184.1,144.6c-6.4,13.7-20.3,23.2-36.4,23.2h-9.8c1-3.8,1.6-7.7,1.6-11.8v-11.8h8.2
c9.1,0,16.5-7.4,16.5-16.5c0-9.1-7.4-16.5-16.5-16.5c-9.1,0-16.5,7.4-16.5,16.5l0,28.3c0,22.1-18,40.1-40.1,40.1
c-16.1,0-30-9.5-36.4-23.2l-19.9,34.5h185.6L184.1,144.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -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

View File

@ -0,0 +1,62 @@
/*
* CLAP - CLever Audio Plugin
* ~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Copyright (c) 2014...2022 Alexandre BIQUE <bique.alexandre@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "entry.h"
#include "plugin-factory.h"
#include "plugin-invalidation.h"
#include "plugin-features.h"
#include "plugin.h"
#include "host.h"
#include "ext/audio-ports.h"
#include "ext/audio-ports-config.h"
#include "ext/gui.h"
#include "ext/log.h"
#include "ext/params.h"
#include "ext/render.h"
#include "ext/state.h"
#include "ext/latency.h"
#include "ext/thread-check.h"
#include "ext/timer-support.h"
#include "ext/posix-fd-support.h"
#include "ext/note-name.h"
#include "ext/note-ports.h"
#include "ext/thread-pool.h"
#include "ext/event-registry.h"
#include "ext/tail.h"
#include "ext/draft/preset-load.h"
#include "ext/draft/quick-controls.h"
#include "ext/draft/track-info.h"
#include "ext/draft/tuning.h"
#include "ext/draft/file-reference.h"
#include "ext/draft/midi-mappings.h"
#include "ext/draft/surround.h"
#include "ext/draft/cv.h"
#include "ext/draft/ambisonic.h"
#include "ext/draft/voice-info.h"

View File

@ -0,0 +1,18 @@
#pragma once
#include "private/std.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_color {
uint8_t alpha;
uint8_t red;
uint8_t green;
uint8_t blue;
} clap_color_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,60 @@
#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
//
// Additionally, extra path may be specified in CLAP_PATH environment variable.
// CLAP_PATH is formated in the same way as the OS' binary search path (PATH on UNIX, Path on Windows).
//
// Every methods 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 very quick scan of the plugin
// descriptors.
//
// It is forbidden to display graphical user interface in this call.
// It is forbidden to perform user inter-action in this call.
//
// If the initialization depends upon expensive computation, maybe try to do them ahead of time
// and cache the result.
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

View File

@ -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 phisical 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 represents a key pressed and key released event.
// 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 two use case:
// - 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 to process 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)
//
// Those 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 to adjust a knob.
// This is not mandatory to wrap parameter changes with gesture events, but this improves a lot
// the user experience 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

View File

@ -0,0 +1,73 @@
#pragma once
#include "../string-sizes.h"
#include "../plugin.h"
/// @page Audio Ports Config
///
/// This extension provides a way for the plugin to describe possible ports configurations, for
/// example mono, stereo, surround, ... and a way for the host to select a configuration.
///
/// After the plugin initialization, the host may scan the list of configurations and eventually
/// select one that fits the plugin context. The host can only select a configuration if the plugin
/// is deactivated.
///
/// A configuration is a very simple description of the audio ports:
/// - it describes the main input and output ports
/// - it has a name that can be displayed to the user
///
/// The idea behind the configurations, is to let the user choose one via a menu.
///
/// Plugin with very complex configuration possibilities should let the user configure the ports
/// from the plugin GUI, and call @ref clap_host_audio_ports.rescan(CLAP_AUDIO_PORTS_RESCAN_ALL).
static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_CONFIG[] = "clap.audio-ports-config";
#ifdef __cplusplus
extern "C" {
#endif
// Minimalistic description of ports configuration
typedef struct clap_audio_ports_config {
clap_id id;
char name[CLAP_NAME_SIZE];
uint32_t input_port_count;
uint32_t output_port_count;
// main input info
bool has_main_input;
uint32_t main_input_channel_count;
const char *main_input_port_type;
// main output info
bool has_main_output;
uint32_t main_output_channel_count;
const char *main_output_port_type;
} clap_audio_ports_config_t;
// The audio ports config scan has to be done while the plugin is deactivated.
typedef struct clap_plugin_audio_ports_config {
// gets the number of available configurations
// [main-thread]
uint32_t (*count)(const clap_plugin_t *plugin);
// gets information about a configuration
// [main-thread]
bool (*get)(const clap_plugin_t *plugin, uint32_t index, clap_audio_ports_config_t *config);
// selects the configuration designated by id
// returns true if the configuration could be applied
// [main-thread,plugin-deactivated]
bool (*select)(const clap_plugin_t *plugin, clap_id config_id);
} clap_plugin_audio_ports_config_t;
typedef struct clap_host_audio_ports_config {
// Rescan the full list of configs.
// [main-thread]
void (*rescan)(const clap_host_t *host);
} clap_host_audio_ports_config_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,114 @@
#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,
// The 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 flags.
// In other words if all ports have this flags 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 {
clap_id id; // stable identifier
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

View File

@ -0,0 +1,55 @@
#pragma once
#include "../../plugin.h"
// This extension can be used to specify the channel mapping used by the plugin.
static CLAP_CONSTEXPR const char CLAP_EXT_AMBISONIC[] = "clap.ambisonic.draft/0";
static CLAP_CONSTEXPR const char CLAP_PORT_AMBISONIC[] = "ambisonic";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// FuMa channel ordering
CLAP_AMBISONIC_FUMA = 0,
// ACN channel ordering
CLAP_AMBISONIC_ACN = 1,
};
enum {
CLAP_AMBISONIC_NORMALIZATION_MAXN = 0,
CLAP_AMBISONIC_NORMALIZATION_SN3D = 1,
CLAP_AMBISONIC_NORMALIZATION_N3D = 2,
CLAP_AMBISONIC_NORMALIZATION_SN2D = 3,
CLAP_AMBISONIC_NORMALIZATION_N2D = 4,
};
typedef struct clap_ambisonic_info {
uint32_t ordering;
uint32_t normalization;
} clap_ambisonic_info_t;
typedef struct clap_plugin_ambisonic {
// Returns true on success
// [main-thread]
bool (*get_info)(const clap_plugin_t *plugin,
bool is_input,
uint32_t port_index,
clap_ambisonic_info_t *info);
} clap_plugin_ambisonic_t;
typedef struct clap_host_ambisonic {
// Informs the host that the info have changed.
// The info can only change when the plugin is de-activated.
// [main-thread]
void (*changed)(const clap_host_t *host);
} clap_host_ambisonic_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,31 @@
#pragma once
#include "../../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_CHECK_FOR_UPDATE[] = "clap.check_for_update.draft/0";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_check_for_update_info {
const char *version; // latest version
const char *release_date; // YYYY-MM-DD
const char *url; // url to a download page which the user can visit
bool is_preview; // true if this version is a preview release
} clap_check_for_update_info_t;
typedef struct clap_plugin_check_for_update {
// [main-thread]
void (*check)(const clap_plugin_t *plugin, bool include_preview);
} clap_plugin_check_for_update;
typedef struct clap_host_check_for_update {
// [main-thread]
void (*on_new_version)(const clap_host_t *host, const clap_check_for_update_info_t *update_info);
} clap_host_check_for_update_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,44 @@
#pragma once
#include "../../plugin.h"
// This extension can be used to specify the cv channel type used by the plugin.
// Work in progress, suggestions are welcome
static CLAP_CONSTEXPR const char CLAP_EXT_CV[] = "clap.cv.draft/0";
static CLAP_CONSTEXPR const char CLAP_PORT_CV[] = "cv";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// TODO: standardize values?
CLAP_CV_VALUE = 0,
CLAP_CV_GATE = 1,
CLAP_CV_PITCH = 2,
};
// TODO: maybe we want a channel_info instead, where we could have more details about the supported
// ranges?
typedef struct clap_plugin_cv {
// Returns true on success.
// [main-thread]
bool (*get_channel_type)(const clap_plugin_t *plugin,
bool is_input,
uint32_t port_index,
uint32_t channel_index,
uint32_t *channel_type);
} clap_plugin_cv_t;
typedef struct clap_host_cv {
// Informs the host that the channels type have changed.
// The channels type can only change when the plugin is de-activated.
// [main-thread,!active]
void (*changed)(const clap_host_t *host);
} clap_host_cv_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,85 @@
#pragma once
#include "../../plugin.h"
#include "../../string-sizes.h"
static CLAP_CONSTEXPR const char CLAP_EXT_FILE_REFERENCE[] = "clap.file-reference.draft/0";
#ifdef __cplusplus
extern "C" {
#endif
/// @page File Reference
///
/// This extension provides a way for the host to know about files which are used
/// by the plugin, like a wavetable, a sample, ...
///
/// The host can then:
/// - collect and save
/// - search for missing files by using:
/// - filename
/// - hash
/// - file size
/// - be aware that some external file references are marked as dirty and needs to be saved.
///
/// Regarding the hashing algorithm, as of 2022 BLAKE3 seems to be the best choice in regards to
/// performances and robustness while also providing a very small pure C library with permissive
/// licensing. For more info see https://github.com/BLAKE3-team/BLAKE3
///
/// This extension only expose one hashing algorithm on purpose.
// This describes a file currently used by the plugin
typedef struct clap_file_reference {
clap_id resource_id;
bool belongs_to_plugin_collection;
size_t path_capacity; // [in] the number of bytes reserved in path
size_t path_size; // [out] the actual length of the path, can be bigger than path_capacity
char *path; // [in,out] path to the file on the disk, must be null terminated, and maybe
// truncated if the capacity is less than the size
} clap_file_reference_t;
typedef struct clap_plugin_file_reference {
// returns the number of file reference this plugin has
// [main-thread]
uint32_t (*count)(const clap_plugin_t *plugin);
// gets the file reference at index
// returns true on success
// [main-thread]
bool (*get)(const clap_plugin_t *plugin, uint32_t index, clap_file_reference_t *file_reference);
// This method can be called even if the file is missing.
// So the plugin is encouraged to store the digest in its state.
//
// digest is an array of 32 bytes.
//
// [main-thread]
bool (*get_blake3_digest)(const clap_plugin_t *plugin, clap_id resource_id, uint8_t *digest);
// This method can be called even if the file is missing.
// So the plugin is encouraged to store the file's size in its state.
//
// [main-thread]
bool (*get_file_size)(const clap_plugin_t *plugin, clap_id resource_id, uint64_t *size);
// updates the path to a file reference
// [main-thread]
bool (*update_path)(const clap_plugin_t *plugin, clap_id resource_id, const char *path);
// [main-thread]
bool (*save_resources)(const clap_plugin_t *plugin);
} clap_plugin_file_reference_t;
typedef struct clap_host_file_reference {
// informs the host that the file references have changed, the host should schedule a full rescan
// [main-thread]
void (*changed)(const clap_host_t *host);
// [main-thread]
void (*set_dirty)(const clap_host_t *host, clap_id resource_id);
} clap_host_file_reference;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,40 @@
#pragma once
#include "../../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_MIDI_MAPPINGS[] = "clap.midi-mappings.draft/0";
#ifdef __cplusplus
extern "C" {
#endif
enum {
CLAP_MIDI_MAPPING_CC7,
CLAP_MIDI_MAPPING_CC14,
CLAP_MIDI_MAPPING_RPN,
CLAP_MIDI_MAPPING_NRPN,
};
typedef int32_t clap_midi_mapping_type;
typedef struct clap_midi_mapping {
int32_t channel;
int32_t number;
clap_id param_id;
} clap_midi_mapping_t;
typedef struct clap_plugin_midi_mappings {
// [main-thread]
uint32_t (*count)(const clap_plugin_t *plugin);
// [main-thread]
bool (*get)(const clap_plugin_t *plugin, uint32_t index, clap_midi_mapping_t *mapping);
} clap_plugin_midi_mappings_t;
typedef struct clap_host_midi_mappings {
// [main-thread]
void (*changed)(const clap_host_t *host);
} clap_host_midi_mappings_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,19 @@
#pragma once
#include "../../plugin.h"
static const char CLAP_EXT_PRESET_LOAD[] = "clap.preset-load.draft/0";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_preset_load {
// Loads a preset in the plugin native preset file format from a path.
// [main-thread]
bool (*from_file)(const clap_plugin_t *plugin, const char *path);
} clap_plugin_preset_load_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,45 @@
#pragma once
#include "../../plugin.h"
#include "../../string-sizes.h"
// This extensions provides a set a pages, where each page contains up to 8 controls.
// Those controls are param_id, and they are meant to be mapped onto a physical controller.
// We chose 8 because this what most controllers offers, and it is more or less a standard.
static CLAP_CONSTEXPR const char CLAP_EXT_QUICK_CONTROLS[] = "clap.quick-controls.draft/0";
#ifdef __cplusplus
extern "C" {
#endif
enum { CLAP_QUICK_CONTROLS_COUNT = 8 };
typedef struct clap_quick_controls_page {
clap_id id;
char name[CLAP_NAME_SIZE];
clap_id param_ids[CLAP_QUICK_CONTROLS_COUNT];
} clap_quick_controls_page_t;
typedef struct clap_plugin_quick_controls {
// [main-thread]
uint32_t (*count)(const clap_plugin_t *plugin);
// [main-thread]
bool (*get)(const clap_plugin_t *plugin, uint32_t page_index, clap_quick_controls_page_t *page);
} clap_plugin_quick_controls_t;
typedef struct clap_host_quick_controls {
// Informs the host that the quick controls have changed.
// [main-thread]
void (*changed)(const clap_host_t *host);
// Suggest a page to the host because it correspond to what the user is currently editing in the
// plugin's GUI.
// [main-thread]
void (*suggest_page)(const clap_host_t *host, clap_id page_id);
} clap_host_quick_controls_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,87 @@
#pragma once
#include "../../plugin.h"
// This extension can be used to specify the channel mapping used by the plugin.
//
// To have a consistent surround features across all the plugin instances,
// here is the proposed workflow:
// 1. the plugin queries the host preferred channel mapping and
// adjusts its configuration to match it.
// 2. the host checks how the plugin is effectively configured and honors it.
//
// If the host decides to change the project's surround setup:
// 1. deactivate the plugin
// 2. host calls clap_plugin_surround->changed()
// 3. plugin calls clap_host_surround->get_preferred_channel_map()
// 4. plugin eventualy calls clap_host_surround->changed()
// 5. host calls clap_plugin_surround->get_channel_map() if changed
// 6. host activates the plugin and can start processing audio
//
// If the plugin wants to change its surround setup:
// 1. call host->request_restart() if the plugin is active
// 2. once deactivated plugin calls clap_host_surround->changed()
// 3. host calls clap_plugin_surround->get_channel_map()
// 4. host activates the plugin and can start processing audio
static CLAP_CONSTEXPR const char CLAP_EXT_SURROUND[] = "clap.surround.draft/1";
static CLAP_CONSTEXPR const char CLAP_PORT_SURROUND[] = "surround";
#ifdef __cplusplus
extern "C" {
#endif
enum {
CLAP_SURROUND_FL = 0, // Front Left
CLAP_SURROUND_FR = 1, // Front Right
CLAP_SURROUND_FC = 2, // Front Center
CLAP_SURROUND_LFE = 3, // Low Frequency
CLAP_SURROUND_BL = 4, // Back Left
CLAP_SURROUND_BR = 5, // Back Right
CLAP_SURROUND_FLC = 6, // Front Left of Center
CLAP_SURROUND_FRC = 7, // Front Right of Center
CLAP_SURROUND_BC = 8, // Back Center
CLAP_SURROUND_SL = 9, // Side Left
CLAP_SURROUND_SR = 10, // Side Right
CLAP_SURROUND_TC = 11, // Top Center
CLAP_SURROUND_TFL = 12, // Front Left Height
CLAP_SURROUND_TFC = 13, // Front Center Height
CLAP_SURROUND_TFR = 14, // Front Right Height
CLAP_SURROUND_TBL = 15, // Rear Left Height
CLAP_SURROUND_TBC = 16, // Rear Center Height
CLAP_SURROUND_TBR = 17, // Rear Right Height
};
typedef struct clap_plugin_surround {
// Stores into the channel_map array, the surround identifer of each channels.
// Returns the number of elements stored in channel_map
// [main-thread]
uint32_t (*get_channel_map)(const clap_plugin_t *plugin,
bool is_input,
uint32_t port_index,
uint8_t *channel_map,
uint32_t channel_map_capacity);
// Informs the plugin that the host preferred channel map has changed.
// [main-thread]
void (*changed)(const clap_plugin_t *plugin);
} clap_plugin_surround_t;
typedef struct clap_host_surround {
// Informs the host that the channel map have changed.
// The channel map can only change when the plugin is de-activated.
// [main-thread]
void (*changed)(const clap_host_t *host);
// Ask the host what is the prefered/project surround channel map.
// [main-thread]
void (*get_preferred_channel_map)(const clap_host_t *host,
uint8_t *channel_map,
uint32_t channel_map_capacity,
uint32_t *channel_count);
} clap_host_surround_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,37 @@
#pragma once
#include "../../plugin.h"
#include "../../color.h"
#include "../../string-sizes.h"
static CLAP_CONSTEXPR const char CLAP_EXT_TRACK_INFO[] = "clap.track-info.draft/0";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_track_info {
clap_id id;
int32_t index;
char name[CLAP_NAME_SIZE];
char path[CLAP_PATH_SIZE]; // Like "/group1/group2/drum-machine/drum-pad-13"
int32_t channel_count;
const char *audio_port_type;
clap_color_t color;
bool is_return_track;
} clap_track_info_t;
typedef struct clap_plugin_track_info {
// [main-thread]
void (*changed)(const clap_plugin_t *plugin);
} clap_plugin_track_info_t;
typedef struct clap_host_track_info {
// Get info about the track the plugin belongs to.
// [main-thread]
bool (*get)(const clap_host_t *host, clap_track_info_t *info);
} clap_host_track_info_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,64 @@
#pragma once
#include "../../plugin.h"
// This extension let the plugin submit transport requests to the host.
// The host has no obligation to execute those request, so the interface maybe
// partially working.
static CLAP_CONSTEXPR const char CLAP_EXT_TRANSPORT_CONTROL[] = "clap.transport-control.draft/0";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_host_transport_control {
// Jumps back to the start point and starts the transport
// [main-thread]
void (*request_start)(const clap_host_t *host);
// Stops the transport, and jumps to the start point
// [main-thread]
void (*request_stop)(const clap_host_t *host);
// If not playing, starts the transport from its current position
// [main-thread]
void (*request_continue)(const clap_host_t *host);
// If playing, stops the transport at the current position
// [main-thread]
void (*request_pause)(const clap_host_t *host);
// Equivalent to what "space bar" does with most DAW
// [main-thread]
void (*request_toggle_play)(const clap_host_t *host);
// Jumps the transport to the given position.
// Does not start the transport.
// [main-thread]
void (*request_jump)(const clap_host_t *host, clap_beattime position);
// Sets the loop region
// [main-thread]
void (*request_loop_region)(const clap_host_t *host, clap_beattime start, clap_beattime duration);
// Toggles looping
// [main-thread]
void (*request_toggle_loop)(const clap_host_t *host);
// Enables/Disables looping
// [main-thread]
void (*request_enable_loop)(const clap_host_t *host, bool is_enabled);
// Enables/Disables recording
// [main-thread]
void (*request_record)(const clap_host_t *host, bool is_recording);
// Toggles recording
// [main-thread]
void (*request_toggle_record)(const clap_host_t *host);
} clap_host_transport_control_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,70 @@
#pragma once
#include "../../plugin.h"
#include "../../events.h"
#include "../../string-sizes.h"
static CLAP_CONSTEXPR const char CLAP_EXT_TUNING[] = "clap.tuning.draft/2";
#ifdef __cplusplus
extern "C" {
#endif
// Use clap_host_event_registry->query(host, CLAP_EXT_TUNING, &space_id) to know the event space.
//
// This event defines the tuning to be used on the given port/channel.
typedef struct clap_event_tuning {
clap_event_header_t header;
int16_t port_index; // -1 global
int16_t channel; // 0..15, -1 global
clap_id tunning_id;
} clap_event_tuning_t;
typedef struct clap_tuning_info {
clap_id tuning_id;
char name[CLAP_NAME_SIZE];
bool is_dynamic; // true if the values may vary with time
} clap_tuning_info_t;
typedef struct clap_plugin_tuning {
// Called when a tuning is added or removed from the pool.
// [main-thread]
void (*changed)(const clap_plugin_t *plugin);
} clap_plugin_tuning_t;
// This extension provides a dynamic tuning table to the plugin.
typedef struct clap_host_tuning {
// Gets the relative tuning in semitone against equal temperament with A4=440Hz.
// The plugin may query the tuning at a rate that makes sense for *low* frequency modulations.
//
// If the tuning_id is not found or equals to CLAP_INVALID_ID,
// then the function shall gracefuly return a sensible value.
//
// sample_offset is the sample offset from the begining of the current process block.
//
// should_play(...) should be checked before calling this function.
//
// [audio-thread & in-process]
double (*get_relative)(const clap_host_t *host,
clap_id tuning_id,
int32_t channel,
int32_t key,
uint32_t sample_offset);
// Returns true if the note should be played.
// [audio-thread & in-process]
bool (*should_play)(const clap_host_t *host, clap_id tuning_id, int32_t channel, int32_t key);
// Returns the number of tunings in the pool.
// [main-thread]
uint32_t (*get_tuning_count)(const clap_host_t *host);
// Gets info about a tuning
// [main-thread]
bool (*get_info)(const clap_host_t *host, uint32_t tuning_index, clap_tuning_info_t *info);
} clap_host_tuning_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,56 @@
#pragma once
#include "../../plugin.h"
// This extensions indicates the number of voices the synthesizer.
// It is useful for the host when performing polyphonic modulations,
// because the host needs its own voice management and should try to follow
// what the plugin is doing:
// - make the host's voice pool coherent with what the plugin has
// - turn the host's voice management to mono when the plugin is mono
static const char CLAP_EXT_VOICE_INFO[] = "clap.voice-info.draft/0";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// Allows the host to send overlapping NOTE_ON events.
// The plugin will then rely upon the note_id to distinguish between them.
CLAP_VOICE_INFO_SUPPORTS_OVERLAPPING_NOTES = 1 << 0,
};
typedef struct clap_voice_info {
// voice_count is the current number of voices that the patch can use
// voice_capacity is the number of voices allocated voices
// voice_count should not be confused with the number of active voices.
//
// 1 <= voice_count <= voice_capacity
//
// For example, a synth can have a capacity of 8 voices, but be configured
// to only use 4 voices: {count: 4, capacity: 8}.
//
// If the voice_count is 1, then the synth is working in mono and the host
// can decide to only use global modulation mapping.
uint32_t voice_count;
uint32_t voice_capacity;
uint64_t flags;
} clap_voice_info_t;
typedef struct clap_plugin_voice_info {
// gets the voice info, returns true on success
// [main-thread && active]
bool (*get)(const clap_plugin_t *plugin, clap_voice_info_t *info);
} clap_plugin_voice_info_t;
typedef struct clap_host_voice_info {
// informs the host that the voice info have changed
// [main-thread]
void (*changed)(const clap_host_t *host);
} clap_host_voice_info_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,22 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_EVENT_REGISTRY[] = "clap.event-registry";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_host_event_registry {
// Queries an event space id.
// The space id 0 is reserved for CLAP's core events. See CLAP_CORE_EVENT_SPACE.
//
// Return false and sets *space to UINT16_MAX if the space name is unknown to the host.
// [main-thread]
bool (*query)(const clap_host_t *host, const char *space_name, uint16_t *space_id);
} clap_host_event_registry_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,218 @@
#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
};
} clap_window_t;
// Information to improve window resizement 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 preseve_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 to define 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 do not free the resources, it just hides
// the window content. Yet it maybe 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
* acknowledge 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

View File

@ -0,0 +1,28 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_LATENCY[] = "clap.latency";
#ifdef __cplusplus
extern "C" {
#endif
// The audio ports scan has to be done while the plugin is deactivated.
typedef struct clap_plugin_latency {
// Returns the plugin latency.
// [main-thread]
uint32_t (*get)(const clap_plugin_t *plugin);
} clap_plugin_latency_t;
typedef struct clap_host_latency {
// Tell the host that the latency changed.
// The latency is only allowed to change if the plugin is deactivated.
// If the plugin is activated, call host->request_restart()
// [main-thread]
void (*changed)(const clap_host_t *host);
} clap_host_latency_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,33 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_LOG[] = "clap.log";
#ifdef __cplusplus
extern "C" {
#endif
enum {
CLAP_LOG_DEBUG = 0,
CLAP_LOG_INFO = 1,
CLAP_LOG_WARNING = 2,
CLAP_LOG_ERROR = 3,
CLAP_LOG_FATAL = 4,
// Those severities should be used to report misbehaviour.
// The plugin one can be used by a layer between the plugin and the host.
CLAP_LOG_HOST_MISBEHAVING = 5,
CLAP_LOG_PLUGIN_MISBEHAVING = 6,
};
typedef int32_t clap_log_severity;
typedef struct clap_host_log {
// Log a message through the host.
// [thread-safe]
void (*log)(const clap_host_t *host, clap_log_severity severity, const char *msg);
} clap_host_log_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,37 @@
#pragma once
#include "../plugin.h"
#include "../string-sizes.h"
#ifdef __cplusplus
extern "C" {
#endif
static CLAP_CONSTEXPR const char CLAP_EXT_NOTE_NAME[] = "clap.note-name";
typedef struct clap_note_name {
char name[CLAP_NAME_SIZE];
int16_t port; // -1 for every port
int16_t key; // -1 for every key
int16_t channel; // -1 for every channel
} clap_note_name_t;
typedef struct clap_plugin_note_name {
// Return the number of note names
// [main-thread]
uint32_t (*count)(const clap_plugin_t *plugin);
// Returns true on success and stores the result into note_name
// [main-thread]
bool (*get)(const clap_plugin_t *plugin, uint32_t index, clap_note_name_t *note_name);
} clap_plugin_note_name;
typedef struct clap_host_note_name {
// Informs the host that the note names has changed.
// [main-thread]
void (*changed)(const clap_host_t *host);
} clap_host_note_name_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,76 @@
#pragma once
#include "../plugin.h"
#include "../string-sizes.h"
/// @page Note Ports
///
/// This extension provides a way for the plugin to describe its current note ports.
/// If the plugin does not implement this extension, it won't have note input or output.
/// The plugin is only allowed to change its note ports configuration while it is deactivated.
static CLAP_CONSTEXPR const char CLAP_EXT_NOTE_PORTS[] = "clap.note-ports";
#ifdef __cplusplus
extern "C" {
#endif
enum clap_note_dialect {
// Uses clap_event_note and clap_event_note_expression.
CLAP_NOTE_DIALECT_CLAP = 1 << 0,
// Uses clap_event_midi, no polyphonic expression
CLAP_NOTE_DIALECT_MIDI = 1 << 1,
// Uses clap_event_midi, with polyphonic expression (MPE)
CLAP_NOTE_DIALECT_MIDI_MPE = 1 << 2,
// Uses clap_event_midi2
CLAP_NOTE_DIALECT_MIDI2 = 1 << 3,
};
typedef struct clap_note_port_info {
clap_id id; // stable identifier
uint32_t supported_dialects; // bitfield, see clap_note_dialect
uint32_t preferred_dialect; // one value of clap_note_dialect
char name[CLAP_NAME_SIZE]; // displayable name, i18n?
} clap_note_port_info_t;
// The note ports scan has to be done while the plugin is deactivated.
typedef struct clap_plugin_note_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 a note port.
// [main-thread]
bool (*get)(const clap_plugin_t *plugin,
uint32_t index,
bool is_input,
clap_note_port_info_t *info);
} clap_plugin_note_ports_t;
enum {
// The ports have changed, the host shall perform a full scan of the ports.
// This flag can only be used if the plugin is not active.
// If the plugin active, call host->request_restart() and then call rescan()
// when the host calls deactivate()
CLAP_NOTE_PORTS_RESCAN_ALL = 1 << 0,
// The ports name did change, the host can scan them right away.
CLAP_NOTE_PORTS_RESCAN_NAMES = 1 << 1,
};
typedef struct clap_host_note_ports {
// Query which dialects the host supports
// [main-thread]
uint32_t (*supported_dialects)(const clap_host_t *host);
// Rescan the full list of note ports according to the flags.
// [main-thread]
void (*rescan)(const clap_host_t *host, uint32_t flags);
} clap_host_note_ports_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,297 @@
#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 controler on top of its parameters.
/// The plugin is responsible to keep in sync its audio processor and its GUI.
///
/// The host can read at any time parameters value on the [main-thread] using
/// @ref clap_plugin_params.value().
///
/// There is two options to communicate parameter value change, and they are not concurrent.
/// - send automation points during clap_plugin.process()
/// - send automation points during clap_plugin_params.flush(), this one is used when the plugin is
/// not processing
///
/// 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 send CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END events.
///
/// @note MIDI CCs are a tricky because you may not know when the parameter adjustment ends.
/// Also if the hosts 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.changed() 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 change
/// (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 to update 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
/// - if the plugin is not processing, call clap_host_params->request_flush() or
/// clap_host->request_process().
/// - send an automation event and don't forget to set begin_adjust, end_adjust and should_record
/// flags
/// - the plugin is responsible to send the parameter value to its audio processor
///
/// IV. Turning a knob via automation
/// - host sends an automation point during clap_plugin->process() or clap_plugin_params->flush().
/// - the plugin is responsible to update 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 param supports per note automations?
CLAP_PARAM_IS_AUTOMATABLE_PER_NOTE_ID = 1 << 6,
// Does this param supports per note automations?
CLAP_PARAM_IS_AUTOMATABLE_PER_KEY = 1 << 7,
// Does this param supports per channel automations?
CLAP_PARAM_IS_AUTOMATABLE_PER_CHANNEL = 1 << 8,
// Does this param supports per port automations?
CLAP_PARAM_IS_AUTOMATABLE_PER_PORT = 1 << 9,
// Does the parameter support the modulation signal?
CLAP_PARAM_IS_MODULATABLE = 1 << 10,
// Does this param supports per note automations?
CLAP_PARAM_IS_MODULATABLE_PER_NOTE_ID = 1 << 11,
// Does this param supports per note automations?
CLAP_PARAM_IS_MODULATABLE_PER_KEY = 1 << 12,
// Does this param supports per channel automations?
CLAP_PARAM_IS_MODULATABLE_PER_CHANNEL = 1 << 13,
// Does this param supports per channel automations?
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().
// This method must not be used if the plugin is processing.
//
// [active && !processing : audio-thread]
// [!active : 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 the host to call clap_plugin_params->fush().
// This is useful if the plugin has parameters value changes to report to the host but the plugin
// is not processing.
//
// eg. the plugin has a USB socket to some hardware controllers and receives a parameter change
// while it is not processing.
//
// This must not be called on the [audio-thread].
//
// [thread-safe]
void (*request_flush)(const clap_host_t *host);
} clap_host_params_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,46 @@
#pragma once
#include "../plugin.h"
// This extension let your plugin hook itself into the host select/poll/epoll/kqueue reactor.
// This is useful to handle asynchronous I/O on the main thread.
static CLAP_CONSTEXPR const char CLAP_EXT_POSIX_FD_SUPPORT[] = "clap.posix-fd-support";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// IO events flags, they can be used to form a mask which describes:
// - which events you are interested in (register_fd/modify_fd)
// - which events happened (on_fd)
CLAP_POSIX_FD_READ = 1 << 0,
CLAP_POSIX_FD_WRITE = 1 << 1,
CLAP_POSIX_FD_ERROR = 1 << 2,
};
typedef uint32_t clap_posix_fd_flags_t;
typedef struct clap_plugin_posix_fd_support {
// This callback is "level-triggered".
// It means that a writable fd will continuously produce "on_fd()" events;
// don't forget using modify_fd() to remove the write notification once you're
// done writting.
//
// [main-thread]
void (*on_fd)(const clap_plugin_t *plugin, int fd, clap_posix_fd_flags_t flags);
} clap_plugin_posix_fd_support_t;
typedef struct clap_host_posix_fd_support {
// [main-thread]
bool (*register_fd)(const clap_host_t *host, int fd, clap_posix_fd_flags_t flags);
// [main-thread]
bool (*modify_fd)(const clap_host_t *host, int fd, clap_posix_fd_flags_t flags);
// [main-thread]
bool (*unregister_fd)(const clap_host_t *host, int fd);
} clap_host_posix_fd_support_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,39 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_RENDER[] = "clap.render";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// Default setting, for "realtime" processing
CLAP_RENDER_REALTIME = 0,
// For processing without realtime pressure
// The plugin may use more expensive algorithms for higher sound quality.
CLAP_RENDER_OFFLINE = 1,
};
typedef int32_t clap_plugin_render_mode;
// The render extension is used to let the plugin know if it has "realtime"
// pressure to process.
//
// If this information does not influence your rendering code, then don't
// implement this extension.
typedef struct clap_plugin_render {
// Returns true if the plugin has an hard requirement to process in real-time.
// This is especially useful for plugin acting as a proxy to an hardware device.
// [main-thread]
bool (*has_hard_realtime_requirement)(const clap_plugin_t *plugin);
// Returns true if the rendering mode could be applied.
// [main-thread]
bool (*set)(const clap_plugin_t *plugin, clap_plugin_render_mode mode);
} clap_plugin_render_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,33 @@
#pragma once
#include "../plugin.h"
#include "../stream.h"
static CLAP_CONSTEXPR const char CLAP_EXT_STATE[] = "clap.state";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_state {
// Saves the plugin state into stream.
// Returns true if the state was correctly saved.
// [main-thread]
bool (*save)(const clap_plugin_t *plugin, const clap_ostream_t *stream);
// Loads the plugin state from stream.
// Returns true if the state was correctly restored.
// [main-thread]
bool (*load)(const clap_plugin_t *plugin, const clap_istream_t *stream);
} clap_plugin_state_t;
typedef struct clap_host_state {
// Tell the host that the plugin state has changed and should be saved again.
// If a parameter value changes, then it is implicit that the state is dirty.
// [main-thread]
void (*mark_dirty)(const clap_host_t *host);
} clap_host_state_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,26 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_TAIL[] = "clap.tail";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_tail {
// Returns tail length in samples.
// Any value greater or equal to INT32_MAX implies infinite tail.
// [main-thread,audio-thread]
uint32_t (*get)(const clap_plugin_t *plugin);
} clap_plugin_tail_t;
typedef struct clap_host_tail {
// Tell the host that the tail has changed.
// [audio-thread]
void (*changed)(const clap_host_t *host);
} clap_host_tail_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,26 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_THREAD_CHECK[] = "clap.thread-check";
#ifdef __cplusplus
extern "C" {
#endif
// This interface is useful to do runtime checks and make
// sure that the functions are called on the correct threads.
// It is highly recommended to implement this extension
typedef struct clap_host_thread_check {
// Returns true if "this" thread is the main thread.
// [thread-safe]
bool (*is_main_thread)(const clap_host_t *host);
// Returns true if "this" thread is one of the audio threads.
// [thread-safe]
bool (*is_audio_thread)(const clap_host_t *host);
} clap_host_thread_check_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,66 @@
#pragma once
#include "../plugin.h"
/// @page
///
/// This extension let the plugin use the host's thread pool.
///
/// The plugin must provide @ref clap_plugin_thread_pool, and the host may provide @ref
/// clap_host_thread_pool. If it doesn't, the plugin should process its data by its own mean. In the
/// worst case, a single threaded for-loop.
///
/// Simple example with N voices to process
///
/// @code
/// void myplug_thread_pool_exec(const clap_plugin *plugin, uint32_t voice_index)
/// {
/// compute_voice(plugin, voice_index);
/// }
///
/// void myplug_process(const clap_plugin *plugin, const clap_process *process)
/// {
/// ...
/// bool didComputeVoices = false;
/// if (host_thread_pool && host_thread_pool.exec)
/// didComputeVoices = host_thread_pool.request_exec(host, plugin, N);
///
/// if (!didComputeVoices)
/// for (uint32_t i = 0; i < N; ++i)
/// myplug_thread_pool_exec(plugin, N);
/// ...
/// }
/// @endcode
///
/// Be aware that using a thread pool may break hard real-time rules due to the thread
/// synchronization involved.
///
/// If the host knows that it is running under hard real-time pressure it may decide to not
/// provide this interface.
static CLAP_CONSTEXPR const char CLAP_EXT_THREAD_POOL[] = "clap.thread-pool";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_thread_pool {
// Called by the thread pool
void (*exec)(const clap_plugin_t *plugin, uint32_t task_index);
} clap_plugin_thread_pool_t;
typedef struct clap_host_thread_pool {
// Schedule num_tasks jobs in the host thread pool.
// It can't be called concurrently or from the thread pool.
// Will block until all the tasks are processed.
// This must be used exclusively for realtime processing within the process call.
// Returns true if the host did execute all the tasks, false if it rejected the request.
// The host should check that the plugin is within the process call, and if not, reject the exec
// request.
// [audio-thread]
bool (*request_exec)(const clap_host_t *host, uint32_t num_tasks);
} clap_host_thread_pool_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,29 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_TIMER_SUPPORT[] = "clap.timer-support";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_timer_support {
// [main-thread]
void (*on_timer)(const clap_plugin_t *plugin, clap_id timer_id);
} clap_plugin_timer_support_t;
typedef struct clap_host_timer_support {
// Registers a periodic timer.
// The host may adjust the period if it is under a certain threshold.
// 30 Hz should be allowed.
// [main-thread]
bool (*register_timer)(const clap_host_t *host, uint32_t period_ms, clap_id *timer_id);
// [main-thread]
bool (*unregister_timer)(const clap_host_t *host, clap_id timer_id);
} clap_host_timer_support_t;
#ifdef __cplusplus
}
#endif

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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 methods 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

View File

@ -0,0 +1,76 @@
#pragma once
#include "private/macros.h"
// This files provides a set of standard plugin features meant to be use
// 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 feature 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"

View File

@ -0,0 +1,45 @@
#pragma once
#include "private/std.h"
#include "private/macros.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_invalidation_source {
// Directory containing the file(s) to scan, must be absolute
const char *directory;
// globing pattern, in the form *.dll
const char *filename_glob;
// should the directory be scanned recursively?
bool recursive_scan;
} clap_plugin_invalidation_source_t;
static const CLAP_CONSTEXPR char CLAP_PLUGIN_INVALIDATION_FACTORY_ID[] =
"clap.plugin-invalidation-factory/draft0";
// Used to figure out when a plugin needs to be scanned again.
// Imagine a situation with a single entry point: my-plugin.clap which then scans itself
// a set of "sub-plugins". New plugin may be available even if my-plugin.clap file doesn't change.
// This interfaces solves this issue and gives a way to the host to monitor additional files.
typedef struct clap_plugin_invalidation_factory {
// Get the number of invalidation source.
uint32_t (*count)(const struct clap_plugin_invalidation_factory *factory);
// Get the invalidation source by its index.
// [thread-safe]
const clap_plugin_invalidation_source_t *(*get)(
const struct clap_plugin_invalidation_factory *factory, uint32_t index);
// In case the host detected a invalidation event, it can call refresh() to let the
// plugin_entry update the set of plugins available.
// If the function returned false, then the plugin needs to be reloaded.
bool (*refresh)(const struct clap_plugin_invalidation_factory *factory);
} clap_plugin_invalidation_factory_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,95 @@
#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 not 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

View File

@ -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

View File

@ -0,0 +1,10 @@
#pragma once
#ifdef __cplusplus
# include <cstdint>
# include <cstddef>
#else
# include <stddef.h>
# include <stdbool.h>
# include <stdint.h>
#endif

View File

@ -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 succeed, keep processing.
CLAP_PROCESS_CONTINUE = 1,
// Processing succeed, 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 succeed, but no more processing is required,
// until 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 frame 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

View File

@ -0,0 +1,26 @@
#pragma once
#include "private/std.h"
#include "private/macros.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_istream {
void *ctx; // reserved pointer for the stream
// returns the number of bytes read; 0 indicates end of file and -1 a read error
int64_t (*read)(const struct clap_istream *stream, void *buffer, uint64_t size);
} clap_istream_t;
typedef struct clap_ostream {
void *ctx; // reserved pointer for the stream
// returns the number of bytes written; -1 on write error
int64_t (*write)(const struct clap_ostream *stream, const void *buffer, uint64_t size);
} clap_ostream_t;
#ifdef __cplusplus
}
#endif

View File

@ -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

View File

@ -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)0)
#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;
}

View File

@ -0,0 +1,6 @@
MY_PLUG_ABI_1.0 {
global:
clap_entry;
local:
*;
};

View File

@ -0,0 +1 @@
_clap_entry

View File

@ -0,0 +1,9 @@
#include <clap/clap.h>
// The purpose of this file is to check that all headers compile
int main(int argc, char **argv) {
(void)argc;
(void)argv;
clap_version_t m = CLAP_VERSION;
return !clap_version_is_compatible(m);
}

View File

@ -0,0 +1,12 @@
#include <clap/clap.h>
// The purpose of this file is to check that all headers compile
static const constexpr clap_version m = CLAP_VERSION;
int main(int, char **) {
clap_param_info param_info;
param_info.module[0] = 'm';
return !clap_version_is_compatible(m);
}

View File

@ -0,0 +1,348 @@
// This file is here to demonstrate how to wire a CLAP plugin
// You can use it as a starting point, however if you are implementing a C++
// plugin, I'd encourage you to use the C++ glue layer instead:
// https://github.com/free-audio/clap-helpers/blob/main/include/clap/helpers/plugin.hh
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <clap/clap.h>
static const clap_plugin_descriptor_t s_my_plug_desc = {
.clap_version = CLAP_VERSION_INIT,
.id = "com.your-company.YourPlugin",
.name = "Plugin Name",
.vendor = "Vendor",
.url = "https://your-domain.com/your-plugin",
.manual_url = "https://your-domain.com/your-plugin/manual",
.support_url = "https://your-domain.com/support",
.version = "1.4.2",
.description = "The plugin description.",
.features = (const char *[]){
CLAP_PLUGIN_FEATURE_INSTRUMENT,
CLAP_PLUGIN_FEATURE_STEREO
},
};
typedef struct {
clap_plugin_t plugin;
const clap_host_t *host;
const clap_host_latency_t *hostLatency;
const clap_host_log_t *hostLog;
const clap_host_thread_check_t *hostThreadCheck;
uint32_t latency;
} my_plug_t;
/////////////////////////////
// clap_plugin_audio_ports //
/////////////////////////////
static uint32_t my_plug_audio_ports_count(const clap_plugin_t *plugin, bool is_input) { return 1; }
static bool my_plug_audio_ports_get(const clap_plugin_t *plugin,
uint32_t index,
bool is_input,
clap_audio_port_info_t *info) {
if (index > 0)
return false;
info->id = 0;
snprintf(info->name, sizeof(info->name), "%s", "My Port Name");
info->channel_count = 2;
info->flags = CLAP_AUDIO_PORT_IS_MAIN;
info->port_type = CLAP_PORT_STEREO;
info->in_place_pair = CLAP_INVALID_ID;
return true;
}
static const clap_plugin_audio_ports_t s_my_plug_audio_ports = {
.count = my_plug_audio_ports_count,
.get = my_plug_audio_ports_get,
};
////////////////////////////
// clap_plugin_note_ports //
////////////////////////////
static uint32_t my_plug_note_ports_count(const clap_plugin_t *plugin, bool is_input) { return 1; }
static bool my_plug_note_ports_get(const clap_plugin_t *plugin,
uint32_t index,
bool is_input,
clap_note_port_info_t *info) {
if (index > 0)
return false;
info->id = 0;
snprintf(info->name, sizeof(info->name), "%s", "My Port Name");
info->supported_dialects =
CLAP_NOTE_DIALECT_CLAP | CLAP_NOTE_DIALECT_MIDI_MPE | CLAP_NOTE_DIALECT_MIDI2;
info->preferred_dialect = CLAP_NOTE_DIALECT_CLAP;
return true;
}
static const clap_plugin_note_ports_t s_my_plug_note_ports = {
.count = my_plug_note_ports_count,
.get = my_plug_note_ports_get,
};
//////////////////
// clap_latency //
//////////////////
uint32_t my_plug_latency_get(const clap_plugin_t *plugin) {
my_plug_t *plug = plugin->plugin_data;
return plug->latency;
}
static const clap_plugin_latency_t s_my_plug_latency = {
.get = my_plug_latency_get,
};
/////////////////
// clap_plugin //
/////////////////
static bool my_plug_init(const struct clap_plugin *plugin) {
my_plug_t *plug = plugin->plugin_data;
// Fetch host's extensions here
plug->hostLog = plug->host->get_extension(plug->host, CLAP_EXT_LOG);
plug->hostThreadCheck = plug->host->get_extension(plug->host, CLAP_EXT_THREAD_CHECK);
plug->hostLatency = plug->host->get_extension(plug->host, CLAP_EXT_LATENCY);
return true;
}
static void my_plug_destroy(const struct clap_plugin *plugin) {}
static bool my_plug_activate(const struct clap_plugin *plugin,
double sample_rate,
uint32_t min_frames_count,
uint32_t max_frames_count) {
return true;
}
static void my_plug_deactivate(const struct clap_plugin *plugin) {}
static bool my_plug_start_processing(const struct clap_plugin *plugin) { return true; }
static void my_plug_stop_processing(const struct clap_plugin *plugin) {}
static void my_plug_reset(const struct clap_plugin *plugin) {}
static void my_plug_process_event(my_plug_t *plug, const clap_event_header_t *hdr) {
if (hdr->space_id == CLAP_CORE_EVENT_SPACE_ID) {
switch (hdr->type) {
case CLAP_EVENT_NOTE_ON: {
const clap_event_note_t *ev = (const clap_event_note_t *)hdr;
// TODO: handle note on
break;
}
case CLAP_EVENT_NOTE_OFF: {
const clap_event_note_t *ev = (const clap_event_note_t *)hdr;
// TODO: handle note on
break;
}
case CLAP_EVENT_NOTE_CHOKE: {
const clap_event_note_t *ev = (const clap_event_note_t *)hdr;
// TODO: handle note choke
break;
}
case CLAP_EVENT_NOTE_EXPRESSION: {
const clap_event_note_expression_t *ev = (const clap_event_note_expression_t *)hdr;
// TODO: handle note expression
break;
}
case CLAP_EVENT_PARAM_VALUE: {
const clap_event_param_value_t *ev = (const clap_event_param_value_t *)hdr;
// TODO: handle parameter change
break;
}
case CLAP_EVENT_PARAM_MOD: {
const clap_event_param_mod_t *ev = (const clap_event_param_mod_t *)hdr;
// TODO: handle parameter modulation
break;
}
case CLAP_EVENT_TRANSPORT: {
const clap_event_transport_t *ev = (const clap_event_transport_t *)hdr;
// TODO: handle transport event
break;
}
case CLAP_EVENT_MIDI: {
const clap_event_midi_t *ev = (const clap_event_midi_t *)hdr;
// TODO: handle MIDI event
break;
}
case CLAP_EVENT_MIDI_SYSEX: {
const clap_event_midi_sysex_t *ev = (const clap_event_midi_sysex_t *)hdr;
// TODO: handle MIDI Sysex event
break;
}
case CLAP_EVENT_MIDI2: {
const clap_event_midi2_t *ev = (const clap_event_midi2_t *)hdr;
// TODO: handle MIDI2 event
break;
}
}
}
}
static clap_process_status my_plug_process(const struct clap_plugin *plugin,
const clap_process_t *process) {
my_plug_t *plug = plugin->plugin_data;
const uint32_t nframes = process->frames_count;
const uint32_t nev = process->in_events->size(process->in_events);
uint32_t ev_index = 0;
uint32_t next_ev_frame = nev > 0 ? 0 : nframes;
for (uint32_t i = 0; i < nframes;) {
/* handle every events that happrens at the frame "i" */
while (ev_index < nev && next_ev_frame == i) {
const clap_event_header_t *hdr = process->in_events->get(process->in_events, ev_index);
if (hdr->time != i) {
next_ev_frame = hdr->time;
break;
}
my_plug_process_event(plug, hdr);
++ev_index;
if (ev_index == nev) {
// we reached the end of the event list
next_ev_frame = nframes;
break;
}
}
/* process every samples until the next event */
for (; i < next_ev_frame; ++i) {
// fetch input samples
const float in_l = process->audio_inputs[0].data32[0][i];
const float in_r = process->audio_inputs[0].data32[1][i];
/* TODO: process samples, here we simply swap left and right channels */
const float out_l = in_r;
const float out_r = in_l;
// store output samples
process->audio_outputs[0].data32[0][i] = out_l;
process->audio_outputs[0].data32[1][i] = out_r;
}
}
return CLAP_PROCESS_CONTINUE;
}
static const void *my_plug_get_extension(const struct clap_plugin *plugin, const char *id) {
if (!strcmp(id, CLAP_EXT_LATENCY))
return &s_my_plug_latency;
if (!strcmp(id, CLAP_EXT_AUDIO_PORTS))
return &s_my_plug_audio_ports;
if (!strcmp(id, CLAP_EXT_NOTE_PORTS))
return &s_my_plug_note_ports;
// TODO: add support to CLAP_EXT_PARAMS
// TODO: add support to CLAP_EXT_STATE
return NULL;
}
static void my_plug_on_main_thread(const struct clap_plugin *plugin) {}
clap_plugin_t *my_plug_create(const clap_host_t *host) {
my_plug_t *p = calloc(1, sizeof(*p));
p->host = host;
p->plugin.desc = &s_my_plug_desc;
p->plugin.plugin_data = p;
p->plugin.init = my_plug_init;
p->plugin.destroy = my_plug_destroy;
p->plugin.activate = my_plug_activate;
p->plugin.deactivate = my_plug_deactivate;
p->plugin.start_processing = my_plug_start_processing;
p->plugin.stop_processing = my_plug_stop_processing;
p->plugin.reset = my_plug_reset;
p->plugin.process = my_plug_process;
p->plugin.get_extension = my_plug_get_extension;
p->plugin.on_main_thread = my_plug_on_main_thread;
// Don't call into the host here
return &p->plugin;
}
/////////////////////////
// clap_plugin_factory //
/////////////////////////
static struct {
const clap_plugin_descriptor_t *desc;
clap_plugin_t *(*create)(const clap_host_t *host);
} s_plugins[] = {
{
.desc = &s_my_plug_desc,
.create = my_plug_create,
},
};
static uint32_t plugin_factory_get_plugin_count(const struct clap_plugin_factory *factory) {
return sizeof(s_plugins) / sizeof(s_plugins[0]);
}
static const clap_plugin_descriptor_t *
plugin_factory_get_plugin_descriptor(const struct clap_plugin_factory *factory, uint32_t index) {
return s_plugins[index].desc;
}
static const clap_plugin_t *plugin_factory_create_plugin(const struct clap_plugin_factory *factory,
const clap_host_t *host,
const char *plugin_id) {
if (!clap_version_is_compatible(host->clap_version)) {
return NULL;
}
const int N = sizeof(s_plugins) / sizeof(s_plugins[0]);
for (int i = 0; i < N; ++i)
if (!strcmp(plugin_id, s_plugins[i].desc->id))
return s_plugins[i].create(host);
return NULL;
}
static const clap_plugin_factory_t s_plugin_factory = {
.get_plugin_count = plugin_factory_get_plugin_count,
.get_plugin_descriptor = plugin_factory_get_plugin_descriptor,
.create_plugin = plugin_factory_create_plugin,
};
////////////////
// clap_entry //
////////////////
static bool entry_init(const char *plugin_path) {
// called only once, and very first
return true;
}
static void entry_deinit(void) {
// called before unloading the DSO
}
static const void *entry_get_factory(const char *factory_id) {
if (!strcmp(factory_id, CLAP_PLUGIN_FACTORY_ID))
return &s_plugin_factory;
return NULL;
}
CLAP_EXPORT const clap_plugin_entry_t clap_entry = {
.clap_version = CLAP_VERSION_INIT,
.init = entry_init,
.deinit = entry_deinit,
.get_factory = entry_get_factory,
};

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
</dict>
</plist>