Do some clean-up and migrate to the latest JUCE

This commit is contained in:
Nikolai Rodionov 2022-11-04 23:11:33 +01:00 committed by Nikolai Rodionov
parent 4257a0f8ba
commit 913d851fd5
No known key found for this signature in database
GPG Key ID: 906851F91B1DA3EF
3393 changed files with 381 additions and 1064540 deletions

View File

@ -1,19 +1,19 @@
---
Language: Cpp
AccessModifierOffset: -3
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
@ -24,7 +24,7 @@ AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: true
AfterEnum: true
@ -32,7 +32,7 @@ BraceWrapping:
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterUnion: false
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
@ -41,7 +41,7 @@ BraceWrapping:
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
@ -49,14 +49,14 @@ BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: true
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 3
ContinuationIndentWidth: 3
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: false
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
@ -80,18 +80,18 @@ IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentGotoLabels: true
IndentPPDirectives: AfterHash
IndentWidth: 3
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 3
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
@ -101,9 +101,9 @@ PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Right
ReflowComments: true
ReflowComments: false
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
@ -129,8 +129,7 @@ Standard: Latest
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
TabWidth: 4
UseCRLF: false
UseTab: Never
...

18
.clang-tidy Normal file
View File

@ -0,0 +1,18 @@
---
Checks: '
bugprone-*,
clang-analyzer-*,
clang-cppcoreguidelines-*,
clang-modernize-*,
performance-*,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-owning-memory,
-bugprone-exception-escape,
-bugprone-branch-clone
'
WarningsAsErrors: '*'
HeaderFilterRegex: '.*'
AnalyzeTemporaryDtors: false
FormatStyle: none
...

View File

@ -19,7 +19,8 @@ steps:
x11-xserver-utils libxrandr-dev \
libxinerama-dev libxcursor-dev \
libfreetype6-dev libfftw3-dev \
libasound2-dev libjack-dev
libasound2-dev libjack-dev git
- git submodule update --init --recursive --progress
- |
cmake -B build -S ./ \
-DCMAKE_BUILD_TYPE=Release \

12
.gitattributes vendored
View File

@ -1,3 +1,11 @@
* text=auto
# Set the default behavior for all files.
* text=auto eol=lf
*.sh text eol=lf
# Normalized and converts to native line endings on checkout.
*.c text
*.cc text
*.cxx
*.cpp text
*.h text
*.hxx text
*.hpp text

147
.gitignore vendored Normal file
View File

@ -0,0 +1,147 @@
################################
########### FILES ############
################################
TODO*.*
*.pptx
*.pdf
################################
########### FOLDERS ############
################################
build/
html/
lectures/
################################
############ C/C++ #############
################################
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
*.ko
*.elf
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.i*86
*.x86_64
*.hex
*.app
*.stackdump
*.exe
*.out
# Linker output
*.ilk
*.map
*.exp
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
################################
########### VS CODE ############
################################
.vscode
*.code-workspace
.history
################################
########### VS ############
################################
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.meta
*.iobj
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e

7
.gitmodules vendored Normal file
View File

@ -0,0 +1,7 @@
[submodule "deps/juce"]
path = Deps/juce
url = https://github.com/juce-framework/JUCE.git
branch = 7.0.7
[submodule "deps/clap-juce-extensions"]
path = Deps/clap-juce-extensions
url = https://github.com/free-audio/clap-juce-extensions.git

50
.woodpecker.yml Normal file
View File

@ -0,0 +1,50 @@
---
when:
event: tag
steps:
build the plugin:
image: ubuntu:22.04
commands:
- apt-get update -y
- |
apt-get install -y \
build-essential libasound2 cmake \
fftw-dev pkg-config libx11-dev \
x11-xserver-utils libxrandr-dev \
libxinerama-dev libxcursor-dev \
libfreetype6-dev libfftw3-dev \
libasound2-dev libjack-dev git
- git submodule update --init --recursive --progress
- |
cmake -B build -S ./ \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr -Wno-dev
- cmake --build build
prepare release assets:
image: ubuntu:22.04
commands:
- apt-get update
- apt-get install zip -y
- mkdir dist
- export RELEASE_DIR=build/PaulXStretch_artefacts/Release
- cp -r $RELEASE_DIR/Standalone/ /tmp
- cp -r $RELEASE_DIR/VST3/ /tmp
- cd /tmp
- |
zip -r paulxstretch-standalone.zip Standalone && \
mv paulxstretch-standalone.zip $DRONE_WORKSPACE/dist/
- |
zip -r paulxstretch-vst3.zip VST3 && \
mv paulxstretch-vst3.zip $DRONE_WORKSPACE/dist/
publish the release:
image: woodpeckerci/plugin-gitea-release
settings:
base_url: https://git.badhouseplants.net
files:
- dist/*
api_key:
from_secret: GITEA_ACCESS_TOKEN_RELEASER
target: main

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 147 KiB

View File

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 147 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,5 +1,11 @@
## PaulXStretch Change History
**v1.7.1** (2023-09-18)
- Updated JUCE to 7.0.6, so the linux VST versions can be open in DAW
- Temporarily dropped support for CLAP
- Switched to git submodules to track deps
**v1.7.0**
- Update JUCE to 7.0.2
- Started using submodules for deps

View File

@ -7,7 +7,7 @@
# information can be found in the CMake docs.
cmake_minimum_required(VERSION 3.15)
set (CMAKE_CXX_STANDARD 20)
if (WIN32)
#set (CMAKE_GENERATOR_TOOLSET ClangCL)
@ -22,7 +22,7 @@ if (APPLE)
set (CMAKE_OSX_DEPLOYMENT_TARGET "10.10" CACHE INTERNAL "")
if (UniversalBinary)
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE INTERNAL "")
#set(CMAKE_OSX_ARCHITECTURES arm64 x86_64)
#set(CMAKE_OSX_ARCHITECTURES arm64 x86_64)
endif()
endif()
@ -54,7 +54,7 @@ set(BUILDVERSION 112)
set(CMAKE_XCODE_GENERATE_SCHEME OFF)
# No ZERO_CHECK target (it helps bust cache for cmake)
set(CMAKE_SUPPRESS_REGENERATION true)
set(CMAKE_SUPPRESS_REGENERATION true)
# prevent install all
#set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)
@ -75,11 +75,11 @@ option(JUCE_ENABLE_MODULE_SOURCE_GROUPS "Show all module sources in IDE projects
# include JUCE
add_subdirectory(deps/juce EXCLUDE_FROM_ALL )
add_subdirectory(Deps/juce EXCLUDE_FROM_ALL )
# Extend JUCE with CLAP support from https://github.com/free-audio/clap-juce-extensions
add_subdirectory(deps/clap-juce-extensions EXCLUDE_FROM_ALL)
add_subdirectory(Deps/clap-juce-extensions EXCLUDE_FROM_ALL)
@ -99,7 +99,7 @@ endif()
if (AAX_SDK_PATH)
juce_set_aax_sdk_path (${AAX_SDK_PATH})
if (APPLE OR (NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")))
list (APPEND AaxFormatsToBuild AAX)
endif()
@ -142,7 +142,7 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
set (vst3cats Instrument Network)
set (vst2cat "kPlugCategSynth")
else()
set (vst3cats Fx Network)
set (vst3cats Fx Network)
set (vst2cat "kPlugCategEffect")
endif()
@ -154,23 +154,23 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
COMPANY_NAME "Sonosaurus"
BUNDLE_ID "com.sonosaurus.paulxstretch"
MICROPHONE_PERMISSION_ENABLED TRUE
ICON_BIG "images/paulxstretch_icon_1024_rounded.png"
ICON_SMALL "images/paulxstretch_icon_256_rounded.png"
ICON_BIG "Assets/paulxstretch_icon_1024_rounded.png"
ICON_SMALL "Assets/paulxstretch_icon_256_rounded.png"
NEEDS_WEB_BROWSER FALSE
VST2_CATEGORY "${vst2cat}"
VST3_CATEGORIES "${vst3cats}"
AAX_CATEGORY "AAX_EPlugInCategory_Effect"
# mac settings
HARDENED_RUNTIME_ENABLED TRUE
HARDENED_RUNTIME_OPTIONS "com.apple.security.device.audio-input"
PLIST_TO_MERGE "${MacPList}"
AU_MAIN_TYPE "kAudioUnitType_MusicEffect"
COPY_PLUGIN_AFTER_BUILD FALSE # Set to TRUE to auto-install
# other settings...
PLUGIN_MANUFACTURER_CODE Sono
PLUGIN_CODE ${plugincode}
@ -212,8 +212,8 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
# platform specific stuff
if (APPLE)
list (APPEND HEADER_INCLUDES deps/mac/include)
list (APPEND LIB_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/deps/mac/lib)
list (APPEND HEADER_INCLUDES Deps/mac/include)
list (APPEND LIB_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/Deps/mac/lib)
list (APPEND PlatSourceFiles Source/CrossPlatformUtilsMac.mm)
if (no_fftw)
@ -225,19 +225,19 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
list (APPEND FFTW_DEPLIBS fftw3f)
endif()
elseif (WIN32)
list (APPEND HEADER_INCLUDES deps/windows ../asiosdk/common)
list (APPEND HEADER_INCLUDES Deps/windows ../asiosdk/common)
list (APPEND PlatSourceFiles Source/CrossPlatformUtilsWindows.cpp)
message (STATUS "Win generator platform is: ${CMAKE_VS_PLATFORM_NAME}" )
if ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")
list (APPEND LIB_PATHS
$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/deps/windows/Debug32>
$<$<CONFIG:Release>:${CMAKE_CURRENT_SOURCE_DIR}/deps/windows/Release32>
$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/Deps/windows/Debug32>
$<$<CONFIG:Release>:${CMAKE_CURRENT_SOURCE_DIR}/Deps/windows/Release32>
)
else()
list (APPEND LIB_PATHS
$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/deps/windows/Debug>
$<$<CONFIG:Release>:${CMAKE_CURRENT_SOURCE_DIR}/deps/windows/Release>
$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/Deps/windows/Debug>
$<$<CONFIG:Release>:${CMAKE_CURRENT_SOURCE_DIR}/Deps/windows/Release>
)
endif()
@ -337,8 +337,8 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
Source/pffft/pffft.c
)
target_sources("${target_name}" PRIVATE
${SourceFiles}
target_sources("${target_name}" PRIVATE
${SourceFiles}
)
# No, we don't want our source buried in extra nested folders
@ -355,7 +355,7 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
# INTERFACE
# $<TARGET_PROPERTY:"${target_name}",INCLUDE_DIRECTORIES>)
target_include_directories("${target_name}"
PUBLIC
@ -365,7 +365,7 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
# Require at least C++17 to build `my_target`
target_compile_features("${target_name}" PRIVATE cxx_std_17)
# This cleans up the folder organization, especially on Xcode.
# It tucks the Plugin varieties into a "Targets" folder and generate an Xcode Scheme manually
@ -378,17 +378,17 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
set_target_properties(${target_name}_${target} PROPERTIES
# Tuck the actual plugin targets into a folder where they won't bother us
FOLDER "Targets"
# MacOS only: Sets the default executable that Xcode will open on build
# For this exact path to to work, manually build the AudioPluginHost.xcodeproj in the JUCE subdir
# XCODE_SCHEME_EXECUTABLE "${CMAKE_CURRENT_SOURCE_DIR}/deps/juce/extras/AudioPluginHost/Builds/MacOSX/build/Debug/AudioPluginHost.app"
# Let us build the target in Xcode
# For this exact path to to work, manually build the AudioPluginHost.xcodeproj in the JUCE subdir
# XCODE_SCHEME_EXECUTABLE "${CMAKE_CURRENT_SOURCE_DIR}/Deps/juce/extras/AudioPluginHost/Builds/MacOSX/build/Debug/AudioPluginHost.app"
# Let us build the target in Xcode
XCODE_GENERATE_SCHEME ON)
endif()
endforeach()
target_compile_definitions("${target_name}"
PUBLIC
JUCE_WEB_BROWSER=0
@ -411,19 +411,19 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
${PLAT_COMPILE_DEFS} )
juce_add_binary_data("${target_name}_PSData" SOURCES
images/freeze.svg
images/loop_icon.svg
images/passthru.svg
images/passthru_enabled.svg
images/pause_icon.svg
images/play_icon.svg
images/power.svg
images/power_sel.svg
images/record_input.svg
images/record_input_active.svg
images/record_output.svg
images/record_output_active.svg
images/skipback_icon.svg
Assets/freeze.svg
Assets/loop_icon.svg
Assets/passthru.svg
Assets/passthru_enabled.svg
Assets/pause_icon.svg
Assets/play_icon.svg
Assets/power.svg
Assets/power_sel.svg
Assets/record_input.svg
Assets/record_input_active.svg
Assets/record_output.svg
Assets/record_output_active.svg
Assets/skipback_icon.svg
)
set_target_properties(${target_name}_PSData PROPERTIES FOLDER "Targets")
@ -447,7 +447,7 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
-march=native
)
endif()
if (TARGET ${target_name}_Standalone)
# make linux executable all lower case
string(TOLOWER ${target_name} tmptargname)
@ -465,13 +465,13 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
${LIB_PATHS}
)
target_link_libraries("${target_name}"
target_link_libraries("${target_name}"
PRIVATE
juce::juce_audio_utils
juce::juce_dsp
juce::juce_audio_plugin_client
juce::juce_cryptography
${target_name}_PSData
${FFTW_DEPLIBS}
@ -481,7 +481,7 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
juce::juce_recommended_lto_flags
# juce::juce_recommended_warning_flags
)
endfunction()
# most of the targets

View File

@ -10,4 +10,3 @@ FROM ubuntu
COPY --from=builder /src/build/PaulXStretch_artefacts/Release/ /release
CMD ["mv", "/release", "/out"]

2
Makefile Normal file
View File

@ -0,0 +1,2 @@
build_docker:

View File

@ -208,7 +208,7 @@ Rectangle<int> CustomLookAndFeel::getTabButtonExtraComponentBounds (const TabBar
default: jassertfalse; break;
}
}
else if (button.getExtraComponentPlacement() == TabBarButton::aboveText)
else if (button.getExtraComponentPlacement() == TabBarButton::beforeText)
{
switch (orientation)
{
@ -224,7 +224,7 @@ Rectangle<int> CustomLookAndFeel::getTabButtonExtraComponentBounds (const TabBar
//DBG("After Extra comp bounds: " << extraComp.toString())
}
else if (button.getExtraComponentPlacement() == TabBarButton::belowText)
else if (button.getExtraComponentPlacement() == TabBarButton::afterText)
{
switch (orientation)
{
@ -1182,9 +1182,9 @@ void CustomLookAndFeel::drawDrawableButton (Graphics& g, DrawableButton& button,
// imageratio = sonobutt->getForegroundImageRatio();
//}
if (button.getStyle() == DrawableButton::ImageAboveTextLabel || button.getStyle() == DrawableButton::ImageBelowTextLabel) {
if (button.getStyle() == DrawableButton::ImageAboveTextLabel || button.getStyle() == DrawableButton::ImageAboveTextLabel) {
textH = jmin (14, button.proportionOfHeight (0.2f));
} else if (button.getStyle() == DrawableButton::ImageLeftOfTextLabel || button.getStyle() == DrawableButton::ImageRightOfTextLabel) {
} else if (button.getStyle() == DrawableButton::ImageAboveTextLabel || button.getStyle() == DrawableButton::ImageAboveTextLabel) {
textH = jmin (14, button.proportionOfHeight (0.8f));
textW = jmax (20, button.proportionOfWidth (1.0f - imageratio));
}
@ -1205,19 +1205,19 @@ void CustomLookAndFeel::drawDrawableButton (Graphics& g, DrawableButton& button,
button.getWidth() - 4, textH,
Justification::centred, 1);
}
else if (button.getStyle() == DrawableButton::ImageBelowTextLabel) {
else if (button.getStyle() == DrawableButton::ImageAboveTextLabel) {
g.drawFittedText (button.getButtonText(),
2, 1,
button.getWidth() - 4, textH,
Justification::centred, 1);
}
else if (button.getStyle() == DrawableButton::ImageRightOfTextLabel) {
else if (button.getStyle() == DrawableButton::ImageAboveTextLabel) {
g.drawFittedText (button.getButtonText(),
2, 1,
textW , button.getHeight() - 2,
Justification::centred, 2, 0.6f);
}
else if (button.getStyle() == DrawableButton::ImageLeftOfTextLabel) {
else if (button.getStyle() == DrawableButton::ImageAboveTextLabel) {
g.drawFittedText (button.getButtonText(),
button.getWidth() - textW - 4 , 1,
textW , button.getHeight() - 2,

View File

@ -3,12 +3,11 @@
#include "../JuceLibraryCode/JuceHeader.h"
#include "juce_core/system/juce_TargetPlatform.h"
#include "juce_audio_plugin_client/utility/juce_CheckSettingMacros.h"
#include "juce_audio_plugin_client/detail/juce_CheckSettingMacros.h"
#include "juce_audio_plugin_client/utility/juce_IncludeSystemHeaders.h"
#include "juce_audio_plugin_client/utility/juce_IncludeModuleHeaders.h"
#include "juce_audio_plugin_client/utility/juce_FakeMouseMoveGenerator.h"
#include "juce_audio_plugin_client/utility/juce_WindowsHooks.h"
#include "juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h"
#include "juce_audio_plugin_client/detail/juce_IncludeModuleHeaders.h"
#include "juce_gui_basics/native/juce_WindowsHooks_windows.h"
#include <juce_audio_devices/juce_audio_devices.h>
#include <juce_gui_extra/juce_gui_extra.h>
@ -51,7 +50,7 @@ public:
appProperties.setStorageParameters (options);
LookAndFeel::setDefaultLookAndFeel(&sonoLNF);
}
const String getApplicationName() override { return JucePlugin_Name; }
@ -63,7 +62,7 @@ public:
}
void urlOpened(const URL& url) override {
void urlOpened(const URL& url) {
DBG("URL opened: " << url.toString(false));
if (mainWindow.get() != nullptr)
@ -72,7 +71,7 @@ public:
CustomLookAndFeel sonoLNF;
virtual StandaloneFilterWindow* createWindow()
{
#ifdef JucePlugin_PreferredChannelConfigurations
@ -81,7 +80,7 @@ public:
AudioDeviceManager::AudioDeviceSetup setupOptions;
setupOptions.bufferSize = 512;
return new StandaloneFilterWindow (getApplicationName(),
LookAndFeel::getDefaultLookAndFeel().findColour (ResizableWindow::backgroundColourId),
appProperties.getUserSettings(),
@ -107,7 +106,7 @@ public:
#endif
mainWindow->setVisible (true);
Desktop::getInstance().setScreenSaverEnabled(false);
}
@ -118,7 +117,7 @@ public:
mainWindow->pluginHolder->savePluginState();
mainWindow->pluginHolder->saveAudioDeviceState();
}
mainWindow = nullptr;
appProperties.saveIfNeeded();
}
@ -143,9 +142,9 @@ public:
appProperties.saveIfNeeded();
Desktop::getInstance().setScreenSaverEnabled(true);
Desktop::getInstance().setScreenSaverEnabled(true);
}
void resumed() override
{
Desktop::getInstance().setScreenSaverEnabled(false);
@ -160,7 +159,7 @@ public:
mainWindow->getDeviceManager().restartLastAudioDevice();
}
}
//==============================================================================
void systemRequestedQuit() override
{
@ -190,7 +189,7 @@ public:
{
DBG("Memory warning");
}
protected:
ApplicationProperties appProperties;
std::unique_ptr<StandaloneFilterWindow> mainWindow;

View File

@ -102,7 +102,7 @@ public:
virtual void createPlugin()
{
#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client
processor.reset (::createPluginFilterOfType (AudioProcessor::wrapperType_Standalone));
processor = createPluginFilterOfType (AudioProcessor::wrapperType_Standalone);
#else
AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Standalone);
processor.reset (createPluginFilter());
@ -524,11 +524,9 @@ private:
};
//==============================================================================
void audioDeviceIOCallback (const float** inputChannelData,
int numInputChannels,
float** outputChannelData,
int numOutputChannels,
int numSamples) override
void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,
float* const* outputChannelData, int numOutputChannels,
int numSamples, const AudioIODeviceCallbackContext& context) override
{
const bool inputMuted = shouldMuteInput.getValue();
@ -538,8 +536,8 @@ private:
inputChannelData = emptyBuffer.getArrayOfReadPointers();
}
player.audioDeviceIOCallback (inputChannelData, numInputChannels,
outputChannelData, numOutputChannels, numSamples);
player.audioDeviceIOCallbackWithContext (inputChannelData, numInputChannels,
outputChannelData, numOutputChannels, numSamples, context);
}
void audioDeviceAboutToStart (AudioIODevice* device) override
@ -644,8 +642,8 @@ public:
: DocumentWindow (title, backgroundColour, DocumentWindow::minimiseButton | DocumentWindow::closeButton),
optionsButton ("Options")
{
#if JUCE_IOS || JUCE_ANDROID
setTitleBarHeight (0);
#else
@ -658,7 +656,7 @@ public:
#endif
setResizable (true, false);
pluginHolder.reset (new StandalonePluginHolder (settingsToUse, takeOwnershipOfSettings,
preferredDefaultDeviceName, preferredSetupOptions,
constrainToConfiguration, autoOpenMidiDevices));
@ -770,7 +768,7 @@ public:
std::unique_ptr<StandalonePluginHolder> pluginHolder;
private:
//==============================================================================
class MainContentComponent : public Component,
@ -829,7 +827,7 @@ private:
}
void resized() override
{
{
auto r = getLocalBounds();
bool portrait = getWidth() < getHeight();
@ -847,7 +845,7 @@ private:
// call resized again if on iOS, due to dumb stuff related to safe area insets not being updated
#if JUCE_IOS
Timer::callAfterDelay(150, [this]() {
this->resized();
this->resized();
});
//return;
#endif
@ -862,18 +860,18 @@ private:
r.removeFromBottom(bottomInset);
r.removeFromLeft(leftInset);
r.removeFromRight(rightInset);
if (shouldShowNotification) {
notification.setBounds (r.removeFromTop (NotificationArea::height));
topInset += NotificationArea::height;
notification.setBounds (r.removeFromTop (NotificationArea::height));
topInset += NotificationArea::height;
}
editor->setBounds (r);
}
private:
bool isPortrait = false;
bool isTall = false;
int orientation = 0;
@ -968,7 +966,7 @@ private:
int bottomInset = 0;
int leftInset = 0;
int rightInset = 0;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};

View File

@ -98,7 +98,6 @@ GenericItemChooser::GenericItemChooser(const Array<GenericItemChooserItem> & ite
table.getViewport()->setScrollBarsShown(true, false);
table.getViewport()->setScrollOnDragEnabled(true);
table.setRowSelectedOnMouseDown(true);
table.setRowClickedOnMouseDown(false);
table.setMultipleSelectionEnabled (false);
table.setRowHeight(rowHeight);

View File

@ -123,7 +123,7 @@ public:
return m_readbuf.getSample(ch, int(pos - m_cached_file_range.getStart()));
else
{
Range<int64_t> activerange((int64_t)(m_activerange.getStart()*info.nsamples),
Range<int64_t> activerange((int64_t)(m_activerange.getStart()*info.nsamples),
(int64_t)(m_activerange.getEnd()*info.nsamples+1));
Range<int64_t> possiblerange(pos, pos + m_readbuf.getNumSamples() + 0);
m_cached_file_range = activerange.getIntersectionWith(possiblerange);
@ -154,7 +154,7 @@ public:
++m_silenceoutputted;
return 0.0f;
};
float** smps = abuf.getArrayOfWritePointers();
float* const* smps = abuf.getArrayOfWritePointers();
int readinc = 1;
if (m_reverseplay)
readinc = -1;
@ -212,7 +212,7 @@ public:
for (int j = 0; j < numchans; ++j)
{
int inchantouse = j % inchans;
smps[j][i] = seekfadegain*getCrossFadedSampleLambda(m_currentsample, inchantouse,
smps[j][i] = seekfadegain*getCrossFadedSampleLambda(m_currentsample, inchantouse,
subsect_t0, subsect_t1,xfadelen);
}
@ -224,7 +224,7 @@ public:
{
m_currentsample = subsect_t0+xfadelen;
++m_loopcount;
}
}
else if (m_reverseplay == true && m_currentsample < subsect_t0)
{
m_currentsample = subsect_t1 - 1;
@ -237,7 +237,7 @@ public:
PlayRangeEndCallback(this);
}
}
return nsmps;
}
void seekImpl(double pos)
@ -282,7 +282,7 @@ public:
}
m_seekfade.length = 16384;
m_seekfade.requestedpos = pos;
}
std::pair<Range<double>,Range<double>> getCachedRangesNormalized()
@ -322,7 +322,7 @@ public:
void setActiveRange(Range<double> rng) override
{
ScopedLock locker(m_mutex);
/*
if (rng.contains(getCurrentPositionPercent()))
{
@ -373,7 +373,7 @@ public:
}
bool isReversed() { return m_reverseplay; }
int64_t getLoopCount() { return m_loopcount; }
private:
std::function<void(AInputS*)> PlayRangeEndCallback;
std::unique_ptr<AudioFormatReader> m_afreader;

View File

@ -316,7 +316,7 @@ void StretchAudioSource::getNextAudioBlock(const AudioSourceChannelInfo & buffer
if (m_vol_smoother.getTargetValue() != maingain)
m_vol_smoother.setTargetValue(maingain);
FloatVectorOperations::disableDenormalisedNumberSupport();
float** outarrays = bufferToFill.buffer->getArrayOfWritePointers();
float* const* outarrays = bufferToFill.buffer->getArrayOfWritePointers();
int outbufchans = jmin(m_num_outchans, bufferToFill.buffer->getNumChannels());
int offset = bufferToFill.startSample;
if (m_stretchers.size() == 0)

View File

@ -573,7 +573,7 @@ void PaulstretchpluginAudioProcessorEditor::showRenderDialog()
int prefh = jmin(contentraw->getPreferredHeight(), getHeight() - 10);
contentraw->setSize(prefw, prefh);
std::unique_ptr<Component> content(contentraw);
auto & cb = CallOutBox::launchAsynchronously(std::move(content), m_render_button.getBounds(), this, false);
auto & cb = CallOutBox::launchAsynchronously(std::move(content), m_render_button.getBounds(), this);
cb.setDismissalMouseClicksAreAlwaysConsumed(true);
}
@ -635,7 +635,7 @@ void PaulstretchpluginAudioProcessorEditor::showSettings(bool flag)
Rectangle<int> bounds = dw->getLocalArea(nullptr, m_settings_button.getScreenBounds().reduced(10));
DBG("callout bounds: " << bounds.toString());
settingsCalloutBox = & CallOutBox::launchAsynchronously (std::move(wrap), bounds , dw, false);
settingsCalloutBox = & CallOutBox::launchAsynchronously(std::move(wrap), bounds , dw);
if (CallOutBox * box = dynamic_cast<CallOutBox*>(settingsCalloutBox.get())) {
box->setDismissalMouseClicksAreAlwaysConsumed(true);
}

View File

@ -52,7 +52,7 @@ public:
SpectralVisualizer();
void setState(const ProcessParameters& pars, int nfreqs, double samplerate);
void paint(Graphics& g) override;
private:
Image m_img;
std::vector<REALTYPE> m_insamples,m_freqs1, m_freqs2, m_freqs3;
@ -174,10 +174,10 @@ private:
class MyThumbCache : public AudioThumbnailCache
{
public:
MyThumbCache() : AudioThumbnailCache(200)
{
MyThumbCache() : AudioThumbnailCache(200)
{
// The default priority of 2 is a bit too low in some cases, it seems...
getTimeSliceThread().setPriority(3);
//getTimeSliceThread().setPriority(juce::Thread::Priority::highest);
}
~MyThumbCache() {}
};
@ -328,11 +328,11 @@ public:
void currentTabChanged(int newCurrentTabIndex, const String&) override
{
//m_cur_tab = newCurrentTabIndex;
}
private:
int& m_cur_tab;
};
class SimpleFFTComponent : public Component,
@ -346,15 +346,15 @@ public:
{
setOpaque(true);
startTimerHz(60);
}
~SimpleFFTComponent()
{
}
void addAudioBlock(const AudioBuffer<float>& bufferToFill)
void addAudioBlock(const AudioBuffer<float>& bufferToFill)
{
if (bufferToFill.getNumChannels() > 0)
{
@ -447,7 +447,7 @@ private:
int fifoIndex = 0;
bool nextFFTBlockReady = false;
};
@ -511,7 +511,7 @@ private:
LookAndFeel_V3 m_filebwlookandfeel;
};
class PaulstretchpluginAudioProcessorEditor : public AudioProcessorEditor,
class PaulstretchpluginAudioProcessorEditor : public AudioProcessorEditor,
public MultiTimer, public FileDragAndDropTarget, public DragAndDropContainer, public ComponentListener
{
@ -535,7 +535,7 @@ public:
void paint (Graphics&) override;
void resized() override;
void timerCallback(int id) override;
bool isInterestedInFileDrag(const StringArray &files) override;
void filesDropped(const StringArray &files, int x, int y) override;
@ -543,9 +543,9 @@ public:
void componentParentHierarchyChanged (Component& component) override;
WaveformComponent m_wavecomponent;
void showRenderDialog();
//SimpleFFTComponent m_sonogram;
String m_last_err;
@ -566,7 +566,7 @@ private:
void showPopTip(const String & message, int timeoutMs, Component * target, int maxwidth=100);
CustomLookAndFeel m_lookandfeel;
PaulstretchpluginAudioProcessor& processor;
@ -600,18 +600,18 @@ private:
WeakReference<Component> settingsCalloutBox;
std::unique_ptr<OptionsView> m_optionsView;
zoom_scrollbar m_zs;
RatioMixerEditor m_ratiomixeditor{ 8 };
FreeFilterComponent m_free_filter_component;
MyTabComponent m_wavefilter_tab;
Component* m_wave_container=nullptr;
void showAudioSetup();
void showSettings(bool flag);
void toggleFileBrowser();
std::vector<int> m_capturelens{ 2,5,10,30,60,120 };
std::unique_ptr<MyFileBrowserComponent> m_filechooser;
std::unique_ptr<FileChooser> fileChooser;
WildcardFileFilter m_filefilter;
@ -645,7 +645,7 @@ private:
// keep this down here, so it gets destroyed early
std::unique_ptr<BubbleMessageComponent> popTip;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PaulstretchpluginAudioProcessorEditor)
};

View File

@ -616,8 +616,8 @@ void PaulstretchpluginAudioProcessor::startplay(Range<double> playrange, int num
m_recreate_buffering_source = false;
}
if (m_bufferingthread.isThreadRunning() == false) {
m_bufferingthread.setPriority(8);
m_bufferingthread.startThread();
// m_bufferingthread.setPriority(juce::Thread::Priority::high);
}
m_stretch_source->setNumOutChannels(numoutchans);
m_stretch_source->setFFTSize(m_fft_size_to_use, true);

View File

@ -1,26 +0,0 @@
#!/bin/bash
OPTS=""
CONFIG="Release"
if [ "$1" = "debug" ]; then
CONFIG="Debug"
fi
JOBS=2
if nproc &> /dev/null ; then
JOBS=$(nproc)
elif sysctl -n hw.logicalcpu &> /dev/null; then
JOBS=$(sysctl -n hw.logicalcpu)
elif [ -n "$NUMBER_OF_PROCESSORS" ] ; then
JOBS=$NUMBER_OF_PROCESSORS
fi
OPTS="-j ${JOBS}"
cmake --build build --config $CONFIG $OPTS
if [ -d build32 ] ; then
cmake --build build32 --config $CONFIG $OPTS
fi

View File

@ -1,59 +0,0 @@
---
BasedOnStyle: LLVM
IndentWidth: 4
---
Language: Cpp
BasedOnStyle: LLVM
IndentWidth: 4
AlignAfterOpenBracket: Align
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
ColumnLimit: 100
SortIncludes: false
---
Language: ObjC
BasedOnStyle: LLVM
IndentWidth: 4
AlignAfterOpenBracket: Align
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
ColumnLimit: 100
SortIncludes: false
---

View File

@ -1,6 +0,0 @@
[submodule "clap-libs/clap"]
path = clap-libs/clap
url = https://github.com/free-audio/clap.git
[submodule "clap-libs/clap-helpers"]
path = clap-libs/clap-helpers
url = https://github.com/free-audio/clap-helpers.git

View File

@ -1,12 +0,0 @@
; 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-juce-extensions
branch = main
commit = 6489846d05a3bc0b743c5c0f301ad1858b4dc919
parent = 345d5a1d9f1c12303202574c23520c8d1780dd6f
method = merge
cmdver = 0.4.3

View File

@ -1,138 +0,0 @@
# CMAKE Support for out of tree clap plugin extensions to Juce 6
#
# To use these in your juce6 cmake project
# 1. Include this cmake file in your build path
# 2. Create your juce plugin as normal with formats VST3 etc...
# 3. After that, add the following lines (or similar) to your cmake
# clap_juce_extensions_plugin(TARGET my-target
# CLAP_ID "com.my-cool-plugs.my-target")
# 4. Reload your CMAKe file and my-target_CLAP will be a buildable target
cmake_minimum_required (VERSION 3.15 FATAL_ERROR)
project(clap-juce-extensions VERSION 0.1 LANGUAGES C CXX)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 14)
add_subdirectory(clap-libs/clap clapjuceext_clap EXCLUDE_FROM_ALL)
add_subdirectory(clap-libs/clap-helpers clapjuceext_claphelpers EXCLUDE_FROM_ALL)
add_library(clap_juce_extensions STATIC src/extensions/clap-juce-extensions.cpp)
set_property(TARGET clap_juce_extensions PROPERTY CXX_STANDARD 14)
target_include_directories(clap_juce_extensions PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_definitions(clap_juce_extensions PUBLIC
HAS_CLAP_JUCE_EXTENSIONS=1)
target_link_libraries(clap_juce_extensions PUBLIC clap-core clap-helpers)
set_target_properties(clap_juce_extensions PROPERTIES
POSITION_INDEPENDENT_CODE TRUE
VISIBILITY_INLINES_HIDDEN TRUE
C_VISBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
)
add_library(clap_juce_sources INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src/wrapper/clap-juce-wrapper.cpp)
set_property(TARGET clap_juce_sources PROPERTY CXX_STANDARD 14)
if (APPLE)
target_sources(clap_juce_sources INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src/wrapper/clap-juce-mac.mm)
endif()
target_include_directories(clap_juce_sources INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
function(clap_juce_extensions_plugin)
set(oneValueArgs TARGET)
set(multiValueArgs CLAP_ID CLAP_FEATURES CLAP_MANUAL_URL CLAP_SUPPORT_URL)
cmake_parse_arguments(CJA "" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN} )
set(target ${CJA_TARGET})
set(claptarget ${target}_CLAP)
message(STATUS "Creating CLAP ${claptarget} from ${target}")
if ("${CJA_CLAP_ID}" STREQUAL "")
message(FATAL_ERROR "You must specify CLAP_ID to add a clap" )
endif()
if ("${CJA_CLAP_FEATURES}" STREQUAL "")
message(WARNING "No CLAP_FEATURES were specified! Using \"instrument\" by default.")
set(CJA_CLAP_FEATURES instrument)
endif()
# we need the list of features as comma separated quoted strings
foreach(feature IN LISTS CJA_CLAP_FEATURES)
list (APPEND CJA_CLAP_FEATURES_PARSED "\"${feature}\"")
endforeach()
list (JOIN CJA_CLAP_FEATURES_PARSED ", " CJA_CLAP_FEATURES_PARSED)
get_property(SRC TARGET clap_juce_sources PROPERTY SOURCES)
add_library(${claptarget} MODULE ${SRC})
set_target_properties(${claptarget} PROPERTIES
CXX_STANDARD 14
ARCHIVE_OUTPUT_DIRECTORY "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},ARCHIVE_OUTPUT_DIRECTORY>>/CLAP"
LIBRARY_OUTPUT_DIRECTORY "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},LIBRARY_OUTPUT_DIRECTORY>>/CLAP"
RUNTIME_OUTPUT_DIRECTORY "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},RUNTIME_OUTPUT_DIRECTORY>>/CLAP")
get_target_property(products_folder ${claptarget} LIBRARY_OUTPUT_DIRECTORY)
set(product_name $<TARGET_PROPERTY:${target},JUCE_PRODUCT_NAME>)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
set_target_properties(${claptarget} PROPERTIES
BUNDLE True
BUNDLE_EXTENSION clap
PREFIX ""
OUTPUT_NAME "${product_name}"
MACOSX_BUNDLE TRUE
)
else()
set_target_properties(${claptarget} PROPERTIES
PREFIX ""
SUFFIX ".clap"
OUTPUT_NAME "${product_name}"
)
endif()
target_include_directories(${claptarget} PRIVATE
$<TARGET_PROPERTY:${target},INCLUDE_DIRECTORIES>)
target_compile_definitions(${claptarget} PRIVATE
CLAP_ID="${CJA_CLAP_ID}"
CLAP_FEATURES=${CJA_CLAP_FEATURES_PARSED}
CLAP_MANUAL_URL="${CJA_CLAP_MANUAL_URL}"
CLAP_SUPPORT_URL="${CJA_CLAP_SUPPORT_URL}")
target_link_libraries(${target} PUBLIC clap_juce_extensions)
target_link_libraries(${claptarget} PUBLIC clap-core clap-helpers clap_juce_sources ${target})
set_property(TARGET ${claptarget} PROPERTY C_VISIBILITY_PRESET hidden)
set_property(TARGET ${claptarget} PROPERTY VISIBILITY_INLINES_HIDDEN ON)
set_target_properties(${claptarget} PROPERTIES
POSITION_INDEPENDENT_CODE TRUE
VISIBILITY_INLINES_HIDDEN TRUE
C_VISBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
)
get_target_property(docopy "${target}" JUCE_COPY_PLUGIN_AFTER_BUILD)
if(docopy)
message(STATUS "Copy After Build" )
if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
add_custom_command(TARGET ${claptarget} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Installing ${products_folder}/${product_name}.clap to ~/Library/Audio/Plug-Ins/CLAP/"
COMMAND ${CMAKE_COMMAND} -E make_directory "~/Library/Audio/Plug-Ins/CLAP"
COMMAND ${CMAKE_COMMAND} -E copy_directory "${products_folder}/${product_name}.clap" "~/Library/Audio/Plug-Ins/CLAP/${product_name}.clap"
)
endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
add_custom_command(TARGET ${claptarget} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Installing ${products_folder}/${product_name}.clap"
COMMAND ${CMAKE_COMMAND} -E make_directory "~/.clap"
COMMAND ${CMAKE_COMMAND} -E copy "${products_folder}/${product_name}.clap" "~/.clap/"
)
endif()
endif()
endfunction()

View File

@ -1,9 +0,0 @@
Copyright 2019-2020, Paul Walker
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

@ -1,171 +0,0 @@
# JUCE6 and 7 Unofficial CMake Clap Plugin Support
This is a set of code which, combined with a JUCE6 or JUCE 7 CMake plugin project, allows you to build a CLAP plugin. It
is licensed under the MIT license, and can be used for both open and closed source projects.
We are labeling it 'unofficial' for four reasons
1. It is not supported by the JUCE team,
2. There are some JUCE features which we have not translated to CLAP yet,
3. It presents a set of completely optional extensions which break JUCE abstractions to allow extended CLAP feature
support and
4. It does not support JUCE-based CLAP hosting
Despite those caveats, the basic use of this library has allowed a wide variety
of synths and effects to generate a CLAP from their JUCE program, including Surge, B-Step,
Monique, several ChowDSP plugins, Dexed and more.
By far the best solution for CLAP in JUCE would be full native support by the JUCE team. Until such a time as that
happens (and it may never happen), this code may help you if you have a JUCE plugin and want to generate a CLAP. We are
happy to merge changes and answer questions as you try to use it. Please feel free to raise github issues in this repo.
This version is based off of CLAP 1.0 and generates plugins which work in BWS 4.3beta5 and later, as well as
other CLAP 1.0 DAWs such as MultitrackStudio.
## Basics: Using these extensions to build a CLAP
Given a starting point of a JUCE plugin using CMake which can build a VST3, AU, Standalone and so forth with
`juce_plugin`, building a CLAP is a simple exercise of checking out this CLAP extension code
somewhere in your dev environment, setting a few CMake variables, and adding a couple of lines to your CMake file.
The instructions are as follows:
1. Add `https://github.com/free-audio/clap-juce-extensions.git` as a submodule of your project, or otherwise make the
source available to your cmake (CPM, side by side check out in CI, etc...).
2. Load the `clap-juce-extension` in your CMake after you have loaded JUCE. For instance, you could do
```cmake
add_subdirectory(libs/JUCE) # this is however you load juce
add_subdirectory(libs/clap-juce-extensions EXCLUDE_FROM_ALL)
```
3. Create your JUCE plugin as normal with flags and formats using the `juce_plugin` CMake function
4. After your `juce_plugin` code, add the following lines (or similar)
to your CMake (a list of pre-defined CLAP
features can be found [here](https://github.com/free-audio/clap/blob/main/include/clap/plugin-features.h)):
```cmake
clap_juce_extensions_plugin(TARGET my-target
CLAP_ID "com.my-cool-plugs.my-target"
CLAP_FEATURES instrument "virtual analog" gritty basses leads pads)
```
5. Reload your CMake file and you will have a new target `my-target_CLAP` which will build a CLAP and leave
it side-by-side with your AU, Standalone, VST3, and so forth. Load that CLAP into a DAW and give it a whirl!
## Risks of using this library
Using this library is, of course, not without risks. There could easily be bugs we haven't found and there are
APIs we don't cover. We are happy to discuss, investigate, and work to fix any of those.
The biggest risk, though, involves JUCE team providing official support in a way which is fundamentally incompatible
with these wrappers. As of this writing, the JUCE team has not committed to supporting CLAP in JUCE 7 or any future
version, although they are aware of the project. But if the JUCE team did provide official future support, it is not
clear that your CLAP plugin which resulted from their official support would work in the same way as the plugin
generated by this library would.
There are a couple of mitigants to that risk.
Most importantly, in the three critical places a DAW interacts with a plugin - CLAP ID, parameter IDs, and state streaming -
we have endeavoured to write in as JUCE-natural a way as possible.
1. The CLAP ID is just a CMake parameter, as we expect it would be in an official build.
2. The parameter IDs we use uses the [internal JUCE hashing mechanism to generate
our `uint32_t`](https://github.com/free-audio/clap-juce-extensions/blob/85bc0d56dc784a5f1271602db46f0748954b180e/src/wrapper/clap-juce-wrapper.cpp#L198)
just like
the [current VST3 wrapper does](https://github.com/juce-framework/JUCE/blob/2f980209cc4091a4490bb1bafc5d530f16834e58/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp#L585).
3. Our stream implementation
transparently [calls `AudioProcessor::setStateInformation` and `AudioProcessor::getStateInformation`](https://github.com/free-audio/clap-juce-extensions/blob/85bc0d56dc784a5f1271602db46f0748954b180e/src/wrapper/clap-juce-wrapper.cpp#L930)
with no intervening
modification of the stream.
While there is no guarantee that an official JUCE implementation, if it were to exist, would make these choices,
it seems quite natural that it would, and in that case, your plugin would continue to work.
If, however, you use the extensions detailed below - which allows features outside of JUCE like note expressions,
sample accurate automation, and polyphonic and non-destructive modulation - there is very little assurance we can
give you that an official JUCE implementation, if it were to exist, would work with your code without modification,
or even that it would support those features at all. That would leave such a synth (of which Surge is the primary
example today) relying on these wrappers still.
## Major Missing API points
1. We have not tested any JUCE version earlier than 6.0.7, and plugins which use deprecated APIs may not work
2. The [`AudioProcessor::WrapperType`](https://docs.juce.com/master/classAudioProcessor.html#a2e1b21b8831ac529965abffc96223dcf)
API doesn't support CLAP. All CLAP plugins will define a `wrapperType` of `wrapperType_Undefined`. We do provide
a workaround for using our extensions mechanism, below.
3. Several parameter features - including discrete (stepped) parameters - don't translate from JUCE to CLAP
in our adapter (although they are supported in the CLAP API of course). We would love a test plugin to help us
resolve this.
## The Extensions API
There are a set of things which JUCE doesn't support which CLAP does. Rather than not support them in our
plugins, we've decided to create an extensions API. These are a set of classes which your AudioProcessor can
implement and, if it does, then the CLAP JUCE wrapper will call the associated functions.
The extension are in "include/clap-juce-extensions.h" and are documented there, but currently have
three classes
- `clap_juce_extensions::clap_properties`
- if you subclass this your AudioProcessor will have a collection of members which give you extra CLAP info
- Most usefully, you get an `is_clap` member which is false if not a CLAP and true if it is, which works around
the fact that our 'forkless' approach doesn't let us add a `AudioProcessor::WrapperType` to the JUCE API
- `clap_juce_extensions::clap_extensions`
- these are a set of advanced extensions which let you optionally interact more directly with the CLAP API
and are mostly useful for advanced features like non-destructive modulation and note expression support
- `clap_juce_extensions::clap_param_extensions`
- If your AudioProcessorParameter subclass implements this API, you can share extended CLAP information on
a parameter by parameter basis
As an example, here's how to use `clap_properties` to work around `AudioProcessor::WrapperType` being `Undefined` in the forkless
CLAP approach
- `#include "clap-juce-extensions/clap-juce-extensions.h"`
- Make your main plugin `juce::AudioProcessor` derive from `clap_juce_extensions::clap_properties`
- Use the `is_clap` member variable to figure out the correct wrapper type.
Here's a minimal example:
```cpp
#include <JuceHeader.h>
#include "clap-juce-extensions/clap-juce-extensions.h"
class MyCoolPlugin : public juce::AudioProcessor,
public clap_juce_extensions::clap_properties
{
String getWrapperTypeString()
{
if (wrapperType == wrapperType_Undefined && is_clap)
return "CLAP";
return juce::AudioProcessor::getWrapperTypeDescription (wrapperType);
}
...
};
```
If you are interested in using these extensions, please consult the documentation in the
[clap-juce-extensions header.](https://github.com/free-audio/clap-juce-extensions/blob/main/include/clap-juce-extensions/clap-juce-extensions.h)
The [Surge XT Synthesizer](https://github.com/surge-synthesizer/surge) is a worked example of using many of these.
We are also happy to discuss them - reach out in the issues here or in a shared discord server.
## Technical Detail: The "Forkless" approach
There's a couple of ways we could have gone adding experimental JUCE support. The way the LV2 extensions to JUCE work
requires a forked JUCE which places LV2 support fully inside the JUCE ecosystem at the cost of maintaining a fork (and
not allowing folks with their own forks to easily use LV2). We instead chose an 'out-of-JUCE' approach which has the
following pros and cons
Pros:
* You can use any JUCE 6 or 7 / CMake method you want and don't need to use our branch.
* We don't have to update our fork to pull latest JUCE features; you don't have to use our fork and choices to build
your plugin.
Cons:
* The CMake API is not consistent. Rather than add "CLAP" as a plugin type, you need a couple of extra lines of CMake to
activate your CLAP.
* We cannot support the `AudioProcessor::WrapperType` API, as discussed above.

View File

@ -1,12 +0,0 @@
; 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-helpers.git
branch = main
commit = 2bb43c18788c689708ead6f127a2d75e772ab389
parent = 8bbddf66e9d6b4b8e0a4fb98122ace8d70a5c14d
method = merge
cmdver = 0.4.3

View File

@ -1,25 +0,0 @@
cmake_minimum_required(VERSION 3.17)
cmake_policy(SET CMP0100 NEW) # handle .hh files
project(CLAP_HELPERS C CXX)
enable_testing()
find_package(Catch2 QUIET)
add_library(clap-helpers INTERFACE)
set_target_properties(clap-helpers PROPERTIES
POSITION_INDEPENDENT_CODE ON
CXX_STANDARD 11)
target_include_directories(clap-helpers INTERFACE include)
target_link_libraries(clap-helpers INTERFACE clap-core)
if (Catch2_FOUND)
add_executable(clap-helpers-tests
tests/plugin.cc
tests/main.cc)
set_target_properties(clap-helpers-tests PROPERTIES CXX_STANDARD 11)
target_link_libraries(clap-helpers-tests clap-helpers clap-core Catch2::Catch2)
target_compile_definitions(clap-helpers-tests PUBLIC -DCATCH_CONFIG_PREFIX_ALL)
add_test(NAME test-clap-helpers COMMAND clap-helpers-tests)
add_dependencies(clap-tests clap-helpers-tests)
endif()
install(DIRECTORY include DESTINATION ".")

View File

@ -1,21 +0,0 @@
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

@ -1,9 +0,0 @@
#pragma once
namespace clap { namespace helpers {
enum class CheckingLevel {
None,
Minimal,
Maximal,
};
}} // namespace clap::helpers

View File

@ -1,148 +0,0 @@
#pragma once
#include <cstring>
#include <cstdint>
#include <vector>
#include <clap/events.h>
#include "heap.hh"
namespace clap { namespace helpers {
class EventList {
public:
explicit EventList(uint32_t initialHeapSize = 4096,
uint32_t initialEventsCapacity = 128,
uint32_t maxEventSize = 1024)
: _maxEventSize(maxEventSize), _heap(initialHeapSize) {
_events.reserve(initialEventsCapacity);
}
EventList(const EventList &) = delete;
EventList(EventList &&) = delete;
EventList &operator=(const EventList &) = delete;
EventList &operator=(EventList &&) = delete;
static const constexpr size_t SAFE_ALIGN = 8;
void reserveEvents(size_t capacity) { _events.reserve(capacity); }
void reserveHeap(size_t size) { _heap.reserve(size); }
clap_event_header *allocate(size_t align, size_t size) {
assert(size >= sizeof(clap_event_header));
if (size > _maxEventSize)
return nullptr;
// ensure we have space to store into the vector
if (_events.capacity() == _events.size())
_events.reserve(_events.capacity() * 2);
auto ptr = _heap.allocate(align, size);
_events.push_back(_heap.offsetFromBase(ptr));
auto hdr = static_cast<clap_event_header *>(ptr);
hdr->size = size;
return hdr;
}
clap_event_header *tryAllocate(size_t align, size_t size) {
assert(size >= sizeof(clap_event_header));
if (size > _maxEventSize)
return nullptr;
// ensure we have space to store into the vector
if (_events.capacity() == _events.size())
return nullptr;
auto ptr = _heap.tryAllocate(align, size);
if (!ptr)
return nullptr;
_events.push_back(_heap.offsetFromBase(ptr));
auto hdr = static_cast<clap_event_header *>(ptr);
hdr->size = size;
return hdr;
}
template <typename T>
T *allocate() {
return allocate(alignof(T), sizeof(T));
}
void push(const clap_event_header *h) {
auto ptr = allocate(SAFE_ALIGN, h->size);
if (!ptr)
return;
std::memcpy(ptr, h, h->size);
}
bool tryPush(const clap_event_header *h) {
auto ptr = tryAllocate(SAFE_ALIGN, h->size);
if (!ptr)
return false;
std::memcpy(ptr, h, h->size);
return true;
}
clap_event_header *get(uint32_t index) const {
const auto offset = _events.at(index);
auto const ptr = _heap.ptrFromBase(offset);
return static_cast<clap_event_header *>(ptr);
}
size_t size() const { return _events.size(); }
bool empty() const { return _events.empty(); }
void clear() {
_heap.clear();
_events.clear();
}
const clap_input_events *clapInputEvents() const noexcept { return &_inputEvents; }
const clap_output_events *clapOutputEvents() const noexcept { return &_outputEvents; }
const clap_output_events *clapBoundedOutputEvents() const noexcept {
return &_boundedOutputEvents;
}
private:
static uint32_t clapSize(const struct clap_input_events *list) {
auto *self = static_cast<const EventList *>(list->ctx);
return self->size();
}
static const clap_event_header_t *clapGet(const struct clap_input_events *list,
uint32_t index) {
auto *self = static_cast<const EventList *>(list->ctx);
return self->get(index);
}
static bool clapPushBack(const struct clap_output_events *list,
const clap_event_header *event) {
auto *self = static_cast<EventList *>(list->ctx);
self->push(event);
return true;
}
static bool clapBoundedPushBack(const struct clap_output_events *list,
const clap_event_header_t *event) {
auto *self = static_cast<EventList *>(list->ctx);
return self->tryPush(event);
}
const clap_input_events _inputEvents = {this, &clapSize, &clapGet};
const clap_output_events _outputEvents = {this, &clapPushBack};
const clap_output_events _boundedOutputEvents = {this, &clapBoundedPushBack};
const uint32_t _maxEventSize;
Heap _heap;
std::vector<uint32_t> _events;
};
}} // namespace clap::helpers

View File

@ -1,84 +0,0 @@
#pragma once
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <stdexcept>
#include <vector>
namespace clap { namespace helpers {
/** Simple heap allocator which ensures alignment. */
class Heap {
public:
explicit Heap(uint32_t initialSize = 4096) { reserve(initialSize); }
~Heap() { std::free(_base); }
Heap(const Heap &) = delete;
Heap(Heap &&) = delete;
Heap &operator=(const Heap &) = delete;
Heap &operator=(Heap &&) = delete;
void reserve(const size_t heapSize) {
if (heapSize <= _size)
return;
auto *const ptr = static_cast<uint8_t *>(std::realloc(_base, heapSize));
if (!ptr)
throw std::bad_alloc();
_base = ptr;
_size = heapSize;
}
void clear() { _brk = 0; }
void *tryAllocate(uint32_t align, uint32_t size) {
assert(_brk <= _size);
void *ptr = _base + _brk;
size_t space = _size - _brk;
if (!std::align(align, size, ptr, space))
return nullptr;
auto offset = static_cast<uint8_t *>(ptr) - _base;
_brk = offset + size;
std::memset(ptr, 0, size);
return ptr;
}
void *allocate(uint32_t align, uint32_t size) {
assert(_brk <= _size);
if (size + _brk > _size)
reserve(_size * 2);
auto ptr = tryAllocate(align, size);
assert(ptr);
return ptr;
}
void *ptrFromBase(size_t offset) const {
assert(offset <= _brk && "out of range");
return static_cast<uint8_t *>(_base) + offset;
}
size_t offsetFromBase(const void *ptr) const {
assert(ptr >= _base && "ptr before heap's base");
size_t offset = static_cast<const uint8_t *>(ptr) - _base;
assert(offset < _size && "ptr after heap's end");
return offset;
}
size_t size() const { return _size; }
bool empty() const { return _brk == 0; }
private:
size_t _size = 0;
size_t _brk = 0;
uint8_t *_base = nullptr;
};
}} // namespace clap::helpers

View File

@ -1,170 +0,0 @@
#pragma once
#include <string>
#include <clap/clap.h>
#include "checking-level.hh"
#include "misbehaviour-handler.hh"
namespace clap { namespace helpers {
template <MisbehaviourHandler h, CheckingLevel l>
class HostProxy {
public:
HostProxy(const clap_host *host);
void init();
///////////////
// clap_host //
///////////////
template <typename T>
void getExtension(const T *&ptr, const char *id) noexcept;
void requestCallback() noexcept;
void requestRestart() noexcept;
void requestProcess() noexcept;
///////////////////
// clap_host_log //
///////////////////
bool canUseHostLog() const noexcept;
void log(clap_log_severity severity, const char *msg) const noexcept;
void hostMisbehaving(const char *msg) const noexcept;
void hostMisbehaving(const std::string &msg) const noexcept { hostMisbehaving(msg.c_str()); }
void pluginMisbehaving(const char *msg) const noexcept;
void pluginMisbehaving(const std::string &msg) const noexcept {
pluginMisbehaving(msg.c_str());
}
////////////////////////////
// clap_host_thread_check //
////////////////////////////
bool canUseThreadCheck() const noexcept;
bool isMainThread() const noexcept;
bool isAudioThread() const noexcept;
//////////////////////////////////
// clap_host_audio_ports_config //
//////////////////////////////////
bool canUseAudioPortsConfig() const noexcept;
void audioPortsConfigRescan() const noexcept;
///////////////////////////
// clap_host_audio_ports //
///////////////////////////
bool canUseAudioPorts() const noexcept;
void audioPortsRescan(uint32_t flags) const noexcept;
//////////////////////////
// clap_host_note_ports //
//////////////////////////
bool canUseNotePorts() const noexcept;
void notePortsRescan(uint32_t flags) const noexcept;
/////////////////////
// clap_host_state //
/////////////////////
bool canUseState() const noexcept;
void stateMarkDirty() const noexcept;
///////////////////////
// clap_host_latency //
///////////////////////
bool canUseLatency() const noexcept;
void latencyChanged() const noexcept;
////////////////////
// clap_host_tail //
////////////////////
bool canUseTail() const noexcept;
void tailChanged() const noexcept;
/////////////////////////
// clap_host_note_name //
/////////////////////////
bool canUseNoteName() const noexcept;
void noteNameChanged() const noexcept;
//////////////////////
// clap_host_params //
//////////////////////
bool canUseParams() const noexcept;
void paramsRescan(clap_param_rescan_flags flags) const noexcept;
void paramsClear(clap_id param_id, clap_param_clear_flags flags) const noexcept;
void paramsRequestFlush() const noexcept;
//////////////////////////
// clap_host_track_info //
//////////////////////////
bool canUseTrackInfo() const noexcept;
bool trackInfoGet(clap_track_info *info) const noexcept;
///////////////////
// clap_host_gui //
///////////////////
bool canUseGui() const noexcept;
bool guiRequestResize(uint32_t width, uint32_t height) const noexcept;
bool guiRequestShow() const noexcept;
bool guiRequestHide() const noexcept;
void guiClosed(bool wasDestroyed) const noexcept;
/////////////////////////////
// clap_host_timer_support //
/////////////////////////////
bool canUseTimerSupport() const noexcept;
bool timerSupportRegister(uint32_t period_ms, clap_id *timer_id) const noexcept;
bool timerSupportUnregister(clap_id timer_id) const noexcept;
//////////////////////////
// clap_host_fd_support //
//////////////////////////
bool canUsePosixFdSupport() const noexcept;
bool posixFdSupportRegister(int fd, int flags) const noexcept;
bool posixFdSupportModify(int fd, int flags) const noexcept;
bool posixFdSupportUnregister(int fd) const noexcept;
//////////////////////////////
// clap_host_quick_controls //
//////////////////////////////
bool canUseQuickControls() const noexcept;
void quickControlsChanged() const noexcept;
void quickControlsSuggestPage(clap_id page_id) const noexcept;
///////////////////////////
// clap_host_thread_pool //
///////////////////////////
bool canUseThreadPool() const noexcept;
bool threadPoolRequestExec(uint32_t numTasks) const noexcept;
//////////////////////////
// clap_host_voice_info //
//////////////////////////
bool canUseVoiceInfo() const noexcept;
void voiceInfoChanged() const noexcept;
protected:
void ensureMainThread(const char *method) const noexcept;
void ensureAudioThread(const char *method) const noexcept;
const clap_host *const _host;
const clap_host_log *_hostLog = nullptr;
const clap_host_thread_check *_hostThreadCheck = nullptr;
const clap_host_thread_pool *_hostThreadPool = nullptr;
const clap_host_audio_ports *_hostAudioPorts = nullptr;
const clap_host_audio_ports_config *_hostAudioPortsConfig = nullptr;
const clap_host_note_ports *_hostNotePorts = nullptr;
const clap_host_file_reference *_hostFileReference = nullptr;
const clap_host_latency *_hostLatency = nullptr;
const clap_host_gui *_hostGui = nullptr;
const clap_host_timer_support *_hostTimerSupport = nullptr;
const clap_host_posix_fd_support *_hostPosixFdSupport = nullptr;
const clap_host_params *_hostParams = nullptr;
const clap_host_track_info *_hostTrackInfo = nullptr;
const clap_host_state *_hostState = nullptr;
const clap_host_note_name *_hostNoteName = nullptr;
const clap_host_quick_controls *_hostQuickControls = nullptr;
const clap_host_voice_info *_hostVoiceInfo = nullptr;
const clap_host_tail *_hostTail = nullptr;
};
}} // namespace clap::helpers

View File

@ -1,546 +0,0 @@
#pragma once
#include <cassert>
#include <iostream>
#include <sstream>
#include "host-proxy.hh"
namespace clap { namespace helpers {
template <MisbehaviourHandler h, CheckingLevel l>
HostProxy<h, l>::HostProxy(const ::clap_host *host) : _host(host) {}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::init() {
getExtension(_hostLog, CLAP_EXT_LOG);
getExtension(_hostThreadCheck, CLAP_EXT_THREAD_CHECK);
getExtension(_hostThreadPool, CLAP_EXT_THREAD_POOL);
getExtension(_hostAudioPorts, CLAP_EXT_AUDIO_PORTS);
getExtension(_hostAudioPortsConfig, CLAP_EXT_AUDIO_PORTS_CONFIG);
getExtension(_hostNotePorts, CLAP_EXT_NOTE_PORTS);
getExtension(_hostTimerSupport, CLAP_EXT_TIMER_SUPPORT);
getExtension(_hostPosixFdSupport, CLAP_EXT_POSIX_FD_SUPPORT);
getExtension(_hostFileReference, CLAP_EXT_FILE_REFERENCE);
getExtension(_hostLatency, CLAP_EXT_LATENCY);
getExtension(_hostGui, CLAP_EXT_GUI);
getExtension(_hostParams, CLAP_EXT_PARAMS);
getExtension(_hostTrackInfo, CLAP_EXT_TRACK_INFO);
getExtension(_hostState, CLAP_EXT_STATE);
getExtension(_hostNoteName, CLAP_EXT_NOTE_NAME);
getExtension(_hostQuickControls, CLAP_EXT_QUICK_CONTROLS);
getExtension(_hostVoiceInfo, CLAP_EXT_VOICE_INFO);
}
template <MisbehaviourHandler h, CheckingLevel l>
template <typename T>
void HostProxy<h, l>::getExtension(const T *&ptr, const char *id) noexcept {
assert(!ptr);
assert(id);
if (_host->get_extension)
ptr = static_cast<const T *>(_host->get_extension(_host, id));
}
///////////////
// clap_host //
///////////////
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::requestCallback() noexcept {
_host->request_callback(_host);
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::requestRestart() noexcept {
_host->request_restart(_host);
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::requestProcess() noexcept {
_host->request_process(_host);
}
/////////////
// Logging //
/////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseHostLog() const noexcept {
return _hostLog && _hostLog->log;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::log(clap_log_severity severity, const char *msg) const noexcept {
if (canUseHostLog()) {
_hostLog->log(_host, severity, msg);
return;
}
switch (severity) {
case CLAP_LOG_ERROR:
case CLAP_LOG_HOST_MISBEHAVING:
std::cerr << msg << std::endl;
break;
default:
std::clog << msg << std::endl;
break;
}
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::hostMisbehaving(const char *msg) const noexcept {
log(CLAP_LOG_HOST_MISBEHAVING, msg);
if (h == MisbehaviourHandler::Terminate)
std::terminate();
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::pluginMisbehaving(const char *msg) const noexcept {
log(CLAP_LOG_PLUGIN_MISBEHAVING, msg);
if (h == MisbehaviourHandler::Terminate)
std::terminate();
}
//////////////////
// Thread Check //
//////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseThreadCheck() const noexcept {
return _hostThreadCheck && _hostThreadCheck->is_audio_thread &&
_hostThreadCheck->is_main_thread;
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::isMainThread() const noexcept {
assert(canUseThreadCheck());
return _hostThreadCheck->is_main_thread(_host);
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::isAudioThread() const noexcept {
assert(canUseThreadCheck());
return _hostThreadCheck->is_audio_thread(_host);
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::ensureMainThread(const char *method) const noexcept {
if (l == CheckingLevel::None)
return;
if (!canUseThreadCheck() || isMainThread())
return;
std::ostringstream msg;
msg << "Plugin called the method clap_host_" << method
<< "() on wrong thread! It must be called on main thread!";
pluginMisbehaving(msg.str());
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::ensureAudioThread(const char *method) const noexcept {
if (l == CheckingLevel::None)
return;
if (!canUseThreadCheck() || isAudioThread())
return;
std::ostringstream msg;
msg << "Plugin called the method clap_host_" << method
<< "() on wrong thread! It must be called on audio thread!";
pluginMisbehaving(msg.str());
}
//////////////////////////////////
// clap_host_audio_ports_config //
//////////////////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseAudioPortsConfig() const noexcept {
if (!_hostAudioPortsConfig)
return false;
if (_hostAudioPortsConfig->rescan)
return true;
hostMisbehaving("clap_host_audio_ports_config is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::audioPortsConfigRescan() const noexcept {
assert(canUseAudioPortsConfig());
ensureMainThread("audio_ports_config.rescan");
_hostAudioPortsConfig->rescan(_host);
}
///////////////////////////
// clap_host_audio_ports //
///////////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseAudioPorts() const noexcept {
if (!_hostAudioPorts)
return false;
if (_hostAudioPorts->rescan)
return true;
hostMisbehaving("clap_host_audio_ports is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::audioPortsRescan(uint32_t flags) const noexcept {
assert(canUseAudioPorts());
ensureMainThread("audio_ports.rescan");
_hostAudioPorts->rescan(_host, flags);
}
//////////////////////////
// clap_host_note_ports //
//////////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseNotePorts() const noexcept {
if (!_hostNotePorts)
return false;
if (_hostNotePorts->rescan)
return true;
hostMisbehaving("clap_host_note_ports is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::notePortsRescan(uint32_t flags) const noexcept {
assert(canUseNotePorts());
ensureMainThread("note_ports.rescan");
_hostNotePorts->rescan(_host, flags);
}
/////////////////////
// clap_host_state //
/////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseState() const noexcept {
if (!_hostState)
return false;
if (_hostState->mark_dirty)
return true;
hostMisbehaving("clap_host_state is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::stateMarkDirty() const noexcept {
assert(canUseState());
ensureMainThread("state.mark_dirty");
_hostState->mark_dirty(_host);
}
///////////////////////
// clap_host_latency //
///////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseLatency() const noexcept {
if (!_hostLatency)
return false;
if (_hostLatency->changed)
return true;
hostMisbehaving("clap_host_latency is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::latencyChanged() const noexcept {
assert(canUseLatency());
ensureMainThread("latency.changed");
_hostLatency->changed(_host);
}
////////////////////
// clap_host_tail //
////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseTail() const noexcept {
if (!_hostTail)
return false;
if (_hostLatency->changed)
return true;
hostMisbehaving("clap_host_tail is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::tailChanged() const noexcept {
assert(canUseTail());
ensureAudioThread("tail.changed");
_hostTail->changed(_host);
}
/////////////////////////
// clap_host_note_name //
/////////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseNoteName() const noexcept {
if (!_hostNoteName)
return false;
if (_hostNoteName->changed)
return true;
hostMisbehaving("clap_host_note_name is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::noteNameChanged() const noexcept {
assert(canUseNoteName());
ensureMainThread("note_name.changed");
_hostNoteName->changed(_host);
}
//////////////////////
// clap_host_params //
//////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseParams() const noexcept {
if (!_hostParams)
return false;
if (_hostParams->rescan && _hostParams->clear && _hostParams->request_flush)
return true;
hostMisbehaving("clap_host_params is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::paramsRescan(clap_param_rescan_flags flags) const noexcept {
assert(canUseParams());
ensureMainThread("params.rescan");
_hostParams->rescan(_host, flags);
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::paramsClear(clap_id param_id,
clap_param_clear_flags flags) const noexcept {
assert(canUseParams());
ensureMainThread("params.clear");
_hostParams->clear(_host, param_id, flags);
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::paramsRequestFlush() const noexcept {
assert(canUseParams());
_hostParams->request_flush(_host);
}
//////////////////////////
// clap_host_track_info //
//////////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseTrackInfo() const noexcept {
if (!_hostTrackInfo)
return false;
if (_hostTrackInfo->get)
return true;
hostMisbehaving("clap_host_track_info is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::trackInfoGet(clap_track_info *info) const noexcept {
assert(canUseTrackInfo());
ensureMainThread("track_info.get");
return _hostTrackInfo->get(_host, info);
}
///////////////////
// clap_host_gui //
///////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseGui() const noexcept {
if (!_hostGui)
return false;
if (_hostGui->resize_hints_changed && _hostGui->request_resize && _hostGui->request_hide &&
_hostGui->request_show && _hostGui->closed)
return true;
hostMisbehaving("clap_host_gui is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::guiRequestResize(uint32_t width, uint32_t height) const noexcept {
assert(canUseGui());
return _hostGui->request_resize(_host, width, height);
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::guiRequestShow() const noexcept {
assert(canUseGui());
return _hostGui->request_show(_host);
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::guiRequestHide() const noexcept {
assert(canUseGui());
return _hostGui->request_hide(_host);
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::guiClosed(bool wasDestroyed) const noexcept {
assert(canUseGui());
_hostGui->closed(_host, wasDestroyed);
}
///////////////////
// Timer Support //
///////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseTimerSupport() const noexcept {
if (!_hostTimerSupport)
return false;
auto &x = *_hostTimerSupport;
if (x.register_timer && x.unregister_timer)
return true;
hostMisbehaving("clap_timer_support is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::timerSupportRegister(uint32_t period_ms,
clap_id *timer_id) const noexcept {
assert(canUseTimerSupport());
ensureMainThread("timer_support.register_timer");
return _hostTimerSupport->register_timer(_host, period_ms, timer_id);
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::timerSupportUnregister(clap_id timer_id) const noexcept {
assert(canUseTimerSupport());
ensureMainThread("timer_support.unregister_timer");
return _hostTimerSupport->unregister_timer(_host, timer_id);
}
//////////////////////////
// clap_host_fd_support //
//////////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUsePosixFdSupport() const noexcept {
if (!_hostPosixFdSupport)
return false;
auto &x = *_hostPosixFdSupport;
if (x.modify_fd && x.register_fd && x.unregister_fd)
return true;
hostMisbehaving("clap_posix_fd_support is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::posixFdSupportRegister(int fd, int flags) const noexcept {
assert(canUsePosixFdSupport());
ensureMainThread("posix_fd_support.register");
return _hostPosixFdSupport->register_fd(_host, fd, flags);
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::posixFdSupportModify(int fd, int flags) const noexcept {
assert(canUsePosixFdSupport());
ensureMainThread("posix_fd_support.modify");
return _hostPosixFdSupport->modify_fd(_host, fd, flags);
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::posixFdSupportUnregister(int fd) const noexcept {
assert(canUsePosixFdSupport());
ensureMainThread("posix_fd_support.unregister");
return _hostPosixFdSupport->unregister_fd(_host, fd);
}
///////////////////////////
// clap_host_thread_pool //
///////////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseThreadPool() const noexcept {
if (!_hostThreadPool)
return false;
if (_hostThreadPool->request_exec)
return true;
hostMisbehaving("clap_host_thread_pool is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::threadPoolRequestExec(uint32_t numTasks) const noexcept {
assert(canUseThreadPool());
ensureAudioThread("thread_pool.request_exec");
return _hostThreadPool->request_exec(_host, numTasks);
}
//////////////////////////
// clap_host_voice_info //
//////////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseVoiceInfo() const noexcept {
if (!_hostVoiceInfo)
return false;
if (_hostVoiceInfo->changed)
return true;
hostMisbehaving("clap_host_voice_info is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::voiceInfoChanged() const noexcept {
assert(canUseVoiceInfo());
ensureMainThread("voice_info.changed");
return _hostVoiceInfo->changed(_host);
}
//////////////////////////////
// clap_host_quick_controls //
//////////////////////////////
template <MisbehaviourHandler h, CheckingLevel l>
bool HostProxy<h, l>::canUseQuickControls() const noexcept {
if (!_hostQuickControls)
return false;
if (_hostQuickControls->changed && _hostQuickControls->suggest_page)
return true;
hostMisbehaving("clap_host_quick_controls is partially implemented");
return false;
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::quickControlsChanged() const noexcept {
assert(canUseQuickControls());
ensureMainThread("quick_controls.changed");
_hostQuickControls->changed(_host);
}
template <MisbehaviourHandler h, CheckingLevel l>
void HostProxy<h, l>::quickControlsSuggestPage(clap_id page_id) const noexcept {
assert(canUseQuickControls());
ensureMainThread("quick_controls.suggest_page");
_hostQuickControls->suggest_page(_host, page_id);
}
}} // namespace clap::helpers

View File

@ -1,8 +0,0 @@
#pragma once
namespace clap { namespace helpers {
enum class MisbehaviourHandler {
Ignore,
Terminate,
};
}} // namespace clap::helpers

View File

@ -1,75 +0,0 @@
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <unordered_set>
#include <clap/clap.h>
namespace clap { namespace helpers {
class NoteEndQueue {
public:
explicit NoteEndQueue(std::size_t initialBucketSize = 19)
: _voicesToKill(initialBucketSize) {}
void onNoteOn(int32_t noteId, int16_t port, int16_t channel, int16_t key) {
assert(checkValidEntry(noteId, port, channel, key));
_voicesToKill.erase(Entry(noteId, port, channel, key));
}
void onNoteEnd(int32_t noteId, int16_t port, int16_t channel, int16_t key) {
assert(checkValidEntry(noteId, port, channel, key));
_voicesToKill.insert(Entry(noteId, port, channel, key));
}
void flush(const clap_output_events *out) {
clap_event_note ev;
ev.velocity = 0;
ev.header.flags = 0;
ev.header.size = sizeof(ev);
ev.header.space_id = CLAP_CORE_EVENT_SPACE_ID;
ev.header.time = 0; // time is irrelevant here
ev.header.type = CLAP_EVENT_NOTE_END;
for (auto &e : _voicesToKill) {
ev.port_index = e._port;
ev.channel = e._channel;
ev.key = e._key;
ev.note_id = e._noteId;
out->try_push(out, &ev.header);
}
_voicesToKill.clear();
}
private:
bool checkValidEntry(int32_t noteId, int16_t port, int16_t channel, int16_t key) {
assert(noteId >= -1);
assert(port >= 0);
assert(channel >= 0 && channel < 16);
assert(key >= 0 && key < 127);
return true;
}
struct Entry {
constexpr Entry(int32_t noteId, int16_t port, int16_t channel, int16_t key)
: _noteId(noteId), _port(port), _channel(channel), _key(key) {}
constexpr bool operator==(const Entry &o) const noexcept {
return _port == o._port && _channel == o._channel && _key == o._key;
}
const int32_t _noteId;
const int16_t _port;
const int16_t _channel;
const int16_t _key;
};
struct EntryHash {
std::size_t operator()(const Entry &e) const noexcept {
return e._key ^ (e._channel << 8) ^ (e._port << 16) ^ (int64_t(e._noteId) << 32LL);
}
};
std::unordered_set<Entry, EntryHash> _voicesToKill;
};
}} // namespace clap::helpers

View File

@ -1,71 +0,0 @@
#pragma once
#include <array>
#include <atomic>
#include <cassert>
#include <cstddef>
namespace clap { namespace helpers {
template <typename T, size_t CAPACITY>
class ParamQueue {
public:
using value_type = T;
ParamQueue() = default;
void push(const T &value) {
while (!tryPush(value))
;
}
bool tryPush(const T &value) {
int w = _writeOffset; // write element
int wn = (w + 1) % CAPACITY; // next write element
if (wn == _readOffset)
return false;
_data[w] = value;
_writeOffset = wn;
return true;
}
bool tryPeek(T &value) {
int r = _readOffset;
if (r == _writeOffset)
return false; // empty
value = _data[r];
return true;
}
void consume() {
int r = _readOffset;
if (r == _writeOffset) {
assert(false && "consume should not have been called");
return; // empty
}
int rn = (r + 1) % CAPACITY;
_readOffset = rn;
}
bool tryPop(T &value) {
if (!tryPeek(value))
return false;
consume();
return true;
}
void reset() {
_writeOffset = 0;
_readOffset = 0;
}
private:
std::array<T, CAPACITY> _data;
std::atomic<int> _writeOffset = {0};
std::atomic<int> _readOffset = {0};
};
}} // namespace clap::helpers

View File

@ -1,37 +0,0 @@
#pragma once
#include "host-proxy.hh"
namespace clap { namespace helpers {
template <MisbehaviourHandler h, CheckingLevel l>
class PluginProxy {
public:
PluginProxy(const clap_host *host, const clap_plugin *plugin);
void init();
template <typename T>
void getExtension(const T *&ptr, const char *id) noexcept;
protected:
void ensureMainThread(const char *method) const noexcept;
void ensureAudioThread(const char *method) const noexcept;
HostProxy<h, l> _host;
const clap_plugin *const _plugin;
const clap_plugin_params *_pluginParams = nullptr;
const clap_plugin_quick_controls *_pluginQuickControls = nullptr;
const clap_plugin_audio_ports *_pluginAudioPorts = nullptr;
const clap_plugin_gui *_pluginGui = nullptr;
const clap_plugin_gui_x11 *_pluginGuiX11 = nullptr;
const clap_plugin_gui_win32 *_pluginGuiWin32 = nullptr;
const clap_plugin_gui_cocoa *_pluginGuiCocoa = nullptr;
const clap_plugin_gui_free_standing *_pluginGuiFreeStanding = nullptr;
const clap_plugin_timer_support *_pluginTimerSupport = nullptr;
const clap_plugin_fd_support *_pluginFdSupport = nullptr;
const clap_plugin_thread_pool *_pluginThreadPool = nullptr;
const clap_plugin_preset_load *_pluginPresetLoad = nullptr;
const clap_plugin_state *_pluginState = nullptr;
};
}} // namespace clap::helpers

View File

@ -1,434 +0,0 @@
#pragma once
#include <cassert>
#include <functional>
#include <mutex>
#include <queue>
#include <string>
#include <string_view>
#include <vector>
#include <clap/clap.h>
#include "checking-level.hh"
#include "host-proxy.hh"
#include "misbehaviour-handler.hh"
namespace clap { namespace helpers {
/// @brief C++ glue and checks
///
/// @note for an higher level implementation, see @ref PluginHelper
template <MisbehaviourHandler h, CheckingLevel l>
class Plugin {
public:
const clap_plugin *clapPlugin() noexcept { return &_plugin; }
protected:
Plugin(const clap_plugin_descriptor *desc, const clap_host *host);
virtual ~Plugin() = default;
// not copyable, not moveable
Plugin(const Plugin &) = delete;
Plugin(Plugin &&) = delete;
Plugin &operator=(const Plugin &) = delete;
Plugin &operator=(Plugin &&) = delete;
/////////////////////////
// Methods to override //
/////////////////////////
//-------------//
// clap_plugin //
//-------------//
virtual bool init() noexcept { return true; }
virtual bool
activate(double sampleRate, uint32_t minFrameCount, uint32_t maxFrameCount) noexcept {
return true;
}
virtual void deactivate() noexcept {}
virtual bool startProcessing() noexcept { return true; }
virtual void stopProcessing() noexcept {}
virtual clap_process_status process(const clap_process *process) noexcept {
return CLAP_PROCESS_SLEEP;
}
virtual void reset() noexcept {}
virtual void onMainThread() noexcept {}
virtual const void *extension(const char *id) noexcept { return nullptr; }
//---------------------//
// clap_plugin_latency //
//---------------------//
virtual bool implementsLatency() const noexcept { return false; }
virtual uint32_t latencyGet() const noexcept { return 0; }
//------------------//
// clap_plugin_tail //
//------------------//
virtual bool implementsTail() const noexcept { return false; }
virtual uint32_t tailGet(const clap_plugin_t *plugin) const noexcept { return 0; }
//--------------------//
// clap_plugin_render //
//--------------------//
virtual bool implementsRender() const noexcept { return false; }
virtual bool renderHasHardRealtimeRequirement() noexcept { return false; }
virtual bool renderSetMode(clap_plugin_render_mode mode) noexcept { return false; }
//-------------------------//
// clap_plugin_thread_pool //
//-------------------------//
virtual bool implementsThreadPool() const noexcept { return false; }
virtual void threadPoolExec(uint32_t taskIndex) noexcept {}
//-------------------//
// clap_plugin_state //
//-------------------//
virtual bool implementsState() const noexcept { return false; }
virtual bool stateSave(const clap_ostream *stream) noexcept { return false; }
virtual bool stateLoad(const clap_istream *stream) noexcept { return false; }
//-------------------------//
// clap_plugin_preset_load //
//-------------------------//
virtual bool implementsPresetLoad() const noexcept { return false; }
virtual bool presetLoadFromFile(const char *path) noexcept { return false; }
//------------------------//
// clap_plugin_track_info //
//------------------------//
virtual bool implementsTrackInfo() const noexcept { return false; }
virtual void trackInfoChanged() noexcept {}
//-------------------------//
// clap_plugin_audio_ports //
//-------------------------//
virtual bool implementsAudioPorts() const noexcept { return false; }
virtual uint32_t audioPortsCount(bool isInput) const noexcept { return 0; }
virtual bool
audioPortsInfo(uint32_t index, bool isInput, clap_audio_port_info *info) const noexcept {
return false;
}
virtual uint32_t audioPortsConfigCount() const noexcept { return 0; }
virtual bool audioPortsGetConfig(uint32_t index,
clap_audio_ports_config *config) const noexcept {
return false;
}
virtual bool audioPortsSetConfig(clap_id configId) noexcept { return false; }
//--------------------//
// clap_plugin_params //
//--------------------//
virtual bool implementsParams() const noexcept { return false; }
virtual uint32_t paramsCount() const noexcept { return 0; }
virtual bool paramsInfo(uint32_t paramIndex, clap_param_info *info) const noexcept {
return false;
}
virtual bool paramsValue(clap_id paramId, double *value) noexcept { return false; }
virtual bool
paramsValueToText(clap_id paramId, double value, char *display, uint32_t size) noexcept {
return false;
}
virtual bool paramsTextToValue(clap_id paramId, const char *display, double *value) noexcept {
return false;
}
virtual void paramsFlush(const clap_input_events *in,
const clap_output_events *out) noexcept {}
virtual bool isValidParamId(clap_id paramId) const noexcept;
//----------------------------//
// clap_plugin_quick_controls //
//----------------------------//
virtual bool implementQuickControls() const noexcept { return false; }
virtual uint32_t quickControlsPageCount() noexcept { return 0; }
virtual bool quickControlsPageGet(uint32_t pageIndex,
clap_quick_controls_page *page) noexcept {
return false;
}
virtual void quickControlsSelectPage(clap_id pageId) noexcept {}
virtual clap_id quickControlsSelectedPage() noexcept { return CLAP_INVALID_ID; }
//------------------------//
// clap_plugin_note_ports //
//------------------------//
virtual bool implementsNotePorts() const noexcept { return false; }
virtual uint32_t notePortsCount(bool isInput) const noexcept { return 0; }
virtual bool
notePortsInfo(uint32_t index, bool isInput, clap_note_port_info *info) const noexcept {
return false;
}
//-----------------------//
// clap_plugin_note_name //
//-----------------------//
virtual bool implementsNoteName() const noexcept { return false; }
virtual int noteNameCount() noexcept { return 0; }
virtual bool noteNameGet(int index, clap_note_name *noteName) noexcept { return false; }
//---------------------------//
// clap_plugin_timer_support //
//---------------------------//
virtual bool implementsTimerSupport() const noexcept { return false; }
virtual void onTimer(clap_id timerId) noexcept {}
//------------------------------//
// clap_plugin_posix_fd_support //
//------------------------------//
virtual bool implementsPosixFdSupport() const noexcept { return false; }
virtual void onPosixFd(int fd, int flags) noexcept {}
//-----------------//
// clap_plugin_gui //
//-----------------//
virtual bool implementsGui() const noexcept { return false; }
virtual bool guiIsApiSupported(const char *api, bool isFloating) noexcept { return false; }
virtual bool guiGetPreferredApi(const char **api, bool *is_floating) noexcept {
return false;
}
virtual bool guiCreate(const char *api, bool isFloating) noexcept { return false; }
virtual void guiDestroy() noexcept {}
virtual bool guiSetScale(double scale) noexcept { return false; }
virtual bool guiShow() noexcept { return false; }
virtual bool guiHide() noexcept { return false; }
virtual bool guiGetSize(uint32_t *width, uint32_t *height) noexcept { return false; }
virtual bool guiCanResize() const noexcept { return false; }
virtual bool guiGetResizeHints(clap_gui_resize_hints_t *hints) noexcept { return false; }
virtual bool guiAdjustSize(uint32_t *width, uint32_t *height) noexcept {
return guiGetSize(width, height);
}
virtual bool guiSetSize(uint32_t width, uint32_t height) noexcept { return false; }
virtual void guiSuggestTitle(const char *title) noexcept {}
virtual bool guiSetParent(const clap_window *window) noexcept { return false; }
virtual bool guiSetTransient(const clap_window *window) noexcept { return false; }
//------------------------//
// clap_plugin_voice_info //
//------------------------//
virtual bool implementsVoiceInfo() const noexcept { return false; }
virtual bool voiceInfoGet(clap_voice_info *info) noexcept { return false; }
/////////////
// Logging //
/////////////
void log(clap_log_severity severity, const char *msg) const noexcept;
void hostMisbehaving(const char *msg) const noexcept;
void hostMisbehaving(const std::string &msg) const noexcept { hostMisbehaving(msg.c_str()); }
// Receives a copy of all the logging messages sent to the host.
// This is useful to have the messages in both the host's logs and the plugin's logs.
virtual void logTee(clap_log_severity severity, const char *msg) const noexcept {}
/////////////////////
// Thread Checking //
/////////////////////
void checkMainThread() const noexcept;
void checkAudioThread() const noexcept;
void checkParamThread() const noexcept;
void ensureMainThread(const char *method) const noexcept;
void ensureAudioThread(const char *method) const noexcept;
void ensureParamThread(const char *method) const noexcept;
///////////////
// Utilities //
///////////////
static Plugin &from(const clap_plugin *plugin, bool requireInitialized = true) noexcept;
// runs the callback immediately if on the main thread, otherwise queue it.
// be aware that the callback may be ran during the plugin destruction phase,
// so check isBeingDestroyed() and ajust your code.
void runOnMainThread(std::function<void()> callback);
// This actually runs callbacks on the main thread, you should not need to call it
void runCallbacksOnMainThread();
template <typename T>
void initInterface(const T *&ptr, const char *id) noexcept;
void initInterfaces() noexcept;
static uint32_t compareAudioPortsInfo(const clap_audio_port_info &a,
const clap_audio_port_info &b) noexcept;
//////////////////////
// Processing State //
//////////////////////
bool isActive() const noexcept { return _isActive; }
bool isProcessing() const noexcept { return _isProcessing; }
int sampleRate() const noexcept {
assert(_isActive && "sample rate is only known if the plugin is active");
assert(_sampleRate > 0);
return _sampleRate;
}
bool isBeingDestroyed() const noexcept { return _isBeingDestroyed; }
protected:
HostProxy<h, l> _host;
private:
/////////////////////
// CLAP Interfaces //
/////////////////////
clap_plugin _plugin;
// clap_plugin
static bool clapInit(const clap_plugin *plugin) noexcept;
static void clapDestroy(const clap_plugin *plugin) noexcept;
static bool clapActivate(const clap_plugin *plugin,
double sample_rate,
uint32_t minFrameCount,
uint32_t maxFrameCount) noexcept;
static void clapDeactivate(const clap_plugin *plugin) noexcept;
static bool clapStartProcessing(const clap_plugin *plugin) noexcept;
static void clapStopProcessing(const clap_plugin *plugin) noexcept;
static void clapReset(const clap_plugin *plugin) noexcept;
static clap_process_status clapProcess(const clap_plugin *plugin,
const clap_process *process) noexcept;
static void clapOnMainThread(const clap_plugin *plugin) noexcept;
static const void *clapExtension(const clap_plugin *plugin, const char *id) noexcept;
// latency
static uint32_t clapLatencyGet(const clap_plugin *plugin) noexcept;
// clap_plugin_tail
static uint32_t clapTailGet(const clap_plugin_t *plugin) noexcept;
// clap_plugin_render
static bool clapRenderHasHardRealtimeRequirement(const clap_plugin_t *plugin) noexcept;
static bool clapRenderSetMode(const clap_plugin *plugin,
clap_plugin_render_mode mode) noexcept;
// clap_plugin_thread_pool
static void clapThreadPoolExec(const clap_plugin *plugin, uint32_t task_index) noexcept;
// clap_plugin_state
static bool clapStateSave(const clap_plugin *plugin, const clap_ostream *stream) noexcept;
static bool clapStateLoad(const clap_plugin *plugin, const clap_istream *stream) noexcept;
// clap_plugin_preset
static bool clapPresetLoadFromFile(const clap_plugin *plugin, const char *path) noexcept;
// clap_plugin_track_info
static void clapTrackInfoChanged(const clap_plugin *plugin) noexcept;
// clap_plugin_audio_ports
static uint32_t clapAudioPortsCount(const clap_plugin *plugin, bool is_input) noexcept;
static bool clapAudioPortsInfo(const clap_plugin *plugin,
uint32_t index,
bool is_input,
clap_audio_port_info *info) noexcept;
static uint32_t clapAudioPortsConfigCount(const clap_plugin *plugin) noexcept;
static bool clapAudioPortsGetConfig(const clap_plugin *plugin,
uint32_t index,
clap_audio_ports_config *config) noexcept;
static bool clapAudioPortsSetConfig(const clap_plugin *plugin, clap_id config_id) noexcept;
// clap_plugin_params
static uint32_t clapParamsCount(const clap_plugin *plugin) noexcept;
static bool clapParamsInfo(const clap_plugin *plugin,
uint32_t param_index,
clap_param_info *param_info) noexcept;
static bool
clapParamsValue(const clap_plugin *plugin, clap_id param_id, double *value) noexcept;
static bool clapParamsValueToText(const clap_plugin *plugin,
clap_id param_id,
double value,
char *display,
uint32_t size) noexcept;
static bool clapParamsTextToValue(const clap_plugin *plugin,
clap_id param_id,
const char *display,
double *value) noexcept;
static void clapParamsFlush(const clap_plugin *plugin,
const clap_input_events *in,
const clap_output_events *out) noexcept;
// clap_plugin_quick_controls
static uint32_t clapQuickControlsPageCount(const clap_plugin *plugin) noexcept;
static bool clapQuickControlsPageGet(const clap_plugin *plugin,
uint32_t page_index,
clap_quick_controls_page *page) noexcept;
// clap_plugin_note_port
static uint32_t clapNotePortsCount(const clap_plugin *plugin, bool is_input) noexcept;
static bool clapNotePortsInfo(const clap_plugin *plugin,
uint32_t index,
bool is_input,
clap_note_port_info *info) noexcept;
// clap_plugin_note_name
static uint32_t clapNoteNameCount(const clap_plugin *plugin) noexcept;
static bool clapNoteNameGet(const clap_plugin *plugin,
uint32_t index,
clap_note_name *note_name) noexcept;
// clap_plugin_timer_support
static void clapOnTimer(const clap_plugin *plugin, clap_id timer_id) noexcept;
// clap_plugin_fd_support
static void
clapOnPosixFd(const clap_plugin *plugin, int fd, clap_posix_fd_flags_t flags) noexcept;
// clap_plugin_gui
static bool
clapGuiIsApiSupported(const clap_plugin *plugin, const char *api, bool isFloating) noexcept;
static bool clapGuiGetPreferredApi(const clap_plugin_t *plugin,
const char **api,
bool *is_floating) noexcept;
static bool
clapGuiCreate(const clap_plugin *plugin, const char *api, bool isFloating) noexcept;
static void clapGuiDestroy(const clap_plugin *plugin) noexcept;
static bool clapGuiSetScale(const clap_plugin *plugin, double scale) noexcept;
static bool
clapGuiGetSize(const clap_plugin *plugin, uint32_t *width, uint32_t *height) noexcept;
static bool
clapGuiSetSize(const clap_plugin *plugin, uint32_t width, uint32_t height) noexcept;
static bool clapGuiCanResize(const clap_plugin *plugin) noexcept;
static bool clapGuiGetResizeHints(const clap_plugin_t *plugin,
clap_gui_resize_hints_t *hints) noexcept;
static bool
clapGuiAdjustSize(const clap_plugin *plugin, uint32_t *width, uint32_t *height) noexcept;
static bool clapGuiShow(const clap_plugin *plugin) noexcept;
static bool clapGuiHide(const clap_plugin *plugin) noexcept;
static bool clapGuiSetParent(const clap_plugin *plugin, const clap_window *window) noexcept;
static bool clapGuiSetTransient(const clap_plugin *plugin,
const clap_window *window) noexcept;
static void clapGuiSuggestTitle(const clap_plugin *plugin, const char *title) noexcept;
static bool clapVoiceInfoGet(const clap_plugin *plugin, clap_voice_info *info) noexcept;
// interfaces
static const clap_plugin_render _pluginRender;
static const clap_plugin_thread_pool _pluginThreadPool;
static const clap_plugin_state _pluginState;
static const clap_plugin_preset_load _pluginPresetLoad;
static const clap_plugin_track_info _pluginTrackInfo;
static const clap_plugin_audio_ports _pluginAudioPorts;
static const clap_plugin_audio_ports_config _pluginAudioPortsConfig;
static const clap_plugin_params _pluginParams;
static const clap_plugin_quick_controls _pluginQuickControls;
static const clap_plugin_latency _pluginLatency;
static const clap_plugin_note_ports _pluginNotePorts;
static const clap_plugin_note_name _pluginNoteName;
static const clap_plugin_timer_support _pluginTimerSupport;
static const clap_plugin_posix_fd_support _pluginPosixFdSupport;
static const clap_plugin_gui _pluginGui;
static const clap_plugin_voice_info _pluginVoiceInfo;
static const clap_plugin_tail _pluginTail;
// state
bool _wasInitialized = false;
bool _isActive = false;
bool _isProcessing = false;
bool _isBeingDestroyed = false;
double _sampleRate = 0;
std::string _guiApi;
bool _isGuiCreated = false;
bool _isGuiFloating = false;
bool _isGuiEmbedded = false;
std::mutex _mainThredCallbacksLock;
std::queue<std::function<void()>> _mainThredCallbacks;
};
}} // namespace clap::helpers

View File

@ -1,48 +0,0 @@
#pragma once
#include <atomic>
#include <cstddef>
#include <functional>
#include <unordered_map>
#include <clap/private/macros.h>
namespace clap { namespace helpers {
#ifdef CLAP_HAS_CXX20
template <typename T>
concept UpdatableValue = requires(T &a, const T &b) {
// update a with b, b being newer than a
{ a.update(b) };
};
#endif
// TODO: when switching to C++20
// template <typename K, UpdatableValue V>
template <typename K, typename V>
class ReducingParamQueue {
public:
using key_type = K;
using value_type = V;
using queue_type = std::unordered_map<key_type, value_type>;
using consumer_type = const std::function<void(const key_type &key, const value_type &value)>;
ReducingParamQueue();
void setCapacity(size_t capacity);
void set(const key_type &key, const value_type &value);
void setOrUpdate(const key_type &key, const value_type &value);
void producerDone();
void consume(const consumer_type &consumer);
void reset();
private:
queue_type _queues[2];
std::atomic<queue_type *> _free = nullptr;
std::atomic<queue_type *> _producer = nullptr;
std::atomic<queue_type *> _consumer = nullptr;
};
}} // namespace clap::helpers

View File

@ -1,72 +0,0 @@
#pragma once
#include <cassert>
#include "reducing-param-queue.hh"
namespace clap { namespace helpers {
template <typename K, typename V>
ReducingParamQueue<K, V>::ReducingParamQueue() {
reset();
}
template <typename K, typename V>
void ReducingParamQueue<K, V>::reset() {
for (auto &q : _queues)
q.clear();
_free = &_queues[0];
_producer = &_queues[1];
_consumer = nullptr;
}
template <typename K, typename V>
void ReducingParamQueue<K, V>::setCapacity(size_t capacity) {
for (auto &q : _queues)
q.reserve(2 * capacity);
}
template <typename K, typename V>
void ReducingParamQueue<K, V>::set(const key_type &key, const value_type &value) {
_producer.load()->insert_or_assign(key, value);
}
template <typename K, typename V>
void ReducingParamQueue<K, V>::setOrUpdate(const key_type &key, const value_type &value) {
auto prod = _producer.load();
auto res = prod->insert({key, value});
if (!res.second && res.first != prod->end())
res.first->second.update(value);
}
template <typename K, typename V>
void ReducingParamQueue<K, V>::producerDone() {
if (_consumer)
return;
auto tmp = _producer.load();
_producer = _free.load();
_free = nullptr;
_consumer = tmp;
assert(_producer);
}
template <typename K, typename V>
void ReducingParamQueue<K, V>::consume(const consumer_type &consumer) {
assert(consumer);
if (!_consumer)
return;
for (auto &x : *_consumer)
consumer(x.first, x.second);
_consumer.load()->clear();
if (_free)
return;
_free = _consumer.load();
_consumer = nullptr;
}
}} // namespace clap::helpers

View File

@ -1,2 +0,0 @@
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>

View File

@ -1,18 +0,0 @@
#include <clap/helpers/param-queue.hh>
#include <clap/helpers/plugin.hh>
#include <clap/helpers/plugin.hxx>
#include <clap/helpers/reducing-param-queue.hh>
#include <clap/helpers/reducing-param-queue.hxx>
#include <catch2/catch.hpp>
CATCH_TEST_CASE("Plugin - Link") {
clap::helpers::Plugin<clap::helpers::MisbehaviourHandler::Terminate,
clap::helpers::CheckingLevel::Maximal> *p0 = nullptr;
clap::helpers::Plugin<clap::helpers::MisbehaviourHandler::Terminate,
clap::helpers::CheckingLevel::Minimal> *p1 = nullptr;
clap::helpers::Plugin<clap::helpers::MisbehaviourHandler::Terminate,
clap::helpers::CheckingLevel::None> *p2 = nullptr;
clap::helpers::Plugin<clap::helpers::MisbehaviourHandler::Ignore,
clap::helpers::CheckingLevel::Maximal> *p3 = nullptr;
}

View File

@ -1,137 +0,0 @@
---
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

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

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

View File

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

@ -1,12 +0,0 @@
; 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

@ -1,64 +0,0 @@
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

@ -1,40 +0,0 @@
{
"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

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

@ -1,25 +0,0 @@
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

@ -1,21 +0,0 @@
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

@ -1,138 +0,0 @@
<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)

View File

@ -1,17 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,12 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 833 B

View File

@ -1,9 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 794 B

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

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

@ -1,62 +0,0 @@
/*
* 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

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

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

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

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

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

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

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

Some files were not shown because too many files have changed in this diff Show More