From 9e0e4562d72549a73c7d6c6530487c587ca73e77 Mon Sep 17 00:00:00 2001 From: hanez Date: Tue, 27 Oct 2026 17:34:46 +0100 Subject: [PATCH] Phase 31: add CLAP, VST2 and VST3 mono effect hosting --- .gitattributes | 2 + Makefile | 31 +- README.md | 8 + docs/BUILD.md | 7 + docs/KNOWN_LIMITATIONS.md | 10 +- docs/LICENSES.md | 19 +- docs/PLUGIN_HOSTING.md | 53 + docs/PROJECT_FORMAT.md | 46 +- docs/RECOVERY.md | 11 +- docs/RELEASE_NOTES.md | 10 +- docs/ROADMAP.md | 39 + docs/USER_MANUAL.md | 8 + docs/decisions/0010-modern-plugin-effects.md | 42 + include/xtc/xtc.h | 3 + include/xtc/xtc_plugin.h | 19 +- include/xtc/xtc_project.h | 2 +- packaging/xtc.pc.in | 2 +- src/core/xtc.c | 2 +- src/graph/graph.c | 3 +- src/gui/main.cpp | 2 +- src/gui/main_window.cpp | 17 +- src/gui/plugin_dialog.cpp | 6 +- src/main.c | 5 +- src/persistence/project_file.c | 7 + src/plugin/host.c | 108 + src/plugin/ladspa.c | 51 +- src/plugin/modern.c | 315 ++ src/plugin/modern.h | 8 + src/plugin/vst2_abi.h | 26 + tests/fixtures/README.md | 2 +- tests/fixtures/project-v11.xtc | 39 + tests/integration/test_gui.cpp | 26 +- tests/integration/test_install.py | 4 +- tests/integration/test_modern_plugins.c | 116 + tests/integration/test_portability.c | 4 +- tests/integration/test_project_inspection.py | 31 +- tests/plugins/clap_fixture.c | 78 + tests/plugins/vst2_fixture.c | 34 + tests/plugins/vst3_fixture.c | 72 + tests/unit/test_project_diagnostics.c | 4 +- third_party/README.md | 20 + third_party/clap/LICENSE | 21 + third_party/clap/include/clap/all.h | 25 + third_party/clap/include/clap/audio-buffer.h | 37 + third_party/clap/include/clap/clap.h | 64 + third_party/clap/include/clap/color.h | 20 + third_party/clap/include/clap/entry.h | 136 + third_party/clap/include/clap/events.h | 367 ++ third_party/clap/include/clap/ext/ambisonic.h | 63 + .../include/clap/ext/audio-ports-activation.h | 64 + .../include/clap/ext/audio-ports-config.h | 109 + .../clap/include/clap/ext/audio-ports.h | 116 + .../clap/ext/configurable-audio-ports.h | 63 + .../clap/include/clap/ext/context-menu.h | 167 + .../clap/ext/draft/background-activation.h | 45 + .../clap/ext/draft/background-progress.h | 51 + .../clap/ext/draft/background-state-context.h | 44 + .../clap/ext/draft/extensible-audio-ports.h | 33 + .../include/clap/ext/draft/flush-events.h | 48 + .../clap/ext/draft/gain-adjustment-metering.h | 34 + .../clap/ext/draft/mini-curve-display.h | 153 + .../include/clap/ext/draft/octave-number.h | 30 + .../include/clap/ext/draft/param-hovered.h | 29 + .../include/clap/ext/draft/params-origin.h | 61 + .../include/clap/ext/draft/project-location.h | 108 + .../clap/ext/draft/resource-directory.h | 88 + .../include/clap/ext/draft/scratch-memory.h | 90 + .../clap/ext/draft/transport-control.h | 75 + .../clap/include/clap/ext/draft/triggers.h | 144 + .../clap/include/clap/ext/draft/tuning.h | 76 + .../clap/include/clap/ext/draft/undo.h | 201 + .../clap/include/clap/ext/draft/webview.h | 77 + .../clap/include/clap/ext/event-registry.h | 22 + third_party/clap/include/clap/ext/gui.h | 249 ++ third_party/clap/include/clap/ext/latency.h | 27 + third_party/clap/include/clap/ext/log.h | 33 + third_party/clap/include/clap/ext/note-name.h | 37 + .../clap/include/clap/ext/note-ports.h | 79 + .../clap/include/clap/ext/param-indication.h | 77 + third_party/clap/include/clap/ext/params.h | 386 ++ .../clap/include/clap/ext/posix-fd-support.h | 49 + .../clap/include/clap/ext/preset-load.h | 53 + .../clap/include/clap/ext/remote-controls.h | 83 + third_party/clap/include/clap/ext/render.h | 39 + .../clap/include/clap/ext/state-context.h | 72 + third_party/clap/include/clap/ext/state.h | 45 + third_party/clap/include/clap/ext/surround.h | 86 + third_party/clap/include/clap/ext/tail.h | 26 + .../clap/include/clap/ext/thread-check.h | 83 + .../clap/include/clap/ext/thread-pool.h | 66 + .../clap/include/clap/ext/timer-support.h | 31 + .../clap/include/clap/ext/track-info.h | 66 + .../clap/include/clap/ext/voice-info.h | 56 + .../clap/factory/draft/plugin-invalidation.h | 47 + .../factory/draft/plugin-state-converter.h | 99 + .../include/clap/factory/plugin-factory.h | 43 + .../include/clap/factory/preset-discovery.h | 313 ++ third_party/clap/include/clap/fixedpoint.h | 16 + third_party/clap/include/clap/host.h | 51 + third_party/clap/include/clap/id.h | 8 + .../clap/include/clap/plugin-features.h | 79 + third_party/clap/include/clap/plugin.h | 114 + .../clap/include/clap/private/macros.h | 50 + third_party/clap/include/clap/private/std.h | 16 + third_party/clap/include/clap/process.h | 66 + third_party/clap/include/clap/stream.h | 38 + third_party/clap/include/clap/string-sizes.h | 21 + third_party/clap/include/clap/timestamp.h | 11 + .../clap/include/clap/universal-plugin-id.h | 26 + third_party/clap/include/clap/version.h | 42 + third_party/vst3/LICENSE.txt | 27 + third_party/vst3/vst3_c_api.h | 3777 +++++++++++++++++ tools/analyze.py | 2 + tools/install_layout.py | 2 + 114 files changed, 10369 insertions(+), 75 deletions(-) create mode 100644 .gitattributes create mode 100644 docs/decisions/0010-modern-plugin-effects.md create mode 100644 src/plugin/host.c create mode 100644 src/plugin/modern.c create mode 100644 src/plugin/modern.h create mode 100644 src/plugin/vst2_abi.h create mode 100644 tests/fixtures/project-v11.xtc create mode 100644 tests/integration/test_modern_plugins.c create mode 100644 tests/plugins/clap_fixture.c create mode 100644 tests/plugins/vst2_fixture.c create mode 100644 tests/plugins/vst3_fixture.c create mode 100644 third_party/README.md create mode 100644 third_party/clap/LICENSE create mode 100644 third_party/clap/include/clap/all.h create mode 100644 third_party/clap/include/clap/audio-buffer.h create mode 100644 third_party/clap/include/clap/clap.h create mode 100644 third_party/clap/include/clap/color.h create mode 100644 third_party/clap/include/clap/entry.h create mode 100644 third_party/clap/include/clap/events.h create mode 100644 third_party/clap/include/clap/ext/ambisonic.h create mode 100644 third_party/clap/include/clap/ext/audio-ports-activation.h create mode 100644 third_party/clap/include/clap/ext/audio-ports-config.h create mode 100644 third_party/clap/include/clap/ext/audio-ports.h create mode 100644 third_party/clap/include/clap/ext/configurable-audio-ports.h create mode 100644 third_party/clap/include/clap/ext/context-menu.h create mode 100644 third_party/clap/include/clap/ext/draft/background-activation.h create mode 100644 third_party/clap/include/clap/ext/draft/background-progress.h create mode 100644 third_party/clap/include/clap/ext/draft/background-state-context.h create mode 100644 third_party/clap/include/clap/ext/draft/extensible-audio-ports.h create mode 100644 third_party/clap/include/clap/ext/draft/flush-events.h create mode 100644 third_party/clap/include/clap/ext/draft/gain-adjustment-metering.h create mode 100644 third_party/clap/include/clap/ext/draft/mini-curve-display.h create mode 100644 third_party/clap/include/clap/ext/draft/octave-number.h create mode 100644 third_party/clap/include/clap/ext/draft/param-hovered.h create mode 100644 third_party/clap/include/clap/ext/draft/params-origin.h create mode 100644 third_party/clap/include/clap/ext/draft/project-location.h create mode 100644 third_party/clap/include/clap/ext/draft/resource-directory.h create mode 100644 third_party/clap/include/clap/ext/draft/scratch-memory.h create mode 100644 third_party/clap/include/clap/ext/draft/transport-control.h create mode 100644 third_party/clap/include/clap/ext/draft/triggers.h create mode 100644 third_party/clap/include/clap/ext/draft/tuning.h create mode 100644 third_party/clap/include/clap/ext/draft/undo.h create mode 100644 third_party/clap/include/clap/ext/draft/webview.h create mode 100644 third_party/clap/include/clap/ext/event-registry.h create mode 100644 third_party/clap/include/clap/ext/gui.h create mode 100644 third_party/clap/include/clap/ext/latency.h create mode 100644 third_party/clap/include/clap/ext/log.h create mode 100644 third_party/clap/include/clap/ext/note-name.h create mode 100644 third_party/clap/include/clap/ext/note-ports.h create mode 100644 third_party/clap/include/clap/ext/param-indication.h create mode 100644 third_party/clap/include/clap/ext/params.h create mode 100644 third_party/clap/include/clap/ext/posix-fd-support.h create mode 100644 third_party/clap/include/clap/ext/preset-load.h create mode 100644 third_party/clap/include/clap/ext/remote-controls.h create mode 100644 third_party/clap/include/clap/ext/render.h create mode 100644 third_party/clap/include/clap/ext/state-context.h create mode 100644 third_party/clap/include/clap/ext/state.h create mode 100644 third_party/clap/include/clap/ext/surround.h create mode 100644 third_party/clap/include/clap/ext/tail.h create mode 100644 third_party/clap/include/clap/ext/thread-check.h create mode 100644 third_party/clap/include/clap/ext/thread-pool.h create mode 100644 third_party/clap/include/clap/ext/timer-support.h create mode 100644 third_party/clap/include/clap/ext/track-info.h create mode 100644 third_party/clap/include/clap/ext/voice-info.h create mode 100644 third_party/clap/include/clap/factory/draft/plugin-invalidation.h create mode 100644 third_party/clap/include/clap/factory/draft/plugin-state-converter.h create mode 100644 third_party/clap/include/clap/factory/plugin-factory.h create mode 100644 third_party/clap/include/clap/factory/preset-discovery.h create mode 100644 third_party/clap/include/clap/fixedpoint.h create mode 100644 third_party/clap/include/clap/host.h create mode 100644 third_party/clap/include/clap/id.h create mode 100644 third_party/clap/include/clap/plugin-features.h create mode 100644 third_party/clap/include/clap/plugin.h create mode 100644 third_party/clap/include/clap/private/macros.h create mode 100644 third_party/clap/include/clap/private/std.h create mode 100644 third_party/clap/include/clap/process.h create mode 100644 third_party/clap/include/clap/stream.h create mode 100644 third_party/clap/include/clap/string-sizes.h create mode 100644 third_party/clap/include/clap/timestamp.h create mode 100644 third_party/clap/include/clap/universal-plugin-id.h create mode 100644 third_party/clap/include/clap/version.h create mode 100644 third_party/vst3/LICENSE.txt create mode 100644 third_party/vst3/vst3_c_api.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..01ce234 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Retain upstream header/license snapshots byte-for-byte. +third_party/** -whitespace diff --git a/Makefile b/Makefile index ba8c339..99be9ae 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ CXXFLAGS ?= -O2 -g CXXFLAGS += -std=c++17 -Wall -Wextra -Wpedantic -Iinclude LDFLAGS ?= -CORE_SOURCES := src/control/model.c src/audio/waveform.c src/plugin/ladspa.c src/native/processor.c src/audio/recovery.c src/dsp/ramp.c src/native/native.c src/mixer/model.c src/mixer/render.c src/project/history.c src/midi/model.c src/midi/instrument.c src/audio/wave.c src/audio/arrangement.c src/audio/recorder.c src/core/xtc.c src/project/project.c src/persistence/project_file.c src/graph/graph.c src/dsp/gain.c src/engine/offline_engine.c src/engine/realtime.c src/backend/jack_backend.c +CORE_SOURCES := src/control/model.c src/audio/waveform.c src/plugin/ladspa.c src/plugin/host.c src/plugin/modern.c src/native/processor.c src/audio/recovery.c src/dsp/ramp.c src/native/native.c src/mixer/model.c src/mixer/render.c src/project/history.c src/midi/model.c src/midi/instrument.c src/audio/wave.c src/audio/arrangement.c src/audio/recorder.c src/core/xtc.c src/project/project.c src/persistence/project_file.c src/graph/graph.c src/dsp/gain.c src/engine/offline_engine.c src/engine/realtime.c src/backend/jack_backend.c JACK_AVAILABLE := $(shell $(PKG_CONFIG) --exists jack 2>/dev/null && echo yes) ifeq ($(JACK_AVAILABLE),yes) JACK_CFLAGS := $(shell $(PKG_CONFIG) --cflags jack) @@ -461,3 +461,32 @@ test-stress-plugins: $(BUILD_DIR)/test_realtime $(BUILD_DIR)/test_reliability $( .PHONY: test-install-layout test-install-layout: all $(if $(GUI_AVAILABLE),gui) $(PYTHON) tests/integration/test_install.py --build-dir "$(abspath $(BUILD_DIR))" --custom-layout $(if $(GUI_AVAILABLE),--gui) + +$(BUILD_DIR)/src/plugin/modern.o: override CPPFLAGS += -isystem third_party/clap/include -isystem third_party/vst3 + +$(BUILD_DIR)/clap-fixture.clap: tests/plugins/clap_fixture.c + @mkdir -p $(@D) + $(CC) $(CPPFLAGS) $(CFLAGS) -isystem third_party/clap/include $(LDFLAGS) -fPIC -shared -o $@ $< +$(BUILD_DIR)/vst2-fixture.so: tests/plugins/vst2_fixture.c src/plugin/vst2_abi.h + @mkdir -p $(@D) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -fPIC -shared -o $@ $< +$(BUILD_DIR)/vst3-fixture.so: tests/plugins/vst3_fixture.c + @mkdir -p $(@D) + $(CC) $(CPPFLAGS) $(CFLAGS) -isystem third_party/vst3 $(LDFLAGS) -fPIC -shared -o $@ $< +$(BUILD_DIR)/test_modern_plugins: $(BUILD_DIR)/tests/integration/test_modern_plugins.o $(BUILD_DIR)/libxtc.a + $(CC) $(LDFLAGS) -o $@ $^ -lm -ldl -Wl,--wrap=malloc,--wrap=calloc,--wrap=realloc,--wrap=free,--wrap=dlopen,--wrap=dlclose +.PHONY: test-modern-plugins +test-modern-plugins: $(BUILD_DIR)/test_modern_plugins $(BUILD_DIR)/clap-fixture.clap $(BUILD_DIR)/vst2-fixture.so $(BUILD_DIR)/vst3-fixture.so + ./$(BUILD_DIR)/test_modern_plugins "$(abspath $(BUILD_DIR))/clap-fixture.clap" "$(abspath $(BUILD_DIR))/vst2-fixture.so" "$(abspath $(BUILD_DIR))/vst3-fixture.so" +test: test-modern-plugins +-include $(BUILD_DIR)/tests/integration/test_modern_plugins.d + +.PHONY: test-gui-modern-plugins +ifeq ($(GUI_AVAILABLE),yes) +test-gui-modern-plugins: $(BUILD_DIR)/test_gui $(BUILD_DIR)/clap-fixture.clap $(BUILD_DIR)/vst2-fixture.so $(BUILD_DIR)/vst3-fixture.so + XTC_TEST_CLAP="$(abspath $(BUILD_DIR))/clap-fixture.clap" XTC_TEST_VST2="$(abspath $(BUILD_DIR))/vst2-fixture.so" XTC_TEST_VST3="$(abspath $(BUILD_DIR))/vst3-fixture.so" xvfb-run -a -s "-screen 0 1280x800x24" ./$(BUILD_DIR)/test_gui +else +test-gui-modern-plugins: + @echo "FLTK development files are required for modern plugin GUI tests." + @exit 1 +endif diff --git a/README.md b/README.md index 5e8a344..1e193d7 100644 --- a/README.md +++ b/README.md @@ -161,3 +161,11 @@ or starting JACK. Exit codes: 0 = valid metadata and available files, 2 = missin or unreadable references, 1 = metadata/I/O error. File availability does not certify WAV contents or plugin compatibility. See [PROJECT_FORMAT.md](docs/PROJECT_FORMAT.md) for the compatibility and relocation policy. + +Phase 31: **File → Load plugin** supports LADSPA plus an initial Linux +CLAP/VST2/VST3 effect subset. Select the actual module binary (`.clap` or `.so`, +including a VST3 bundle's inner binary). Modern effects require one mono input +and output, float32 and zero latency; they use default configuration. Instruments, +modern parameter editing/automation, opaque state and custom editors are not +implemented. Projects now save v11 and read v1–v11. See PLUGIN_HOSTING.md for the +full contract and test/qualification limits. diff --git a/docs/BUILD.md b/docs/BUILD.md index 5d48d59..8fb6cb5 100644 --- a/docs/BUILD.md +++ b/docs/BUILD.md @@ -272,3 +272,10 @@ removal. Override `PREFIX`, `exec_prefix`, `bindir`, `libdir`, `includedir`, `datarootdir`, `datadir`, `docdir`, `pkgconfigdir`, `licensedir`, `examplesdir` or `desktopdir` as needed. `DESTDIR` adds staging separately; pass the same layout to uninstall. See RELEASING.md for commands and RELEASE_NOTES.md for upgrades. + +Phase 31 modern plugin adapters build in C99 using the pinned header-only CLAP +and VST3 C APIs under third_party; there is no network build or SDK runtime. +VST2 compatibility uses original ABI declarations. `make test-modern-plugins` +runs original shared-library fixtures without a server; `make test-gui-modern-plugins` +adds GUI/browser/undo/reopen tests under Xvfb. The fixtures also run in `make test` +and therefore in sanitizer/release builds. Notices are installed with LICENSE. diff --git a/docs/KNOWN_LIMITATIONS.md b/docs/KNOWN_LIMITATIONS.md index ede5e6a..e6892cb 100644 --- a/docs/KNOWN_LIMITATIONS.md +++ b/docs/KNOWN_LIMITATIONS.md @@ -22,7 +22,7 @@ plus baseline and at most one reserved metadata snapshot; GUI edits reserve history before mutation/publication. Media is never removed by undo/delete. Broad screen-reader/accessibility testing is pending. -- Format v10 reads v1–v9 and uses relative local media references. External absolute +- Format v11 reads v1–v10 and uses relative local media references. External absolute media/module paths need manual repair after relocation. Saving does not bundle media; missing media stays referenced, missing plugins reject GUI installation. Unknown data is rejected rather than stripped. Post-rename directory-sync errors @@ -73,3 +73,11 @@ The project format is Linux/POSIX oriented; absolute plugin paths, architecture, ABI and JACK/device configuration must be supplied on another system. Unknown fields are rejected, not preserved. See PROJECT_FORMAT.md for versions 1–10 and RECOVERY.md for save failures after rename. + +Phase 31 CLAP/VST2/VST3 loading supports Linux binary modules, one-input mono +float32 zero-latency effects at default configuration. No modern parameter edit, +automation, programs, opaque state, MIDI/instruments, transport, custom editor, +workers, sidechains or true stereo/multichannel buses are implemented. Plugin +bundles must be opened at their actual Linux shared-library binary. Only original +ABI fixtures are qualified; arbitrary third-party modern plugins remain untested. +See PLUGIN_HOSTING.md and decision 0010 for lifecycle and licensing boundaries. diff --git a/docs/LICENSES.md b/docs/LICENSES.md index 9e0a617..b64d3a5 100644 --- a/docs/LICENSES.md +++ b/docs/LICENSES.md @@ -2,7 +2,8 @@ The repository's original code, example and documentation are under the MIT license in LICENSE (copyright Johannes Findeisen). No energyXT source, artwork, -external plugin SDK, vendored DSP or binary asset is included. The source archive +proprietary SDK, vendored DSP or plugin binary is included. Phase 31 vendors +permissively licensed ABI headers with their own notices. The source archive contains repository files and an export manifest; it does not bundle system libraries. Installation includes LICENSE and these documents. @@ -54,3 +55,19 @@ GPL-2.0-or-later). Testing/loading a user-installed module does not grant the ri to bundle or relicense it. Redistributors must review each chosen module and the combined distribution's obligations separately; xtc's MIT grant covers only its original code. No third-party plugin is included in source archives or installs. + +## Phase 31 pinned header dependencies + +CLAP headers are MIT, copyright Alexandre BIQUE, from upstream commit +`a47f6badb49d948fd009998f28309cdab78979c9`. The generated VST3 C ABI header is +BSD-3-Clause, copyright Steinberg Media Technologies GmbH, from commit +`93a116f7c6c52a317ec3aaee9b13789068b5234e`. Exact licenses are retained under +third_party and installed as CLAP-LICENSE / VST3-C-API-LICENSE. These are header +specifications only: no external runtime SDK or network build step was added. +Review updates explicitly; do not assume future revisions share the same license. + +The VST2 compatibility declarations and all three ABI fixtures are original MIT +repository code; no Steinberg VST2 SDK or third-party plugin is bundled. Hosting +an installed binary is distinct from SDK, trademark and plugin redistribution +rights. Review those separately for any proposed distribution. Source archives +retain upstream notices; binary installs also ship both header licenses. diff --git a/docs/PLUGIN_HOSTING.md b/docs/PLUGIN_HOSTING.md index 3bf46eb..6462b82 100644 --- a/docs/PLUGIN_HOSTING.md +++ b/docs/PLUGIN_HOSTING.md @@ -204,3 +204,56 @@ live-sine CC maps without changing plugin state records. Direct static edits do not override existing lanes. Live CCs do not map to plugins; missing targets or modules fail without installing partial state. See CONTROL.md for timing, precedence, reset and backward-jump behavior. + +## Phase 31: CLAP, VST2 and VST3 effect loaders + +**File → Load plugin** now detects LADSPA, CLAP, VST2 and VST3 entry points in an +explicit trusted Linux module. **Insert plugin on selected wire** and **Replace +selected plugin** use the same browser and transactional graph preparation. The +identity/editor dialog names the format and stable ID. Existing LADSPA controls +and automation continue to work. Modern effects currently use their default +configuration: the editor shows identity but no editable parameters. + +Choose the actual binary: `.clap` for CLAP, a VST2 `.so` exporting `VSTPluginMain`, +or a VST3 bundle's `Contents/-linux/.so` exporting +`ModuleEntry`, `ModuleExit` and `GetPluginFactory`. The chooser does not resolve +bundle directories or recursively scan plugin folders. On Linux this avoids +executing unrelated plugins just to discover one selected module. Auto-detection +prefers CLAP, then VST2, then VST3, otherwise LADSPA; the C API also provides +`xtc_plugin_probe_format` for an explicit format. + +The modern subset is **one mono audio input and one mono output, float32, default +configuration, zero reported latency**. Stereo graph playback uses independent +instances. True stereo/multichannel/sidechain buses, instruments, MIDI/events, +custom editors, parameter changes/automation, programs/presets, opaque state, +transport/time information, workers and latency compensation are not implemented +for these three formats. Modern metadata with controls/automation is rejected, +not silently ignored. VST3 event buses and CLAP note ports are rejected. Plugins +requiring unsupported host extensions may refuse initialization. This is not a +claim that all CLAP/VST2/VST3 plugins will load or sound identically after updates. + +Only original effect fixtures have been qualified for the new formats. Trusted +plugin code is in-process and can crash/hang or violate realtime rules. No plugin +binary is included in packages. A VST2 ABI adapter does not provide rights to the +discontinued SDK or plugin redistribution. See decision 0010 and LICENSES.md. + +The control/main thread owns discovery, activation, module reference accounting, +retirement and unloading. CLAP's start-processing call runs on the audio owner; +main-thread callbacks are coalesced and serviced via `xtc_plugin_idle` (GUI timer, +currently 100 ms). C hosts using CLAP must pump that API on their serialized main +thread while instances live, and stop/join audio before destruction. Restart and +VST2 I/O-change requests make subsequent blocks fail/silence; stop and rebuild or +reload the plugin rather than reconfiguring inside the callback. CLAP process +errors and VST3 failure results silence a block. VST2 has no process error return. + +```sh +make all test gui test-modern-plugins test-gui-modern-plugins +make test-sanitize analyze +``` + +Original CLAP/VST2/VST3 shared-library fixtures exercise exact in-place and stereo +processing, entry/instance lifetimes, rejected layouts, partial initialization, +CLAP start/process failures, graph replacement rollback, 50 plan retirements per +format, missing modules, v11 save/reopen and GUI add/browser/undo/reopen. Host +allocation/loading/unloading guards remain active while rendering. This evidence +qualifies the subset above, not arbitrary external plugins or physical audio. diff --git a/docs/PROJECT_FORMAT.md b/docs/PROJECT_FORMAT.md index a59fdf4..8ef1381 100644 --- a/docs/PROJECT_FORMAT.md +++ b/docs/PROJECT_FORMAT.md @@ -1,6 +1,6 @@ -# Project format v10 (reads v1–v9) +# Project format v11 (reads v1–v10) -Phases 5–28 use a bounded text format implemented in C99 without a parser library. +Phases 5–31 use a bounded text format implemented in C99 without a parser library. The extension is `.xtc`. File operations run exclusively on the control thread. The project owns its graph, tracks and silent/audio arrangement regions. Audio samples remain in external WAV files; MIDI notes are stored inline. @@ -12,7 +12,7 @@ Fields use ASCII spaces. Integers are unsigned decimal, without signs. Counts determine the number of subsequent records: ```text -XTC_PROJECT 10 +XTC_PROJECT 11 APP 0 1 0 TEMPO 120000 IDS 1 1 @@ -104,8 +104,8 @@ node types 1..4, migrating their clips to empty asset paths. Version 2 accepts node types 1..5 and ASSET records. Both migrate to MIDI=0 and no notes. Version 3 accepts instrument nodes and MIDI/NOTES records. Versions 1–3 migrate all tracks to unity gain, centered pan, mute/solo off and no automation. -Saving always writes v10. Unknown versions are rejected without replacing the destination; older -applications without v10 support cannot read current saves. Migration and maximum-path roundtrips are tested. +Saving always writes v11. Unknown versions are rejected without replacing the destination; older +applications without v11 support cannot read current saves. Migration and maximum-path roundtrips are tested. ## Ownership and failures @@ -254,7 +254,7 @@ v9 exact roundtrips and malformed routing. ## Phase 26: version 10 interpolation and controller bindings -The current writer emits v10 and reads v1–v9. Track/bus automation points are +Phase 26 introduced v10 with migration from v1–v9. Track/bus automation points are `POINT track_id parameter tick value_bits step`, where step is 0 linear or 1 hold for the segment starting there. v1–v9 points migrate to step=0. LADSPA `PARAM` encoding remains unchanged (already has interpolation mode). @@ -274,8 +274,8 @@ must rebuild and initialize the appended `xtc_automation_point.step` field. ## Phase 28 compatibility and diagnostic contract -The current reader accepts versions 1–10 and the writer always emits version 10. -There is no format change in Phase 28. Saving an older document upgrades it; +The current reader accepts versions 1–11 and the writer always emits version 11. +Phase 28 made no format change; Phase 31 adds plugin format identity in v11. Saving an older document upgrades it; retain an original backup if an older application must still open it. APP is informational; compatibility depends on the format version, not the producer's application version. A future incompatible schema requires a new format number. @@ -337,3 +337,33 @@ preserve the old bytes and remove the temporary. After rename, a sync failure reports I/O while leaving a complete new document; inspect it before retrying. Fault wrappers are linked into tests only. These tests complement killed-writer coverage in `make test-recovery`; they do not qualify power-cut behavior. + +## Phase 31: version 11 plugin format identity + +Immediately after every plugin MODULE record, v11 requires: + +```text +FORMAT format_number hex_identity_or_dash +``` + +0 = LADSPA, 1 = CLAP, 2 = VST2, 3 = VST3. Identity is `-` for LADSPA/VST2; +CLAP uses its stable plugin ID (1–127 non-NUL bytes); VST3 uses the 32-character lowercase +hex class ID string, itself hex-encoded like other byte strings. PLUGIN's unique +ID remains the VST2/LADSPA integer ID (zero for CLAP/VST3), descriptor index and +label. MODULE is still the actual absolute binary path. Versions 1–10 migrate +to format 0 and empty extra identity. Older readers reject v11. The public plugin +struct has grown; C/C++ consumers must rebuild and initialize it to zero. + +Modern adapters accept one-input mono effects, default configuration only, with +zero controls and automation points. Unsupported modern control metadata is +rejected, not discarded. State/editor/preset changes are not exposed, so no opaque +state is serialized. Reloading recreates plugin defaults, which can change after +a plugin update or with its external configuration. Matching ID/name/layout is +not a binary hash or sound-reproducibility guarantee. See PLUGIN_HOSTING.md. + +Metadata validation and inspection never initialize modules. Actual graph +preparation verifies format, descriptor, stable identity, name and layout before +publishing. Missing module metadata survives C load/save; GUI preparation retains +the existing document on failure. No automatic path search or plugin substitution +occurs. Current and historical migration fixtures, malformed fields, identity +mismatch, missing-module and exact-render roundtrips cover this extension. diff --git a/docs/RECOVERY.md b/docs/RECOVERY.md index cb1cc2b..5e337b7 100644 --- a/docs/RECOVERY.md +++ b/docs/RECOVERY.md @@ -1,6 +1,6 @@ # Persistence and failure recovery -The project format is v10. Readers migrate v1–v9, validate bounded input +The project format is v11. Readers migrate v1–v10, validate bounded input and atomically install a candidate only after complete success. Existing tests cover exact migration/roundtrip, truncations, malformed references, counts, IDs, nonfinite values and failed GUI/backend installation. Native processors @@ -87,5 +87,12 @@ rename and directory-sync errors. Pre-rename failures retain the previous bytes and clean temporary files. Post-rename sync errors leave a complete new file and return failure; there is no rollback after replacement. Load diagnostics identify the expected record and syntax line, or line zero for whole-model/I/O stages. -Unknown versions report the supported range (1–10); unknown records/fields are +Unknown versions report the supported range (1–11); unknown records/fields are rejected without partially changing the current project. + +Modern CLAP/VST2/VST3 module identity is preserved in v11 metadata even when the +binary is unavailable. Restore the compatible saved binary path and retry Open. +CLAP restart and VST2 I/O-change requests fail/silence subsequent blocks; stop +and rebuild/reload rather than attempting callback-time reconfiguration. Modern +instances restart at default configuration; no edited opaque state is exposed +or saved by the initial adapters. Trusted plugin crashes cannot be contained. diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md index cf76236..497e4df 100644 --- a/docs/RELEASE_NOTES.md +++ b/docs/RELEASE_NOTES.md @@ -15,7 +15,7 @@ undo/redo and a generic LADSPA editor. JACK is the only live audio/MIDI backend; core validation and offline rendering work without it. Native/LADSPA processors are trusted in-process code. No proprietary energyXT resources are included. -Project format v10 reads versions 1–10 transactionally. Syntax diagnostics identify +Project format v11 reads versions 1–11 transactionally. Syntax diagnostics identify records and lines. `xtc-check --inspect` lists dependency paths without executing plugins. Phase 29 adds timing/CPU/RSS reports, repeatable stress runs and virtual endurance. Phase 30 adds configurable install directories, shared install/remove @@ -24,7 +24,7 @@ inventory, installed MIDI examples and source archive checksum sidecars. ## Upgrading and removal Back up documents and external media before upgrading. Opening an older project -does not rewrite it; saving upgrades it to v10, which older readers may reject. +does not rewrite it; saving upgrades it to v11, which older readers may reject. Use Save As for a separate migrated copy. Moving a project folder preserves media stored inside it via relative references. Absolute media and plugin module paths must be restored separately. There is no bundled plugin/media migration or saved @@ -51,3 +51,9 @@ the shared development host; the project timing comparison passed. This alert was not hidden by changing the baseline. See PERFORMANCE.md before using these measurements as latency expectations. Sanitizers and virtual endurance qualify software paths, not hardware timing. + +Phase 31 adds default-configuration CLAP/VST2/VST3 mono effect loaders, common +GUI discovery/insertion/replacement and v11 format identity. Pinned MIT CLAP and +BSD-3-Clause VST3 C headers ship with notices; VST2 uses original compatibility +declarations. Modern instruments, parameters/state/editors and multichannel +layouts remain unsupported. No third-party modern plugin has been qualified. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index c1d486f..78e986a 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -860,6 +860,45 @@ byte-identical binaries and repacks; and binary manifest/hash/relocation checks. No public release, tag, version bump or system install is performed. Physical qualification and the Phase 29 graph timing alert remain documented limitations. +## Phase 31 — CLAP, VST2 and VST3 Plugin Loading + +### Goal +Load trusted Linux CLAP, VST2 and VST3 audio effects through the graph and GUI, +with explicit lifecycle, format compatibility and realtime ownership contracts. + +### Tasks +- Review and pin redistributable ABI headers and license notices; keep C99 adapters. +- Add explicit format probing and compatible mono float32 effect initialization. +- Integrate processing, immutable plans, retirement and failure rollback. +- Share module entry lifetimes across overlapping instances; defer main-thread callbacks. +- Add format/stable identity metadata with v11 migration and missing-module retention. +- Generalize the GUI browser, insertion/replacement and identity presentation. +- Test original fixtures for all three ABIs, partial failure cleanup, callback safety, + save/reopen, missing dependencies and GUI lifecycle. +- Document the initial default-configuration effect subset and unsupported extensions. + +### Acceptance criteria +- Compatible fixtures for all three formats render exact expected audio in graphs. +- Failed loading/identity/layout/initialization retains the current project/plan. +- Loading and reclamation remain off the audio callback, with bounded host processing. +- Project files preserve identity and missing references without executing plugins. +- Core/GUI builds, regressions, sanitizers and release installation checks pass. + +### Implementation status +Implemented in C99 with pinned permissive ABI headers, shared entry lifetimes, +CLAP main-thread scheduling, graph/GUI integration and v11 plugin identity. +Normal/minimal builds, core and GUI plugin fixtures, live JACK/workflow, +ASan/UBSan core and GUI checks, static analysis, staged installation and +source/binary release checks pass. Tests include activation/start/process and +restart errors, rejected layouts/identities, missing modules and retirement. +GUI leak checking retains only the existing Fontconfig suppression; core checks +use none. Only original ABI fixtures are qualified; arbitrary third-party plugins +and physical audio remain unverified. See PLUGIN_HOSTING.md and decision 0010. + +The initial subset excludes instruments/events, editable modern parameters, +opaque state/custom editors, true stereo/multichannel and latency compensation. +These require separate future work; they are not claimed as implemented by loading. + --- ## Recommended Execution Order diff --git a/docs/USER_MANUAL.md b/docs/USER_MANUAL.md index 46807a5..868b2a4 100644 --- a/docs/USER_MANUAL.md +++ b/docs/USER_MANUAL.md @@ -160,3 +160,11 @@ or starting JACK. Exit codes: 0 = valid metadata and available files, 2 = missin or unreadable references, 1 = metadata/I/O error. File availability does not certify WAV contents or plugin compatibility. See [PROJECT_FORMAT.md](PROJECT_FORMAT.md) for the compatibility and relocation policy. + +Phase 31: **File → Load plugin** supports LADSPA plus an initial Linux +CLAP/VST2/VST3 effect subset. Select the actual module binary (`.clap` or `.so`, +including a VST3 bundle's inner binary). Modern effects require one mono input +and output, float32 and zero latency; they use default configuration. Instruments, +modern parameter editing/automation, opaque state and custom editors are not +implemented. Projects now save v11 and read v1–v11. See PLUGIN_HOSTING.md for the +full contract and test/qualification limits. diff --git a/docs/decisions/0010-modern-plugin-effects.md b/docs/decisions/0010-modern-plugin-effects.md new file mode 100644 index 0000000..b825d8c --- /dev/null +++ b/docs/decisions/0010-modern-plugin-effects.md @@ -0,0 +1,42 @@ +# 0010 — Bounded CLAP, VST2 and VST3 effect loading + +Accepted for Phase 31. The user's request to support these three formats +supersedes the earlier recommendation to choose only one external format. + +Keep the engine/model/host adapters in C99. CLAP uses pinned MIT headers and VST3 +uses the upstream BSD-3-Clause generated C ABI. No SDK runtime library is needed; +Linux dynamic loading and POSIX thread identity are existing platform facilities. +VST2 uses original minimal compatibility declarations, not the discontinued SDK. +See third_party/README.md and LICENSES.md for exact revisions and notices. + +Reuse the existing plugin graph node, paired mono instances and immutable plan +ownership. The common facade routes LADSPA to its existing implementation and +modern formats to a separate adapter. This preserves LADSPA controls/automation +and metadata behavior. All three new adapters initially accept one mono input +and output, float32, zero reported latency and no event buses. Default plugin +configuration is used; no parameter/controller/editor or opaque-state access is +exposed. These are usable effect loaders, not complete implementations of every +extension in the formats. Unsupported layouts fail explicitly. + +Project v11 adds format plus CLAP stable ID or VST3 class ID to each saved plugin. +Older plugins migrate to LADSPA with an empty extra ID. VST2 retains its integer +unique ID. Reopening checks format/index/identity/name/layout; metadata operations +never open modules. This does not authenticate a binary or freeze defaults across +plugin releases. No modified opaque state exists in this initial API to persist. + +Discovery and instance creation execute trusted module code on one serialized +main/control thread. A module cache balances CLAP entry init/deinit and Linux +VST3 ModuleEntry/ModuleExit across overlapping graph instances and retired plans. +CLAP start_processing runs on the processing owner; stop_processing runs after +quiescence with the symbolic audio-thread context. CLAP callback requests use +lock-free flags and are serviced by xtc_plugin_idle on main/control (the GUI timer +calls it). Restart/I/O-change requests latch an error for re-preparation; the audio +callback does not reconfigure or wait for GUI work. CLAP process wakeups need no +queue because playback processes every block, including silence. + +Only preallocated buffers and plugin processing occur in audio. Error status +silences the failed block; nonfinite/subnormal samples are sanitized. Plugin code +can still allocate, block, corrupt memory or crash; there is no sandbox, scanner +subprocess or recoverable crash boundary. Modules unload only after destruction +on a quiescent/control owner. Real third-party plugins and hardware timing remain +unqualified; original ABI fixtures demonstrate the bounded contracts. diff --git a/include/xtc/xtc.h b/include/xtc/xtc.h index d45b432..724e5ff 100644 --- a/include/xtc/xtc.h +++ b/include/xtc/xtc.h @@ -11,6 +11,9 @@ extern "C" { typedef struct xtc_app xtc_app; #define XTC_FEATURE_JACK 1U #define XTC_FEATURE_LADSPA 2U +#define XTC_FEATURE_CLAP 4U +#define XTC_FEATURE_VST2 8U +#define XTC_FEATURE_VST3 16U /* Compile-time capabilities, no loading/server connection or I/O. */ unsigned int xtc_build_features(void); diff --git a/include/xtc/xtc_plugin.h b/include/xtc/xtc_plugin.h index 3d7f56e..8b2af37 100644 --- a/include/xtc/xtc_plugin.h +++ b/include/xtc/xtc_plugin.h @@ -4,6 +4,8 @@ #ifdef __cplusplus extern "C" { #endif +typedef enum { XTC_PLUGIN_LADSPA = 0, XTC_PLUGIN_CLAP, XTC_PLUGIN_VST2, XTC_PLUGIN_VST3 } xtc_plugin_format; +const char *xtc_plugin_format_name(xtc_plugin_format format); #define XTC_PLUGIN_CONTROLS 16U #define XTC_PLUGIN_POINTS 32U /* Absolute project ticks. Mode belongs to segment starting at this point: @@ -11,17 +13,21 @@ extern "C" { * sample rounding collides. Integer/toggle controls require mode 1. */ typedef struct { uint64_t tick; unsigned int port, step; float value; } xtc_plugin_point; /* Plain copied model: no library handles or callback pointers. Absolute trusted - * module path, descriptor index + unique ID + label checked again on compile. - * Controls are actual LADSPA port indices, in ascending order. */ + * binary path, format/index/integer or string identity/label verified on compile. + * Controls are LADSPA port indices; modern effects use default configuration + * with zero controls/points. Initialize the complete struct to zero. */ typedef struct { char path[512], label[64]; + xtc_plugin_format format; + char identifier[128]; /* CLAP stable ID / VST3 class hex; empty for LADSPA/VST2. */ unsigned int index, unique_id, inputs, control_count; unsigned int ports[XTC_PLUGIN_CONTROLS]; float values[XTC_PLUGIN_CONTROLS]; unsigned int tempo, point_count; /* milli-BPM, 20000..300000 */ xtc_plugin_point points[XTC_PLUGIN_POINTS]; } xtc_plugin_spec; -/* Copied discovery metadata, never descriptor/module pointers. LADSPA provides +/* Copied discovery metadata, never descriptor/module pointers. Modern adapters + * currently expose the name only (zero controls). LADSPA provides * no standardized units; unit is empty. Flags describe input control hints. */ #define XTC_PLUGIN_INTEGER 1U #define XTC_PLUGIN_TOGGLED 2U @@ -44,9 +50,14 @@ xtc_result xtc_plugin_reset(xtc_plugin_spec *spec, double rate, unsigned int por * are accepted, preserving all wires. Metadata-only; compile before adoption. */ xtc_result xtc_graph_replace_plugin(xtc_graph *graph, size_t id, const xtc_plugin_spec *spec); typedef struct xtc_plugin xtc_plugin; -/* Control thread only. Probe explicitly enumerates a file by descriptor index; +/* Serialized control/main thread: service CLAP callback requests. */ +void xtc_plugin_idle(void); +/* Serialized main/control thread only (also create/destroy/idle). Probe explicitly + * enumerates a Linux binary file by descriptor index; * NOT_FOUND means end, UNSUPPORTED means descriptor/layout unsupported. Loading * trusted libraries can execute arbitrary constructors. Never probe in audio. */ +xtc_result xtc_plugin_probe_format(xtc_plugin_format format, const char *path, unsigned int index, double rate, xtc_plugin_spec *out); +/* Auto-detect exported entry point; may execute module constructors. */ xtc_result xtc_plugin_probe(const char *path, unsigned int index, double rate, xtc_plugin_spec *out); /* Control-thread parameter names, computed ranges/defaults at this sample rate. * Output has spec->control_count entries; IDs are LADSPA port indices. */ diff --git a/include/xtc/xtc_project.h b/include/xtc/xtc_project.h index de3c222..aa993f2 100644 --- a/include/xtc/xtc_project.h +++ b/include/xtc/xtc_project.h @@ -7,7 +7,7 @@ extern "C" { #endif -#define XTC_PROJECT_FORMAT_VERSION 10U +#define XTC_PROJECT_FORMAT_VERSION 11U #define XTC_PROJECT_MAX_TRACKS 64U #define XTC_PROJECT_MAX_CLIPS 1024U #define XTC_PROJECT_NAME_BYTES 64U diff --git a/packaging/xtc.pc.in b/packaging/xtc.pc.in index 5877398..f75d6b0 100644 --- a/packaging/xtc.pc.in +++ b/packaging/xtc.pc.in @@ -7,5 +7,5 @@ Name: xtc Description: Modular C audio engine and project library Version: @VERSION@ Requires.private: @JACK@ -Libs: -L"${libdir}" -lxtc -lm -ldl +Libs: -L"${libdir}" -lxtc -lm -ldl -pthread Cflags: -I"${includedir}" diff --git a/src/core/xtc.c b/src/core/xtc.c index 7221934..5cf7bb2 100644 --- a/src/core/xtc.c +++ b/src/core/xtc.c @@ -77,7 +77,7 @@ void xtc_app_destroy(xtc_app *app) unsigned int xtc_build_features(void) { - unsigned int features = 0; + unsigned int features = XTC_FEATURE_CLAP | XTC_FEATURE_VST2 | XTC_FEATURE_VST3; #ifdef XTC_HAVE_JACK features |= XTC_FEATURE_JACK; #endif diff --git a/src/graph/graph.c b/src/graph/graph.c index 5043a85..97b7ef2 100644 --- a/src/graph/graph.c +++ b/src/graph/graph.c @@ -590,7 +590,8 @@ xtc_result xtc_graph_set_plugin(xtc_graph *g, size_t id, const xtc_plugin_spec * if (i == SIZE_MAX) return XTC_ERR_NOT_FOUND; if (g->nodes[i].type != XTC_NODE_PLUGIN) return XTC_ERR_INVALID_ARGUMENT; /* Parameter edits cannot replace identity/layout or invalidate wiring. */ - if (strcmp(s->path,g->nodes[i].plugin.path) || strcmp(s->label,g->nodes[i].plugin.label) || + if (s->format != g->nodes[i].plugin.format || strcmp(s->identifier,g->nodes[i].plugin.identifier) || + strcmp(s->path,g->nodes[i].plugin.path) || strcmp(s->label,g->nodes[i].plugin.label) || s->index != g->nodes[i].plugin.index || s->unique_id != g->nodes[i].plugin.unique_id || s->inputs != g->nodes[i].plugin.inputs || s->control_count != g->nodes[i].plugin.control_count || memcmp(s->ports,g->nodes[i].plugin.ports,s->control_count*sizeof(*s->ports))) return XTC_ERR_UNSUPPORTED; diff --git a/src/gui/main.cpp b/src/gui/main.cpp index 729b253..9104802 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -22,7 +22,7 @@ int main(int argc, char **argv) } if (argc == 2 && !std::strcmp(argv[1], "--diagnose")) { unsigned int features = xtc_build_features(); - std::printf("xtc %s; project formats 1..%u; JACK %s; LADSPA %s\nFor limits and recovery commands run xtc-check --diagnose/--help.\n", + std::printf("xtc %s; project formats 1..%u; JACK %s; LADSPA %s; CLAP/VST2/VST3 mono effects compiled\nFor limits and recovery commands run xtc-check --diagnose/--help.\n", XTC_VERSION_STRING,XTC_PROJECT_FORMAT_VERSION,features & XTC_FEATURE_JACK ? "compiled" : "disabled", features & XTC_FEATURE_LADSPA ? "compiled" : "disabled"); return EXIT_SUCCESS; diff --git a/src/gui/main_window.cpp b/src/gui/main_window.cpp index b97cf53..5bac2aa 100644 --- a/src/gui/main_window.cpp +++ b/src/gui/main_window.cpp @@ -88,9 +88,9 @@ MainWindow::MainWindow(bool prompt_unsaved) menu->add("Audio/Panic", FL_F + 9, panic_callback, this); menu->add("View/Piano roll", FL_CTRL + '4', piano_callback, this); menu->add("Audio/Record WAV", FL_SHIFT + FL_F + 5, audio_file_callback, this); - menu->add("File/Load LADSPA plugin", 0, plugin_callback, this); + menu->add("File/Load plugin", 0, plugin_callback, this); menu->add("Edit/Replace selected plugin", 0, plugin_callback, this); - menu->add("Edit/Insert LADSPA on selected wire", 0, plugin_callback, this); + menu->add("Edit/Insert plugin on selected wire", 0, plugin_callback, this); menu->add("Edit/Reset selected plugin", 0, plugin_callback, this); menu->add("Edit/Selected plugin automation", 0, plugin_callback, this); menu->add("Edit/Selected plugin control", 0, plugin_callback, this); @@ -765,6 +765,7 @@ void MainWindow::about_callback(Fl_Widget *, void *) */ void MainWindow::timer_callback(void *context) { + xtc_plugin_idle(); auto *window = static_cast(context); if (window->recorder_) { xtc_result r = xtc_recorder_drain(window->recorder_); @@ -1579,12 +1580,12 @@ void MainWindow::plugin_callback(Fl_Widget *widget, void *context) xtc_result r; if (std::strcmp(label,"Reset selected plugin") == 0) { r = w->reset_plugin(w->graph_widget_->selected_node()); - } else if (std::strcmp(label,"Load LADSPA plugin") == 0 || + } else if (std::strcmp(label,"Load plugin") == 0 || std::strcmp(label,"Replace selected plugin") == 0 || - std::strcmp(label,"Insert LADSPA on selected wire") == 0) { + std::strcmp(label,"Insert plugin on selected wire") == 0) { const size_t selected = w->graph_widget_->selected_node(); xtc_connection_info wire{}; - const bool insert = std::strcmp(label,"Insert LADSPA on selected wire") == 0; + const bool insert = std::strcmp(label,"Insert plugin on selected wire") == 0; const bool replace = std::strcmp(label,"Replace selected plugin") == 0; if (insert && !w->graph_widget_->selected_connection(wire)) { w->report_error("Select an existing wire before inserting an effect",XTC_ERR_INVALID_STATE); return; @@ -1592,10 +1593,10 @@ void MainWindow::plugin_callback(Fl_Widget *widget, void *context) if (replace) { xtc_plugin_spec old{}; r = xtc_graph_get_plugin(xtc_project_graph(w->project_.get()),selected,&old); - if (r != XTC_OK) { w->report_error("Select a LADSPA node to replace",r); return; } + if (r != XTC_OK) { w->report_error("Select a plugin node to replace",r); return; } } Fl_Native_File_Chooser chooser; - chooser.title("Choose trusted LADSPA module (executes native code)"); chooser.filter("LADSPA\t*.so"); + chooser.title("Choose trusted plugin binary (LADSPA, CLAP, VST2, VST3)"); chooser.filter("Plugin binaries\t*.{so,clap}\nAll files\t*"); if (chooser.show() != 0 || !chooser.filename()) return; double rate = 48000; xtc_backend_status status{}; if (w->ready_ && xtc_backend_get_status(w->backend_,&status) == XTC_OK) rate = status.sample_rate; @@ -1603,7 +1604,7 @@ void MainWindow::plugin_callback(Fl_Widget *widget, void *context) xtc_plugin_spec probe{}; r = xtc_plugin_probe(chooser.filename(),0,rate,&probe); if (r != XTC_OK && r != XTC_ERR_UNSUPPORTED) { - w->report_error("Cannot discover LADSPA module; check path, dependencies and ladspa_descriptor export",r); return; + w->report_error("Cannot discover plugin; check binary path, format, mono layout and dependencies",r); return; } if (!xtc_choose_plugin(chooser.filename(),rate,index)) return; if (replace) r = w->replace_plugin(selected,chooser.filename(),index); diff --git a/src/gui/plugin_dialog.cpp b/src/gui/plugin_dialog.cpp index c6695ac..41ef2be 100644 --- a/src/gui/plugin_dialog.cpp +++ b/src/gui/plugin_dialog.cpp @@ -24,7 +24,7 @@ struct Dialog : Fl_Double_Window { } bool xtc_choose_plugin(const char *path, double rate, unsigned int &index) { - Dialog dialog(760,450,"LADSPA descriptors"); + Dialog dialog(760,450,"Plugin descriptors"); auto *heading = new Fl_Box(15,10,730,40); heading->copy_label(path); heading->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP); auto *list = new Fl_Hold_Browser(15,55,730,325); @@ -56,9 +56,9 @@ bool xtc_edit_plugin(const xtc_plugin_spec &spec, const xtc_plugin_details &deta Dialog dialog(800,600,"Plugin identity and controls"); auto *identity = new Fl_Box(15,10,770,125); std::string text = std::string(details.name) + " — " + details.maker + "\n" + spec.label + - " | LADSPA ID " + std::to_string(spec.unique_id) + " | descriptor " + std::to_string(spec.index) + + " | " + std::string(xtc_plugin_format_name(spec.format)) + " ID " + std::to_string(spec.unique_id) + " | descriptor " + std::to_string(spec.index) + " | identity " + spec.identifier + "\n" + spec.path + "\n" + details.copyright + - "\nMetadata verified; Apply validates initialization. Units unspecified by LADSPA."; + "\nMetadata verified; Apply validates initialization. Adapter may not expose units or editable controls."; identity->copy_label(text.c_str()); identity->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP); auto *scroll = new Fl_Scroll(10,140,780,370); std::array inputs{}; diff --git a/src/main.c b/src/main.c index 038056a..4a523ac 100644 --- a/src/main.c +++ b/src/main.c @@ -55,7 +55,8 @@ static int inspect(const xtc_project *project, uint64_t version) xtc_graph_get_node(graph,i,&node); if (xtc_graph_get_plugin(graph,node.id,&spec) == XTC_OK) { int available = readable_file(spec.path); - printf("LADSPA node %zu ID %u descriptor %u ",node.id,spec.unique_id,spec.index); + printf("%s node %zu ID %u descriptor %u ",xtc_plugin_format_name(spec.format),node.id,spec.unique_id,spec.index); + if (spec.identifier[0]) { quoted(spec.identifier); putchar(' '); } quoted(spec.label); printf(": %s ",available ? "available" : "missing/unreadable"); quoted(spec.path); putchar('\n'); if (!available) ++missing; @@ -86,7 +87,7 @@ int main(int argc, char **argv) } if (argc == 2 && !strcmp(argv[1], "--diagnose")) { unsigned int features = xtc_build_features(); - printf("xtc %s; %zu-bit process\nProject formats: 1..%u\nJACK compiled: %s\nLADSPA compiled: %s\n" + printf("xtc %s; %zu-bit process\nProject formats: 1..%u\nJACK compiled: %s\nLADSPA compiled: %s\nCLAP/VST2/VST3: compiled (mono effects, default configuration)\n" "Limits: 256 graph nodes (64/project), %u tracks, %u clips, %u notes, 65536 frames/block\n" "No server, device or plugin probed. Runtime errors appear in GUI status/stderr.\n", XTC_VERSION_STRING,sizeof(void *)*CHAR_BIT,XTC_PROJECT_FORMAT_VERSION, diff --git a/src/persistence/project_file.c b/src/persistence/project_file.c index b783ce8..ad4fa7d 100644 --- a/src/persistence/project_file.c +++ b/src/persistence/project_file.c @@ -259,6 +259,12 @@ static xtc_result read_project(reader *input, xtc_project *project, const char * if (!decode_bytes(input->tokens[5],p->label,sizeof(p->label))) return XTC_ERR_FORMAT; READ("MODULE",2U); if (!decode_bytes(input->tokens[1],p->path,sizeof(p->path))) return XTC_ERR_FORMAT; + if (format_version >= 11U) { + READ("FORMAT",3U); NUM(1U,value); + if (value > XTC_PLUGIN_VST3) return XTC_ERR_UNSUPPORTED; + p->format = (xtc_plugin_format)value; + if (strcmp(input->tokens[2],"-") && !decode_bytes(input->tokens[2],p->identifier,sizeof(p->identifier))) return XTC_ERR_FORMAT; + } for (k = 0; k < p->control_count; ++k) { READ("CONTROL",3U); NUM(1U,value); if (value >= 64 || !decode_float(input->tokens[2],p->values+k)) return XTC_ERR_FORMAT; @@ -506,6 +512,7 @@ static xtc_result write_project(FILE *file, const xtc_project *project, const ch if (xtc_plugin_spec_validate(p) != XTC_OK) return XTC_ERR_FORMAT; if (fprintf(file,"PLUGIN %u %u %u %u ",p->unique_id,p->index,p->inputs,p->control_count) < 0 || !write_name(file,p->label) || fputs("MODULE ",file) == EOF || !write_name(file,p->path)) return XTC_ERR_IO; + if (fprintf(file,"FORMAT %u ",(unsigned int)p->format) < 0 || (p->identifier[0] ? !write_name(file,p->identifier) : fputs("-\n",file) == EOF)) return XTC_ERR_IO; for (k = 0; k < p->control_count; ++k) { uint32_t value; memcpy(&value,p->values+k,4); if (fprintf(file,"CONTROL %u %08" PRIx32 "\n",p->ports[k],value) < 0) return XTC_ERR_IO; diff --git a/src/plugin/host.c b/src/plugin/host.c new file mode 100644 index 0000000..5d73562 --- /dev/null +++ b/src/plugin/host.c @@ -0,0 +1,108 @@ +#include "modern.h" +#include +#include +#include +#include +#include +typedef struct xtc_ladspa_plugin xtc_ladspa_plugin; +xtc_result xtc_ladspa_probe(const char *, unsigned int, double, xtc_plugin_spec *); +xtc_result xtc_ladspa_describe(const xtc_plugin_spec *, double, xtc_plugin_details *); +xtc_result xtc_ladspa_create(const xtc_plugin_spec *, double, size_t, xtc_ladspa_plugin **); +void xtc_ladspa_destroy(xtc_ladspa_plugin *); +xtc_result xtc_ladspa_process_at(xtc_ladspa_plugin *, const float *, float *, size_t, uint64_t); +struct xtc_plugin { xtc_ladspa_plugin *ladspa; xtc_modern *modern; uint64_t next; }; +const char *xtc_plugin_format_name(xtc_plugin_format f) +{ static const char *names[] = {"LADSPA", "CLAP", "VST2", "VST3"}; return f >= 0 && f <= XTC_PLUGIN_VST3 ? names[f] : "Unknown"; } +xtc_result xtc_plugin_probe_format(xtc_plugin_format f, const char *path, unsigned int index, double rate, xtc_plugin_spec *out) +{ + xtc_modern *p = NULL; xtc_result r; + if (!out || !path || path[0] != '/' || strlen(path) >= 512 || index >= 1024 || !isfinite(rate) || rate < 1 || rate > 768000) + return XTC_ERR_INVALID_ARGUMENT; + if (f == XTC_PLUGIN_LADSPA) return xtc_ladspa_probe(path,index,rate,out); + if (f < XTC_PLUGIN_CLAP || f > XTC_PLUGIN_VST3) return XTC_ERR_INVALID_ARGUMENT; + r = xtc_modern_open(f,path,index,rate,256,&p,out); + xtc_modern_destroy(p); return r; +} +xtc_result xtc_plugin_probe(const char *path, unsigned int index, double rate, xtc_plugin_spec *out) +{ + void *module; xtc_plugin_format f = XTC_PLUGIN_LADSPA; + if (!path || path[0] != '/' || strlen(path) >= 512) return XTC_ERR_INVALID_ARGUMENT; + module = dlopen(path,RTLD_NOW | RTLD_LOCAL); + if (!module) return XTC_ERR_NOT_FOUND; + if (dlsym(module,"clap_entry")) f = XTC_PLUGIN_CLAP; + else if (dlsym(module,"VSTPluginMain")) f = XTC_PLUGIN_VST2; + else if (dlsym(module,"GetPluginFactory")) f = XTC_PLUGIN_VST3; + dlclose(module); + return xtc_plugin_probe_format(f,path,index,rate,out); +} +xtc_result xtc_plugin_describe(const xtc_plugin_spec *s, double rate, xtc_plugin_details *out) +{ + xtc_plugin_spec actual; xtc_result r; + if (!out || xtc_plugin_spec_validate(s) != XTC_OK) return XTC_ERR_INVALID_ARGUMENT; + if (s->format == XTC_PLUGIN_LADSPA) return xtc_ladspa_describe(s,rate,out); + r = xtc_plugin_probe_format(s->format,s->path,s->index,rate,&actual); + if (r != XTC_OK) return r; + if (actual.unique_id != s->unique_id || strcmp(actual.identifier,s->identifier) || strcmp(actual.label,s->label)) return XTC_ERR_UNSUPPORTED; + memset(out,0,sizeof(*out)); snprintf(out->name,sizeof(out->name),"%s",s->label); + snprintf(out->maker,sizeof(out->maker),"Not exposed by this adapter"); + snprintf(out->copyright,sizeof(out->copyright),"See plugin license"); + return XTC_OK; +} +void xtc_plugin_destroy(xtc_plugin *p) +{ if (p) { xtc_ladspa_destroy(p->ladspa); xtc_modern_destroy(p->modern); free(p); } } +xtc_result xtc_plugin_create(const xtc_plugin_spec *s, double rate, size_t frames, xtc_plugin **out) +{ + xtc_plugin *p; xtc_result r; xtc_plugin_spec actual; + if (!out) return XTC_ERR_INVALID_ARGUMENT; + *out = NULL; + r = xtc_plugin_spec_validate(s); if (r != XTC_OK) return r; + if (!frames || frames > 65536 || !isfinite(rate) || rate < 1 || rate > 768000) return XTC_ERR_INVALID_ARGUMENT; + p = calloc(1,sizeof(*p)); if (!p) return XTC_ERR_OUT_OF_MEMORY; + if (s->format == XTC_PLUGIN_LADSPA) r = xtc_ladspa_create(s,rate,frames,&p->ladspa); + else { + r = xtc_modern_open(s->format,s->path,s->index,rate,frames,&p->modern,&actual); + if (r == XTC_OK && (actual.unique_id != s->unique_id || actual.inputs != s->inputs || + strcmp(actual.identifier,s->identifier) || strcmp(actual.label,s->label))) r = XTC_ERR_UNSUPPORTED; + } + if (r != XTC_OK) { xtc_plugin_destroy(p); return r; } + *out = p; return XTC_OK; +} +xtc_result xtc_plugin_process_at(xtc_plugin *p, const float *in, float *out, size_t frames, uint64_t position) +{ + xtc_result r; + if (!p) return XTC_ERR_INVALID_ARGUMENT; + r = p->modern ? xtc_modern_process(p->modern,in,out,frames) : xtc_ladspa_process_at(p->ladspa,in,out,frames,position); + if (r == XTC_OK) p->next = position <= UINT64_MAX-frames ? position+frames : 0; + return r; +} +xtc_result xtc_plugin_process(xtc_plugin *p, const float *in, float *out, size_t frames) +{ return xtc_plugin_process_at(p,in,out,frames,p ? p->next : 0); } +xtc_result xtc_plugin_parameters(const xtc_plugin_spec *s, double rate, xtc_parameter_info out[XTC_PLUGIN_CONTROLS]) +{ + xtc_plugin_details details; + xtc_result r; + if (!out) return XTC_ERR_INVALID_ARGUMENT; + r = xtc_plugin_describe(s,rate,&details); + if (r == XTC_OK) memcpy(out,details.parameters,sizeof(details.parameters)); + return r; +} +xtc_result xtc_plugin_reset(xtc_plugin_spec *s, double rate, unsigned int port) +{ + xtc_plugin_details details; + xtc_plugin_spec candidate; + size_t i, count = 0; + int found = port == UINT32_MAX; + xtc_result r = xtc_plugin_describe(s,rate,&details); + if (r != XTC_OK) return r; + candidate = *s; + for (i = 0; i < s->control_count; ++i) if (port == UINT32_MAX || s->ports[i] == port) { + candidate.values[i] = details.parameters[i].default_value; + found = 1; + } + if (!found) return XTC_ERR_NOT_FOUND; + for (i = 0; i < s->point_count; ++i) + if (port != UINT32_MAX && s->points[i].port != port) candidate.points[count++] = s->points[i]; + candidate.point_count = (unsigned int)count; + *s = candidate; + return XTC_OK; +} diff --git a/src/plugin/ladspa.c b/src/plugin/ladspa.c index 664a4e2..c950447 100644 --- a/src/plugin/ladspa.c +++ b/src/plugin/ladspa.c @@ -1,3 +1,10 @@ +#define xtc_plugin xtc_ladspa_plugin +#define xtc_plugin_probe xtc_ladspa_probe +#define xtc_plugin_describe xtc_ladspa_describe +#define xtc_plugin_create xtc_ladspa_create +#define xtc_plugin_destroy xtc_ladspa_destroy +#define xtc_plugin_process_at xtc_ladspa_process_at +#define xtc_plugin_process xtc_ladspa_process #include "xtc/xtc_plugin.h" #include "xtc/xtc_dsp.h" #include "xtc/xtc_project.h" @@ -17,6 +24,20 @@ xtc_result xtc_plugin_spec_validate(const xtc_plugin_spec *s) !terminated(s->label,sizeof(s->label)) || !s->label[0] || s->index >= 1024 || s->inputs > 1 || s->control_count > XTC_PLUGIN_CONTROLS || s->tempo < 20000 || s->tempo > 300000 || s->point_count > XTC_PLUGIN_POINTS) return XTC_ERR_INVALID_ARGUMENT; + if (s->format < XTC_PLUGIN_LADSPA || s->format > XTC_PLUGIN_VST3 || + !terminated(s->identifier,sizeof(s->identifier))) return XTC_ERR_INVALID_ARGUMENT; + if (s->format != XTC_PLUGIN_LADSPA) { + if (s->inputs != 1 || s->control_count || s->point_count || + ((s->format == XTC_PLUGIN_CLAP || s->format == XTC_PLUGIN_VST3) && !s->identifier[0])) + return XTC_ERR_UNSUPPORTED; + if (s->format == XTC_PLUGIN_VST2 && s->identifier[0]) return XTC_ERR_INVALID_ARGUMENT; + if (s->format == XTC_PLUGIN_VST3) { + if (strlen(s->identifier) != 32) return XTC_ERR_INVALID_ARGUMENT; + for (i = 0; i < 32; ++i) + if (!((s->identifier[i] >= '0' && s->identifier[i] <= '9') || + (s->identifier[i] >= 'a' && s->identifier[i] <= 'f'))) return XTC_ERR_INVALID_ARGUMENT; + } + } else if (s->identifier[0]) return XTC_ERR_INVALID_ARGUMENT; for (i = 0; i < s->control_count; ++i) if (s->ports[i] >= 64 || (i && s->ports[i] <= s->ports[i-1]) || !isfinite(s->values[i])) return XTC_ERR_INVALID_ARGUMENT; @@ -282,33 +303,3 @@ xtc_result xtc_plugin_process_at(xtc_plugin *p, const float *i, float *o, size_t xtc_result xtc_plugin_process(xtc_plugin *p, const float *i, float *o, size_t f) { (void)p; (void)i; (void)o; (void)f; return XTC_ERR_UNSUPPORTED; } #endif - -xtc_result xtc_plugin_parameters(const xtc_plugin_spec *s, double rate, xtc_parameter_info out[XTC_PLUGIN_CONTROLS]) -{ - xtc_plugin_details details; - xtc_result r; - if (!out) return XTC_ERR_INVALID_ARGUMENT; - r = xtc_plugin_describe(s,rate,&details); - if (r == XTC_OK) memcpy(out,details.parameters,sizeof(details.parameters)); - return r; -} -xtc_result xtc_plugin_reset(xtc_plugin_spec *s, double rate, unsigned int port) -{ - xtc_plugin_details details; - xtc_plugin_spec candidate; - size_t i, count = 0; - int found = port == UINT32_MAX; - xtc_result r = xtc_plugin_describe(s,rate,&details); - if (r != XTC_OK) return r; - candidate = *s; - for (i = 0; i < s->control_count; ++i) if (port == UINT32_MAX || s->ports[i] == port) { - candidate.values[i] = details.parameters[i].default_value; - found = 1; - } - if (!found) return XTC_ERR_NOT_FOUND; - for (i = 0; i < s->point_count; ++i) - if (port != UINT32_MAX && s->points[i].port != port) candidate.points[count++] = s->points[i]; - candidate.point_count = (unsigned int)count; - *s = candidate; - return XTC_OK; -} diff --git a/src/plugin/modern.c b/src/plugin/modern.c new file mode 100644 index 0000000..411ea28 --- /dev/null +++ b/src/plugin/modern.c @@ -0,0 +1,315 @@ +#define _POSIX_C_SOURCE 200809L +#include "modern.h" +#include "vst2_abi.h" +#include "xtc/xtc_dsp.h" +#include "xtc/xtc_version.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Module cache is control-thread owned. Entry initialization is once per loaded + * module, even when stereo preparation and retired plans overlap. */ +typedef struct module { + void *handle; + xtc_plugin_format format; + unsigned int references; + const clap_plugin_entry_t *entry; + bool (*exit3)(void); + struct module *next; +} module; +static module *modules; +struct xtc_modern { + module *module; + xtc_plugin_format format; + const clap_plugin_t *clap; + clap_host_t host; + xtc_v2_effect *v2; + Steinberg_IPluginFactory *factory; + Steinberg_Vst_IComponent *component; + Steinberg_Vst_IAudioProcessor *processor; + float *input, *output; + size_t frames; + double rate; + pthread_t control_thread; + int initialized, active, started; + unsigned int callback, restart; + struct xtc_modern *next; +}; +static xtc_modern *instances; +static __thread int in_audio; +static __thread xtc_modern *constructing; + +static int symbol(void *handle, const char *name, void *out, size_t size) +{ + void *value = dlsym(handle,name); + if (!value || size != sizeof(value)) return 0; + memcpy(out,&value,size); return 1; +} +static void module_release(module *m) +{ + module **slot; + if (!m || --m->references) return; + for (slot = &modules; *slot && *slot != m; slot = &(*slot)->next) {} + if (*slot) *slot = m->next; + if (m->entry) m->entry->deinit(); + if (m->exit3) m->exit3(); + dlclose(m->handle); free(m); +} +static xtc_result module_open(xtc_plugin_format format, const char *path, module **out) +{ + void *handle = dlopen(path,RTLD_NOW | RTLD_LOCAL); + module *m; xtc_result r = XTC_ERR_UNSUPPORTED; + if (!handle) return XTC_ERR_NOT_FOUND; + for (m = modules; m; m = m->next) if (m->handle == handle && m->format == format) { + ++m->references; dlclose(handle); *out = m; return XTC_OK; + } + m = calloc(1,sizeof(*m)); + if (!m) { dlclose(handle); return XTC_ERR_OUT_OF_MEMORY; } + m->handle = handle; m->format = format; m->references = 1; + if (format == XTC_PLUGIN_CLAP) { + const clap_plugin_entry_t *entry = dlsym(handle,"clap_entry"); + if (!entry || !clap_version_is_compatible(entry->clap_version) || !entry->init || !entry->deinit || !entry->get_factory) goto fail; + if (!entry->init(path)) { r = XTC_ERR_INVALID_STATE; goto fail; } + m->entry = entry; + } else if (format == XTC_PLUGIN_VST3) { + bool (*entry)(void *) = NULL; bool (*exit_module)(void) = NULL; + if (!symbol(handle,"ModuleEntry",&entry,sizeof(entry)) || !symbol(handle,"ModuleExit",&exit_module,sizeof(exit_module))) goto fail; + if (!entry(handle)) { r = XTC_ERR_INVALID_STATE; goto fail; } + m->exit3 = exit_module; + } + m->next = modules; modules = m; *out = m; return XTC_OK; +fail: + module_release(m); return r; +} +static void request_callback(const clap_host_t *h) +{ xtc_modern *p = h->host_data; __atomic_store_n(&p->callback,1U,__ATOMIC_RELEASE); } +static void request_restart(const clap_host_t *h) +{ xtc_modern *p = h->host_data; __atomic_store_n(&p->restart,1U,__ATOMIC_RELEASE); } +static void request_process(const clap_host_t *h) { (void)h; /* Always processed when transport runs. */ } +static bool is_main(const clap_host_t *h) +{ const xtc_modern *p = h->host_data; return !in_audio && pthread_equal(pthread_self(),p->control_thread); } +static bool is_audio(const clap_host_t *h) { (void)h; return in_audio != 0; } +static const void *host_extension(const clap_host_t *h, const char *id) +{ + static const clap_host_thread_check_t check = {is_main,is_audio}; + (void)h; return id && !strcmp(id,CLAP_EXT_THREAD_CHECK) ? &check : NULL; +} +void xtc_plugin_idle(void) +{ + xtc_modern *p; + for (p = instances; p; p = p->next) + if (p->clap && __atomic_exchange_n(&p->callback,0U,__ATOMIC_ACQ_REL)) p->clap->on_main_thread(p->clap); +} +static uint32_t event_count(const clap_input_events_t *list) { (void)list; return 0; } +static const clap_event_header_t *event_get(const clap_input_events_t *list, uint32_t index) +{ (void)list; (void)index; return NULL; } +static bool event_push(const clap_output_events_t *list, const clap_event_header_t *event) +{ (void)list; (void)event; return false; } +static xtc_result open_clap(xtc_modern *p, unsigned int index, xtc_plugin_spec *s) +{ + const clap_plugin_factory_t *factory = p->module->entry->get_factory(CLAP_PLUGIN_FACTORY_ID); + const clap_plugin_descriptor_t *d; const clap_plugin_audio_ports_t *ports; + clap_audio_port_info_t info; + if (!factory || !factory->get_plugin_count || !factory->get_plugin_descriptor || !factory->create_plugin) return XTC_ERR_UNSUPPORTED; + if (index >= factory->get_plugin_count(factory)) return XTC_ERR_NOT_FOUND; + d = factory->get_plugin_descriptor(factory,index); + if (!d || !clap_version_is_compatible(d->clap_version) || !d->id || !d->name || + !d->id[0] || strlen(d->id) >= sizeof(s->identifier) || !d->name[0]) return XTC_ERR_UNSUPPORTED; + snprintf(s->identifier,sizeof(s->identifier),"%s",d->id); snprintf(s->label,sizeof(s->label),"%s",d->name); + p->host = (clap_host_t){CLAP_VERSION,p,"xtc","xtc","",XTC_VERSION_STRING,host_extension,request_restart,request_process,request_callback}; + p->clap = factory->create_plugin(factory,&p->host,d->id); + if (!p->clap) return XTC_ERR_INVALID_STATE; + if (!p->clap->init || !p->clap->destroy || !p->clap->activate || !p->clap->deactivate || + !p->clap->start_processing || !p->clap->stop_processing || !p->clap->process || !p->clap->get_extension || !p->clap->on_main_thread) + return XTC_ERR_UNSUPPORTED; + if (!p->clap->init(p->clap)) return XTC_ERR_INVALID_STATE; + ports = p->clap->get_extension(p->clap,CLAP_EXT_AUDIO_PORTS); + if (!ports || !ports->count || !ports->get || ports->count(p->clap,true) != 1 || ports->count(p->clap,false) != 1 || + !ports->get(p->clap,0,true,&info) || info.channel_count != 1 || + !ports->get(p->clap,0,false,&info) || info.channel_count != 1) return XTC_ERR_UNSUPPORTED; + { const clap_plugin_note_ports_t *notes = p->clap->get_extension(p->clap,CLAP_EXT_NOTE_PORTS); + if (notes && (!notes->count || notes->count(p->clap,true) || notes->count(p->clap,false))) return XTC_ERR_UNSUPPORTED; } + if (!p->clap->activate(p->clap,p->rate,1,(uint32_t)p->frames)) return XTC_ERR_INVALID_STATE; + p->active = 1; + { const clap_plugin_latency_t *latency = p->clap->get_extension(p->clap,CLAP_EXT_LATENCY); + if (latency && (!latency->get || latency->get(p->clap))) return XTC_ERR_UNSUPPORTED; } + return XTC_OK; +} +static intptr_t v2_host(xtc_v2_effect *effect, int32_t opcode, int32_t index, intptr_t value, void *ptr, float option) +{ + xtc_modern *p = constructing ? constructing : effect ? effect->user : NULL; + (void)index; (void)value; (void)option; + switch (opcode) { + case 1: return 2400; /* host API version */ + case 13: if (p) __atomic_store_n(&p->restart,1U,__ATOMIC_RELEASE); return 0; + case 16: return p ? (intptr_t)p->rate : 48000; + case 17: return p ? (intptr_t)p->frames : 256; + case 32: if (ptr) memcpy(ptr,"xtc",4); return 1; + case 33: if (ptr) memcpy(ptr,"xtc",4); return 1; + case 34: return 1; + case 23: return in_audio ? 2 : 1; /* Realtime or user/main process level. */ + default: return 0; + } +} +static xtc_result open_v2(xtc_modern *p, unsigned int index, xtc_plugin_spec *s) +{ + xtc_v2_effect *(*entry)(xtc_v2_host) = NULL; + char name[64] = {0}; + if (index) return XTC_ERR_NOT_FOUND; + if (!symbol(p->module->handle,"VSTPluginMain",&entry,sizeof(entry))) return XTC_ERR_UNSUPPORTED; + constructing = p; p->v2 = entry(v2_host); constructing = NULL; + if (!p->v2 || p->v2->magic != XTC_V2_MAGIC || !p->v2->dispatch) return XTC_ERR_UNSUPPORTED; + p->v2->user = p; + p->v2->dispatch(p->v2,0,0,0,NULL,0); p->initialized = 1; + if (p->v2->inputs != 1 || p->v2->outputs != 1 || !p->v2->replace || !(p->v2->flags & 16) || + (p->v2->flags & 256) || p->v2->initial_delay) return XTC_ERR_UNSUPPORTED; + p->v2->dispatch(p->v2,45,0,0,name,0); name[63] = 0; + if (!name[0]) return XTC_ERR_UNSUPPORTED; + snprintf(s->label,sizeof(s->label),"%s",name); s->unique_id = (unsigned int)p->v2->unique_id; + p->v2->dispatch(p->v2,10,0,0,NULL,(float)p->rate); + p->v2->dispatch(p->v2,11,0,(intptr_t)p->frames,NULL,0); + p->v2->dispatch(p->v2,12,0,1,NULL,0); p->active = 1; + p->v2->dispatch(p->v2,71,0,0,NULL,0); p->started = 1; + return XTC_OK; +} +static Steinberg_tresult host_query(void *self, const Steinberg_TUID iid, void **out) +{ + if (!out || !iid) return Steinberg_kInvalidArgument; + *out = NULL; + if (!memcmp(iid,Steinberg_FUnknown_iid,16) || !memcmp(iid,Steinberg_Vst_IHostApplication_iid,16)) { *out = self; return 0; } + return Steinberg_kNoInterface; +} +static Steinberg_uint32 host_ref(void *self) { (void)self; return 1; } +static Steinberg_tresult host_name(void *self, Steinberg_Vst_String128 name) +{ (void)self; if (!name) return Steinberg_kInvalidArgument; memset(name,0,sizeof(Steinberg_Vst_String128)); name[0] = 'x'; name[1] = 't'; name[2] = 'c'; return 0; } +static Steinberg_tresult host_create(void *self, Steinberg_TUID cid, Steinberg_TUID iid, void **out) +{ (void)self; (void)cid; (void)iid; if (!out) return Steinberg_kInvalidArgument; *out = NULL; return Steinberg_kNoInterface; } +static Steinberg_Vst_IHostApplicationVtbl host_vtable = {host_query,host_ref,host_ref,host_name,host_create}; +static Steinberg_Vst_IHostApplication application = {&host_vtable}; +static xtc_result open_v3(xtc_modern *p, unsigned int index, xtc_plugin_spec *s) +{ + Steinberg_IPluginFactory *(*entry)(void) = NULL; + struct Steinberg_PClassInfo info; + struct Steinberg_Vst_ProcessSetup setup = {0,0,(Steinberg_int32)p->frames,p->rate}; + Steinberg_Vst_SpeakerArrangement mono = Steinberg_Vst_SpeakerArr_kMono; + unsigned int i; + if (!symbol(p->module->handle,"GetPluginFactory",&entry,sizeof(entry))) return XTC_ERR_UNSUPPORTED; + p->factory = entry(); + if (!p->factory || !p->factory->lpVtbl || !p->factory->lpVtbl->release || + !p->factory->lpVtbl->countClasses || !p->factory->lpVtbl->getClassInfo || !p->factory->lpVtbl->createInstance) return XTC_ERR_UNSUPPORTED; + if ((Steinberg_int32)index >= p->factory->lpVtbl->countClasses(p->factory)) return XTC_ERR_NOT_FOUND; + memset(&info,0,sizeof(info)); + if (p->factory->lpVtbl->getClassInfo(p->factory,(Steinberg_int32)index,&info) != 0 || + !memchr(info.category,0,sizeof(info.category)) || strcmp(info.category,"Audio Module Class") || + !memchr(info.name,0,sizeof(info.name)) || !info.name[0]) return XTC_ERR_UNSUPPORTED; + for (i = 0; i < 16; ++i) snprintf(s->identifier+i*2,3,"%02x",(unsigned char)info.cid[i]); + snprintf(s->label,sizeof(s->label),"%s",info.name); + if (p->factory->lpVtbl->createInstance(p->factory,info.cid,Steinberg_Vst_IComponent_iid,(void **)&p->component) != 0 || !p->component) + return XTC_ERR_INVALID_STATE; + if (!p->component->lpVtbl || !p->component->lpVtbl->initialize || !p->component->lpVtbl->terminate || + !p->component->lpVtbl->queryInterface || !p->component->lpVtbl->release || !p->component->lpVtbl->getBusCount || + !p->component->lpVtbl->getBusInfo || !p->component->lpVtbl->activateBus || !p->component->lpVtbl->setActive) return XTC_ERR_UNSUPPORTED; + if (p->component->lpVtbl->initialize(p->component,(Steinberg_FUnknown *)&application) != 0) return XTC_ERR_INVALID_STATE; + p->initialized = 1; + if (p->component->lpVtbl->queryInterface(p->component,Steinberg_Vst_IAudioProcessor_iid,(void **)&p->processor) != 0 || !p->processor) + return XTC_ERR_UNSUPPORTED; + if (!p->processor->lpVtbl || !p->processor->lpVtbl->release || !p->processor->lpVtbl->canProcessSampleSize || + !p->processor->lpVtbl->setBusArrangements || !p->processor->lpVtbl->setupProcessing || !p->processor->lpVtbl->getLatencySamples || + !p->processor->lpVtbl->setProcessing || !p->processor->lpVtbl->process) return XTC_ERR_UNSUPPORTED; + if (p->component->lpVtbl->getBusCount(p->component,0,0) != 1 || p->component->lpVtbl->getBusCount(p->component,0,1) != 1 || + p->component->lpVtbl->getBusCount(p->component,1,0) || p->component->lpVtbl->getBusCount(p->component,1,1) || + p->processor->lpVtbl->canProcessSampleSize(p->processor,0) != 0 || + p->processor->lpVtbl->setBusArrangements(p->processor,&mono,1,&mono,1) != 0) return XTC_ERR_UNSUPPORTED; + for (i = 0; i < 2; ++i) { + struct Steinberg_Vst_BusInfo bus; + if (p->component->lpVtbl->getBusInfo(p->component,0,(Steinberg_int32)i,0,&bus) != 0 || bus.channelCount != 1 || + p->component->lpVtbl->activateBus(p->component,0,(Steinberg_int32)i,0,1) != 0) return XTC_ERR_UNSUPPORTED; + } + if (p->processor->lpVtbl->setupProcessing(p->processor,&setup) != 0 || p->processor->lpVtbl->getLatencySamples(p->processor)) return XTC_ERR_UNSUPPORTED; + if (p->component->lpVtbl->setActive(p->component,1) != 0) return XTC_ERR_INVALID_STATE; + p->active = 1; + if (p->processor->lpVtbl->setProcessing(p->processor,1) != 0) return XTC_ERR_INVALID_STATE; + p->started = 1; return XTC_OK; +} +xtc_result xtc_modern_open(xtc_plugin_format format, const char *path, unsigned int index, double rate, size_t frames, xtc_modern **out, xtc_plugin_spec *spec) +{ + xtc_modern *p; xtc_plugin_spec s = {0}; xtc_result r; + if (!__atomic_always_lock_free(sizeof(unsigned int),0)) return XTC_ERR_UNSUPPORTED; + p = calloc(1,sizeof(*p)); + if (!p) return XTC_ERR_OUT_OF_MEMORY; + p->format = format; p->frames = frames; p->rate = rate; p->control_thread = pthread_self(); + p->input = calloc(frames,sizeof(float)); p->output = calloc(frames,sizeof(float)); + if (!p->input || !p->output) { xtc_modern_destroy(p); return XTC_ERR_OUT_OF_MEMORY; } + r = module_open(format,path,&p->module); + s.format = format; s.index = index; s.inputs = 1; s.tempo = 120000; + snprintf(s.path,sizeof(s.path),"%s",path); + if (r == XTC_OK) r = format == XTC_PLUGIN_CLAP ? open_clap(p,index,&s) : format == XTC_PLUGIN_VST2 ? open_v2(p,index,&s) : open_v3(p,index,&s); + if (r != XTC_OK) { xtc_modern_destroy(p); return r; } + p->next = instances; instances = p; *out = p; *spec = s; return XTC_OK; +} +void xtc_modern_destroy(xtc_modern *p) +{ + xtc_modern **slot; + if (!p) return; + for (slot = &instances; *slot && *slot != p; slot = &(*slot)->next) {} + if (*slot) *slot = p->next; + if (p->clap) { + if (p->started) { in_audio = 1; p->clap->stop_processing(p->clap); in_audio = 0; } + if (p->active) p->clap->deactivate(p->clap); + if (p->clap->destroy) p->clap->destroy(p->clap); + } + if (p->v2 && p->v2->magic == XTC_V2_MAGIC && p->v2->dispatch && p->initialized) { + if (p->started) p->v2->dispatch(p->v2,72,0,0,NULL,0); + if (p->active) p->v2->dispatch(p->v2,12,0,0,NULL,0); + p->v2->dispatch(p->v2,1,0,0,NULL,0); + } + if (p->processor && p->processor->lpVtbl) { + if (p->started) p->processor->lpVtbl->setProcessing(p->processor,0); + if (p->active) p->component->lpVtbl->setActive(p->component,0); + if (p->processor->lpVtbl->release) p->processor->lpVtbl->release(p->processor); + } + if (p->component && p->component->lpVtbl) { + if (p->initialized) p->component->lpVtbl->terminate(p->component); + if (p->component->lpVtbl->release) p->component->lpVtbl->release(p->component); + } + if (p->factory && p->factory->lpVtbl && p->factory->lpVtbl->release) p->factory->lpVtbl->release(p->factory); + module_release(p->module); free(p->input); free(p->output); free(p); +} +xtc_result xtc_modern_process(xtc_modern *p, const float *input, float *output, size_t frames) +{ + size_t i; int ok = 1; + if (!p || !output || frames > p->frames) return XTC_ERR_INVALID_ARGUMENT; + if (!frames) return XTC_OK; + if (__atomic_load_n(&p->restart,__ATOMIC_ACQUIRE)) { memset(output,0,frames*sizeof(float)); return XTC_ERR_INVALID_STATE; } + for (i = 0; i < frames; ++i) p->input[i] = input ? xtc_dsp_finite(input[i]) : 0; + memset(p->output,0,frames*sizeof(float)); + in_audio = 1; + if (p->clap) { + clap_input_events_t events = {NULL,event_count,event_get}; clap_output_events_t sink = {NULL,event_push}; + clap_audio_buffer_t in = {&p->input,NULL,1,0,0}, out = {&p->output,NULL,1,0,0}; + clap_process_t block = {-1,(uint32_t)frames,NULL,&in,&out,1,1,&events,&sink}; + if (!p->started) { p->started = p->clap->start_processing(p->clap); if (!p->started) ok = 0; } + if (ok) { + clap_process_status status = p->clap->process(p->clap,&block); + ok = status >= CLAP_PROCESS_CONTINUE && status <= CLAP_PROCESS_SLEEP; + } + } else if (p->v2) p->v2->replace(p->v2,&p->input,&p->output,(int32_t)frames); + else { + struct Steinberg_Vst_AudioBusBuffers in = {0}, out = {0}; + struct Steinberg_Vst_ProcessData data = {0}; + in.numChannels = out.numChannels = 1; + in.Steinberg_Vst_AudioBusBuffers_channelBuffers32 = &p->input; + out.Steinberg_Vst_AudioBusBuffers_channelBuffers32 = &p->output; + data.numSamples = (Steinberg_int32)frames; data.numInputs = data.numOutputs = 1; data.inputs = ∈ data.outputs = &out; + ok = p->processor->lpVtbl->process(p->processor,&data) == 0; + } + in_audio = 0; + for (i = 0; i < frames; ++i) output[i] = ok ? xtc_dsp_finite(p->output[i]) : 0; + return ok ? XTC_OK : XTC_ERR_INVALID_STATE; +} diff --git a/src/plugin/modern.h b/src/plugin/modern.h new file mode 100644 index 0000000..1f3b28f --- /dev/null +++ b/src/plugin/modern.h @@ -0,0 +1,8 @@ +#ifndef XTC_MODERN_H +#define XTC_MODERN_H +#include "xtc/xtc_plugin.h" +typedef struct xtc_modern xtc_modern; +xtc_result xtc_modern_open(xtc_plugin_format format, const char *path, unsigned int index, double rate, size_t frames, xtc_modern **out, xtc_plugin_spec *spec); +xtc_result xtc_modern_process(xtc_modern *plugin, const float *input, float *output, size_t frames); +void xtc_modern_destroy(xtc_modern *plugin); +#endif diff --git a/src/plugin/vst2_abi.h b/src/plugin/vst2_abi.h new file mode 100644 index 0000000..d2e85b2 --- /dev/null +++ b/src/plugin/vst2_abi.h @@ -0,0 +1,26 @@ +#ifndef XTC_VST2_ABI_H +#define XTC_VST2_ABI_H +/* Original, minimal Linux ABI declarations for legacy VST2 interoperability. + * No Steinberg VST2 SDK code is included. Not a complete SDK or VST2 wrapper. */ +#include +typedef struct xtc_v2_effect xtc_v2_effect; +typedef intptr_t (*xtc_v2_host)(xtc_v2_effect *, int32_t, int32_t, intptr_t, void *, float); +typedef intptr_t (*xtc_v2_dispatch)(xtc_v2_effect *, int32_t, int32_t, intptr_t, void *, float); +struct xtc_v2_effect { + int32_t magic; + xtc_v2_dispatch dispatch; + void (*process)(xtc_v2_effect *, float **, float **, int32_t); + void (*set_parameter)(xtc_v2_effect *, int32_t, float); + float (*get_parameter)(xtc_v2_effect *, int32_t); + int32_t programs, parameters, inputs, outputs, flags; + intptr_t reserved1, reserved2; + int32_t initial_delay, quality1, quality2; + float ratio; + void *object, *user; + int32_t unique_id, version; + void (*replace)(xtc_v2_effect *, float **, float **, int32_t); + void (*replace64)(xtc_v2_effect *, double **, double **, int32_t); + char future[56]; +}; +#define XTC_V2_MAGIC INT32_C(0x56737450) +#endif diff --git a/tests/fixtures/README.md b/tests/fixtures/README.md index 1a3dadd..fa1b184 100644 --- a/tests/fixtures/README.md +++ b/tests/fixtures/README.md @@ -3,7 +3,7 @@ Store small, redistributable fixtures here. Document their origin and license. Do not commit large recordings or assets with unclear licensing. -`project-v1.xtc` through `project-v10.xtc` are hand-authored xtc metadata fixtures +`project-v1.xtc` through `project-v11.xtc` are hand-authored xtc metadata fixtures created for this repository, under the project license. They contain no audio or third-party resources. The v5/v6 plugin fixtures intentionally reference a missing module to exercise metadata migration without loading code. diff --git a/tests/fixtures/project-v11.xtc b/tests/fixtures/project-v11.xtc new file mode 100644 index 0000000..99e06b0 --- /dev/null +++ b/tests/fixtures/project-v11.xtc @@ -0,0 +1,39 @@ +XTC_PROJECT 11 +APP 0 1 0 +TEMPO 120000 +IDS 1 1 +GRAPH 1 2 2 1 +NODE 0 1 3f000000 +NODE 1 4 00000000 +EDGE 0 1 +TRACKS 1 +TRACK 0 4b657973 +MIX 3f800000 00000000 0 0 +ROUTE 0 18446744073709551615 +CLIPS 1 +CLIP 0 0 0 960 0 960 5665727365 +ASSET - +MIDI 1 +AUDIO 3f800000 0 0 +NOTES 1 1 +NOTE 0 0 0 480 69 100 0 +AUTOMATION 1 +POINT 0 0 0 3f800000 0 +CONTROL_MAPS 16 +MAP 0 7 10 64 +MAP 1 7 10 64 +MAP 2 7 10 64 +MAP 3 7 10 64 +MAP 4 7 10 64 +MAP 5 7 10 64 +MAP 6 7 10 64 +MAP 7 7 10 64 +MAP 8 7 10 64 +MAP 9 7 10 64 +MAP 10 7 10 64 +MAP 11 7 10 64 +MAP 12 7 10 64 +MAP 13 7 10 64 +MAP 14 7 10 64 +MAP 15 7 10 64 +END diff --git a/tests/integration/test_gui.cpp b/tests/integration/test_gui.cpp index 89fc4b8..6d732c1 100644 --- a/tests/integration/test_gui.cpp +++ b/tests/integration/test_gui.cpp @@ -711,7 +711,7 @@ int main(int argc, char **argv) // Exercise the actual modal chooser/editor with copied metadata only. Fl::add_timeout(.05,[](void *) { auto *dialog = Fl::first_window(); - CHECK(dialog && dialog->label() && std::strcmp(dialog->label(),"LADSPA descriptors") == 0); + CHECK(dialog && dialog->label() && std::strcmp(dialog->label(),"Plugin descriptors") == 0); if (!dialog) return; for (int i = 0; i < dialog->children(); ++i) if (auto *list = dynamic_cast(dialog->child(i))) { @@ -803,6 +803,30 @@ int main(int argc, char **argv) unlink("/tmp/xtc-gui-plugin-test.xtc"); window.do_callback(); } + for (const char *variable : {"XTC_TEST_CLAP","XTC_TEST_VST2","XTC_TEST_VST3"}) { + if (const char *module = std::getenv(variable)) { + reset(); MainWindow window(false); auto *sequence = timeline(&window); + size_t id = SIZE_MAX; xtc_plugin_spec spec{}; + CHECK(window.add_plugin(module,0,&id) == XTC_OK); + CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK); + CHECK(spec.format != XTC_PLUGIN_LADSPA && spec.inputs == 1 && !spec.control_count); + CHECK(window.undo(false) == XTC_OK && window.undo(true) == XTC_OK); + Fl::add_timeout(.05,[](void *) { + auto *dialog = Fl::first_window(); CHECK(dialog); + auto *choose = find(dialog,"Choose"); CHECK(choose); if (choose) choose->do_callback(); + }); + unsigned int chosen = UINT32_MAX; + CHECK(xtc_choose_plugin(module,48000,chosen) && chosen == 0); + CHECK(window.save_project("/tmp/xtc-gui-modern-test.xtc") == XTC_OK); + CHECK(window.new_project() == XTC_OK); + CHECK(window.open_project("/tmp/xtc-gui-modern-test.xtc") == XTC_OK); + xtc_plugin_spec loaded{}; + CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&loaded) == XTC_OK && loaded.format == spec.format); + const xtc_project *before = sequence->project(); + CHECK(window.replace_plugin(id,"/absent/modern.so",0) == XTC_ERR_NOT_FOUND && sequence->project() == before); + unlink("/tmp/xtc-gui-modern-test.xtc"); window.do_callback(); + } + } if (failures != 0) return 1; std::printf("GUI controls/errors/views/timers/cleanup passed: %u opens, %u closes.\n", opens, closes); return 0; diff --git a/tests/integration/test_install.py b/tests/integration/test_install.py index fe26141..1bcabfa 100644 --- a/tests/integration/test_install.py +++ b/tests/integration/test_install.py @@ -44,6 +44,8 @@ def main(): assert not (binaries / 'xtc').exists() assert (resources / 'licenses/xtc/LICENSE').read_bytes() == (source / 'LICENSE').read_bytes() assert (docs / 'PROJECT_FORMAT.md').is_file() + assert (resources / 'licenses/xtc/CLAP-LICENSE').is_file() + assert (resources / 'licenses/xtc/VST3-C-API-LICENSE').is_file() assert os.access(binaries / 'xtc-check', os.X_OK) run([str(binaries / 'xtc-check')]) for filename in ('performance-baseline.json', 'project-performance-baseline.json', 'graph-performance-phase29.json'): @@ -52,7 +54,7 @@ def main(): run([str(binaries / 'xtc-check'), '--inspect', str(example)]) assert (resources / 'xtc/examples/README.md').is_file() diagnose = subprocess.check_output([str(binaries / 'xtc-check'), '--diagnose'], text=True) - assert 'Project formats: 1..10' in diagnose and 'JACK compiled:' in diagnose + assert 'Project formats: 1..11' in diagnose and 'JACK compiled:' in diagnose # Replacing a file symlink must not overwrite an unrelated target. protected = stage / 'unrelated-target' protected.write_text('keep unrelated target\n') diff --git a/tests/integration/test_modern_plugins.c b/tests/integration/test_modern_plugins.c new file mode 100644 index 0000000..6b8fb45 --- /dev/null +++ b/tests/integration/test_modern_plugins.c @@ -0,0 +1,116 @@ +#define _POSIX_C_SOURCE 200809L +#include "xtc/xtc_plugin.h" +#include "xtc/xtc_project.h" +#include "xtc/xtc_realtime.h" +#include +#include +#include +#include +#include +#include +static int audio; +void *__real_malloc(size_t); +void *__real_calloc(size_t,size_t); +void *__real_realloc(void *,size_t); +void __real_free(void *); +void *__real_dlopen(const char *,int); +int __real_dlclose(void *); +void *__wrap_malloc(size_t n) { assert(!audio); return __real_malloc(n); } +void *__wrap_calloc(size_t n,size_t s) { assert(!audio); return __real_calloc(n,s); } +void *__wrap_realloc(void *p,size_t n) { assert(!audio); return __real_realloc(p,n); } +void __wrap_free(void *p) { assert(!audio); __real_free(p); } +void *__wrap_dlopen(const char *p,int mode) { assert(!audio); return __real_dlopen(p,mode); } +int __wrap_dlclose(void *p) { assert(!audio); return __real_dlclose(p); } +static void render(xtc_realtime *rt) +{ + float in[31],left[31],right[31]; size_t i; + for (i = 0; i < 31; ++i) in[i] = i % 2 ? -.5f : .25f; + audio = 1; + assert(xtc_realtime_process_stereo(rt,in,NULL,NULL,NULL,NULL,left,right,31) == XTC_OK); + audio = 0; + for (i = 0; i < 31; ++i) assert(left[i] == in[i]*.5f && right[i] == left[i]); + xtc_plugin_idle(); +} +static void check(const char *path, xtc_plugin_format format) +{ + xtc_plugin_spec spec, actual, bad; + xtc_plugin_details details; + xtc_plugin *plugin = NULL, *other = NULL; + xtc_project *p = NULL, *loaded = NULL; + xtc_graph *graph = NULL; + xtc_realtime *rt = NULL; + size_t node, output, i; + char document[] = "/tmp/xtc-modern-XXXXXX"; + int fd = mkstemp(document); assert(fd >= 0); close(fd); + assert(xtc_plugin_probe(path,0,48000,&spec) == XTC_OK && spec.format == format); + assert(xtc_plugin_probe_format(format,path,0,48000,&actual) == XTC_OK); + assert(!memcmp(&spec,&actual,sizeof(spec))); + assert(xtc_plugin_describe(&spec,48000,&details) == XTC_OK && details.name[0]); + assert(xtc_plugin_create(&spec,48000,31,&plugin) == XTC_OK); + assert(xtc_plugin_create(&spec,48000,31,&other) == XTC_OK); + { float data[31]; for (i = 0; i < 31; ++i) data[i] = 1; + audio = 1; assert(xtc_plugin_process(plugin,data,data,31) == XTC_OK); audio = 0; + for (i = 0; i < 31; ++i) assert(data[i] == .5f); + audio = 1; assert(xtc_plugin_process(other,NULL,data,31) == XTC_OK); audio = 0; + for (i = 0; i < 31; ++i) assert(data[i] == 0); + assert(xtc_plugin_process(plugin,data,data,32) == XTC_ERR_INVALID_ARGUMENT); } + xtc_plugin_idle(); xtc_plugin_destroy(plugin); xtc_plugin_destroy(other); plugin = NULL; + assert(xtc_project_create(&p) == XTC_OK && xtc_project_create(&loaded) == XTC_OK); + assert(xtc_graph_create(2,&graph) == XTC_OK); + assert(xtc_graph_add_plugin(graph,&spec,&node) == XTC_OK && xtc_graph_add_output(graph,&output) == XTC_OK); + assert(xtc_graph_connect(graph,node,output) == XTC_OK); + assert(xtc_project_set_graph(p,graph) == XTC_OK); + assert(xtc_project_save(p,document) == XTC_OK && xtc_project_load(loaded,document) == XTC_OK); + assert(xtc_graph_get_plugin(xtc_project_graph(loaded),node,&actual) == XTC_OK); + assert(!memcmp(&actual,&spec,sizeof(spec))); + assert(xtc_realtime_create(48000,31,&rt) == XTC_OK); + assert(xtc_realtime_submit(rt,xtc_project_graph(loaded)) == XTC_OK); render(rt); + for (i = 0; i < 50; ++i) { + xtc_realtime_collect(rt); + assert(xtc_realtime_submit(rt,graph) == XTC_OK); render(rt); + } + if (format == XTC_PLUGIN_VST3) { + bad = spec; strcpy(bad.identifier,"not-a-class-id"); + assert(xtc_plugin_spec_validate(&bad) == XTC_ERR_INVALID_ARGUMENT); + } + bad = spec; bad.control_count = 1; + assert(xtc_plugin_spec_validate(&bad) == XTC_ERR_UNSUPPORTED); + bad = spec; ++bad.unique_id; + assert(xtc_graph_replace_plugin(graph,node,&bad) == XTC_OK); + xtc_realtime_collect(rt); + assert(xtc_realtime_submit(rt,graph) == XTC_ERR_UNSUPPORTED); render(rt); + bad = spec; strcpy(bad.path,"/missing/xtc-modern-plugin.so"); + assert(xtc_graph_replace_plugin(graph,node,&bad) == XTC_OK && xtc_project_set_graph(p,graph) == XTC_OK); + assert(xtc_project_save(p,document) == XTC_OK && xtc_project_load(loaded,document) == XTC_OK); + assert(xtc_graph_get_plugin(xtc_project_graph(loaded),node,&actual) == XTC_OK && !strcmp(actual.path,bad.path)); + assert(xtc_plugin_create(&actual,48000,31,&plugin) == XTC_ERR_NOT_FOUND && !plugin); + xtc_realtime_destroy(rt); xtc_graph_destroy(graph); xtc_project_destroy(p); xtc_project_destroy(loaded); unlink(document); + printf("%s identity, buffers, stereo graph, retirement, reload and missing dependency passed.\n",xtc_plugin_format_name(format)); +} +int main(int argc,char **argv) +{ + unsigned int i; xtc_plugin_spec spec; xtc_plugin *p = NULL; float data[1] = {1}; + assert(argc == 4); + check(argv[1],XTC_PLUGIN_CLAP); check(argv[2],XTC_PLUGIN_VST2); check(argv[3],XTC_PLUGIN_VST3); + for (i = 1; i < 4; ++i) assert(xtc_plugin_probe_format(XTC_PLUGIN_CLAP,argv[1],i,48000,&spec) != XTC_OK); + assert(xtc_plugin_probe_format(XTC_PLUGIN_CLAP,argv[1],4,48000,&spec) == XTC_OK); + assert(xtc_plugin_create(&spec,48000,1,&p) == XTC_OK); + assert(xtc_plugin_process(p,data,data,1) == XTC_ERR_INVALID_STATE && data[0] == 0); xtc_plugin_destroy(p); p = NULL; + assert(xtc_plugin_probe_format(XTC_PLUGIN_CLAP,argv[1],5,48000,&spec) == XTC_OK); + assert(xtc_plugin_create(&spec,48000,1,&p) == XTC_OK); + assert(xtc_plugin_process(p,data,data,1) == XTC_ERR_INVALID_STATE && data[0] == 0); xtc_plugin_destroy(p); + assert(xtc_plugin_probe_format(XTC_PLUGIN_CLAP,argv[1],6,48000,&spec) == XTC_OK); + p = NULL; data[0] = 1; + assert(xtc_plugin_create(&spec,48000,1,&p) == XTC_OK); + assert(xtc_plugin_process(p,data,data,1) == XTC_OK && data[0] == .5f); + xtc_plugin_idle(); + assert(xtc_plugin_process(p,data,data,1) == XTC_ERR_INVALID_STATE && data[0] == 0); xtc_plugin_destroy(p); + assert(xtc_plugin_probe_format(XTC_PLUGIN_CLAP,argv[1],7,48000,&spec) == XTC_ERR_NOT_FOUND); + assert(setenv("XTC_VST2_FIXTURE_LAYOUT","1",1) == 0); + assert(xtc_plugin_probe_format(XTC_PLUGIN_VST2,argv[2],0,48000,&spec) == XTC_ERR_UNSUPPORTED); + unsetenv("XTC_VST2_FIXTURE_LAYOUT"); + assert(setenv("XTC_VST3_FIXTURE_INIT","1",1) == 0); + assert(xtc_plugin_probe_format(XTC_PLUGIN_VST3,argv[3],0,48000,&spec) == XTC_ERR_INVALID_STATE); + unsetenv("XTC_VST3_FIXTURE_INIT"); + puts("Modern plugin partial initialization/start/process failures passed."); return 0; +} diff --git a/tests/integration/test_portability.c b/tests/integration/test_portability.c index a5f70b5..08f2123 100644 --- a/tests/integration/test_portability.c +++ b/tests/integration/test_portability.c @@ -19,7 +19,7 @@ int main(void) assert(mkdtemp(root)); assert(xtc_project_create(&p) == XTC_OK); snprintf(file,sizeof(file),"%s/migration.xtc",root); - for (version = 1; version <= 10; ++version) { + for (version = 1; version <= 11; ++version) { xtc_track_info t; xtc_clip_info c; size_t notes, points; snprintf(old,sizeof(old),"tests/fixtures/project-v%u.xtc",version); assert(xtc_project_load(p,old) == XTC_OK); @@ -89,6 +89,6 @@ int main(void) assert(xtc_project_load(p,file) == XTC_ERR_FORMAT); { xtc_clip_info c; assert(xtc_project_find_clip(p,clip,&c) == XTC_OK && c.asset_path[0]); } } xtc_project_destroy(p); unlink(file); rmdir(moved); - puts("v1-v10 migration, current folder relocation, cwd independence and missing-media preservation passed."); + puts("v1-v11 migration, current folder relocation, cwd independence and missing-media preservation passed."); return 0; } diff --git a/tests/integration/test_project_inspection.py b/tests/integration/test_project_inspection.py index 22ddae5..95ac2a6 100644 --- a/tests/integration/test_project_inspection.py +++ b/tests/integration/test_project_inspection.py @@ -36,8 +36,37 @@ with tempfile.TemporaryDirectory(prefix="xtc-inspect-") as directory: # Inspection succeeds for readable files without trying dlopen or decoding. module.write_text("Deliberately not an executable module") check("--inspect", project, 0, "no plugin code executed") + # Current metadata-only inspection must not execute any modern plugin ABI. + maps = base[base.index("CONTROL_MAPS"):] + for number, name, identity in ((1, "CLAP", "org.xtc.fixture"), (2, "VST2", ""), + (3, "VST3", "0123456789abcdef0123456789abcdef")): + lines = [] + for line in plugin.splitlines(): + if line.startswith(("CONTROL ", "PARAM ")): + continue + if line.startswith("XTC_PROJECT "): + line = "XTC_PROJECT 11" + elif line.startswith("PLUGIN "): + fields = line.split() + fields[4] = "0" + line = " ".join(fields) + elif line.startswith("PLUGIN_AUTOMATION "): + line = "PLUGIN_AUTOMATION 0" + elif line == "END": + line = maps.rstrip() + lines.append(line) + if line.startswith("MODULE "): + lines.append(f"FORMAT {number} {identity.encode().hex() if identity else '-'}") + modern = "\n".join(lines) + "\n" + project.write_text(modern) + check("--inspect", project, 0, name + " node 0", "Project format 11") + project.write_text(modern.replace(f"FORMAT {number} ", "FORMAT 99 ")) + check("--validate", project, 1, "Unsupported") + if number == 3: + project.write_text(modern.replace(identity.encode().hex(), b"bad-class-id".hex())) + check("--validate", project, 1) for text, messages in [ - (base.replace("XTC_PROJECT 10", "XTC_PROJECT 999"), ("line 1", "999", "1..10")), + (base.replace("XTC_PROJECT 10", "XTC_PROJECT 999"), ("line 1", "999", "1..11")), ("XTC_PROJECT 10\n", ("line 2", "APP")), (base.replace("TEMPO 120000", "TEMPO 0"), ("line 3", "TEMPO")), (base + "OPTIONAL_FUTURE 1\n", ("Unknown fields",)), diff --git a/tests/plugins/clap_fixture.c b/tests/plugins/clap_fixture.c new file mode 100644 index 0000000..dcb111d --- /dev/null +++ b/tests/plugins/clap_fixture.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +static int loaded, count; +static const char *features[] = {CLAP_PLUGIN_FEATURE_AUDIO_EFFECT,NULL}; +static const clap_plugin_descriptor_t descriptors[] = { + {CLAP_VERSION,"xtc.fixture.gain","CLAP gain","xtc","","","","1","",features}, + {CLAP_VERSION,"xtc.fixture.stereo","Stereo","xtc","","","","1","",features}, + {CLAP_VERSION,"xtc.fixture.init","Init failure","xtc","","","","1","",features}, + {CLAP_VERSION,"xtc.fixture.activate","Activate failure","xtc","","","","1","",features}, + {CLAP_VERSION,"xtc.fixture.start","Start failure","xtc","","","","1","",features}, + {CLAP_VERSION,"xtc.fixture.process","Process failure","xtc","","","","1","",features}, + {CLAP_VERSION,"xtc.fixture.restart","Restart request","xtc","","","","1","",features} +}; +typedef struct { clap_plugin_t plugin; const clap_host_t *host; unsigned int index; int active, started; } instance; +static bool init(const clap_plugin_t *plugin) +{ instance *p = plugin->plugin_data; assert(loaded); return p->index != 2; } +static void destroy(const clap_plugin_t *plugin) +{ instance *p = plugin->plugin_data; assert(!p->active && !p->started); --count; free(p); } +static bool activate(const clap_plugin_t *plugin, double rate, uint32_t min, uint32_t max) +{ instance *p = plugin->plugin_data; assert(rate > 0 && min && max >= min && !p->active); if (p->index == 3) return false; p->active = 1; return true; } +static void deactivate(const clap_plugin_t *plugin) +{ instance *p = plugin->plugin_data; assert(p->active && !p->started); p->active = 0; } +static bool start(const clap_plugin_t *plugin) +{ + instance *p = plugin->plugin_data; + const clap_host_thread_check_t *check = p->host->get_extension(p->host,CLAP_EXT_THREAD_CHECK); + assert(p->active && !p->started && check->is_audio_thread(p->host)); + if (p->index == 4) return false; + p->started = 1; return true; +} +static void stop(const clap_plugin_t *plugin) +{ instance *p = plugin->plugin_data; assert(p->started); p->started = 0; } +static void reset(const clap_plugin_t *plugin) { (void)plugin; } +static clap_process_status process(const clap_plugin_t *plugin, const clap_process_t *block) +{ + instance *p = plugin->plugin_data; uint32_t i; + assert(p->started && block->audio_inputs_count == 1 && block->audio_outputs_count == 1 && block->in_events->size(block->in_events) == 0); + if (p->index == 5) return CLAP_PROCESS_ERROR; + for (i = 0; i < block->frames_count; ++i) block->audio_outputs[0].data32[0][i] = block->audio_inputs[0].data32[0][i]*.5f; + p->host->request_callback(p->host); + if (p->index == 6) p->host->request_restart(p->host); + return CLAP_PROCESS_CONTINUE; +} +static uint32_t port_count(const clap_plugin_t *plugin, bool input) { (void)plugin; (void)input; return 1; } +static bool port_get(const clap_plugin_t *plugin, uint32_t index, bool input, clap_audio_port_info_t *info) +{ instance *p = plugin->plugin_data; (void)input; if (index) return false; memset(info,0,sizeof(*info)); info->channel_count = p->index == 1 ? 2 : 1; return true; } +static uint32_t latency(const clap_plugin_t *plugin) +{ instance *p = plugin->plugin_data; assert(p->active); return 0; } +static const void *extension(const clap_plugin_t *plugin, const char *id) +{ + static const clap_plugin_audio_ports_t ports = {port_count,port_get}; + static const clap_plugin_latency_t delay = {latency}; (void)plugin; + if (!strcmp(id,CLAP_EXT_AUDIO_PORTS)) return &ports; + return !strcmp(id,CLAP_EXT_LATENCY) ? &delay : NULL; +} +static void on_main(const clap_plugin_t *plugin) +{ instance *p = plugin->plugin_data; const clap_host_thread_check_t *check = p->host->get_extension(p->host,CLAP_EXT_THREAD_CHECK); assert(check->is_main_thread(p->host)); } +static uint32_t plugin_count(const clap_plugin_factory_t *factory) { (void)factory; return 7; } +static const clap_plugin_descriptor_t *descriptor(const clap_plugin_factory_t *factory, uint32_t index) +{ (void)factory; return index < 7 ? descriptors+index : NULL; } +static const clap_plugin_t *create(const clap_plugin_factory_t *factory, const clap_host_t *host, const char *id) +{ + unsigned int i; instance *p; (void)factory; + for (i = 0; i < 7 && strcmp(id,descriptors[i].id); ++i) {} + if (i == 7) return NULL; + p = calloc(1,sizeof(*p)); if (!p) return NULL; + p->host = host; p->index = i; + p->plugin = (clap_plugin_t){descriptors+i,p,init,destroy,activate,deactivate,start,stop,reset,process,extension,on_main}; + ++count; return &p->plugin; +} +static bool entry_init(const char *path) { (void)path; assert(!loaded); loaded = 1; return true; } +static void entry_exit(void) { assert(loaded && !count); loaded = 0; } +static const void *factory(const char *id) +{ static const clap_plugin_factory_t f = {plugin_count,descriptor,create}; return !strcmp(id,CLAP_PLUGIN_FACTORY_ID) ? &f : NULL; } +CLAP_EXPORT const clap_plugin_entry_t clap_entry = {CLAP_VERSION,entry_init,entry_exit,factory}; diff --git a/tests/plugins/vst2_fixture.c b/tests/plugins/vst2_fixture.c new file mode 100644 index 0000000..fc8f207 --- /dev/null +++ b/tests/plugins/vst2_fixture.c @@ -0,0 +1,34 @@ +/* Original MIT ABI fixture; not built from or linked to a proprietary SDK. */ +#include "../../src/plugin/vst2_abi.h" +#include +#include +#include +typedef struct { xtc_v2_effect effect; int open, active, started; } instance; +static intptr_t dispatch(xtc_v2_effect *e, int32_t op, int32_t index, intptr_t value, void *ptr, float option) +{ + instance *p = (instance *)e; (void)index; (void)option; + switch (op) { + case 0: assert(!p->open); p->open = 1; break; + case 1: assert(p->open && !p->active && !p->started); free(p); break; + case 12: p->active = value != 0; break; + case 45: strcpy(ptr,"VST2 gain"); return 1; + case 71: assert(p->active); p->started = 1; break; + case 72: p->started = 0; break; + default: break; + } + return 0; +} +static void process(xtc_v2_effect *e, float **input, float **output, int32_t frames) +{ instance *p = (instance *)e; int32_t i; assert(p->started); for (i = 0; i < frames; ++i) output[0][i] = input[0][i]*.5f; } +xtc_v2_effect *VSTPluginMain(xtc_v2_host host); +xtc_v2_effect *VSTPluginMain(xtc_v2_host host) +{ + instance *p; assert(host(NULL,1,0,0,NULL,0) == 2400); + p = calloc(1,sizeof(*p)); if (!p) return NULL; + p->effect.magic = XTC_V2_MAGIC; p->effect.dispatch = dispatch; + p->effect.inputs = p->effect.outputs = 1; + if (getenv("XTC_VST2_FIXTURE_LAYOUT")) p->effect.inputs = 2; + p->effect.flags = 16; + p->effect.unique_id = 0x58544332; p->effect.replace = process; + return &p->effect; +} diff --git a/tests/plugins/vst3_fixture.c b/tests/plugins/vst3_fixture.c new file mode 100644 index 0000000..6176e57 --- /dev/null +++ b/tests/plugins/vst3_fixture.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +static int loaded, instances; +static const Steinberg_TUID cid = SMTG_INLINE_UID(0x58544333,0x12345678,0x12345678,0x12345678); +typedef struct { Steinberg_Vst_IComponent component; Steinberg_Vst_IAudioProcessor processor; unsigned int refs; int initialized, active, started; } instance; +static instance *from_processor(void *p) { return (instance *)((char *)p - offsetof(instance,processor)); } +static Steinberg_tresult cq(void *self, const Steinberg_TUID iid, void **out) +{ + instance *p = self; *out = NULL; + if (!memcmp(iid,Steinberg_Vst_IAudioProcessor_iid,16)) *out = &p->processor; + else if (!memcmp(iid,Steinberg_Vst_IComponent_iid,16) || !memcmp(iid,Steinberg_FUnknown_iid,16)) *out = &p->component; + if (!*out) return -1; + ++p->refs; return 0; +} +static Steinberg_uint32 add(void *self) { return ++((instance *)self)->refs; } +static Steinberg_uint32 release(void *self) +{ instance *p = self; unsigned int refs = --p->refs; if (!refs) { assert(!p->initialized); --instances; free(p); } return refs; } +static Steinberg_tresult pq(void *self, const Steinberg_TUID iid, void **out) { return cq(from_processor(self),iid,out); } +static Steinberg_uint32 pa(void *self) { return add(from_processor(self)); } +static Steinberg_uint32 pr(void *self) { return release(from_processor(self)); } +static Steinberg_tresult init(void *self, Steinberg_FUnknown *host) +{ instance *p = self; assert(loaded && host && !p->initialized); if (getenv("XTC_VST3_FIXTURE_INIT")) return -1; p->initialized = 1; return 0; } +static Steinberg_tresult terminate(void *self) { instance *p = self; assert(p->initialized && !p->active); p->initialized = 0; return 0; } +static Steinberg_tresult controller(void *self, Steinberg_TUID id) { (void)self; (void)id; return -1; } +static Steinberg_tresult mode(void *self, Steinberg_Vst_IoMode m) { (void)self; (void)m; return 0; } +static Steinberg_int32 buses(void *self, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir) { (void)self; (void)dir; return type == 0 ? 1 : 0; } +static Steinberg_tresult bus_info(void *self, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, struct Steinberg_Vst_BusInfo *info) +{ (void)self; (void)dir; assert(type == 0 && index == 0); memset(info,0,sizeof(*info)); info->channelCount = 1; return 0; } +static Steinberg_tresult routing(void *self, struct Steinberg_Vst_RoutingInfo *in, struct Steinberg_Vst_RoutingInfo *out) +{ (void)self; (void)in; (void)out; return -1; } +static Steinberg_tresult activate_bus(void *self, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, Steinberg_TBool state) +{ (void)self; (void)type; (void)dir; (void)index; (void)state; return 0; } +static Steinberg_tresult active(void *self, Steinberg_TBool state) { instance *p = self; assert(!p->started); p->active = state; return 0; } +static Steinberg_tresult state(void *self, Steinberg_IBStream *stream) { (void)self; (void)stream; return -1; } +static Steinberg_tresult arrangements(void *self, Steinberg_Vst_SpeakerArrangement *in, Steinberg_int32 ni, Steinberg_Vst_SpeakerArrangement *out, Steinberg_int32 no) +{ (void)self; return ni == 1 && no == 1 && in[0] == Steinberg_Vst_SpeakerArr_kMono && out[0] == in[0] ? 0 : -1; } +static Steinberg_tresult arrangement(void *self, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, Steinberg_Vst_SpeakerArrangement *out) +{ (void)self; (void)dir; (void)index; *out = Steinberg_Vst_SpeakerArr_kMono; return 0; } +static Steinberg_tresult sample_size(void *self, Steinberg_int32 size) { (void)self; return size == 0 ? 0 : -1; } +static Steinberg_uint32 latency(void *self) { (void)self; return 0; } +static Steinberg_tresult setup(void *self, struct Steinberg_Vst_ProcessSetup *data) { (void)self; return data->maxSamplesPerBlock > 0 && data->sampleRate > 0 ? 0 : -1; } +static Steinberg_tresult processing(void *self, Steinberg_TBool value) { instance *p = from_processor(self); assert(p->active); p->started = value; return 0; } +static Steinberg_tresult process(void *self, struct Steinberg_Vst_ProcessData *data) +{ instance *p = from_processor(self); int32_t i; assert(p->started); for (i = 0; i < data->numSamples; ++i) data->outputs[0].Steinberg_Vst_AudioBusBuffers_channelBuffers32[0][i] = data->inputs[0].Steinberg_Vst_AudioBusBuffers_channelBuffers32[0][i]*.5f; return 0; } +static Steinberg_Vst_IComponentVtbl component_vtable = {cq,add,release,init,terminate,controller,mode,buses,bus_info,routing,activate_bus,active,state,state}; +static Steinberg_Vst_IAudioProcessorVtbl processor_vtable = {pq,pa,pr,arrangements,arrangement,sample_size,latency,setup,processing,process,latency}; +static Steinberg_tresult fq(void *self, const Steinberg_TUID iid, void **out) { (void)iid; *out = self; return 0; } +static Steinberg_uint32 fr(void *self) { (void)self; return 1; } +static Steinberg_tresult factory_info(void *self, struct Steinberg_PFactoryInfo *info) { (void)self; memset(info,0,sizeof(*info)); return 0; } +static Steinberg_int32 classes(void *self) { (void)self; return 1; } +static Steinberg_tresult class_info(void *self, Steinberg_int32 index, struct Steinberg_PClassInfo *info) +{ (void)self; if (index) return -1; memset(info,0,sizeof(*info)); memcpy(info->cid,cid,16); strcpy(info->category,"Audio Module Class"); strcpy(info->name,"VST3 gain"); return 0; } +static Steinberg_tresult create(void *self, Steinberg_FIDString id, Steinberg_FIDString iid, void **out) +{ + instance *p; (void)self; *out = NULL; + if (memcmp(id,cid,16) || memcmp(iid,Steinberg_Vst_IComponent_iid,16)) return -1; + p = calloc(1,sizeof(*p)); if (!p) return -1; + p->component.lpVtbl = &component_vtable; p->processor.lpVtbl = &processor_vtable; p->refs = 1; + ++instances; *out = p; return 0; +} +static Steinberg_IPluginFactoryVtbl factory_vtable = {fq,fr,fr,factory_info,classes,class_info,create}; +static Steinberg_IPluginFactory factory = {&factory_vtable}; +bool ModuleEntry(void *handle); +bool ModuleExit(void); +Steinberg_IPluginFactory *GetPluginFactory(void); +bool ModuleEntry(void *handle) { assert(handle && !loaded); loaded = 1; return true; } +bool ModuleExit(void) { assert(loaded && !instances); loaded = 0; return true; } +Steinberg_IPluginFactory *GetPluginFactory(void) { assert(loaded); return &factory; } diff --git a/tests/unit/test_project_diagnostics.c b/tests/unit/test_project_diagnostics.c index 85281d7..da2e10e 100644 --- a/tests/unit/test_project_diagnostics.c +++ b/tests/unit/test_project_diagnostics.c @@ -68,7 +68,7 @@ int main(void) assert(xtc_project_add_track(old,"Old",&id) == XTC_OK && xtc_project_add_track(next,"New",&id) == XTC_OK); assert(xtc_project_save(old,song) == XTC_OK); size = bytes(song,before); assert(xtc_project_load_diagnostic(loaded,song,&diagnostic) == XTC_OK && diagnostic.result == XTC_OK && - diagnostic.format_version == 10 && !diagnostic.line); + diagnostic.format_version == 11 && !diagnostic.line); for (mode = 1; mode <= 5; ++mode) { fault = mode; assert(xtc_project_save(next,song) == XTC_ERR_IO); @@ -81,7 +81,7 @@ int main(void) } write_text(bad,"XTC_PROJECT 999\n"); assert(xtc_project_load_diagnostic(loaded,bad,&diagnostic) == XTC_ERR_UNSUPPORTED && diagnostic.line == 1 && - diagnostic.format_version == 999 && !strcmp(diagnostic.record,"XTC_PROJECT") && strstr(diagnostic.message,"1..10")); + diagnostic.format_version == 999 && !strcmp(diagnostic.record,"XTC_PROJECT") && strstr(diagnostic.message,"1..11")); write_text(bad,"XTC_PROJECT 10\nAPP 0 1 0\nTEMPO nope\n"); assert(xtc_project_load_diagnostic(loaded,bad,&diagnostic) == XTC_ERR_FORMAT && diagnostic.line == 3 && !strcmp(diagnostic.record,"TEMPO")); diff --git a/third_party/README.md b/third_party/README.md new file mode 100644 index 0000000..1458663 --- /dev/null +++ b/third_party/README.md @@ -0,0 +1,20 @@ +# Pinned plugin ABI headers + +No plugin binaries or SDK runtime library are bundled. Updates are explicit, +reviewed source changes; ordinary builds never fetch from the network. + +| Headers | Upstream revision | License | Maintenance/build impact | +| --- | --- | --- | --- | +| `clap/include` | [free-audio/clap](https://github.com/free-audio/clap), `a47f6badb49d948fd009998f28309cdab78979c9` | MIT, `clap/LICENSE` | Active CLAP header specification, pinned snapshot; C99 compile-time dependency only | +| `vst3/vst3_c_api.h` | [steinbergmedia/vst3_c_api](https://github.com/steinbergmedia/vst3_c_api), `93a116f7c6c52a317ec3aaee9b13789068b5234e` | BSD-3-Clause, `vst3/LICENSE.txt` | Official generated C ABI; review compatibility when updating the SDK snapshot; no C++ runtime adapter | + +Files are unmodified upstream snapshots. The VST3 header's opening comment refers +to its accompanying license; that upstream license is retained verbatim. Install +and binary packages include both notices under the xtc license directory. These +headers define interoperability ABIs, not a grant to redistribute user plugins. + +`src/plugin/vst2_abi.h` is original minimal Linux compatibility declarations; no +Steinberg VST2 SDK, implementation or VST2-wrapping SDK is copied or distributed. +Legacy VST2 support does not grant SDK/trademark/plugin distribution rights. There +is no VST2 plugin-building target for third-party SDKs. The original test fixture +implements only the ABI subset needed to test this host. diff --git a/third_party/clap/LICENSE b/third_party/clap/LICENSE new file mode 100644 index 0000000..428a3e5 --- /dev/null +++ b/third_party/clap/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Alexandre BIQUE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/clap/include/clap/all.h b/third_party/clap/include/clap/all.h new file mode 100644 index 0000000..a1063f9 --- /dev/null +++ b/third_party/clap/include/clap/all.h @@ -0,0 +1,25 @@ +#pragma once + +#include "clap.h" + +#include "factory/draft/plugin-invalidation.h" +#include "factory/draft/plugin-state-converter.h" + +#include "ext/draft/background-activation.h" +#include "ext/draft/background-progress.h" +#include "ext/draft/background-state-context.h" +#include "ext/draft/extensible-audio-ports.h" +#include "ext/draft/flush-events.h" +#include "ext/draft/gain-adjustment-metering.h" +#include "ext/draft/mini-curve-display.h" +#include "ext/draft/octave-number.h" +#include "ext/draft/params-origin.h" +#include "ext/draft/param-hovered.h" +#include "ext/draft/project-location.h" +#include "ext/draft/resource-directory.h" +#include "ext/draft/scratch-memory.h" +#include "ext/draft/transport-control.h" +#include "ext/draft/triggers.h" +#include "ext/draft/tuning.h" +#include "ext/draft/undo.h" +#include "ext/draft/webview.h" diff --git a/third_party/clap/include/clap/audio-buffer.h b/third_party/clap/include/clap/audio-buffer.h new file mode 100644 index 0000000..cd18f3a --- /dev/null +++ b/third_party/clap/include/clap/audio-buffer.h @@ -0,0 +1,37 @@ +#pragma once + +#include "private/std.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Sample code for reading a stereo buffer: +// +// bool isLeftConstant = (buffer->constant_mask & (1 << 0)) != 0; +// bool isRightConstant = (buffer->constant_mask & (1 << 1)) != 0; +// +// for (int i = 0; i < N; ++i) { +// float l = data32[0][isLeftConstant ? 0 : i]; +// float r = data32[1][isRightConstant ? 0 : i]; +// } +// +// Note: checking the constant mask is optional, and this implies that +// the buffer must be filled with the constant value. +// Rationale: if a buffer reader doesn't check the constant mask, then it may +// process garbage samples and in result, garbage samples may be transmitted +// to the audio interface with all the bad consequences it can have. +// +// The constant mask is a hint. +typedef struct clap_audio_buffer { + // Either data32 or data64 pointer will be set. + float **data32; + double **data64; + uint32_t channel_count; + uint32_t latency; // latency from/to the audio interface + uint64_t constant_mask; +} clap_audio_buffer_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/clap.h b/third_party/clap/include/clap/clap.h new file mode 100644 index 0000000..6da5676 --- /dev/null +++ b/third_party/clap/include/clap/clap.h @@ -0,0 +1,64 @@ +/* + * CLAP - CLever Audio Plugin + * ~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Copyright (c) 2014...2022 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. + */ + +#pragma once + +#include "entry.h" + +#include "factory/plugin-factory.h" +#include "factory/preset-discovery.h" + +#include "plugin.h" +#include "plugin-features.h" +#include "host.h" +#include "universal-plugin-id.h" + +#include "ext/ambisonic.h" +#include "ext/audio-ports-activation.h" +#include "ext/audio-ports-config.h" +#include "ext/audio-ports.h" +#include "ext/configurable-audio-ports.h" +#include "ext/context-menu.h" +#include "ext/event-registry.h" +#include "ext/gui.h" +#include "ext/latency.h" +#include "ext/log.h" +#include "ext/note-name.h" +#include "ext/note-ports.h" +#include "ext/param-indication.h" +#include "ext/params.h" +#include "ext/posix-fd-support.h" +#include "ext/preset-load.h" +#include "ext/remote-controls.h" +#include "ext/render.h" +#include "ext/state-context.h" +#include "ext/state.h" +#include "ext/surround.h" +#include "ext/tail.h" +#include "ext/thread-check.h" +#include "ext/thread-pool.h" +#include "ext/timer-support.h" +#include "ext/track-info.h" +#include "ext/voice-info.h" diff --git a/third_party/clap/include/clap/color.h b/third_party/clap/include/clap/color.h new file mode 100644 index 0000000..9da24fa --- /dev/null +++ b/third_party/clap/include/clap/color.h @@ -0,0 +1,20 @@ +#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; + +static const CLAP_CONSTEXPR clap_color_t CLAP_COLOR_TRANSPARENT = { 0, 0, 0, 0 }; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/entry.h b/third_party/clap/include/clap/entry.h new file mode 100644 index 0000000..3ff1ad5 --- /dev/null +++ b/third_party/clap/include/clap/entry.h @@ -0,0 +1,136 @@ +#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 +// - %COMMONPROGRAMFILES%\CLAP +// - %LOCALAPPDATA%\Programs\Common\CLAP +// +// MacOS +// - /Library/Audio/Plug-Ins/CLAP +// - ~/Library/Audio/Plug-Ins/CLAP +// +// In addition to the OS-specific default locations above, a CLAP host must query the environment +// for a CLAP_PATH variable, which is a list of directories formatted in the same manner as the host +// OS binary search path (PATH on Unix, separated by `:` and Path on Windows, separated by ';', as +// of this writing). +// +// Each directory should be recursively searched for files and/or bundles as appropriate in your OS +// ending with the extension `.clap`. +// +// init and deinit in most cases are called once, in a matched pair, when the dso is loaded / unloaded. +// In some rare situations it may be called multiple times in a process, so the functions must be defensive, +// mutex locking and counting calls if undertaking non trivial non idempotent actions. +// +// Rationale: +// +// The intent of the init() and deinit() functions is to provide a "normal" initialization pattern +// which occurs when the shared object is loaded or unloaded. As such, hosts will call each once and +// in matched pairs. In CLAP specifications prior to 1.2.0, this single-call was documented as a +// requirement. +// +// We realized, though, that this is not a requirement hosts can meet. If hosts load a plugin +// which itself wraps another CLAP for instance, while also loading that same clap in its memory +// space, both the host and the wrapper will call init() and deinit() and have no means to communicate +// the state. +// +// With CLAP 1.2.0 and beyond we are changing the spec to indicate that a host should make an +// absolute best effort to call init() and deinit() once, and always in matched pairs (for every +// init() which returns true, one deinit() should be called). +// +// This takes the de-facto burden on plugin writers to deal with multiple calls into a hard requirement. +// +// Most init() / deinit() pairs we have seen are the relatively trivial {return true;} and {}. But +// if your init() function does non-trivial one time work, the plugin author must maintain a counter +// and must manage a mutex lock. The most obvious implementation will maintain a static counter and a +// global mutex, increment the counter on each init, decrement it on each deinit, and only undertake +// the init or deinit action when the counter is zero. +typedef struct clap_plugin_entry { + clap_version_t clap_version; // initialized to CLAP_VERSION + + // Initializes the DSO. + // + // This function must be called first, before any-other CLAP-related function or symbol from this + // DSO. + // + // It also must only be called once, until a later call to deinit() is made, after which init() + // can be called once more to re-initialize the DSO. + // This enables hosts to e.g. quickly load and unload a DSO for scanning its plugins, and then + // load it again later to actually use the plugins if needed. + // + // As stated above, even though hosts are forbidden to do so directly, multiple calls before any + // deinit() call may still happen. Implementations *should* take this into account, and *must* + // do so as of CLAP 1.2.0. + // + // It should be as fast as possible, in order to perform a very quick scan of the plugin + // descriptors. + // + // It is forbidden to display graphical user interfaces in this call. + // It is forbidden to perform any user interaction in this call. + // + // If the initialization depends upon expensive computation, maybe try to do them ahead of time + // and cache the result. + // + // Returns true on success. If init() returns false, then the DSO must be considered + // uninitialized, and the host must not call deinit() nor any other CLAP-related symbols from the + // DSO. + // This function also returns true in the case where the DSO is already initialized, and no + // actual initialization work is done in this call, as explain above. + // + // plugin_path is the path to the DSO (Linux, Windows), or the bundle (macOS). + // + // This function may be called on any thread, including a different one from the one a later call + // to deinit() (or a later init()) can be made. + // However, it is forbidden to call this function simultaneously from multiple threads. + // It is also forbidden to call it simultaneously with *any* other CLAP-related symbols from the + // DSO, including (but not limited to) deinit(). + bool(CLAP_ABI *init)(const char *plugin_path); + + // De-initializes the DSO, freeing any resources allocated or initialized by init(). + // + // After this function is called, no more calls into the DSO must be made, except calling init() + // again to re-initialize the DSO. + // This means that after deinit() is called, the DSO can be considered to be in the same state + // as if init() was never called at all yet, enabling it to be re-initialized as needed. + // + // As stated above, even though hosts are forbidden to do so directly, multiple calls before any + // new init() call may still happen. Implementations *should* take this into account, and *must* + // do so as of CLAP 1.2.0. + // + // Just like init(), this function may be called on any thread, including a different one from + // the one init() was called from, or from the one a later init() call can be made. + // However, it is forbidden to call this function simultaneously from multiple threads. + // It is also forbidden to call it simultaneously with *any* other CLAP-related symbols from the + // DSO, including (but not limited to) deinit(). + void(CLAP_ABI *deinit)(void); + + // Get the pointer to a factory. See factory/plugin-factory.h for an example. + // + // Returns null if the factory is not provided. + // The returned pointer must *not* be freed by the caller. + // + // Unlike init() and deinit(), this function can be called simultaneously by multiple threads. + // + // [thread-safe] + const void *(CLAP_ABI *get_factory)(const char *factory_id); +} clap_plugin_entry_t; + +/* Entry point */ +CLAP_EXPORT extern const clap_plugin_entry_t clap_entry; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/events.h b/third_party/clap/include/clap/events.h new file mode 100644 index 0000000..a39df02 --- /dev/null +++ b/third_party/clap/include/clap/events.h @@ -0,0 +1,367 @@ +#pragma once + +#include "private/std.h" +#include "fixedpoint.h" +#include "id.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// event header +// All clap events start with an event header to determine the overall +// size of the event and its type and space (a namespacing for types). +// clap_event objects are contiguous regions of memory which can be copied +// with a memcpy of `size` bytes starting at the top of the header. As +// such, be very careful when designing clap events with internal pointers +// and other non-value-types to consider the lifetime of those members. +typedef struct clap_event_header { + uint32_t size; // event size including this header, eg: sizeof (clap_event_note) + uint32_t time; // sample offset within the buffer for this event + uint16_t space_id; // event space, see clap_host_event_registry + uint16_t type; // event type + uint32_t flags; // see clap_event_flags +} clap_event_header_t; + +// The clap core event space +static const CLAP_CONSTEXPR uint16_t CLAP_CORE_EVENT_SPACE_ID = 0; + +enum clap_event_flags { + // Indicate a live user event, for example a user turning a physical knob + // or playing a physical key. + CLAP_EVENT_IS_LIVE = 1 << 0, + + // Indicate that the event should not be recorded. + // For example this is useful when a parameter changes because of a MIDI CC, + // because if the host records both the MIDI CC automation and the parameter + // automation there will be a conflict. + CLAP_EVENT_DONT_RECORD = 1 << 1, +}; + +// Some of the following events overlap, a note on can be expressed with: +// - CLAP_EVENT_NOTE_ON +// - CLAP_EVENT_MIDI +// - CLAP_EVENT_MIDI2 +// +// The preferred way of sending a note event is to use CLAP_EVENT_NOTE_*. +// +// The same event must not be sent twice: it is forbidden to send a the same note on +// encoded with both CLAP_EVENT_NOTE_ON and CLAP_EVENT_MIDI. +// +// The plugins are encouraged to be able to handle note events encoded as raw midi or midi2, +// or implement clap_plugin_event_filter and reject raw midi and midi2 events. +enum { + // NOTE_ON and NOTE_OFF represent a key pressed and key released event, respectively. + // A NOTE_ON with a velocity of 0 is valid and should not be interpreted as a NOTE_OFF. + // + // NOTE_CHOKE is meant to choke the voice(s), like in a drum machine when a closed hihat + // chokes an open hihat. This event can be sent by the host to the plugin. Here are two use + // cases: + // - a plugin is inside a drum pad in Bitwig Studio's drum machine, and this pad is choked by + // another one + // - the user double-clicks the DAW's stop button in the transport which then stops the sound on + // every track + // + // NOTE_END is sent by the plugin to the host. The port, channel, key and note_id are those given + // by the host in the NOTE_ON event. In other words, this event is matched against the + // plugin's note input port. + // NOTE_END is useful to help the host to match the plugin's voice life time. + // + // When using polyphonic modulations, the host has to allocate and release voices for its + // polyphonic modulator. Yet only the plugin effectively knows when the host should terminate + // a voice. NOTE_END solves that issue in a non-intrusive and cooperative way. + // + // CLAP assumes that the host will allocate a unique voice on NOTE_ON event for a given port, + // channel and key. This voice will run until the plugin will instruct the host to terminate + // it by sending a NOTE_END event. + // + // Consider the following sequence: + // - process() + // Host->Plugin NoteOn(port:0, channel:0, key:16, time:t0) + // Host->Plugin NoteOn(port:0, channel:0, key:64, time:t0) + // Host->Plugin NoteOff(port:0, channel:0, key:16, t1) + // Host->Plugin NoteOff(port:0, channel:0, key:64, t1) + // # on t2, both notes did terminate + // Host->Plugin NoteOn(port:0, channel:0, key:64, t3) + // # Here the plugin finished processing all the frames and will tell the host + // # to terminate the voice on key 16 but not 64, because a note has been started at t3 + // Plugin->Host NoteEnd(port:0, channel:0, key:16, time:ignored) + // + // These four events use clap_event_note. + CLAP_EVENT_NOTE_ON = 0, + CLAP_EVENT_NOTE_OFF = 1, + CLAP_EVENT_NOTE_CHOKE = 2, + CLAP_EVENT_NOTE_END = 3, + + // Represents a note expression. + // Uses clap_event_note_expression. + CLAP_EVENT_NOTE_EXPRESSION = 4, + + // 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 = 5, + CLAP_EVENT_PARAM_MOD = 6, + + // Indicates that the user started or finished adjusting a knob. + // This is not mandatory to wrap parameter changes with gesture events, but this improves + // the user experience a lot when recording automation or overriding automation playback. + // Uses clap_event_param_gesture. + CLAP_EVENT_PARAM_GESTURE_BEGIN = 7, + CLAP_EVENT_PARAM_GESTURE_END = 8, + + CLAP_EVENT_TRANSPORT = 9, // update the transport info; clap_event_transport + CLAP_EVENT_MIDI = 10, // raw midi event; clap_event_midi + CLAP_EVENT_MIDI_SYSEX = 11, // raw midi sysex event; clap_event_midi_sysex + CLAP_EVENT_MIDI2 = 12, // raw midi 2 event; clap_event_midi2 +}; + +// Note on, off, end and choke events. +// +// Clap addresses notes and voices using the 4-value tuple +// (port, channel, key, note_id). Note on/off/end/choke +// events and parameter modulation messages are delivered with +// these values populated. +// +// Values in a note and voice address are either >= 0 if they +// are specified, or -1 to indicate a wildcard. A wildcard +// means a voice with any value in that part of the tuple +// matches the message. +// +// For instance, a (PCKN) of (0, 3, -1, -1) will match all voices +// on channel 3 of port 0. And a PCKN of (-1, 0, 60, -1) will match +// all channel 0 key 60 voices, independent of port or note id. +// +// Especially in the case of note-on note-off pairs, and in the +// absence of voice stacking or polyphonic modulation, a host may +// choose to issue a note id only at note on. So you may see a +// message stream like +// +// CLAP_EVENT_NOTE_ON [0,0,60,184] +// CLAP_EVENT_NOTE_OFF [0,0,60,-1] +// +// and the host will expect the first voice to be released. +// Well constructed plugins will search for voices and notes using +// the entire tuple. +// +// In the case of note on events: +// - The port, channel and key must be specified with a value >= 0 +// - A note-on event with a '-1' for port, channel or key is invalid and +// can be rejected or ignored by a plugin or host. +// - A host which does not support note ids should set the note id to -1. +// +// In the case of note choke or end events: +// - the velocity is ignored. +// - key and channel are used to match active notes +// - note_id is optionally provided by the host +typedef struct clap_event_note { + clap_event_header_t header; + + int32_t note_id; // host provided note id >= 0, or -1 if unspecified or wildcard + int16_t port_index; // port index from ext/note-ports; -1 for wildcard + int16_t channel; // 0..15, same as MIDI1 Channel Number, -1 for wildcard + int16_t key; // 0..127, same as MIDI1 Key Number (60==Middle C), -1 for wildcard + double velocity; // 0..1 +} clap_event_note_t; + +// Note Expressions are well named modifications of a voice targeted to +// voices using the same wildcard rules described above. Note Expressions are delivered +// as sample accurate events and should be applied at the sample when received. +// +// Note expressions are a statement of value, not cumulative. A PAN event of 0 followed by 1 +// followed by 0.5 would pan hard left, hard right, and center. They are intended as +// an offset from the non-note-expression voice default. A voice which had a volume of +// -20db absent note expressions which received a +4db note expression would move the +// voice to -16db. +// +// A plugin which receives a note expression at the same sample as a NOTE_ON event +// should apply that expression to all generated samples. A plugin which receives +// a note expression after a NOTE_ON event should initiate the voice with default +// values and then apply the note expression when received. A plugin may make a choice +// to smooth note expression streams. +enum { + // with 0 < x <= 4, plain = 20 * log(x) + CLAP_NOTE_EXPRESSION_VOLUME = 0, + + // pan, 0 left, 0.5 center, 1 right + CLAP_NOTE_EXPRESSION_PAN = 1, + + // Relative tuning in semitones, from -120 to +120. Semitones are in + // equal temperament and are doubles; the resulting note would be + // retuned by `100 * evt->value` cents. + CLAP_NOTE_EXPRESSION_TUNING = 2, + + // 0..1 + CLAP_NOTE_EXPRESSION_VIBRATO = 3, + CLAP_NOTE_EXPRESSION_EXPRESSION = 4, + CLAP_NOTE_EXPRESSION_BRIGHTNESS = 5, + CLAP_NOTE_EXPRESSION_PRESSURE = 6, +}; +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, with + // -1 meaning wildcard, per the wildcard discussion above + 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, with + // -1 meaning wildcard, per the wildcard discussion above + 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, with + // -1 meaning wildcard, per the wildcard discussion above + 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, +}; + +// clap_event_transport provides song position, tempo, and similar information +// from the host to the plugin. There are two ways a host communicates these values. +// In the `clap_process` structure sent to each processing block, the host may +// provide a transport structure which indicates the available information at the +// start of the block. If the host provides sample-accurate tempo or transport changes, +// it can also provide subsequent inter-block transport updates by delivering a new event. +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 sample 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; + +// clap_event_midi_sysex contains a pointer to a sysex contents buffer. +// The lifetime of this buffer is (from host->plugin) only the process +// call in which the event is delivered or (from plugin->host) only the +// duration of a try_push call. +// +// Since `clap_output_events.try_push` requires hosts to make a copy of +// an event, host implementers receiving sysex messages from plugins need +// to take care to both copy the event (so header, size, etc...) but +// also memcpy the contents of the sysex pointer to host-owned memory, and +// not just copy the data pointer. +// +// Similarly plugins retaining the sysex outside the lifetime of a single +// process call must copy the sysex buffer to plugin-owned memory. +// +// As a consequence, the data structure pointed to by the sysex buffer +// must be contiguous and copyable with `memcpy` of `size` bytes. +typedef struct clap_event_midi_sysex { + clap_event_header_t header; + + uint16_t port_index; + const uint8_t *buffer; // midi buffer. See lifetime comment above. + 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. The host will deliver these sorted in sample order. +typedef struct clap_input_events { + void *ctx; // reserved pointer for the list + + // returns the number of events in the list + uint32_t(CLAP_ABI *size)(const struct clap_input_events *list); + + // Don't free the returned event, it belongs to the list + const clap_event_header_t *(CLAP_ABI *get)(const struct clap_input_events *list, uint32_t index); +} clap_input_events_t; + +// Output event list. The plugin must insert events in sample sorted order when inserting events +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(CLAP_ABI *try_push)(const struct clap_output_events *list, + const clap_event_header_t *event); +} clap_output_events_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/ambisonic.h b/third_party/clap/include/clap/ext/ambisonic.h new file mode 100644 index 0000000..8889904 --- /dev/null +++ b/third_party/clap/include/clap/ext/ambisonic.h @@ -0,0 +1,63 @@ +#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/3"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_AMBISONIC_COMPAT[] = "clap.ambisonic.draft/3"; + +static CLAP_CONSTEXPR const char CLAP_PORT_AMBISONIC[] = "ambisonic"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum clap_ambisonic_ordering { + // FuMa channel ordering + CLAP_AMBISONIC_ORDERING_FUMA = 0, + + // ACN channel ordering + CLAP_AMBISONIC_ORDERING_ACN = 1, +}; + +enum clap_ambisonic_normalization { + 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_config { + uint32_t ordering; // see clap_ambisonic_ordering + uint32_t normalization; // see clap_ambisonic_normalization +} clap_ambisonic_config_t; + +typedef struct clap_plugin_ambisonic { + // Returns true if the given configuration is supported. + // [main-thread] + bool(CLAP_ABI *is_config_supported)(const clap_plugin_t *plugin, + const clap_ambisonic_config_t *config); + + // Returns true on success + // [main-thread] + bool(CLAP_ABI *get_config)(const clap_plugin_t *plugin, + bool is_input, + uint32_t port_index, + clap_ambisonic_config_t *config); + +} clap_plugin_ambisonic_t; + +typedef struct clap_host_ambisonic { + // Informs the host that the info has changed. + // The info can only change when the plugin is de-activated. + // [main-thread] + void(CLAP_ABI *changed)(const clap_host_t *host); +} clap_host_ambisonic_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/audio-ports-activation.h b/third_party/clap/include/clap/ext/audio-ports-activation.h new file mode 100644 index 0000000..f63085c --- /dev/null +++ b/third_party/clap/include/clap/ext/audio-ports-activation.h @@ -0,0 +1,64 @@ +#pragma once + +#include "../plugin.h" + +/// @page Audio Ports Activation +/// +/// This extension provides a way for the host to activate and de-activate audio ports. +/// Deactivating a port provides the following benefits: +/// - the plugin knows ahead of time that a given input is not present and can choose +/// an optimized computation path, +/// - the plugin knows that an output is not consumed by the host, and doesn't need to +/// compute it. +/// +/// Audio ports can only be activated or deactivated when the plugin is deactivated, unless +/// can_activate_while_processing() returns true. +/// +/// Audio buffers must still be provided if the audio port is deactivated. +/// In such case, they shall be filled with 0 (or whatever is the neutral value in your context) +/// and the constant_mask shall be set. +/// +/// Audio ports are initially in the active state after creating the plugin instance. +/// Audio ports state are not saved in the plugin state, so the host must restore the +/// audio ports state after creating the plugin instance. +/// +/// Audio ports state is invalidated by clap_plugin_audio_ports_config.select() and +/// clap_host_audio_ports.rescan(CLAP_AUDIO_PORTS_RESCAN_LIST). + +static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_ACTIVATION[] = + "clap.audio-ports-activation/2"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_ACTIVATION_COMPAT[] = + "clap.audio-ports-activation/draft-2"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_audio_ports_activation { + // Returns true if the plugin supports activation/deactivation while processing. + // [main-thread] + bool(CLAP_ABI *can_activate_while_processing)(const clap_plugin_t *plugin); + + // Activate the given port. + // + // It is only possible to activate and de-activate on the audio-thread if + // can_activate_while_processing() returns true. + // + // sample_size indicate if the host will provide 32 bit audio buffers or 64 bits one. + // Possible values are: 32, 64 or 0 if unspecified. + // + // returns false if failed, or invalid parameters + // [active ? audio-thread : main-thread] + bool(CLAP_ABI *set_active)(const clap_plugin_t *plugin, + bool is_input, + uint32_t port_index, + bool is_active, + uint32_t sample_size); +} clap_plugin_audio_ports_activation_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/audio-ports-config.h b/third_party/clap/include/clap/ext/audio-ports-config.h new file mode 100644 index 0000000..2ab8657 --- /dev/null +++ b/third_party/clap/include/clap/ext/audio-ports-config.h @@ -0,0 +1,109 @@ +#pragma once + +#include "../string-sizes.h" +#include "../plugin.h" +#include "audio-ports.h" + +/// @page Audio Ports Config +/// +/// This extension let the plugin provide port configurations presets. +/// For example mono, stereo, surround, ambisonic, ... +/// +/// 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. +/// +/// Plugins 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). +/// +/// To inquire the exact bus layout, the plugin implements the clap_plugin_audio_ports_config_info_t +/// extension where all busses can be retrieved in the same way as in the audio-port extension. + +static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_CONFIG[] = "clap.audio-ports-config"; + +static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_CONFIG_INFO[] = + "clap.audio-ports-config-info/1"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_CONFIG_INFO_COMPAT[] = + "clap.audio-ports-config-info/draft-0"; + +#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(CLAP_ABI *count)(const clap_plugin_t *plugin); + + // Gets information about a configuration + // Returns true on success and stores the result into config. + // [main-thread] + bool(CLAP_ABI *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. + // Once applied the host should scan again the audio ports. + // [main-thread & plugin-deactivated] + bool(CLAP_ABI *select)(const clap_plugin_t *plugin, clap_id config_id); +} clap_plugin_audio_ports_config_t; + +// Extended config info +typedef struct clap_plugin_audio_ports_config_info { + + // Gets the id of the currently selected config, or CLAP_INVALID_ID if the current port + // layout isn't part of the config list. + // + // [main-thread] + clap_id(CLAP_ABI *current_config)(const clap_plugin_t *plugin); + + // Get info about an audio port, for a given config_id. + // This is analogous to clap_plugin_audio_ports.get(). + // Returns true on success and stores the result into info. + // [main-thread] + bool(CLAP_ABI *get)(const clap_plugin_t *plugin, + clap_id config_id, + uint32_t port_index, + bool is_input, + clap_audio_port_info_t *info); +} clap_plugin_audio_ports_config_info_t; + +typedef struct clap_host_audio_ports_config { + // Rescan the full list of configs. + // [main-thread] + void(CLAP_ABI *rescan)(const clap_host_t *host); +} clap_host_audio_ports_config_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/audio-ports.h b/third_party/clap/include/clap/ext/audio-ports.h new file mode 100644 index 0000000..3988049 --- /dev/null +++ b/third_party/clap/include/clap/ext/audio-ports.h @@ -0,0 +1,116 @@ +#pragma once + +#include "../plugin.h" +#include "../string-sizes.h" + +/// @page Audio Ports +/// +/// This extension provides a way for the plugin to describe its current audio ports. +/// +/// If the plugin does not implement this extension, it won't have audio ports. +/// +/// 32 bits support is required for both host and plugins. 64 bits audio is optional. +/// +/// The plugin is only allowed to change its ports configuration while it is deactivated. + +static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS[] = "clap.audio-ports"; +static CLAP_CONSTEXPR const char CLAP_PORT_MONO[] = "mono"; +static CLAP_CONSTEXPR const char CLAP_PORT_STEREO[] = "stereo"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // This port is the main audio input or output. + // There can be only one main input and main output. + // Main port must be at index 0. + CLAP_AUDIO_PORT_IS_MAIN = 1 << 0, + + // This port can be used with 64 bits audio + CLAP_AUDIO_PORT_SUPPORTS_64BITS = 1 << 1, + + // 64 bits audio is preferred with this port + CLAP_AUDIO_PORT_PREFERS_64BITS = 1 << 2, + + // This port must be used with the same sample size as all the other ports which have this flag. + // In other words if all ports have this flag then the plugin may either be used entirely with + // 64 bits audio or 32 bits audio, but it can't be mixed. + CLAP_AUDIO_PORT_REQUIRES_COMMON_SAMPLE_SIZE = 1 << 3, +}; + +typedef struct clap_audio_port_info { + // id identifies a port and must be stable. + // id may overlap between input and output ports. + clap_id id; + char name[CLAP_NAME_SIZE]; // displayable name + + uint32_t flags; + uint32_t channel_count; + + // If null or empty then it is unspecified (arbitrary audio). + // This field 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) + // + // 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(CLAP_ABI *count)(const clap_plugin_t *plugin, bool is_input); + + // Get info about an audio port. + // Returns true on success and stores the result into info. + // [main-thread] + bool(CLAP_ABI *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(CLAP_ABI *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(CLAP_ABI *rescan)(const clap_host_t *host, uint32_t flags); +} clap_host_audio_ports_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/configurable-audio-ports.h b/third_party/clap/include/clap/ext/configurable-audio-ports.h new file mode 100644 index 0000000..08bade9 --- /dev/null +++ b/third_party/clap/include/clap/ext/configurable-audio-ports.h @@ -0,0 +1,63 @@ +#pragma once + +#include "audio-ports.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// This extension lets the host configure the plugin's input and output audio ports. +// This is a "push" approach to audio ports configuration. + +static CLAP_CONSTEXPR const char CLAP_EXT_CONFIGURABLE_AUDIO_PORTS[] = + "clap.configurable-audio-ports/1"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_CONFIGURABLE_AUDIO_PORTS_COMPAT[] = + "clap.configurable-audio-ports.draft1"; + +typedef struct clap_audio_port_configuration_request { + // Identifies the port by is_input and port_index + bool is_input; + uint32_t port_index; + + // The requested number of channels. + uint32_t channel_count; + + // The port type, see audio-ports.h, clap_audio_port_info.port_type for interpretation. + const char *port_type; + + // cast port_details according to port_type: + // - CLAP_PORT_MONO: (discard) + // - CLAP_PORT_STEREO: (discard) + // - CLAP_PORT_SURROUND: const uint8_t *channel_map + // - CLAP_PORT_AMBISONIC: const clap_ambisonic_config_t *info + const void *port_details; +} clap_audio_port_configuration_request_t; + +typedef struct clap_plugin_configurable_audio_ports { + // Returns true if the given configurations can be applied using apply_configuration(). + // [main-thread & !active] + bool(CLAP_ABI *can_apply_configuration)( + const clap_plugin_t *plugin, + const struct clap_audio_port_configuration_request *requests, + uint32_t request_count); + + // Submit a bunch of configuration requests which will atomically be applied together, + // or discarded together. + // + // Once the configuration is successfully applied, it isn't necessary for the plugin to call + // clap_host_audio_ports->changed(); and it isn't necessary for the host to scan the + // audio ports. + // + // Returns true if applied. + // [main-thread & !active] + bool(CLAP_ABI *apply_configuration)(const clap_plugin_t *plugin, + const struct clap_audio_port_configuration_request *requests, + uint32_t request_count); +} clap_plugin_configurable_audio_ports_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/context-menu.h b/third_party/clap/include/clap/ext/context-menu.h new file mode 100644 index 0000000..293f59a --- /dev/null +++ b/third_party/clap/include/clap/ext/context-menu.h @@ -0,0 +1,167 @@ +#pragma once + +#include "../plugin.h" + +// This extension lets the host and plugin exchange menu items and let the plugin ask the host to +// show its context menu. + +static CLAP_CONSTEXPR const char CLAP_EXT_CONTEXT_MENU[] = "clap.context-menu/1"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_CONTEXT_MENU_COMPAT[] = "clap.context-menu.draft/0"; + +#ifdef __cplusplus +extern "C" { +#endif + +// There can be different target kind for a context menu +enum { + CLAP_CONTEXT_MENU_TARGET_KIND_GLOBAL = 0, + CLAP_CONTEXT_MENU_TARGET_KIND_PARAM = 1, +}; + +// Describes the context menu target +typedef struct clap_context_menu_target { + uint32_t kind; + clap_id id; +} clap_context_menu_target_t; + +enum { + // Adds a clickable menu entry. + // data: const clap_context_menu_item_entry_t* + CLAP_CONTEXT_MENU_ITEM_ENTRY, + + // Adds a clickable menu entry which will feature both a checkmark and a label. + // data: const clap_context_menu_item_check_entry_t* + CLAP_CONTEXT_MENU_ITEM_CHECK_ENTRY, + + // Adds a separator line. + // data: NULL + CLAP_CONTEXT_MENU_ITEM_SEPARATOR, + + // Starts a sub menu with the given label. + // data: const clap_context_menu_item_begin_submenu_t* + CLAP_CONTEXT_MENU_ITEM_BEGIN_SUBMENU, + + // Ends the current sub menu. + // data: NULL + CLAP_CONTEXT_MENU_ITEM_END_SUBMENU, + + // Adds a title entry + // data: const clap_context_menu_item_title_t * + CLAP_CONTEXT_MENU_ITEM_TITLE, +}; +typedef uint32_t clap_context_menu_item_kind_t; + +typedef struct clap_context_menu_entry { + // text to be displayed + const char *label; + + // if false, then the menu entry is greyed out and not clickable + bool is_enabled; + clap_id action_id; +} clap_context_menu_entry_t; + +typedef struct clap_context_menu_check_entry { + // text to be displayed + const char *label; + + // if false, then the menu entry is greyed out and not clickable + bool is_enabled; + + // if true, then the menu entry will be displayed as checked + bool is_checked; + clap_id action_id; +} clap_context_menu_check_entry_t; + +typedef struct clap_context_menu_item_title { + // text to be displayed + const char *title; + + // if false, then the menu entry is greyed out + bool is_enabled; +} clap_context_menu_item_title_t; + +typedef struct clap_context_menu_submenu { + // text to be displayed + const char *label; + + // if false, then the menu entry is greyed out and won't show submenu + bool is_enabled; +} clap_context_menu_submenu_t; + +// Context menu builder. +// This object isn't thread-safe and must be used on the same thread as it was provided. +typedef struct clap_context_menu_builder { + void *ctx; + + // Adds an entry to the menu. + // item_data type is determined by item_kind. + // Returns true on success. + bool(CLAP_ABI *add_item)(const struct clap_context_menu_builder *builder, + clap_context_menu_item_kind_t item_kind, + const void *item_data); + + // Returns true if the menu builder supports the given item kind + bool(CLAP_ABI *supports)(const struct clap_context_menu_builder *builder, + clap_context_menu_item_kind_t item_kind); +} clap_context_menu_builder_t; + +typedef struct clap_plugin_context_menu { + // Insert plugin's menu items into the menu builder. + // If target is null, assume global context. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *populate)(const clap_plugin_t *plugin, + const clap_context_menu_target_t *target, + const clap_context_menu_builder_t *builder); + + // Performs the given action, which was previously provided to the host via populate(). + // If target is null, assume global context. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *perform)(const clap_plugin_t *plugin, + const clap_context_menu_target_t *target, + clap_id action_id); +} clap_plugin_context_menu_t; + +typedef struct clap_host_context_menu { + // Insert host's menu items into the menu builder. + // If target is null, assume global context. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *populate)(const clap_host_t *host, + const clap_context_menu_target_t *target, + const clap_context_menu_builder_t *builder); + + // Performs the given action, which was previously provided to the plugin via populate(). + // If target is null, assume global context. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *perform)(const clap_host_t *host, + const clap_context_menu_target_t *target, + clap_id action_id); + + // Returns true if the host can display a popup menu for the plugin. + // This may depend upon the current windowing system used to display the plugin, so the + // return value is invalidated after creating the plugin window. + // [main-thread] + bool(CLAP_ABI *can_popup)(const clap_host_t *host); + + // Shows the host popup menu for a given parameter. + // If the plugin is using embedded GUI, then x and y are relative to the plugin's window, + // otherwise they're absolute coordinate, and screen index might be set accordingly. + // If target is null, assume global context. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *popup)(const clap_host_t *host, + const clap_context_menu_target_t *target, + int32_t screen_index, + int32_t x, + int32_t y); +} clap_host_context_menu_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/background-activation.h b/third_party/clap/include/clap/ext/draft/background-activation.h new file mode 100644 index 0000000..d238bc2 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/background-activation.h @@ -0,0 +1,45 @@ +#pragma once + +#include "../../plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// @page background activation +/// @brief Activate and Deactivate from a background thread. +/// +/// Some plugin needs to perform complex computation or even I/O during activation +/// and this blocks the main thread. +/// +/// This extension is here to offer an alternative way to activate the plugin from a background +/// thread, to keep the main-thread running. +/// +/// Background activation must not be concurrent to a plugin activation/deactivation on the +/// main-thread. +/// +/// Implementing this extension implies that background activation and deactivation +/// are beneficial and preferred for this plugin. + +static CLAP_CONSTEXPR const char CLAP_EXT_BACKGROUND_ACTIVATION[] = "clap.background-activation/1"; + +typedef struct clap_plugin_background_activation { + // Same as clap_plugin.activate() but it is called from a background thread. + // See clap_host_background_progress for progress feedback and cancelation. + // + // [background-thread] + bool(CLAP_ABI *activate_from_background_thread)(clap_plugin_t *plugin, + double sample_rate, + uint32_t min_frames_count, + uint32_t max_frames_count); + + // Same as clap_plugin.deactivate() but it is called from a background thread. + // See clap_host_background_progress for progress feedback and cancelation. + // + // [background-thread] + void(CLAP_ABI *deactivate_from_background_thread)(const struct clap_plugin *plugin); +} clap_plugin_background_activation_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/background-progress.h b/third_party/clap/include/clap/ext/draft/background-progress.h new file mode 100644 index 0000000..63a4b0e --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/background-progress.h @@ -0,0 +1,51 @@ +#pragma once + +#include "../state.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// @page background-progress +/// +/// @brief Let the plugin report progress to the host for the current background task, and check for +/// cancelation as well. +/// +/// This interface reports progress and checks for cancelation for the task currently active on this +/// background thread. +/// +/// This interface is used by CLAP_EXT_BACKGROUND_ACTIVATION and CLAP_EXT_BACKGROUND_STATE_CONTEXT. +/// +/// Typical execution: +/// plugin->do_something_from_background_thread() { +/// while (!host->is_canceled()) { +/// // do some work +/// host->progress(x, "doing something"); +/// } +/// } + + +static CLAP_CONSTEXPR const char CLAP_EXT_BACKGROUND_PROGRESS[] = "clap.background-progress/1"; + +typedef struct clap_host_background_progress { + // Returns true if the host wants to cancel this task. + // [background-thread] + bool(CLAP_ABI *is_canceled)(const clap_host_t *host); + + // Reports progress to the host. + // The progress value is from 0 to 1. + // 0 at the begining and 1 at the end. + // + // Be aware that the progress may go backward if a sub-task fails and the plugin decides to retry + // it. + // + // msg: an optional null terminated message (maybe nullptr) explaining what the plugin is currently + // doing. For example: "Downloading xxx...", "Analyzing...", "Connecting to HW...", and so on. + // + // [background-thread] + void(CLAP_ABI *progress)(const clap_host_t *host, double progress, const char *msg); +} clap_host_background_progress_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/background-state-context.h b/third_party/clap/include/clap/ext/draft/background-state-context.h new file mode 100644 index 0000000..96e0249 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/background-state-context.h @@ -0,0 +1,44 @@ +#pragma once + +#include "../state-context.h" + +/// @page background state context +/// @brief Save and Load state from a background thread. +/// +/// Some plugin needs to perform complex computation or even I/O during state loading or saving and +/// this blocks the main thread. +/// +/// This extension is here to offer an alternative way to load or save the plugin from a +/// background thread, to keep the main-thread running. +/// +/// Background save and load must not be concurrent to main-thread save and load. +/// +/// Implementing this extension implies that background state saving and loading +/// are beneficial and preferred for this plugin. + +#ifdef __cplusplus +extern "C" { +#endif + +static CLAP_CONSTEXPR const char CLAP_EXT_BACKGROUND_STATE_CONTEXT[] = + "clap.background-state-context/1"; + +typedef struct clap_plugin_background_state_context { + // Same as clap_plugin_state_context.save() but it is called from a background thread. + // See clap_host_background_progress for progress feedback and cancelation. + // [background-thread] + bool(CLAP_ABI *save_from_background_thread)(const clap_plugin_t *plugin, + const clap_ostream_t *stream, + uint32_t context_type); + + // Same as clap_plugin_state_context.load() but it is called from a background thread. + // See clap_host_background_progress for progress feedback and cancelation. + // [background-thread] + bool(CLAP_ABI *load_from_background_thread)(const clap_plugin_t *plugin, + const clap_istream_t *stream, + uint32_t context_type); +} clap_plugin_background_state_context_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/extensible-audio-ports.h b/third_party/clap/include/clap/ext/draft/extensible-audio-ports.h new file mode 100644 index 0000000..5bbe966 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/extensible-audio-ports.h @@ -0,0 +1,33 @@ +#pragma once + +#include "../audio-ports.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// This extension lets the host add and remove audio ports to the plugin. +static CLAP_CONSTEXPR const char CLAP_EXT_EXTENSIBLE_AUDIO_PORTS[] = + "clap.extensible-audio-ports/1"; + +typedef struct clap_plugin_extensible_audio_ports { + // Asks the plugin to add a new port (at the end of the list), with the following settings. + // port_type: see clap_audio_port_info.port_type for interpretation. + // port_details: see clap_audio_port_configuration_request.port_details for interpretation. + // Returns true on success. + // [main-thread & !active] + bool(CLAP_ABI *add_port)(const clap_plugin_t *plugin, + bool is_input, + uint32_t channel_count, + const char *port_type, + const void *port_details); + + // Asks the plugin to remove a port. + // Returns true on success. + // [main-thread & !active] + bool(CLAP_ABI *remove_port)(const clap_plugin_t *plugin, bool is_input, uint32_t index); +} clap_plugin_extensible_audio_ports_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/flush-events.h b/third_party/clap/include/clap/ext/draft/flush-events.h new file mode 100644 index 0000000..63eaf20 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/flush-events.h @@ -0,0 +1,48 @@ +#pragma once + +#include "../../plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// @page flush events +/// +/// This interface is useful to exchange events with the plugin while not processing. +/// +/// This is useful to perform MIDI 2.0 non realtime communication on the main-thread +/// before activating the plugin. + +static CLAP_CONSTEXPR const char CLAP_EXT_FLUSH_EVENTS[] = "clap.flush-events/1"; + +typedef struct clap_plugin_flush_events { + // Flushes a set of events. + // This method must not be called concurrently to clap_plugin->process(). + // + // Note: if the plugin is processing, then the process() call will already perform events I/O, so + // a call to flush isn't required, also be aware that the plugin may use the sample offset in + // process(), while this information would be lost within flush(). + // + // [active ? audio-thread : main-thread] + void(CLAP_ABI *flush)(const clap_plugin_t *plugin, + const clap_input_events_t *in, + const clap_output_events_t *out); +} clap_plugin_flush_events_t; + +typedef struct clap_host_flush_events { + // Request an event flush. + // + // The host will then schedule a call to either: + // - clap_plugin.process() + // - clap_plugin_flush_events.flush() + // + // This function is always safe to use and should not be called from an [audio-thread] as the + // plugin would already be within process() or flush(). + // + // [thread-safe,!audio-thread] + void(CLAP_ABI *request_flush)(const clap_host_t *host); +} clap_host_flush_events_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/gain-adjustment-metering.h b/third_party/clap/include/clap/ext/draft/gain-adjustment-metering.h new file mode 100644 index 0000000..3bf2935 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/gain-adjustment-metering.h @@ -0,0 +1,34 @@ +#pragma once + +#include "../../plugin.h" + +// This extension lets the plugin report the current gain adjustment +// (typically, gain reduction) to the host. + +static CLAP_CONSTEXPR const char CLAP_EXT_GAIN_ADJUSTMENT_METERING[] = "clap.gain-adjustment-metering/0"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_gain_adjustment_metering { + // Returns the current gain adjustment in dB. The value is intended + // for informational display, for example in a host meter or tooltip. + // The returned value represents the gain adjustment that the plugin + // applied to the last sample in the most recently processed block. + // + // The returned value is in dB. Zero means the plugin is applying no gain + // reduction, or is not processing. A negative value means the plugin is + // applying gain reduction, as with a compressor or limiter. A positive + // value means the plugin is adding gain, as with an expander. The value + // represents the dynamic gain reduction or expansion applied by the + // plugin, before any make-up gain or other adjustment. A single value is + // returned for all audio channels. + // + // [audio-thread] + double(CLAP_ABI *get)(const clap_plugin_t *plugin); +} clap_plugin_gain_adjustment_metering_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/mini-curve-display.h b/third_party/clap/include/clap/ext/draft/mini-curve-display.h new file mode 100644 index 0000000..ad518eb --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/mini-curve-display.h @@ -0,0 +1,153 @@ +#pragma once + +#include "../../plugin.h" + +// This extension allows a host to render a small curve provided by the plugin. +// A useful application is to render an EQ frequency response in the DAW mixer view. + +static CLAP_CONSTEXPR const char CLAP_EXT_MINI_CURVE_DISPLAY[] = "clap.mini-curve-display/3"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum clap_mini_curve_display_curve_kind { + // If the curve's kind doesn't fit in any proposed kind, use this one + // and perhaps, make a pull request to extend the list. + CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_UNSPECIFIED = 0, + + // The mini curve is intended to draw the total gain response of the plugin. + // In this case the y values are in dB and the x values are in Hz (logarithmic). + // This would be useful in for example an equalizer. + CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_GAIN_RESPONSE = 1, + + // The mini curve is intended to draw the total phase response of the plugin. + // In this case the y values are in radians and the x values are in Hz (logarithmic). + // This would be useful in for example an equalizer. + CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_PHASE_RESPONSE = 2, + + // The mini curve is intended to draw the transfer curve of the plugin. + // In this case the both x and y values are in dB. + // This would be useful in for example a compressor or distortion plugin. + CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_TRANSFER_CURVE = 3, + + // This mini curve is intended to draw gain reduction over time. In this case + // x refers to the window in seconds and y refers to level in dB, x_min is + // always 0, and x_max would be the duration of the window. + // This would be useful in for example a compressor or limiter. + CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_GAIN_REDUCTION = 4, + + // This curve is intended as a generic time series plot. In this case + // x refers to the window in seconds. x_min is always 0, and x_max would be the duration of the + // window. + // Y is not specified and up to the plugin. + CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_TIME_SERIES = 5, + + // Note: more entries could be added here in the future +}; + +typedef struct clap_mini_curve_display_curve_hints { + + // Range for the x axis. + double x_min; + double x_max; + + // Range for the y axis. + double y_min; + double y_max; + +} clap_mini_curve_display_curve_hints_t; + +// A set of points representing the curve to be painted. +typedef struct clap_mini_curve_display_curve_data { + // Indicates the kind of curve those values represent, the host can use this + // information to paint the curve using a meaningful color. + int32_t curve_kind; + + // values[0] will be the leftmost value and values[data_size -1] will be the rightmost + // value. + // + // The value 0 and UINT16_MAX won't be painted. + // The value 1 will be at the bottom of the curve and UINT16_MAX - 1 will be at the top. + uint16_t *values; + uint32_t values_count; +} clap_mini_curve_display_curve_data_t; + +typedef struct clap_plugin_mini_curve_display { + // Returns the number of curves the plugin wants to paint. + // Be aware that the space to display those curves will be small, and too much data will make + // the output hard to read. + uint32_t(CLAP_ABI *get_curve_count)(const clap_plugin_t *plugin); + + // Renders the curve into each the curves buffer. + // + // curves is an array, and each entries (up to curves_size) contains pre-allocated + // values buffer that must be filled by the plugin. + // + // The host will "stack" the curves, from the first one to the last one. + // curves[0] is the first curve to be painted. + // curves[n + 1] will be painted over curves[n]. + // + // Returns the number of curves rendered. + // [main-thread] + uint32_t(CLAP_ABI *render)(const clap_plugin_t *plugin, + clap_mini_curve_display_curve_data_t *curves, + uint32_t curves_size); + + // Tells the plugin if the curve is currently observed or not. + // When it isn't observed render() can't be called. + // + // When is_obseverd becomes true, the curve content and axis name are implicitly invalidated. So + // the plugin don't need to call host->changed. + // + // [main-thread] + void(CLAP_ABI *set_observed)(const clap_plugin_t *plugin, bool is_observed); + + // Retrives the axis name. + // x_name and y_name must not to be null. + // Returns true on success, if the name capacity was sufficient. + // [main-thread] + bool(CLAP_ABI *get_axis_name)(const clap_plugin_t *plugin, + uint32_t curve_index, + char *x_name, + char *y_name, + uint32_t name_capacity); +} clap_plugin_mini_curve_display_t; + +enum clap_mini_curve_display_change_flags { + // Informs the host that the curve content changed. + // Can only be called if the curve is observed and is static. + CLAP_MINI_CURVE_DISPLAY_CURVE_CHANGED = 1 << 0, + + // Informs the host that the curve axis name changed. + // Can only be called if the curve is observed. + CLAP_MINI_CURVE_DISPLAY_AXIS_NAME_CHANGED = 1 << 1, +}; + +typedef struct clap_host_mini_curve_display { + // Fills in the given clap_mini_display_curve_hints_t structure and returns + // true if successful. If not, return false. + // [main-thread] + bool(CLAP_ABI *get_hints)(const clap_host_t *host, + uint32_t kind, + clap_mini_curve_display_curve_hints_t *hints); + + // Mark the curve as being static or dynamic. + // The curve is initially considered as static, though the plugin should explicitely + // initialize this state. + // + // When static, the curve changes will be notified by calling host->changed(). + // When dynamic, the curve is constantly changing and the host is expected to + // periodically re-render. + // + // [main-thread] + void(CLAP_ABI *set_dynamic)(const clap_host_t *host, bool is_dynamic); + + // See clap_mini_curve_display_change_flags + // [main-thread] + void(CLAP_ABI *changed)(const clap_host_t *host, uint32_t flags); +} clap_host_mini_curve_display_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/octave-number.h b/third_party/clap/include/clap/ext/draft/octave-number.h new file mode 100644 index 0000000..9d01bb7 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/octave-number.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../../plugin.h" + +// This extension allows a host to communicate to a plugin the +// octave number associated with MIDI Note 60 (aka "Middle C"). +// Since various hosts and standards call note 60 either C3, C4 or C5, +// host displays and plugin displays often mismatch absent this information +// being shared. + +static CLAP_CONSTEXPR const char CLAP_EXT_OCTAVE_NUMBER[] = "clap.octave-number/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_octave_number { + // If displaying the name of a note, and using standard CDEFGAB scale note names + // on a piano-roll-like display, this api will tell the plugin which octave number is + // associated with note 60. For instance, calling this with '3' would indicate to + // the plugin that the consistent name for note 60 is "C3", for 72 is "C4" etc... + // if using CDEFGAB note names across a 12 note display. + // [main-thread] + void(CLAP_ABI *set_note60_octave)(const clap_plugin_t *plugin, + int8_t octave_number); +} clap_plugin_octave_number_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/param-hovered.h b/third_party/clap/include/clap/ext/draft/param-hovered.h new file mode 100644 index 0000000..a863d47 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/param-hovered.h @@ -0,0 +1,29 @@ +#pragma once + +#include "../../plugin.h" + +// This extension lets a plugin report to the host the parameter's clap_id of its last hovered UI +// control and whether it is currently hovered (usually hovered by pointer device). + +static CLAP_CONSTEXPR const char CLAP_EXT_PARAM_HOVERED[] = "clap.param-hovered/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_host_param_hovered { + // Plugin informs the host about a new hover state. + // + // Should be called whenever the hovered UI control's parameter ID changes or when it changes + // from hovered to not being hovered. + // + // Only one parameter can be hovered at a time. Use CLAP_INVALID_ID as param_id if no parameter + // is hovered. + // + // [main-thread] + void(CLAP_ABI *update)(const clap_host_t *host, clap_id hovered_param_id); +} clap_host_param_hovered_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/params-origin.h b/third_party/clap/include/clap/ext/draft/params-origin.h new file mode 100644 index 0000000..3692523 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/params-origin.h @@ -0,0 +1,61 @@ +#pragma once + +#include "../../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_PARAMS_ORIGIN[] = "clap.params-origin/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +/// This extension provides an optional value per parameter that lets the host draw a visual +/// indication for the parameter's origin. +/// +/// examples: +/// - lowpass filter cutoff parameter with an origin equal to param_info.min_value +/// [--------------> ] +/// 60Hz 20kHz +/// min=origin max +/// - highpass filter cutoff parameter with an origin equal to param_info.max_value +/// [ <--------------] +/// 60Hz 20kHz +/// min max=origin +/// - (bipolar) parameter with a range from -1.0 to +1.0 with an origin of 0.0 +/// [ <------| ] +/// -1.0 0.0 +1.0 +/// min origin max +/// - crossfade parameter without an origin +/// [ o ] +/// A B +/// min max + +typedef struct clap_plugin_params_origin { + // Get the origin value for a parameter. + // Returns false if the parameter has no origin, true otherwise. + // The host must not call this for params with CLAP_PARAM_IS_ENUM flag set. + // + // out_value constraints: + // - has to be in the range from param_info.min_value to param_info.max_value + // - has to be an integer value if CLAP_PARAM_IS_STEPPED flag is set + // [main-thread] + bool(CLAP_ABI *get)(const clap_plugin_t *plugin, clap_id param_id, double *out_value); +} clap_plugin_params_origin_t; + +typedef struct clap_host_params_origin { + // Informs the host that param origins have changed. + // + // Note: If the plugin calls params.rescan with CLAP_PARAM_RESCAN_ALL, all previously scanned + // parameter origins must be considered invalid. It is thus not necessary for the plugin to call + // param_origin.changed in this case. + // + // Note: This is useful if a parameter origin changes on-the-fly. For example a plugin might want + // to change the origin of a filter cutoff frequency parameter when the corresponding filter type + // (LP/BP/HP) has changed. + // + // [main-thread] + void(CLAP_ABI *changed)(const clap_host_t *host); +} clap_host_params_origin_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/project-location.h b/third_party/clap/include/clap/ext/draft/project-location.h new file mode 100644 index 0000000..4496cc3 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/project-location.h @@ -0,0 +1,108 @@ +#pragma once + +#include "../../color.h" +#include "../../plugin.h" +#include "../../string-sizes.h" + +// This extension allows a host to tell the plugin more about its position +// within a project or session. + +static CLAP_CONSTEXPR const char CLAP_EXT_PROJECT_LOCATION[] = "clap.project-location/2"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum clap_project_location_kind { + // Represents a document/project/session. + CLAP_PROJECT_LOCATION_PROJECT = 1, + + // Represents a group of tracks. + // It can contain track groups, tracks, and devices (post processing). + // The first device within a track group has the index of + // the last track or track group within this group + 1. + CLAP_PROJECT_LOCATION_TRACK_GROUP = 2, + + // Represents a single track. + // It contains devices (serial). + CLAP_PROJECT_LOCATION_TRACK = 3, + + // Represents a single device. + // It can contain other nested device chains. + CLAP_PROJECT_LOCATION_DEVICE = 4, + + // Represents a nested device chain (serial). + // Its parent must be a device. + // It contains other devices. + CLAP_PROJECT_LOCATION_NESTED_DEVICE_CHAIN = 5, +}; + +enum clap_project_location_track_kind { + // This track is an instrument track. + CLAP_PROJECT_LOCATION_INSTUMENT_TRACK = 1, + + // This track is an audio track. + CLAP_PROJECT_LOCATION_AUDIO_TRACK = 2, + + // This track is both an instrument and audio track. + CLAP_PROJECT_LOCATION_HYBRID_TRACK = 3, + + // This track is a return track. + CLAP_PROJECT_LOCATION_RETURN_TRACK = 4, + + // This track is a master track. + // Each group have a master track for processing the sum of all its children tracks. + CLAP_PROJECT_LOCATION_MASTER_TRACK = 5, +}; + +enum clap_project_location_flags { + CLAP_PROJECT_LOCATION_HAS_INDEX = 1 << 0, + CLAP_PROJECT_LOCATION_HAS_COLOR = 1 << 1, +}; + +typedef struct clap_project_location_element { + // A bit-mask, see clap_project_location_flags. + uint64_t flags; + + // Kind of the element, must be one of the CLAP_PROJECT_LOCATION_* values. + uint32_t kind; + + // Only relevant if kind is CLAP_PLUGIN_LOCATION_TRACK. + // see enum CLAP_PROJECT_LOCATION_track_kind. + uint32_t track_kind; + + // Index within the parent element. + // Only usable if CLAP_PROJECT_LOCATION_HAS_INDEX is set in flags. + uint32_t index; + + // Internal ID of the element. + // This is not intended for display to the user, + // but rather to give the host a potential quick way for lookups. + char id[CLAP_PATH_SIZE]; + + // User friendly name of the element. + char name[CLAP_NAME_SIZE]; + + // Color for this element. + // Only usable if CLAP_PROJECT_LOCATION_HAS_COLOR is set in flags. + clap_color_t color; +} clap_project_location_element_t; + +typedef struct clap_plugin_project_location { + // Called by the host when the location of the plugin instance changes. + // + // The last item in this array always refers to the device itself, and as + // such is expected to be of kind CLAP_PLUGIN_LOCATION_DEVICE. + // The first item in this array always refers to the project this device is in and must be of + // kind CLAP_PROJECT_LOCATION_PROJECT. The path is expected to be something like: PROJECT > + // TRACK_GROUP+ > TRACK > (DEVICE > NESTED_DEVICE_CHAIN)* > DEVICE + // + // [main-thread] + void(CLAP_ABI *set)(const clap_plugin_t *plugin, + const clap_project_location_element_t *path, + uint32_t num_elements); +} clap_plugin_project_location_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/resource-directory.h b/third_party/clap/include/clap/ext/draft/resource-directory.h new file mode 100644 index 0000000..6b8bd57 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/resource-directory.h @@ -0,0 +1,88 @@ +#pragma once + +#include "../../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_RESOURCE_DIRECTORY[] = "clap.resource-directory/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +/// @page Resource Directory +/// +/// This extension provides a way for the plugin to store its resources as file in a directory +/// provided by the host and recover them later on. +/// +/// The plugin **must** store relative path in its state toward resource directories. +/// +/// Resource sharing: +/// - shared directory is shared among all plugin instances, hence mostly appropriate for read-only +/// content +/// -> suitable for read-only content +/// - exclusive directory is exclusive to the plugin instance +/// -> if the plugin, then its exclusive directory must be duplicated too +/// -> suitable for read-write content +/// +/// Keeping the shared directory clean: +/// - to avoid clashes in the shared directory, plugins are encouraged to organize their files in +/// sub-folders, for example create one subdirectory using the vendor name +/// - don't use symbolic links or hard links which points outside of the directory +/// +/// Resource life-time: +/// - exclusive folder content is managed by the plugin instance +/// - exclusive folder content is deleted when the plugin instance is removed from the project +/// - shared folder content isn't managed by the host, until all plugins using the shared directory +/// are removed from the project +/// +/// Note for the host +/// - try to use the filesystem's copy-on-write feature when possible for reducing exclusive folder +/// space usage on duplication +/// - host can "garbage collect" the files in the shared folder using: +/// clap_plugin_resource_directory.get_files_count() +/// clap_plugin_resource_directory.get_file_path() +/// but be **very** careful before deleting any resources + +typedef struct clap_plugin_resource_directory { + // Sets the directory in which the plugin can save its resources. + // The directory remains valid until it is overridden or the plugin is destroyed. + // If path is null or blank, it clears the directory location. + // path must be absolute. + // [main-thread] + void(CLAP_ABI *set_directory)(const clap_plugin_t *plugin, const char *path, bool is_shared); + + // Asks the plugin to put its resources into the resource directory. + // It is not necessary to collect files which belongs to the plugin's + // factory content unless the param all is true. + // [main-thread] + void(CLAP_ABI *collect)(const clap_plugin_t *plugin, bool all); + + // Returns the number of files used by the plugin in the shared resource folder. + // [main-thread] + uint32_t(CLAP_ABI *get_files_count)(const clap_plugin_t *plugin); + + // Retrieves relative file path to the resource directory. + // @param path writable memory to store the path + // @param path_size number of available bytes in path + // Returns the number of bytes in the path, or -1 on error + // [main-thread] + int32_t(CLAP_ABI *get_file_path)(const clap_plugin_t *plugin, + uint32_t index, + char *path, + uint32_t path_size); +} clap_plugin_resource_directory_t; + +typedef struct clap_host_resource_directory { + // Request the host to setup a resource directory with the specified sharing. + // Returns true if the host will perform the request. + // [main-thread] + bool(CLAP_ABI *request_directory)(const clap_host_t *host, bool is_shared); + + // Tell the host that the resource directory of the specified sharing is no longer required. + // If is_shared = false, then the host may delete the directory content. + // [main-thread] + void(CLAP_ABI *release_directory)(const clap_host_t *host, bool is_shared); +} clap_host_resource_directory_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/scratch-memory.h b/third_party/clap/include/clap/ext/draft/scratch-memory.h new file mode 100644 index 0000000..8beaa84 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/scratch-memory.h @@ -0,0 +1,90 @@ +#pragma once + +#include "../../plugin.h" + +// This extension lets the plugin request "scratch" memory from the host. +// +// The scratch memory is thread-local, and can be accessed during +// `clap_plugin->process()` and `clap_plugin_thread_pool->exec()`; +// its content is not persistent between callbacks. +// +// The motivation for this extension is to allow the plugin host +// to "share" a single scratch buffer across multiple plugin +// instances. +// +// For example, imagine the host needs to process N plugins +// in sequence, and each plugin requires 10K of scratch memory. +// If each plugin pre-allocates its own scratch memory, then N * 10K +// of memory is being allocated in total. However, if each plugin +// requests 10K of scratch memory from the host, then the host can +// allocate a single 10K scratch buffer, and make it available to all +// plugins. +// +// This optimization may allow for reduced memory usage and improved +// CPU cache usage. + +static CLAP_CONSTEXPR const char CLAP_EXT_SCRATCH_MEMORY[] = "clap.scratch-memory/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_host_scratch_memory { + // Asks the host to reserve scratch memory. + // + // The plugin may call this method multiple times (for + // example, gradually decreasing the amount of scratch + // being asked for until the host returns true), however, + // the plugin should avoid calling this method un-neccesarily + // since the host implementation may be relatively expensive. + // If the plugin calls `reserve()` multiple times, then the + // last call invalidates all previous calls. + // + // De-activating the plugin releases the scratch memory. + // + // `max_concurrency_hint` is an optional hint which indicates + // the maximum number of threads concurrently accessing the scratch memory. + // Set to 0 if unspecified. + // + // Returns true on success. + // + // [main-thread & being-activated] + bool(CLAP_ABI *reserve)(const clap_host_t *host, + uint32_t scratch_size_bytes, + uint32_t max_concurrency_hint); + + // Returns a pointer to the "thread-local" scratch memory. + // + // If the scratch memory wasn't successfully reserved, returns NULL. + // + // If the plugin crosses `max_concurrency_hint`, then the return value + // is either NULL or a valid scratch memory pointer. + // + // This method may only be called by the plugin from the audio thread, + // (i.e. during the process() or thread_pool.exec() callback), and + // the provided memory is only valid until the plugin returns from + // that callback. The plugin must not hold any references to data + // that lives in the scratch memory after returning from the callback, + // as that data will likely be over-written by another plugin using + // the same scratch memory. + // + // The provided memory is not initialized, and may have been used + // by other plugin instances, so the plugin must correctly initialize + // the memory when using it. + // + // The provided memory is owned by the host, so the plugin must not + // free the memory. + // + // If the plugin wants to share the same scratch memory pointer with + // many threads, it must access the the scratch at the beginning of the + // `process()` callback, cache the returned pointer before calling + // `clap_host_thread_pool->request_exec()` and clear the cached pointer + // before returning from `process()`. + // + // [audio-thread] + void *(CLAP_ABI *access)(const clap_host_t *host); +} clap_host_scratch_memory_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/transport-control.h b/third_party/clap/include/clap/ext/draft/transport-control.h new file mode 100644 index 0000000..5094dc0 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/transport-control.h @@ -0,0 +1,75 @@ +#pragma once + +#include "../../plugin.h" + +// This extension lets the plugin submit transport requests to the host. +// The host has no obligation to execute these requests, so the interface may be +// partially working. + +static CLAP_CONSTEXPR const char CLAP_EXT_TRANSPORT_CONTROL[] = "clap.transport-control/2"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_host_transport_control { + // Jumps back to the start point and starts the transport + // [main-thread] + void(CLAP_ABI *request_start)(const clap_host_t *host); + + // Stops the transport, and jumps to the start point + // [main-thread] + void(CLAP_ABI *request_stop)(const clap_host_t *host); + + // If not playing, starts the transport from its current position + // [main-thread] + void(CLAP_ABI *request_continue)(const clap_host_t *host); + + // If playing, stops the transport at the current position + // [main-thread] + void(CLAP_ABI *request_pause)(const clap_host_t *host); + + // Equivalent to what "space bar" does with most DAWs + // [main-thread] + void(CLAP_ABI *request_toggle_play)(const clap_host_t *host); + + // Jumps the transport to the given position. + // Does not start the transport. + // [main-thread] + void(CLAP_ABI *request_jump)(const clap_host_t *host, clap_beattime position); + + // Sets the loop region + // [main-thread] + void(CLAP_ABI *request_loop_region)(const clap_host_t *host, + clap_beattime start, + clap_beattime duration); + + // Toggles looping + // [main-thread] + void(CLAP_ABI *request_toggle_loop)(const clap_host_t *host); + + // Enables/Disables looping + // [main-thread] + void(CLAP_ABI *request_enable_loop)(const clap_host_t *host, bool is_enabled); + + // Enables/Disables recording + // [main-thread] + void(CLAP_ABI *request_record)(const clap_host_t *host, bool is_recording); + + // Toggles recording + // [main-thread] + void(CLAP_ABI *request_toggle_record)(const clap_host_t *host); + + // Sets tempo + // [main-thread] + void(CLAP_ABI *request_tempo)(const clap_host_t *host, double tempo); + + // Sets time signature, same format as in clap_event_transport_t. + // [main-thread] + void(CLAP_ABI *request_time_signature)(const clap_host_t *host, uint16_t tsig_num, uint16_t tsig_denom); + +} clap_host_transport_control_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/triggers.h b/third_party/clap/include/clap/ext/draft/triggers.h new file mode 100644 index 0000000..bf85dee --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/triggers.h @@ -0,0 +1,144 @@ +#pragma once + +#include "../../plugin.h" +#include "../../events.h" +#include "../../string-sizes.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_TRIGGERS[] = "clap.triggers/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +/// @page Trigger events +/// +/// This extension enables the plugin to expose a set of triggers to the host. +/// +/// Some examples for triggers: +/// - trigger an envelope which is independent of the notes +/// - trigger a sample-and-hold unit (maybe even per-voice) + +enum { + // Does this trigger support per note automations? + CLAP_TRIGGER_IS_AUTOMATABLE_PER_NOTE_ID = 1 << 0, + + // Does this trigger support per key automations? + CLAP_TRIGGER_IS_AUTOMATABLE_PER_KEY = 1 << 1, + + // Does this trigger support per channel automations? + CLAP_TRIGGER_IS_AUTOMATABLE_PER_CHANNEL = 1 << 2, + + // Does this trigger support per port automations? + CLAP_TRIGGER_IS_AUTOMATABLE_PER_PORT = 1 << 3, +}; +typedef uint32_t clap_trigger_info_flags; + +// Given that this extension is still draft, it'll use the event-registry and its own event +// namespace until we stabilize it. +// +// #include +// +// uint16_t CLAP_EXT_TRIGGER_EVENT_SPACE_ID = UINT16_MAX; +// if (host_event_registry->query(host, CLAP_EXT_TRIGGERS, &CLAP_EXT_TRIGGER_EVENT_SPACE_ID)) { +// /* we can use trigger events */ +// } +// +// /* later on */ +// clap_event_trigger ev; +// ev.header.space_id = CLAP_EXT_TRIGGER_EVENT_SPACE_ID; +// ev.header.type = CLAP_EVENT_TRIGGER; + +enum { CLAP_EVENT_TRIGGER = 0 }; + +typedef struct clap_event_trigger { + clap_event_header_t header; + + // target trigger + clap_id trigger_id; // @ref clap_trigger_info.id + void *cookie; // @ref clap_trigger_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; +} clap_event_trigger_t; + +/* This describes a trigger */ +typedef struct clap_trigger_info { + // stable trigger identifier, it must never change. + clap_id id; + + clap_trigger_info_flags flags; + + // in analogy to clap_param_info.cookie + void *cookie; + + // displayable name + char name[CLAP_NAME_SIZE]; + + // the module path containing the trigger, eg:"sequencers/seq1" + // '/' will be used as a separator to show a tree like structure. + char module[CLAP_PATH_SIZE]; +} clap_trigger_info_t; + +typedef struct clap_plugin_triggers { + // Returns the number of triggers. + // [main-thread] + uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin); + + // Copies the trigger's info to trigger_info and returns true on success. + // [main-thread] + bool(CLAP_ABI *get_info)(const clap_plugin_t *plugin, + uint32_t index, + clap_trigger_info_t *trigger_info); +} clap_plugin_triggers_t; + +enum { + // The trigger info did change, use this flag for: + // - name change + // - module change + // New info takes effect immediately. + CLAP_TRIGGER_RESCAN_INFO = 1 << 0, + + // Invalidates everything the host knows about triggers. + // It can only be used while the plugin is deactivated. + // If the plugin is activated use clap_host->restart() and delay any change until the host calls + // clap_plugin->deactivate(). + // + // You must use this flag if: + // - some triggers were added or removed. + // - some triggers had critical changes: + // - is_per_note (flag) + // - is_per_key (flag) + // - is_per_channel (flag) + // - is_per_port (flag) + // - cookie + CLAP_TRIGGER_RESCAN_ALL = 1 << 1, +}; +typedef uint32_t clap_trigger_rescan_flags; + +enum { + // Clears all possible references to a trigger + CLAP_TRIGGER_CLEAR_ALL = 1 << 0, + + // Clears all automations to a trigger + CLAP_TRIGGER_CLEAR_AUTOMATIONS = 1 << 1, +}; +typedef uint32_t clap_trigger_clear_flags; + +typedef struct clap_host_triggers { + // Rescan the full list of triggers according to the flags. + // [main-thread] + void(CLAP_ABI *rescan)(const clap_host_t *host, clap_trigger_rescan_flags flags); + + // Clears references to a trigger. + // [main-thread] + void(CLAP_ABI *clear)(const clap_host_t *host, + clap_id trigger_id, + clap_trigger_clear_flags flags); +} clap_host_triggers_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/tuning.h b/third_party/clap/include/clap/ext/draft/tuning.h new file mode 100644 index 0000000..ae668b1 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/tuning.h @@ -0,0 +1,76 @@ +#pragma once + +#include "../../plugin.h" +#include "../../events.h" +#include "../../string-sizes.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_TUNING[] = "clap.tuning/2"; + +#ifdef __cplusplus +extern "C" { +#endif + +// Use clap_host_event_registry->query(host, CLAP_EXT_TUNING, &space_id) to know the event space. +// +// This event defines the tuning to be used on the given port/channel. +typedef struct clap_event_tuning { + clap_event_header_t header; + + int16_t port_index; // -1 global + int16_t channel; // 0..15, -1 global + clap_id tunning_id; +} clap_event_tuning_t; + +typedef struct clap_tuning_info { + clap_id tuning_id; + char name[CLAP_NAME_SIZE]; + bool is_dynamic; // true if the values may vary with time +} clap_tuning_info_t; + +typedef struct clap_plugin_tuning { + // Called when a tuning is added or removed from the pool. + // [main-thread] + void(CLAP_ABI *changed)(const clap_plugin_t *plugin); +} clap_plugin_tuning_t; + +// This extension provides a dynamic tuning table to the plugin. +typedef struct clap_host_tuning { + // Gets the relative tuning in semitones against equal temperament with A4=440Hz. + // The plugin may query the tuning at a rate that makes sense for *low* frequency modulations. + // + // If the tuning_id is not found or equals to CLAP_INVALID_ID, + // then the function shall gracefully return a sensible value. + // + // sample_offset is the sample offset from the beginning of the current process block. + // + // should_play(...) should be checked before calling this function. + // + // [audio-thread & in-process] + double(CLAP_ABI *get_relative)(const clap_host_t *host, + clap_id tuning_id, + int32_t channel, + int32_t key, + uint32_t sample_offset); + + // Returns true if the note should be played. + // [audio-thread & in-process] + bool(CLAP_ABI *should_play)(const clap_host_t *host, + clap_id tuning_id, + int32_t channel, + int32_t key); + + // Returns the number of tunings in the pool. + // [main-thread] + uint32_t(CLAP_ABI *get_tuning_count)(const clap_host_t *host); + + // Gets info about a tuning + // Returns true on success and stores the result into info. + // [main-thread] + bool(CLAP_ABI *get_info)(const clap_host_t *host, + uint32_t tuning_index, + clap_tuning_info_t *info); +} clap_host_tuning_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/undo.h b/third_party/clap/include/clap/ext/draft/undo.h new file mode 100644 index 0000000..76070c3 --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/undo.h @@ -0,0 +1,201 @@ +#pragma once + +#include "../../plugin.h" +#include "../../stream.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_UNDO[] = "clap.undo/4"; +static CLAP_CONSTEXPR const char CLAP_EXT_UNDO_CONTEXT[] = "clap.undo_context/4"; +static CLAP_CONSTEXPR const char CLAP_EXT_UNDO_DELTA[] = "clap.undo_delta/4"; + +#ifdef __cplusplus +extern "C" { +#endif + +/// @page Undo +/// +/// This extension enables the plugin to merge its undo history with the host. +/// This leads to a single undo history shared by the host and many plugins. +/// +/// Calling host->undo() or host->redo() is equivalent to clicking undo/redo within the host's GUI. +/// +/// If the plugin uses this interface then its undo and redo should be entirely delegated to +/// the host; clicking in the plugin's UI undo or redo is equivalent to clicking undo or redo in the +/// host's UI. +/// +/// Some changes are long running changes, for example a mouse interaction will begin editing some +/// complex data and it may take multiple events and a long duration to complete the change. +/// In such case the plugin will call host->begin_change() to indicate the beginning of a long +/// running change and complete the change by calling host->change_made(). +/// +/// The host may group changes together: +/// [---------------------------------] +/// ^-T0 ^-T1 ^-T2 ^-T3 +/// Here a long running change C0 begin at T0. +/// A instantaneous change C1 at T1, and another one C2 at T2. +/// Then at T3 the long running change is completed. +/// The host will then create a single undo step that will merge all the changes into C0. +/// +/// This leads to another important consideration: starting a long running change without +/// terminating is **VERY BAD**, because while a change is running it is impossible to call undo or +/// redo. +/// +/// Rationale: multiple designs were considered and this one has the benefit of having a single undo +/// history. This simplifies the host implementation, leading to less bugs, a more robust design +/// and maybe an easier experience for the user because there's a single undo context versus one +/// for the host and one for each plugin instance. +/// +/// This extension tries to make it as easy as possible for the plugin to hook into the host undo +/// and make it efficient when possible by using deltas. The plugin interfaces are all optional, and +/// the plugin can for a minimal implementation, just use the host interface and call +/// host->change_made() without providing a delta. This is enough for the host to know that it can +/// capture a plugin state for the undo step. + +typedef struct clap_undo_delta_properties { + // If true, then the plugin will provide deltas in host->change_made(). + // If false, then all clap_undo_delta_properties's attributes become irrelevant. + bool has_delta; + + // If true, then the deltas can be stored on disk and re-used in the future as long as the plugin + // is compatible with the given format_version. + // + // If false, then format_version must be set to CLAP_INVALID_ID. + bool are_deltas_persistent; + + // This represents the delta format version that the plugin is currently using. + // Use CLAP_INVALID_ID for invalid value. + clap_id format_version; +} clap_undo_delta_properties_t; + +// Use CLAP_EXT_UNDO_DELTA. +// This is an optional interface, using deltas is an optimization versus making a state snapshot. +typedef struct clap_plugin_undo_delta { + // Asks the plugin the delta properties. + // [main-thread] + void(CLAP_ABI *get_delta_properties)(const clap_plugin_t *plugin, + clap_undo_delta_properties_t *properties); + + // Asks the plugin if it can apply a delta using the given format version. + // Returns true if it is possible. + // [main-thread] + bool(CLAP_ABI *can_use_delta_format_version)(const clap_plugin_t *plugin, + clap_id format_version); + + // Undo using the delta. + // Returns true on success. + // + // [main-thread] + bool(CLAP_ABI *undo)(const clap_plugin_t *plugin, + clap_id format_version, + const void *delta, + size_t delta_size); + + // Redo using the delta. + // Returns true on success. + // + // [main-thread] + bool(CLAP_ABI *redo)(const clap_plugin_t *plugin, + clap_id format_version, + const void *delta, + size_t delta_size); +} clap_plugin_undo_delta_t; + +// Use CLAP_EXT_UNDO_CONTEXT. +// This is an optional interface, that the plugin can implement in order to know about +// the current undo context. +typedef struct clap_plugin_undo_context { + // Indicate if it is currently possible to perform an undo or redo operation. + // [main-thread & plugin-subscribed-to-undo-context] + void(CLAP_ABI *set_can_undo)(const clap_plugin_t *plugin, bool can_undo); + void(CLAP_ABI *set_can_redo)(const clap_plugin_t *plugin, bool can_redo); + + // Sets the name of the next undo or redo step. + // name: null terminated string. + // [main-thread & plugin-subscribed-to-undo-context] + void(CLAP_ABI *set_undo_name)(const clap_plugin_t *plugin, const char *name); + void(CLAP_ABI *set_redo_name)(const clap_plugin_t *plugin, const char *name); +} clap_plugin_undo_context_t; + +// Use CLAP_EXT_UNDO. +typedef struct clap_host_undo { + // Begins a long running change. + // The plugin must not call this twice: there must be either a call to cancel_change() or + // change_made() before calling begin_change() again. + // [main-thread] + void(CLAP_ABI *begin_change)(const clap_host_t *host); + + // Cancels a long running change. + // cancel_change() must not be called without a preceding begin_change(). + // [main-thread] + void(CLAP_ABI *cancel_change)(const clap_host_t *host); + + // Completes an undoable change. + // At the moment of this function call, plugin_state->save() would include the current change. + // + // name: mandatory null terminated string describing the change, this is displayed to the user + // + // delta: optional, it is a binary blobs used to perform the undo and redo. When not available + // the host will save the plugin state and use state->load() to perform undo and redo. + // The plugin must be able to perform a redo operation using the delta, though the undo operation + // is only possible if delta_can_undo is true. + // + // Note: the provided delta may be used for incremental state saving and crash recovery. The + // plugin can indicate a format version id and the validity lifetime for the binary blobs. + // The host can use these to verify the compatibility before applying the delta. + // If the plugin is unable to use a delta, a notification should be provided to the user and + // the crash recovery should perform a best effort job, at least restoring the latest saved + // state. + // + // Special case: for objects with shared and synchronized state, changes shouldn't be reported + // as the host already knows about it. + // For example, plugin parameter changes shouldn't produce a call to change_made(). + // + // Note: if the plugin asked for this interface, then host_state->mark_dirty() will not create an + // implicit undo step. + // + // Note: if the plugin did load a preset or did something that leads to a large delta, + // it may consider not producing a delta (pass null) and let the host make a state snapshot + // instead. + // + // Note: if a plugin is producing a lot of changes within a small amount of time, the host + // may merge them into a single undo step. + // + // [main-thread] + void(CLAP_ABI *change_made)(const clap_host_t *host, + const char *name, + const void *delta, + size_t delta_size, + bool delta_can_undo); + + // Asks the host to perform the next undo or redo step. + // + // Note: this maybe a complex and asynchronous operation, which may complete after + // this function returns. + // + // Note: the host may ignore this request if there is no undo/redo step to perform, + // or if the host is unable to perform undo/redo at the time (eg: a long running + // change is going on). + // + // [main-thread] + void(CLAP_ABI *request_undo)(const clap_host_t *host); + void(CLAP_ABI *request_redo)(const clap_host_t *host); + + // Subscribes to or unsubscribes from undo context info. + // + // This method helps reducing the number of calls the host has to perform when updating + // the undo context info. Consider a large project with 1000+ plugins, we don't want to + // call 1000+ times update, while the plugin may only need the context info if its GUI + // is shown and it wants to display undo/redo info. + // + // Initial state is unsubscribed. + // + // is_subscribed: set to true to receive context info + // + // It is mandatory for the plugin to implement CLAP_EXT_UNDO_CONTEXT when using this method. + // + // [main-thread] + void(CLAP_ABI *set_wants_context_updates)(const clap_host_t *host, bool is_subscribed); +} clap_host_undo_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/draft/webview.h b/third_party/clap/include/clap/ext/draft/webview.h new file mode 100644 index 0000000..761c28b --- /dev/null +++ b/third_party/clap/include/clap/ext/draft/webview.h @@ -0,0 +1,77 @@ +#pragma once + +#include "../../plugin.h" +#include "../../stream.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_WEBVIEW[] = "clap.webview/3"; + +// clap.gui API constant. The pointer in clap_window must be NULL, but sizing methods are useful. +// This uses logical size, don't call clap_plugin_gui->set_scale() +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WEBVIEW[] = "webview"; + +#ifdef __cplusplus +extern "C" { +#endif + +/// @page Webview +/// +/// This extension enables the plugin to provide the start-page for a webview UI, and exchange +/// messages back and forth. +/// +/// Messages are received in the webview using a standard MessageEvent, with the data in an +/// ArrayBuffer. They are posted back to the plugin using window.parent.postMessage(), with the +/// data in an ArrayBuffer or TypedArray. + +typedef struct clap_plugin_webview { + // Writes the URL for the webview's initial navigation to the provided `uri` buffer as a + // null-terminated UTF-8 string. + // + // This must be called at least once before any messages are sent (or accepted) by the host. + // Absolute URIs (including `data:`, and `file:` URIs on local systems) are always supported. + // Relative URIs (with absolute paths) refer to resources provided by .get_resource(), which + // may be provided to the webview with an arbitrary scheme or URI prefix. The host may also + // translate `file:` URIs to some other scheme or path root, to limit access scope or handle + // virtual filesystems. Therefore, when using either relative or `file:` URIs, pages must not + // assume a particular absolute path, only relative paths between resources. + // + // Returns either the full length of the URI (including the null terminator), or <= 0 for an + // error. If the value returned is greater than the capacity, then the result was truncated. + // If the capacity is 0, `uri` may be a null pointer. In this case, the length of the URI is + // returned without writing to `uri`, allowing the host to preallocate a buffer for a subsequent + // call. + // [main-thread] + int32_t(CLAP_ABI *get_uri)(const clap_plugin_t *plugin, char *uri, uint32_t uri_capacity); + + // Provides the media type and data for resources, starting with the URI from get_uri(). + // The path must be absolute (starting with `/`) with any host-defined path prefix removed. + // Writes null-terminated media type (MIME type) to the `mime` output buffer if the capacity + // is large enough, and streams resource data to `data_stream`. + // Returns true if the media type and entire contents of the resource were provided. + // + // See https://www.rfc-editor.org/rfc/rfc6838#section-4.2 + // + // [main-thread] + bool(CLAP_ABI *get_resource)(const clap_plugin_t *plugin, + const char *path, + char *mime, + uint32_t mime_capacity, + const clap_ostream_t *data_stream); + + // Receives a single message from the webview, which must be open and ready to receive replies. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *receive)(const clap_plugin_t *plugin, const void *buffer, uint32_t size); + +} clap_plugin_webview_t; + +typedef struct clap_host_webview { + // Sends a single message to the webview. + // Returns true on success. It must fail (false) if the webview is not open. + // [main-thread] + bool(CLAP_ABI *send)(const clap_host_t *host, const void *buffer, uint32_t size); + +} clap_host_webview_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/event-registry.h b/third_party/clap/include/clap/ext/event-registry.h new file mode 100644 index 0000000..c89cea4 --- /dev/null +++ b/third_party/clap/include/clap/ext/event-registry.h @@ -0,0 +1,22 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_EVENT_REGISTRY[] = "clap.event-registry"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_host_event_registry { + // Queries an event space id. + // The space id 0 is reserved for CLAP's core events. See CLAP_CORE_EVENT_SPACE. + // + // Return false and sets *space_id to UINT16_MAX if the space name is unknown to the host. + // [main-thread] + bool(CLAP_ABI *query)(const clap_host_t *host, const char *space_name, uint16_t *space_id); +} clap_host_event_registry_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/gui.h b/third_party/clap/include/clap/ext/gui.h new file mode 100644 index 0000000..38f2c5e --- /dev/null +++ b/third_party/clap/include/clap/ext/gui.h @@ -0,0 +1,249 @@ +#pragma once + +#include "../plugin.h" + +/// @page GUI +/// +/// This extension defines how the plugin will present its GUI. +/// +/// There are two approaches: +/// 1. the plugin creates a window and embeds it into the host's window +/// 2. the plugin creates a floating window +/// +/// Embedding the window gives more control to the host, and feels more integrated. +/// Floating window are sometimes the only option due to technical limitations. +/// +/// The Embedding protocol is by far the most common, supported by all hosts to date, +/// and a plugin author should support at least that case. +/// +/// Showing the GUI works as follow: +/// 1. clap_plugin_gui->is_api_supported(), check what can work +/// 2. clap_plugin_gui->create(), allocates gui resources +/// 3. if the plugin window is floating +/// 4. -> clap_plugin_gui->set_transient() +/// 5. -> clap_plugin_gui->suggest_title() +/// 6. else +/// 7. -> clap_plugin_gui->set_scale() +/// 8. -> clap_plugin_gui->can_resize() +/// 9. -> if resizable and has known size from previous session, clap_plugin_gui->set_size() +/// 10. -> else clap_plugin_gui->get_size(), gets initial size +/// 11. -> clap_plugin_gui->set_parent() +/// 12. clap_plugin_gui->show() +/// 13. clap_plugin_gui->hide()/show() ... +/// 14. clap_plugin_gui->destroy() when done with the gui +/// +/// Resizing the window (initiated by the plugin, if embedded): +/// 1. Plugins calls clap_host_gui->request_resize() +/// 2. If the host returns true the new size is accepted, +/// the host doesn't have to call clap_plugin_gui->set_size(). +/// If the host returns false, the new size is rejected. +/// +/// Resizing the window (drag, if embedded)): +/// 1. Only possible if clap_plugin_gui->can_resize() returns true +/// 2. Mouse drag -> new_size +/// 3. clap_plugin_gui->adjust_size(new_size) -> working_size +/// 4. clap_plugin_gui->set_size(working_size) + +static CLAP_CONSTEXPR const char CLAP_EXT_GUI[] = "clap.gui"; + +// If your windowing API is not listed here, please open an issue and we'll figure it out. +// https://github.com/free-audio/clap/issues/new + +// uses physical size +// embed using https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WIN32[] = "win32"; + +// uses logical size, don't call clap_plugin_gui->set_scale() +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_COCOA[] = "cocoa"; + +// uses logical size, don't call clap_plugin_gui->set_scale() +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_UIKIT[] = "uikit"; + +// uses physical size +// embed using https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_X11[] = "x11"; + +// uses physical size +// embed is currently not supported, use floating windows +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WAYLAND[] = "wayland"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *clap_hwnd; +typedef void *clap_nsview; +typedef void *clap_uiview; +typedef unsigned long clap_xwnd; + +// Represent a window reference. +typedef struct clap_window { + const char *api; // one of CLAP_WINDOW_API_XXX + union { + clap_nsview cocoa; + clap_uiview uikit; + clap_xwnd x11; + clap_hwnd win32; + void *ptr; // for anything defined outside of clap + }; +} clap_window_t; + +// Information to improve window resizing when initiated by the host or window manager. +typedef struct clap_gui_resize_hints { + bool can_resize_horizontally; + bool can_resize_vertically; + + // if both horizontal and vertical resize are available, do we preserve the + // aspect ratio, and if so, what is the width x height aspect ratio to preserve. + // These flags are unused if can_resize_horizontally or vertically are false, + // and ratios are unused if preserve is false. + bool preserve_aspect_ratio; + uint32_t aspect_ratio_width; + uint32_t aspect_ratio_height; +} clap_gui_resize_hints_t; + +// Size (width, height) is in pixels; the corresponding windowing system extension is +// responsible for defining if it is physical pixels or logical pixels. +typedef struct clap_plugin_gui { + // Returns true if the requested gui api is supported, either in floating (plugin-created) + // or non-floating (embedded) mode. + // [main-thread] + bool(CLAP_ABI *is_api_supported)(const clap_plugin_t *plugin, const char *api, bool is_floating); + + // Returns true if the plugin has a preferred api. + // The host has no obligation to honor the plugin preference, this is just a hint. + // The const char **api variable should be explicitly assigned as a pointer to + // one of the CLAP_WINDOW_API_ constants defined above, not strcopied. + // [main-thread] + bool(CLAP_ABI *get_preferred_api)(const clap_plugin_t *plugin, + const char **api, + bool *is_floating); + + // Create and allocate all resources necessary for the gui. + // + // If is_floating is true, then the window will not be managed by the host. The plugin + // can set its window to stays above the parent window, see set_transient(). + // api may be null or blank for floating window. + // + // If is_floating is false, then the plugin has to embed its window into the parent window, see + // set_parent(). + // + // After this call, the GUI may not be visible yet; don't forget to call show(). + // + // Returns true if the GUI is successfully created. + // [main-thread] + bool(CLAP_ABI *create)(const clap_plugin_t *plugin, const char *api, bool is_floating); + + // Free all resources associated with the gui. + // [main-thread] + void(CLAP_ABI *destroy)(const clap_plugin_t *plugin); + + // Set the absolute GUI scaling factor, and override any OS info. + // Should not be used if the windowing api relies upon logical pixels. + // + // If the plugin prefers to work out the scaling factor itself by querying the OS directly, + // then ignore the call. + // + // scale = 2 means 200% scaling. + // + // Returns true if the scaling could be applied + // Returns false if the call was ignored, or the scaling could not be applied. + // [main-thread] + bool(CLAP_ABI *set_scale)(const clap_plugin_t *plugin, double scale); + + // Get the current size of the plugin UI. + // clap_plugin_gui->create() must have been called prior to asking the size. + // + // Returns true if the plugin could get the size. + // [main-thread] + bool(CLAP_ABI *get_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height); + + // Returns true if the window is resizeable (mouse drag). + // [main-thread & !floating] + bool(CLAP_ABI *can_resize)(const clap_plugin_t *plugin); + + // Returns true if the plugin can provide hints on how to resize the window. + // [main-thread & !floating] + bool(CLAP_ABI *get_resize_hints)(const clap_plugin_t *plugin, clap_gui_resize_hints_t *hints); + + // If the plugin gui is resizable, then the plugin will calculate the closest + // usable size which fits in the given size. + // This method does not change the size. + // + // Returns true if the plugin could adjust the given size. + // [main-thread & !floating] + bool(CLAP_ABI *adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height); + + // Sets the window size. + // + // Returns true if the plugin could resize its window to the given size. + // [main-thread & !floating] + bool(CLAP_ABI *set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height); + + // Embeds the plugin window into the given window. + // + // Returns true on success. + // [main-thread & !floating] + bool(CLAP_ABI *set_parent)(const clap_plugin_t *plugin, const clap_window_t *window); + + // Set the plugin floating window to stay above the given window. + // + // Returns true on success. + // [main-thread & floating] + bool(CLAP_ABI *set_transient)(const clap_plugin_t *plugin, const clap_window_t *window); + + // Suggests a window title. Only for floating windows. + // + // [main-thread & floating] + void(CLAP_ABI *suggest_title)(const clap_plugin_t *plugin, const char *title); + + // Show the window. + // + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *show)(const clap_plugin_t *plugin); + + // Hide the window, this method does not free the resources, it just hides + // the window content. Yet it may be a good idea to stop painting timers. + // + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *hide)(const clap_plugin_t *plugin); +} clap_plugin_gui_t; + +typedef struct clap_host_gui { + // The host should call get_resize_hints() again. + // [thread-safe & !floating] + void(CLAP_ABI *resize_hints_changed)(const clap_host_t *host); + + // Request the host to resize the client area to width, height. + // Return true if the new size is accepted, false otherwise. + // The host doesn't have to call set_size(). + // + // Note: if not called from the main thread, then a return value simply means that the host + // acknowledged the request and will process it asynchronously. If the request then can't be + // satisfied then the host will call set_size() to revert the operation. + // [thread-safe & !floating] + bool(CLAP_ABI *request_resize)(const clap_host_t *host, uint32_t width, uint32_t height); + + // Request the host to show the plugin gui. + // Return true on success, false otherwise. + // [thread-safe] + bool(CLAP_ABI *request_show)(const clap_host_t *host); + + // Request the host to hide the plugin gui. + // Return true on success, false otherwise. + // [thread-safe] + bool(CLAP_ABI *request_hide)(const clap_host_t *host); + + // The floating window has been closed, or the connection to the gui has been lost. + // + // If was_destroyed is true, then the host must call clap_plugin_gui->destroy() to acknowledge + // the gui destruction. + // [thread-safe] + void(CLAP_ABI *closed)(const clap_host_t *host, bool was_destroyed); +} clap_host_gui_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/latency.h b/third_party/clap/include/clap/ext/latency.h new file mode 100644 index 0000000..d10a132 --- /dev/null +++ b/third_party/clap/include/clap/ext/latency.h @@ -0,0 +1,27 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_LATENCY[] = "clap.latency"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_latency { + // Returns the plugin latency in samples. + // [main-thread & (being-activated | active)] + uint32_t(CLAP_ABI *get)(const clap_plugin_t *plugin); +} clap_plugin_latency_t; + +typedef struct clap_host_latency { + // Tell the host that the latency changed. + // The latency is only allowed to change during plugin->activate. + // If the plugin is activated, call host->request_restart() + // [main-thread & being-activated] + void(CLAP_ABI *changed)(const clap_host_t *host); +} clap_host_latency_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/log.h b/third_party/clap/include/clap/ext/log.h new file mode 100644 index 0000000..9609c6c --- /dev/null +++ b/third_party/clap/include/clap/ext/log.h @@ -0,0 +1,33 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_LOG[] = "clap.log"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + CLAP_LOG_DEBUG = 0, + CLAP_LOG_INFO = 1, + CLAP_LOG_WARNING = 2, + CLAP_LOG_ERROR = 3, + CLAP_LOG_FATAL = 4, + + // These severities should be used to report misbehaviour. + // The plugin one can be used by a layer between the plugin and the host. + CLAP_LOG_HOST_MISBEHAVING = 5, + CLAP_LOG_PLUGIN_MISBEHAVING = 6, +}; +typedef int32_t clap_log_severity; + +typedef struct clap_host_log { + // Log a message through the host. + // [thread-safe] + void(CLAP_ABI *log)(const clap_host_t *host, clap_log_severity severity, const char *msg); +} clap_host_log_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/note-name.h b/third_party/clap/include/clap/ext/note-name.h new file mode 100644 index 0000000..41e6a83 --- /dev/null +++ b/third_party/clap/include/clap/ext/note-name.h @@ -0,0 +1,37 @@ +#pragma once + +#include "../plugin.h" +#include "../string-sizes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static CLAP_CONSTEXPR const char CLAP_EXT_NOTE_NAME[] = "clap.note-name"; + +typedef struct clap_note_name { + char name[CLAP_NAME_SIZE]; + int16_t port; // -1 for every port + int16_t key; // -1 for every key + int16_t channel; // -1 for every channel +} clap_note_name_t; + +typedef struct clap_plugin_note_name { + // Return the number of note names + // [main-thread] + uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin); + + // Returns true on success and stores the result into note_name + // [main-thread] + bool(CLAP_ABI *get)(const clap_plugin_t *plugin, uint32_t index, clap_note_name_t *note_name); +} clap_plugin_note_name_t; + +typedef struct clap_host_note_name { + // Informs the host that the note names have changed. + // [main-thread] + void(CLAP_ABI *changed)(const clap_host_t *host); +} clap_host_note_name_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/note-ports.h b/third_party/clap/include/clap/ext/note-ports.h new file mode 100644 index 0000000..f91b527 --- /dev/null +++ b/third_party/clap/include/clap/ext/note-ports.h @@ -0,0 +1,79 @@ +#pragma once + +#include "../plugin.h" +#include "../string-sizes.h" + +/// @page Note Ports +/// +/// This extension provides a way for the plugin to describe its current note ports. +/// If the plugin does not implement this extension, it won't have note input or output. +/// The plugin is only allowed to change its note ports configuration while it is deactivated. + +static CLAP_CONSTEXPR const char CLAP_EXT_NOTE_PORTS[] = "clap.note-ports"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum clap_note_dialect { + // Uses clap_event_note and clap_event_note_expression. + CLAP_NOTE_DIALECT_CLAP = 1 << 0, + + // Uses clap_event_midi, no polyphonic expression + CLAP_NOTE_DIALECT_MIDI = 1 << 1, + + // Uses clap_event_midi, with polyphonic expression (MPE) + CLAP_NOTE_DIALECT_MIDI_MPE = 1 << 2, + + // Uses clap_event_midi2 + CLAP_NOTE_DIALECT_MIDI2 = 1 << 3, +}; + +typedef struct clap_note_port_info { + // id identifies a port and must be stable. + // id may overlap between input and output ports. + clap_id id; + uint32_t supported_dialects; // bitfield, see clap_note_dialect + uint32_t preferred_dialect; // one value of clap_note_dialect + char name[CLAP_NAME_SIZE]; // displayable name, i18n? +} clap_note_port_info_t; + +// The note ports scan has to be done while the plugin is deactivated. +typedef struct clap_plugin_note_ports { + // Number of ports, for either input or output. + // [main-thread] + uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin, bool is_input); + + // Get info about a note port. + // Returns true on success and stores the result into info. + // [main-thread] + bool(CLAP_ABI *get)(const clap_plugin_t *plugin, + uint32_t index, + bool is_input, + clap_note_port_info_t *info); +} clap_plugin_note_ports_t; + +enum { + // The ports have changed, the host shall perform a full scan of the ports. + // This flag can only be used if the plugin is not active. + // If the plugin active, call host->request_restart() and then call rescan() + // when the host calls deactivate() + CLAP_NOTE_PORTS_RESCAN_ALL = 1 << 0, + + // The ports name did change, the host can scan them right away. + CLAP_NOTE_PORTS_RESCAN_NAMES = 1 << 1, +}; + +typedef struct clap_host_note_ports { + // Query which dialects the host supports + // [main-thread] + uint32_t(CLAP_ABI *supported_dialects)(const clap_host_t *host); + + // Rescan the full list of note ports according to the flags. + // [main-thread] + void(CLAP_ABI *rescan)(const clap_host_t *host, uint32_t flags); +} clap_host_note_ports_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/param-indication.h b/third_party/clap/include/clap/ext/param-indication.h new file mode 100644 index 0000000..643a953 --- /dev/null +++ b/third_party/clap/include/clap/ext/param-indication.h @@ -0,0 +1,77 @@ +#pragma once + +#include "params.h" +#include "../color.h" + +// This extension lets the host tell the plugin to display a little color based indication on the +// parameter. This can be used to indicate: +// - a physical controller is mapped to a parameter +// - the parameter is current playing an automation +// - the parameter is overriding the automation +// - etc... +// +// The color semantic depends upon the host here and the goal is to have a consistent experience +// across all plugins. + +static CLAP_CONSTEXPR const char CLAP_EXT_PARAM_INDICATION[] = "clap.param-indication/4"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_PARAM_INDICATION_COMPAT[] = "clap.param-indication.draft/4"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // The host doesn't have an automation for this parameter + CLAP_PARAM_INDICATION_AUTOMATION_NONE = 0, + + // The host has an automation for this parameter, but it isn't playing it + CLAP_PARAM_INDICATION_AUTOMATION_PRESENT = 1, + + // The host is playing an automation for this parameter + CLAP_PARAM_INDICATION_AUTOMATION_PLAYING = 2, + + // The host is recording an automation on this parameter + CLAP_PARAM_INDICATION_AUTOMATION_RECORDING = 3, + + // The host should play an automation for this parameter, but the user has started to adjust this + // parameter and is overriding the automation playback + CLAP_PARAM_INDICATION_AUTOMATION_OVERRIDING = 4, +}; + +typedef struct clap_plugin_param_indication { + // Sets or clears a mapping indication. + // + // has_mapping: does the parameter currently has a mapping? + // color: if set, the color to use to highlight the control in the plugin GUI + // label: if set, a small string to display on top of the knob which identifies the hardware + // controller description: if set, a string which can be used in a tooltip, which describes the + // current mapping + // + // Parameter indications should not be saved in the plugin context, and are off by default. + // [main-thread] + void(CLAP_ABI *set_mapping)(const clap_plugin_t *plugin, + clap_id param_id, + bool has_mapping, + const clap_color_t *color, + const char *label, + const char *description); + + // Sets or clears an automation indication. + // + // automation_state: current automation state for the given parameter + // color: if set, the color to use to display the automation indication in the plugin GUI + // + // Parameter indications should not be saved in the plugin context, and are off by default. + // [main-thread] + void(CLAP_ABI *set_automation)(const clap_plugin_t *plugin, + clap_id param_id, + uint32_t automation_state, + const clap_color_t *color); +} clap_plugin_param_indication_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/params.h b/third_party/clap/include/clap/ext/params.h new file mode 100644 index 0000000..08800bb --- /dev/null +++ b/third_party/clap/include/clap/ext/params.h @@ -0,0 +1,386 @@ +#pragma once + +#include "../plugin.h" +#include "../string-sizes.h" + +/// @page Parameters +/// @brief parameters management +/// +/// Main idea: +/// +/// The host sees the plugin as an atomic entity; and acts as a controller on top of its parameters. +/// The plugin is responsible for keeping its audio processor and its GUI in sync. +/// +/// The host can at any time read parameters' value on the [main-thread] using +/// @ref clap_plugin_params.get_value(). +/// +/// There are two options to communicate parameter value changes, and they are not concurrent. +/// - send automation points during clap_plugin.process() +/// - send automation points during clap_plugin_params.flush(), for parameter changes +/// without processing audio +/// +/// When the plugin changes a parameter value, it must inform the host. +/// It will send @ref CLAP_EVENT_PARAM_VALUE event during process() or flush(). +/// If the user is adjusting the value, don't forget to mark the beginning and end +/// of the gesture by sending CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END +/// events. +/// +/// @note MIDI CCs are tricky because you may not know when the parameter adjustment ends. +/// Also if the host records incoming MIDI CC and parameter change automation at the same time, +/// there will be a conflict at playback: MIDI CC vs Automation. +/// The parameter automation will always target the same parameter because the param_id is stable. +/// The MIDI CC may have a different mapping in the future and may result in a different playback. +/// +/// When a MIDI CC changes a parameter's value, set the flag CLAP_EVENT_DONT_RECORD in +/// clap_event_param.header.flags. That way the host may record the MIDI CC automation, but not the +/// parameter change and there won't be conflict at playback. +/// +/// Scenarios: +/// +/// I. Loading a preset +/// - load the preset in a temporary state +/// - call @ref clap_host_params.rescan() if anything changed +/// - call @ref clap_host_latency.changed() if latency changed +/// - invalidate any other info that may be cached by the host +/// - if the plugin is activated and the preset will introduce breaking changes +/// (latency, audio ports, new parameters, ...) be sure to wait for the host +/// to deactivate the plugin to apply those changes. +/// If there are no breaking changes, the plugin can apply them them right away. +/// The plugin is responsible for updating both its audio processor and its gui. +/// +/// II. Turning a knob on the DAW interface +/// - the host will send an automation event to the plugin via a process() or flush() +/// +/// III. Turning a knob on the Plugin interface +/// - the plugin is responsible for sending the parameter value to its audio processor +/// - call clap_host_params->request_flush() or clap_host->request_process(). +/// - when the host calls either clap_plugin->process() or clap_plugin_params->flush(), +/// send an automation event and don't forget to wrap the parameter change(s) +/// with CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END to define the +/// beginning and end of the gesture. +/// +/// IV. Turning a knob via automation +/// - host sends an automation point during clap_plugin->process() or clap_plugin_params->flush(). +/// - the plugin is responsible for updating its GUI +/// +/// V. Turning a knob via plugin's internal MIDI mapping +/// - the plugin sends a CLAP_EVENT_PARAM_VALUE output event, set should_record to false +/// - the plugin is responsible for updating its GUI +/// +/// VI. Adding or removing parameters +/// - if the plugin is activated call clap_host->restart() +/// - once the plugin isn't active: +/// - apply the new state +/// - if a parameter is gone or is created with an id that may have been used before, +/// call clap_host_params.clear(host, param_id, CLAP_PARAM_CLEAR_ALL) +/// - call clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) +/// +/// CLAP allows the plugin to change the parameter range, yet the plugin developer +/// should be aware that doing so isn't without risk, especially if you made the +/// promise to never change the sound. If you want to be 100% certain that the +/// sound will not change with all host, then simply never change the range. +/// +/// There are two approaches to automations, either you automate the plain value, +/// or you automate the knob position. The first option will be robust to a range +/// increase, while the second won't be. +/// +/// If the host goes with the second approach (automating the knob position), it means +/// that the plugin is hosted in a relaxed environment regarding sound changes (they are +/// accepted, and not a concern as long as they are reasonable). Though, stepped parameters +/// should be stored as plain value in the document. +/// +/// If the host goes with the first approach, there will still be situation where the +/// sound may inevitably change. For example, if the plugin increase the range, there +/// is an automation playing at the max value and on top of that an LFO is applied. +/// See the following curve: +/// . +/// . . +/// ..... . . +/// before: . . and after: . . +/// +/// Persisting parameter values: +/// +/// Plugins are responsible for persisting their parameter's values between +/// sessions by implementing the state extension. Otherwise parameter value will +/// not be recalled when reloading a project. Hosts should _not_ try to save and +/// restore parameter values for plugins that don't implement the state +/// extension. +/// +/// Advice for the host: +/// +/// - store plain values in the document (automation) +/// - store modulation amount in plain value delta, not in percentage +/// - when you apply a CC mapping, remember the min/max plain values so you can adjust +/// - do not implement a parameter saving fall back for plugins that don't +/// implement the state extension +/// +/// Advice for the plugin: +/// +/// - think carefully about your parameter range when designing your DSP +/// - avoid shrinking parameter ranges, they are very likely to change the sound +/// - consider changing the parameter range as a tradeoff: what you improve vs what you break +/// - make sure to implement saving and loading the parameter values using the +/// state extension +/// - if you plan to use adapters for other plugin formats, then you need to pay extra +/// attention to the adapter requirements + +static CLAP_CONSTEXPR const char CLAP_EXT_PARAMS[] = "clap.params"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // Is this param stepped? (integer values only) + // if so the double value is converted to integer using a cast (equivalent to trunc). + CLAP_PARAM_IS_STEPPED = 1 << 0, + + // Useful for periodic parameters like a phase + CLAP_PARAM_IS_PERIODIC = 1 << 1, + + // The parameter should not be shown to the user, because it is currently not used. + // It is not necessary to process automation for this parameter. + CLAP_PARAM_IS_HIDDEN = 1 << 2, + + // The parameter can't be changed by the host. + CLAP_PARAM_IS_READONLY = 1 << 3, + + // This parameter is used to merge the plugin and host bypass button. + // It implies that the parameter is stepped. + // Only zero or one bypass parameter is allowed per plugin. + // min: 0 -> bypass off + // max: 1 -> bypass on + // The value of this parameter should not influence whether the host calls plugin->process() or + // not. If a plugin wants to save CPU cycles during bypass, the plugin will implement that in its + // process() routine, possibly returning CLAP_PROCESS_SLEEP at some point. + CLAP_PARAM_IS_BYPASS = 1 << 4, + + // When set: + // - automation can be recorded + // - automation can be played back + // + // The host can send live user changes for this parameter regardless of this flag. + // + // If this parameter affects the internal processing structure of the plugin, ie: max delay, fft + // size, ... and the plugins needs to re-allocate its working buffers, then it should call + // host->request_restart(), and perform the change once the plugin is re-activated. + CLAP_PARAM_IS_AUTOMATABLE = 1 << 5, + + // Does this parameter support per note automations? + CLAP_PARAM_IS_AUTOMATABLE_PER_NOTE_ID = 1 << 6, + + // Does this parameter support per key automations? + CLAP_PARAM_IS_AUTOMATABLE_PER_KEY = 1 << 7, + + // Does this parameter support per channel automations? + CLAP_PARAM_IS_AUTOMATABLE_PER_CHANNEL = 1 << 8, + + // Does this parameter support per port automations? + CLAP_PARAM_IS_AUTOMATABLE_PER_PORT = 1 << 9, + + // Does this parameter support the modulation signal? + CLAP_PARAM_IS_MODULATABLE = 1 << 10, + + // Does this parameter support per note modulations? + CLAP_PARAM_IS_MODULATABLE_PER_NOTE_ID = 1 << 11, + + // Does this parameter support per key modulations? + CLAP_PARAM_IS_MODULATABLE_PER_KEY = 1 << 12, + + // Does this parameter support per channel modulations? + CLAP_PARAM_IS_MODULATABLE_PER_CHANNEL = 1 << 13, + + // Does this parameter support per port modulations? + CLAP_PARAM_IS_MODULATABLE_PER_PORT = 1 << 14, + + // Any change to this parameter will affect the plugin output and requires to be done via + // process() if the plugin is active. + // + // A simple example would be a DC Offset, changing it will change the output signal and must be + // processed. + CLAP_PARAM_REQUIRES_PROCESS = 1 << 15, + + // This parameter represents an enumerated value. + // If you set this flag, then you must set CLAP_PARAM_IS_STEPPED too. + // All values from min to max must not have a blank value_to_text(). + CLAP_PARAM_IS_ENUM = 1 << 16, +}; +typedef uint32_t clap_param_info_flags; + +/* This describes a parameter */ +typedef struct clap_param_info { + // Stable parameter identifier, it must never change. + clap_id id; + + clap_param_info_flags flags; + + // This value is optional and set by the plugin. + // Its purpose is to provide fast access to the plugin parameter object by caching its pointer. + // For instance: + // + // in clap_plugin_params.get_info(): + // Parameter *p = findParameter(param_id); + // param_info->cookie = p; + // + // later, in clap_plugin.process(): + // + // Parameter *p = (Parameter *)event->cookie; + // if (!p) [[unlikely]] + // p = findParameter(event->param_id); + // + // where findParameter() is a function the plugin implements to map parameter ids to internal + // objects. + // + // Important: + // - The cookie is invalidated by a call to clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) or + // when the plugin is destroyed. + // - The host will either provide the cookie as issued or nullptr in events addressing + // parameters. + // - The plugin must gracefully handle the case of a cookie which is nullptr. + // - Many plugins will process the parameter events more quickly if the host can provide the + // cookie in a faster time than a hashmap lookup per param per event. + void *cookie; + + // The display name. eg: "Volume". This does not need to be unique. Do not include the module + // text in this. The host should concatenate/format the module + name in the case where showing + // the name alone would be too vague. + char name[CLAP_NAME_SIZE]; + + // The module path containing the param, eg: "Oscillators/Wavetable 1". + // '/' will be used as a separator to show a tree-like structure. + char module[CLAP_PATH_SIZE]; + + double min_value; // Minimum plain value. Must be finite (`std::isfinite` true) + double max_value; // Maximum plain value. Must be finite + double default_value; // Default plain value. Must be in [min, max] range. +} clap_param_info_t; + +typedef struct clap_plugin_params { + // Returns the number of parameters. + // [main-thread] + uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin); + + // Copies the parameter's info to param_info. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *get_info)(const clap_plugin_t *plugin, + uint32_t param_index, + clap_param_info_t *param_info); + + // Writes the parameter's current value to out_value. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *get_value)(const clap_plugin_t *plugin, clap_id param_id, double *out_value); + + // Fills out_buffer with a null-terminated UTF-8 string that represents the parameter at the + // given 'value' argument. eg: "2.3 kHz". The host should always use this to format parameter + // values before displaying it to the user. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *value_to_text)(const clap_plugin_t *plugin, + clap_id param_id, + double value, + char *out_buffer, + uint32_t out_buffer_capacity); + + // Converts the null-terminated UTF-8 param_value_text into a double and writes it to out_value. + // The host can use this to convert user input into a parameter value. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *text_to_value)(const clap_plugin_t *plugin, + clap_id param_id, + const char *param_value_text, + double *out_value); + + // Flushes a set of parameter changes. + // This method must not be called concurrently to clap_plugin->process(). + // + // Note: if the plugin is processing, then the process() call will already achieve the + // parameter update (bi-directional), so a call to flush isn't required, also be aware + // that the plugin may use the sample offset in process(), while this information would be + // lost within flush(). + // + // [active ? audio-thread : main-thread] + void(CLAP_ABI *flush)(const clap_plugin_t *plugin, + const clap_input_events_t *in, + const clap_output_events_t *out); +} clap_plugin_params_t; + +enum { + // The parameter values did change, eg. after loading a preset. + // The host will scan all the parameters value. + // The host will not record those changes as automation points. + // New values takes effect immediately. + CLAP_PARAM_RESCAN_VALUES = 1 << 0, + + // The value to text conversion changed, and the text needs to be rendered again. + CLAP_PARAM_RESCAN_TEXT = 1 << 1, + + // The parameter info did change, use this flag for: + // - name change + // - module change + // - is_periodic (flag) + // - is_hidden (flag) + // New info takes effect immediately. + CLAP_PARAM_RESCAN_INFO = 1 << 2, + + // Invalidates everything the host knows about parameters. + // It can only be used while the plugin is deactivated. + // If the plugin is activated use clap_host->restart() and delay any change until the host calls + // clap_plugin->deactivate(). + // + // You must use this flag if: + // - some parameters were added or removed. + // - some parameters had critical changes: + // - is_per_note (flag) + // - is_per_key (flag) + // - is_per_channel (flag) + // - is_per_port (flag) + // - is_readonly (flag) + // - is_bypass (flag) + // - is_stepped (flag) + // - is_modulatable (flag) + // - min_value + // - max_value + // - cookie + CLAP_PARAM_RESCAN_ALL = 1 << 3, +}; +typedef uint32_t clap_param_rescan_flags; + +enum { + // Clears all possible references to a parameter + CLAP_PARAM_CLEAR_ALL = 1 << 0, + + // Clears all automations to a parameter + CLAP_PARAM_CLEAR_AUTOMATIONS = 1 << 1, + + // Clears all modulations to a parameter + CLAP_PARAM_CLEAR_MODULATIONS = 1 << 2, +}; +typedef uint32_t clap_param_clear_flags; + +typedef struct clap_host_params { + // Rescan the full list of parameters according to the flags. + // [main-thread] + void(CLAP_ABI *rescan)(const clap_host_t *host, clap_param_rescan_flags flags); + + // Clears references to a parameter. + // [main-thread] + void(CLAP_ABI *clear)(const clap_host_t *host, clap_id param_id, clap_param_clear_flags flags); + + // Request a parameter flush. + // + // The host will then schedule a call to either: + // - clap_plugin.process() + // - clap_plugin_params.flush() + // + // This function is always safe to use and should not be called from an [audio-thread] as the + // plugin would already be within process() or flush(). + // + // [thread-safe,!audio-thread] + void(CLAP_ABI *request_flush)(const clap_host_t *host); +} clap_host_params_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/posix-fd-support.h b/third_party/clap/include/clap/ext/posix-fd-support.h new file mode 100644 index 0000000..c713ec8 --- /dev/null +++ b/third_party/clap/include/clap/ext/posix-fd-support.h @@ -0,0 +1,49 @@ +#pragma once + +#include "../plugin.h" + +// This extension let your plugin hook itself into the host select/poll/epoll/kqueue reactor. +// This is useful to handle asynchronous I/O on the main thread. +static CLAP_CONSTEXPR const char CLAP_EXT_POSIX_FD_SUPPORT[] = "clap.posix-fd-support"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // IO events flags, they can be used to form a mask which describes: + // - which events you are interested in (register_fd/modify_fd) + // - which events happened (on_fd) + CLAP_POSIX_FD_READ = 1 << 0, + CLAP_POSIX_FD_WRITE = 1 << 1, + CLAP_POSIX_FD_ERROR = 1 << 2, +}; +typedef uint32_t clap_posix_fd_flags_t; + +typedef struct clap_plugin_posix_fd_support { + // This callback is "level-triggered". + // It means that a writable fd will continuously produce "on_fd()" events; + // don't forget using modify_fd() to remove the write notification once you're + // done writing. + // + // [main-thread] + void(CLAP_ABI *on_fd)(const clap_plugin_t *plugin, int fd, clap_posix_fd_flags_t flags); +} clap_plugin_posix_fd_support_t; + +typedef struct clap_host_posix_fd_support { + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *register_fd)(const clap_host_t *host, int fd, clap_posix_fd_flags_t flags); + + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *modify_fd)(const clap_host_t *host, int fd, clap_posix_fd_flags_t flags); + + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *unregister_fd)(const clap_host_t *host, int fd); +} clap_host_posix_fd_support_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/preset-load.h b/third_party/clap/include/clap/ext/preset-load.h new file mode 100644 index 0000000..e2c19e3 --- /dev/null +++ b/third_party/clap/include/clap/ext/preset-load.h @@ -0,0 +1,53 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_PRESET_LOAD[] = "clap.preset-load/2"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_PRESET_LOAD_COMPAT[] = "clap.preset-load.draft/2"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_preset_load { + // Loads a preset in the plugin native preset file format from a location. + // The preset discovery provider defines the location and load_key to be passed to this function. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *from_location)(const clap_plugin_t *plugin, + uint32_t location_kind, + const char *location, + const char *load_key); +} clap_plugin_preset_load_t; + +typedef struct clap_host_preset_load { + // Called if clap_plugin_preset_load.from_location() failed. + // os_error: the operating system error, if applicable. If not applicable set it to a non-error + // value, eg: 0 on unix and Windows. + // + // [main-thread] + void(CLAP_ABI *on_error)(const clap_host_t *host, + uint32_t location_kind, + const char *location, + const char *load_key, + int32_t os_error, + const char *msg); + + // Informs the host that the following preset has been loaded. + // This contributes to keep in sync the host preset browser and plugin preset browser. + // If the preset was loaded from a container file, then the load_key must be set, otherwise it + // must be null. + // + // [main-thread] + void(CLAP_ABI *loaded)(const clap_host_t *host, + uint32_t location_kind, + const char *location, + const char *load_key); +} clap_host_preset_load_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/remote-controls.h b/third_party/clap/include/clap/ext/remote-controls.h new file mode 100644 index 0000000..d7bf4fc --- /dev/null +++ b/third_party/clap/include/clap/ext/remote-controls.h @@ -0,0 +1,83 @@ +#pragma once + +#include "../plugin.h" +#include "../string-sizes.h" + +// This extension let the plugin provide a structured way of mapping parameters to an hardware +// controller. +// +// This is done by providing a set of remote control pages organized by section. +// A page contains up to 8 controls, which references parameters using param_id. +// +// |`- [section:main] +// | `- [name:main] performance controls +// |`- [section:osc] +// | |`- [name:osc1] osc1 page +// | |`- [name:osc2] osc2 page +// | |`- [name:osc-sync] osc sync page +// | `- [name:osc-noise] osc noise page +// |`- [section:filter] +// | |`- [name:flt1] filter 1 page +// | `- [name:flt2] filter 2 page +// |`- [section:env] +// | |`- [name:env1] env1 page +// | `- [name:env2] env2 page +// |`- [section:lfo] +// | |`- [name:lfo1] env1 page +// | `- [name:lfo2] env2 page +// `- etc... +// +// One possible workflow is to have a set of buttons, which correspond to a section. +// Pressing that button once gets you to the first page of the section. +// Press it again to cycle through the section's pages. + +static CLAP_CONSTEXPR const char CLAP_EXT_REMOTE_CONTROLS[] = "clap.remote-controls/2"; + +// The latest draft is 100% compatible +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_REMOTE_CONTROLS_COMPAT[] = "clap.remote-controls.draft/2"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { CLAP_REMOTE_CONTROLS_COUNT = 8 }; + +typedef struct clap_remote_controls_page { + char section_name[CLAP_NAME_SIZE]; + clap_id page_id; + char page_name[CLAP_NAME_SIZE]; + clap_id param_ids[CLAP_REMOTE_CONTROLS_COUNT]; + + // This is used to separate device pages versus preset pages. + // If true, then this page is specific to this preset. + bool is_for_preset; +} clap_remote_controls_page_t; + +typedef struct clap_plugin_remote_controls { + // Returns the number of pages. + // [main-thread] + uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin); + + // Get a page by index. + // Returns true on success and stores the result into page. + // [main-thread] + bool(CLAP_ABI *get)(const clap_plugin_t *plugin, + uint32_t page_index, + clap_remote_controls_page_t *page); +} clap_plugin_remote_controls_t; + +typedef struct clap_host_remote_controls { + // Informs the host that the remote controls have changed. + // [main-thread] + void(CLAP_ABI *changed)(const clap_host_t *host); + + // Suggest a page to the host because it corresponds to what the user is currently editing in the + // plugin's GUI. + // [main-thread] + void(CLAP_ABI *suggest_page)(const clap_host_t *host, clap_id page_id); +} clap_host_remote_controls_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/render.h b/third_party/clap/include/clap/ext/render.h new file mode 100644 index 0000000..0e1c1cd --- /dev/null +++ b/third_party/clap/include/clap/ext/render.h @@ -0,0 +1,39 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_RENDER[] = "clap.render"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // Default setting, for "realtime" processing + CLAP_RENDER_REALTIME = 0, + + // For processing without realtime pressure + // The plugin may use more expensive algorithms for higher sound quality. + CLAP_RENDER_OFFLINE = 1, +}; +typedef int32_t clap_plugin_render_mode; + +// The render extension is used to let the plugin know if it has "realtime" +// pressure to process. +// +// If this information does not influence your rendering code, then don't +// implement this extension. +typedef struct clap_plugin_render { + // Returns true if the plugin has a hard requirement to process in real-time. + // This is especially useful for plugin acting as a proxy to an hardware device. + // [main-thread] + bool(CLAP_ABI *has_hard_realtime_requirement)(const clap_plugin_t *plugin); + + // Returns true if the rendering mode could be applied. + // [main-thread] + bool(CLAP_ABI *set)(const clap_plugin_t *plugin, clap_plugin_render_mode mode); +} clap_plugin_render_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/state-context.h b/third_party/clap/include/clap/ext/state-context.h new file mode 100644 index 0000000..20248b3 --- /dev/null +++ b/third_party/clap/include/clap/ext/state-context.h @@ -0,0 +1,72 @@ +#pragma once + +#include "../plugin.h" +#include "../stream.h" + +/// @page state-context extension +/// @brief extended state handling +/// +/// This extension lets the host save and load the plugin state with different semantics depending +/// on the context. +/// +/// Briefly, when loading a preset or duplicating a device, the plugin may want to partially load +/// the state and initialize certain things differently, like handling limited resources or fixed +/// connections to external hardware resources. +/// +/// Save and Load operations may have a different context. +/// All three operations should be equivalent: +/// 1. clap_plugin_state_context.load(clap_plugin_state.save(), CLAP_STATE_CONTEXT_FOR_PRESET) +/// 2. clap_plugin_state.load(clap_plugin_state_context.save(CLAP_STATE_CONTEXT_FOR_PRESET)) +/// 3. clap_plugin_state_context.load( +/// clap_plugin_state_context.save(CLAP_STATE_CONTEXT_FOR_PRESET), +/// CLAP_STATE_CONTEXT_FOR_PRESET) +/// +/// If in doubt, fallback to clap_plugin_state. +/// +/// If the plugin implements CLAP_EXT_STATE_CONTEXT then it is mandatory to also implement +/// CLAP_EXT_STATE. +/// +/// It is unspecified which context is equivalent to clap_plugin_state.{save,load}() + +#ifdef __cplusplus +extern "C" { +#endif + +static CLAP_CONSTEXPR const char CLAP_EXT_STATE_CONTEXT[] = "clap.state-context/2"; + +enum clap_plugin_state_context_type { + // suitable for storing and loading a state as a preset + CLAP_STATE_CONTEXT_FOR_PRESET = 1, + + // suitable for duplicating a plugin instance + CLAP_STATE_CONTEXT_FOR_DUPLICATE = 2, + + // suitable for storing and loading a state within a project/song + CLAP_STATE_CONTEXT_FOR_PROJECT = 3, +}; + +typedef struct clap_plugin_state_context { + // Saves the plugin state into stream, according to context_type. + // Returns true if the state was correctly saved. + // + // Note that the result may be loaded by both clap_plugin_state.load() and + // clap_plugin_state_context.load(). + // [main-thread] + bool(CLAP_ABI *save)(const clap_plugin_t *plugin, + const clap_ostream_t *stream, + uint32_t context_type); + + // Loads the plugin state from stream, according to context_type. + // Returns true if the state was correctly restored. + // + // Note that the state may have been saved by clap_plugin_state.save() or + // clap_plugin_state_context.save() with a different context_type. + // [main-thread] + bool(CLAP_ABI *load)(const clap_plugin_t *plugin, + const clap_istream_t *stream, + uint32_t context_type); +} clap_plugin_state_context_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/state.h b/third_party/clap/include/clap/ext/state.h new file mode 100644 index 0000000..540246b --- /dev/null +++ b/third_party/clap/include/clap/ext/state.h @@ -0,0 +1,45 @@ +#pragma once + +#include "../plugin.h" +#include "../stream.h" + +/// @page State +/// @brief state management +/// +/// Plugins can implement this extension to save and restore both parameter +/// values and non-parameter state. This is used to persist a plugin's state +/// between project reloads, when duplicating and copying plugin instances, and +/// for host-side preset management. +/// +/// If you need to know if the save/load operation is meant for duplicating a plugin +/// instance, for saving/loading a plugin preset or while saving/loading the project +/// then consider implementing CLAP_EXT_STATE_CONTEXT in addition to CLAP_EXT_STATE. + +static CLAP_CONSTEXPR const char CLAP_EXT_STATE[] = "clap.state"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_state { + // Saves the plugin state into stream. + // Returns true if the state was correctly saved. + // [main-thread] + bool(CLAP_ABI *save)(const clap_plugin_t *plugin, const clap_ostream_t *stream); + + // Loads the plugin state from stream. + // Returns true if the state was correctly restored. + // [main-thread] + bool(CLAP_ABI *load)(const clap_plugin_t *plugin, const clap_istream_t *stream); +} clap_plugin_state_t; + +typedef struct clap_host_state { + // Tell the host that the plugin state has changed and should be saved again. + // If a parameter value changes, then it is implicit that the state is dirty. + // [main-thread] + void(CLAP_ABI *mark_dirty)(const clap_host_t *host); +} clap_host_state_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/surround.h b/third_party/clap/include/clap/ext/surround.h new file mode 100644 index 0000000..585ac4c --- /dev/null +++ b/third_party/clap/include/clap/ext/surround.h @@ -0,0 +1,86 @@ +#pragma once + +#include "../plugin.h" + +// This extension can be used to specify the channel mapping used by the plugin. +// +// To have consistent surround features across all the plugin instances, +// here is the proposed workflow: +// 1. the plugin queries the host preferred channel mapping and +// adjusts its configuration to match it. +// 2. the host checks how the plugin is effectively configured and honors it. +// +// If the host decides to change the project's surround setup: +// 1. deactivate the plugin +// 2. host pushes a new configuration using clap_plugin_configurable_audio_ports +// 3. host activates the plugin and can start processing audio +// +// If the plugin wants to change its surround setup: +// 1. call host->request_restart() if the plugin is active +// 2. once deactivated plugin calls clap_host_surround->changed() +// 3. host calls clap_plugin_surround->get_channel_map() +// 4. host activates the plugin and can start processing audio + +static CLAP_CONSTEXPR const char CLAP_EXT_SURROUND[] = "clap.surround/4"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_SURROUND_COMPAT[] = "clap.surround.draft/4"; + +static CLAP_CONSTEXPR const char CLAP_PORT_SURROUND[] = "surround"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + CLAP_SURROUND_FL = 0, // Front Left + CLAP_SURROUND_FR = 1, // Front Right + CLAP_SURROUND_FC = 2, // Front Center + CLAP_SURROUND_LFE = 3, // Low Frequency + CLAP_SURROUND_BL = 4, // Back (Rear) Left + CLAP_SURROUND_BR = 5, // Back (Rear) Right + CLAP_SURROUND_FLC = 6, // Front Left of Center + CLAP_SURROUND_FRC = 7, // Front Right of Center + CLAP_SURROUND_BC = 8, // Back (Rear) Center + CLAP_SURROUND_SL = 9, // Side Left + CLAP_SURROUND_SR = 10, // Side Right + CLAP_SURROUND_TC = 11, // Top (Height) Center + CLAP_SURROUND_TFL = 12, // Top (Height) Front Left + CLAP_SURROUND_TFC = 13, // Top (Height) Front Center + CLAP_SURROUND_TFR = 14, // Top (Height) Front Right + CLAP_SURROUND_TBL = 15, // Top (Height) Back (Rear) Left + CLAP_SURROUND_TBC = 16, // Top (Height) Back (Rear) Center + CLAP_SURROUND_TBR = 17, // Top (Height) Back (Rear) Right + CLAP_SURROUND_TSL = 18, // Top (Height) Side Left + CLAP_SURROUND_TSR = 19, // Top (Height) Side Right +}; + +typedef struct clap_plugin_surround { + // Checks if a given channel mask is supported. + // The channel mask is a bitmask, for example: + // (1 << CLAP_SURROUND_FL) | (1 << CLAP_SURROUND_FR) | ... + // [main-thread] + bool(CLAP_ABI *is_channel_mask_supported)(const clap_plugin_t *plugin, uint64_t channel_mask); + + // Stores the surround identifier of each channel into the channel_map array. + // Returns the number of elements stored in channel_map. + // channel_map_capacity must be greater or equal to the channel count of the given port. + // [main-thread] + uint32_t(CLAP_ABI *get_channel_map)(const clap_plugin_t *plugin, + bool is_input, + uint32_t port_index, + uint8_t *channel_map, + uint32_t channel_map_capacity); +} clap_plugin_surround_t; + +typedef struct clap_host_surround { + // Informs the host that the channel map has changed. + // The channel map can only change when the plugin is de-activated. + // [main-thread] + void(CLAP_ABI *changed)(const clap_host_t *host); +} clap_host_surround_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/tail.h b/third_party/clap/include/clap/ext/tail.h new file mode 100644 index 0000000..5d79e3a --- /dev/null +++ b/third_party/clap/include/clap/ext/tail.h @@ -0,0 +1,26 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_TAIL[] = "clap.tail"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_tail { + // Returns tail length in samples. + // Any value greater or equal to INT32_MAX implies infinite tail. + // [main-thread,audio-thread] + uint32_t(CLAP_ABI *get)(const clap_plugin_t *plugin); +} clap_plugin_tail_t; + +typedef struct clap_host_tail { + // Tell the host that the tail has changed. + // [audio-thread] + void(CLAP_ABI *changed)(const clap_host_t *host); +} clap_host_tail_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/thread-check.h b/third_party/clap/include/clap/ext/thread-check.h new file mode 100644 index 0000000..50dd1b4 --- /dev/null +++ b/third_party/clap/include/clap/ext/thread-check.h @@ -0,0 +1,83 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_THREAD_CHECK[] = "clap.thread-check"; + +#ifdef __cplusplus +extern "C" { +#endif + +/// @page thread-check +/// +/// CLAP defines two symbolic threads: +/// +/// main-thread: +/// This is the thread in which most of the interaction between the plugin and host happens. +/// This will be the same OS thread throughout the lifetime of the plug-in. +/// On macOS and Windows, this must be the thread on which gui and timer events are received +/// (i.e., the main thread of the program). +/// It isn't a realtime thread, yet this thread needs to respond fast enough to allow responsive +/// user interaction, so it is strongly recommended plugins run long,and expensive or blocking +/// tasks such as preset indexing or asset loading in dedicated background threads started by the +/// plugin. +/// +/// audio-thread: +/// This thread can be used for realtime audio processing. Its execution should be as +/// deterministic as possible to meet the audio interface's deadline (can be <1ms). There are a +/// known set of operations that should be avoided: malloc() and free(), contended locks and +/// mutexes, I/O, waiting, and so forth. +/// +/// The audio-thread is symbolic, there isn't one OS thread that remains the +/// audio-thread for the plugin lifetime. A host is may opt to have a +/// thread pool and the plugin.process() call may be scheduled on different OS threads over time. +/// However, the host must guarantee that single plugin instance will not be two audio-threads +/// at the same time. +/// +/// Functions marked with [audio-thread] **ARE NOT CONCURRENT**. The host may mark any OS thread, +/// including the main-thread as the audio-thread, as long as it can guarantee that only one OS +/// thread is the audio-thread at a time in a plugin instance. The audio-thread can be seen as a +/// concurrency guard for all functions marked with [audio-thread]. +/// +/// The real-time constraint on the [audio-thread] interacts closely with the render extension. +/// If a plugin doesn't implement render, then that plugin must have all [audio-thread] functions +/// meet the real time standard. If the plugin does implement render, and returns true when +/// render mode is set to real-time or if the plugin advertises a hard realtime requirement, it +/// must implement realtime constraints. Hosts also provide functions marked [audio-thread]. +/// These can be safely called by a plugin in the audio thread. Therefore hosts must either (1) +/// implement those functions meeting the real-time constraints or (2) not process plugins which +/// advertise a hard realtime constraint or don't implement the render extension. Hosts which +/// provide [audio-thread] functions outside these conditions may experience inconsistent or +/// inaccurate rendering. +/// +/// background-thread: +/// This thread is created by the host to run some heavy operation without blocking the +/// main-thread. +/// +/// Only a few extensions use the background thread and in a very explicit way. If +/// the plugin implement a background interfaces, it must take the necessary thread-safety +/// precautions. +/// +/// It is the host's responsiblity to execute background operations in a way that guarentee +/// a race-free and deterministic execution. +/// +/// Clap also tags some functions as [thread-safe]. Functions tagged as [thread-safe] can be called +/// from any thread unless explicitly counter-indicated (for instance [thread-safe, !audio-thread]) +/// and may be called concurrently. + +// This interface is useful to do runtime checks and make +// sure that the functions are called on the correct threads. +// It is highly recommended that hosts implement this extension. +typedef struct clap_host_thread_check { + // Returns true if "this" thread is the main thread. + // [thread-safe] + bool(CLAP_ABI *is_main_thread)(const clap_host_t *host); + + // Returns true if "this" thread is one of the audio threads. + // [thread-safe] + bool(CLAP_ABI *is_audio_thread)(const clap_host_t *host); +} clap_host_thread_check_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/thread-pool.h b/third_party/clap/include/clap/ext/thread-pool.h new file mode 100644 index 0000000..1d34d9b --- /dev/null +++ b/third_party/clap/include/clap/ext/thread-pool.h @@ -0,0 +1,66 @@ +#pragma once + +#include "../plugin.h" + +/// @page +/// +/// This extension lets the plugin use the host's thread pool. +/// +/// The plugin must provide @ref clap_plugin_thread_pool, and the host may provide @ref +/// clap_host_thread_pool. If it doesn't, the plugin should process its data by its own means. In +/// the worst case, a single threaded for-loop. +/// +/// Simple example with N voices to process +/// +/// @code +/// void myplug_thread_pool_exec(const clap_plugin *plugin, uint32_t voice_index) +/// { +/// compute_voice(plugin, voice_index); +/// } +/// +/// void myplug_process(const clap_plugin *plugin, const clap_process *process) +/// { +/// ... +/// bool didComputeVoices = false; +/// if (host_thread_pool && host_thread_pool->request_exec) +/// didComputeVoices = host_thread_pool->request_exec(host, N); +/// +/// if (!didComputeVoices) +/// for (uint32_t i = 0; i < N; ++i) +/// myplug_thread_pool_exec(plugin, i); +/// ... +/// } +/// @endcode +/// +/// Be aware that using a thread pool may break hard real-time rules due to the thread +/// synchronization involved. +/// +/// If the host knows that it is running under hard real-time pressure it may decide to not +/// provide this interface. + +static CLAP_CONSTEXPR const char CLAP_EXT_THREAD_POOL[] = "clap.thread-pool"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_thread_pool { + // Called by the thread pool + void(CLAP_ABI *exec)(const clap_plugin_t *plugin, uint32_t task_index); +} clap_plugin_thread_pool_t; + +typedef struct clap_host_thread_pool { + // Schedule num_tasks jobs in the host thread pool. + // It can't be called concurrently or from the thread pool. + // Will block until all the tasks are processed. + // This must be used exclusively for realtime processing within the process call. + // Returns true if the host did execute all the tasks, false if it rejected the request. + // The host should check that the plugin is within the process call, and if not, reject the exec + // request. + // [audio-thread] + bool(CLAP_ABI *request_exec)(const clap_host_t *host, uint32_t num_tasks); +} clap_host_thread_pool_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/timer-support.h b/third_party/clap/include/clap/ext/timer-support.h new file mode 100644 index 0000000..221de96 --- /dev/null +++ b/third_party/clap/include/clap/ext/timer-support.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_TIMER_SUPPORT[] = "clap.timer-support"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_timer_support { + // [main-thread] + void(CLAP_ABI *on_timer)(const clap_plugin_t *plugin, clap_id timer_id); +} clap_plugin_timer_support_t; + +typedef struct clap_host_timer_support { + // Registers a periodic timer. + // The host may adjust the period if it is under a certain threshold. + // 30 Hz should be allowed. + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *register_timer)(const clap_host_t *host, uint32_t period_ms, clap_id *timer_id); + + // Returns true on success. + // [main-thread] + bool(CLAP_ABI *unregister_timer)(const clap_host_t *host, clap_id timer_id); +} clap_host_timer_support_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/track-info.h b/third_party/clap/include/clap/ext/track-info.h new file mode 100644 index 0000000..3e1a555 --- /dev/null +++ b/third_party/clap/include/clap/ext/track-info.h @@ -0,0 +1,66 @@ +#pragma once + +#include "../plugin.h" +#include "../color.h" +#include "../string-sizes.h" + +// This extension let the plugin query info about the track it's in. +// It is useful when the plugin is created, to initialize some parameters (mix, dry, wet) +// and pick a suitable configuration regarding audio port type and channel count. + +static CLAP_CONSTEXPR const char CLAP_EXT_TRACK_INFO[] = "clap.track-info/1"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static CLAP_CONSTEXPR const char CLAP_EXT_TRACK_INFO_COMPAT[] = "clap.track-info.draft/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + CLAP_TRACK_INFO_HAS_TRACK_NAME = (1 << 0), + CLAP_TRACK_INFO_HAS_TRACK_COLOR = (1 << 1), + CLAP_TRACK_INFO_HAS_AUDIO_CHANNEL = (1 << 2), + + // This plugin is on a return track, initialize with wet 100% + CLAP_TRACK_INFO_IS_FOR_RETURN_TRACK = (1 << 3), + + // This plugin is on a bus track, initialize with appropriate settings for bus processing + CLAP_TRACK_INFO_IS_FOR_BUS = (1 << 4), + + // This plugin is on the master, initialize with appropriate settings for channel processing + CLAP_TRACK_INFO_IS_FOR_MASTER = (1 << 5), +}; + +typedef struct clap_track_info { + uint64_t flags; // see the flags above + + // track name, available if flags contain CLAP_TRACK_INFO_HAS_TRACK_NAME + char name[CLAP_NAME_SIZE]; + + // track color, available if flags contain CLAP_TRACK_INFO_HAS_TRACK_COLOR + clap_color_t color; + + // available if flags contain CLAP_TRACK_INFO_HAS_AUDIO_CHANNEL + // see audio-ports.h, struct clap_audio_port_info to learn how to use channel count and port type + int32_t audio_channel_count; + const char *audio_port_type; +} clap_track_info_t; + +typedef struct clap_plugin_track_info { + // Called when the info changes. + // [main-thread] + void(CLAP_ABI *changed)(const clap_plugin_t *plugin); +} clap_plugin_track_info_t; + +typedef struct clap_host_track_info { + // Get info about the track the plugin belongs to. + // Returns true on success and stores the result into info. + // [main-thread] + bool(CLAP_ABI *get)(const clap_host_t *host, clap_track_info_t *info); +} clap_host_track_info_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/ext/voice-info.h b/third_party/clap/include/clap/ext/voice-info.h new file mode 100644 index 0000000..49651f6 --- /dev/null +++ b/third_party/clap/include/clap/ext/voice-info.h @@ -0,0 +1,56 @@ +#pragma once + +#include "../plugin.h" + +// This extension indicates the number of voices the synthesizer has. +// It is useful for the host when performing polyphonic modulations, +// because the host needs its own voice management and should try to follow +// what the plugin is doing: +// - make the host's voice pool coherent with what the plugin has +// - turn the host's voice management to mono when the plugin is mono + +static CLAP_CONSTEXPR const char CLAP_EXT_VOICE_INFO[] = "clap.voice-info"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // Allows the host to send overlapping NOTE_ON events. + // The plugin will then rely upon the note_id to distinguish between them. + CLAP_VOICE_INFO_SUPPORTS_OVERLAPPING_NOTES = 1 << 0, +}; + +typedef struct clap_voice_info { + // voice_count is the current number of voices that the patch can use + // voice_capacity is the number of voices allocated voices + // voice_count should not be confused with the number of active voices. + // + // 1 <= voice_count <= voice_capacity + // + // For example, a synth can have a capacity of 8 voices, but be configured + // to only use 4 voices: {count: 4, capacity: 8}. + // + // If the voice_count is 1, then the synth is working in mono and the host + // can decide to only use global modulation mapping. + uint32_t voice_count; + uint32_t voice_capacity; + + uint64_t flags; +} clap_voice_info_t; + +typedef struct clap_plugin_voice_info { + // gets the voice info, returns true on success + // [main-thread & active] + bool(CLAP_ABI *get)(const clap_plugin_t *plugin, clap_voice_info_t *info); +} clap_plugin_voice_info_t; + +typedef struct clap_host_voice_info { + // informs the host that the voice info has changed + // [main-thread] + void(CLAP_ABI *changed)(const clap_host_t *host); +} clap_host_voice_info_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/factory/draft/plugin-invalidation.h b/third_party/clap/include/clap/factory/draft/plugin-invalidation.h new file mode 100644 index 0000000..7f65dd0 --- /dev/null +++ b/third_party/clap/include/clap/factory/draft/plugin-invalidation.h @@ -0,0 +1,47 @@ +#pragma once + +#include "../../private/std.h" +#include "../../private/macros.h" + +// Use it to retrieve const clap_plugin_invalidation_factory_t* from +// clap_plugin_entry.get_factory() +static const CLAP_CONSTEXPR char CLAP_PLUGIN_INVALIDATION_FACTORY_ID[] = + "clap.plugin-invalidation-factory/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_invalidation_source { + // Directory containing the file(s) to scan, must be absolute + const char *directory; + + // globing pattern, in the form *.dll + const char *filename_glob; + + // should the directory be scanned recursively? + bool recursive_scan; +} clap_plugin_invalidation_source_t; + +// Used to figure out when a plugin needs to be scanned again. +// Imagine a situation with a single entry point: my-plugin.clap which then scans itself +// a set of "sub-plugins". New plugin may be available even if my-plugin.clap file doesn't change. +// This interfaces solves this issue and gives a way to the host to monitor additional files. +typedef struct clap_plugin_invalidation_factory { + // Get the number of invalidation source. + uint32_t(CLAP_ABI *count)(const struct clap_plugin_invalidation_factory *factory); + + // Get the invalidation source by its index. + // [thread-safe] + const clap_plugin_invalidation_source_t *(CLAP_ABI *get)( + const struct clap_plugin_invalidation_factory *factory, uint32_t index); + + // In case the host detected a invalidation event, it can call refresh() to let the + // plugin_entry update the set of plugins available. + // If the function returned false, then the plugin needs to be reloaded. + bool(CLAP_ABI *refresh)(const struct clap_plugin_invalidation_factory *factory); +} clap_plugin_invalidation_factory_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/factory/draft/plugin-state-converter.h b/third_party/clap/include/clap/factory/draft/plugin-state-converter.h new file mode 100644 index 0000000..20badb3 --- /dev/null +++ b/third_party/clap/include/clap/factory/draft/plugin-state-converter.h @@ -0,0 +1,99 @@ +#pragma once + +#include "../../id.h" +#include "../../universal-plugin-id.h" +#include "../../stream.h" +#include "../../version.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_state_converter_descriptor { + clap_version_t clap_version; + + clap_universal_plugin_id_t src_plugin_id; + clap_universal_plugin_id_t dst_plugin_id; + + const char *id; // eg: "com.u-he.diva-converter", mandatory + const char *name; // eg: "Diva Converter", mandatory + const char *vendor; // eg: "u-he" + const char *version; // eg: 1.1.5 + const char *description; // eg: "Official state converter for u-he Diva." +} clap_plugin_state_converter_descriptor_t; + +// This interface provides a mechanism for the host to convert a plugin state and its automation +// points to a new plugin. +// +// This is useful to convert from one plugin ABI to another one. +// This is also useful to offer an upgrade path: from EQ version 1 to EQ version 2. +// This can also be used to convert the state of a plugin that isn't maintained anymore into +// another plugin that would be similar. +typedef struct clap_plugin_state_converter { + const clap_plugin_state_converter_descriptor_t *desc; + + void *converter_data; + + // Destroy the converter. + void(CLAP_ABI *destroy)(struct clap_plugin_state_converter *converter); + + // Converts the input state to a state usable by the destination plugin. + // + // error_buffer is a place holder of error_buffer_size bytes for storing a null-terminated + // error message in case of failure, which can be displayed to the user. + // + // Returns true on success. + // [thread-safe] + bool(CLAP_ABI *convert_state)(struct clap_plugin_state_converter *converter, + const clap_istream_t *src, + const clap_ostream_t *dst, + char *error_buffer, + size_t error_buffer_size); + + // Converts a normalized value. + // Returns true on success. + // [thread-safe] + bool(CLAP_ABI *convert_normalized_value)(struct clap_plugin_state_converter *converter, + clap_id src_param_id, + double src_normalized_value, + clap_id *dst_param_id, + double *dst_normalized_value); + + // Converts a plain value. + // Returns true on success. + // [thread-safe] + bool(CLAP_ABI *convert_plain_value)(struct clap_plugin_state_converter *converter, + clap_id src_param_id, + double src_plain_value, + clap_id *dst_param_id, + double *dst_plain_value); +} clap_plugin_state_converter_t; + +// Factory identifier +static CLAP_CONSTEXPR const char CLAP_PLUGIN_STATE_CONVERTER_FACTORY_ID[] = + "clap.plugin-state-converter-factory/1"; + +// List all the plugin state converters available in the current DSO. +typedef struct clap_plugin_state_converter_factory { + // Get the number of converters. + // [thread-safe] + uint32_t(CLAP_ABI *count)(const struct clap_plugin_state_converter_factory *factory); + + // Retrieves a plugin state converter descriptor by its index. + // Returns null in case of error. + // The descriptor must not be freed. + // [thread-safe] + const clap_plugin_state_converter_descriptor_t *(CLAP_ABI *get_descriptor)( + const struct clap_plugin_state_converter_factory *factory, uint32_t index); + + // Create a plugin state converter by its converter_id. + // The returned pointer must be freed by calling converter->destroy(converter); + // Returns null in case of error. + // [thread-safe] + clap_plugin_state_converter_t *(CLAP_ABI *create)( + const struct clap_plugin_state_converter_factory *factory, const char *converter_id); +} clap_plugin_state_converter_factory_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/factory/plugin-factory.h b/third_party/clap/include/clap/factory/plugin-factory.h new file mode 100644 index 0000000..5b15773 --- /dev/null +++ b/third_party/clap/include/clap/factory/plugin-factory.h @@ -0,0 +1,43 @@ +#pragma once + +#include "../plugin.h" + +// Use it to retrieve const clap_plugin_factory_t* from +// clap_plugin_entry.get_factory() +static const CLAP_CONSTEXPR char CLAP_PLUGIN_FACTORY_ID[] = "clap.plugin-factory"; + +#ifdef __cplusplus +extern "C" { +#endif + +// Every method must be thread-safe. +// It is very important to be able to scan the plugin as quickly as possible. +// +// The host may use clap_plugin_invalidation_factory to detect filesystem changes +// which may change the factory's content. +typedef struct clap_plugin_factory { + // Get the number of plugins available. + // [thread-safe] + uint32_t(CLAP_ABI *get_plugin_count)(const struct clap_plugin_factory *factory); + + // Retrieves a plugin descriptor by its index. + // The descriptor is owned by the plugin and is valid until the call to clap_plugin_entry->deinit() + // Returns null in case of error. + // [thread-safe] + const clap_plugin_descriptor_t *(CLAP_ABI *get_plugin_descriptor)( + const struct clap_plugin_factory *factory, uint32_t index); + + // Create a clap_plugin by its plugin_id. + // The clap_host pointer must be valid until after the call to plugin->destroy(plugin). + // The returned pointer is owned by the plugin and must be freed by calling plugin->destroy(plugin); + // The plugin is not allowed to use the host callbacks in the create method. + // Returns null in case of error. + // [thread-safe] + const clap_plugin_t *(CLAP_ABI *create_plugin)(const struct clap_plugin_factory *factory, + const clap_host_t *host, + const char *plugin_id); +} clap_plugin_factory_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/factory/preset-discovery.h b/third_party/clap/include/clap/factory/preset-discovery.h new file mode 100644 index 0000000..fbb0244 --- /dev/null +++ b/third_party/clap/include/clap/factory/preset-discovery.h @@ -0,0 +1,313 @@ +/* + Preset Discovery API. + + Preset Discovery enables a plug-in host to identify where presets are found, what + extensions they have, which plug-ins they apply to, and other metadata associated with the + presets so that they can be indexed and searched for quickly within the plug-in host's browser. + + This has a number of advantages for the user: + - it allows them to browse for presets from one central location in a consistent way + - the user can browse for presets without having to commit to a particular plug-in first + + The API works as follow to index presets and presets metadata: + 1. clap_plugin_entry.get_factory(CLAP_PRESET_DISCOVERY_FACTORY_ID) + 2. clap_preset_discovery_factory_t.create(...) + 3. clap_preset_discovery_provider.init() (only necessary the first time, declarations + can be cached) + `-> clap_preset_discovery_indexer.declare_filetype() + `-> clap_preset_discovery_indexer.declare_location() + `-> clap_preset_discovery_indexer.declare_soundpack() (optional) + `-> clap_preset_discovery_indexer.set_invalidation_watch_file() (optional) + 4. crawl the given locations and monitor file system changes + `-> clap_preset_discovery_indexer.get_metadata() for each presets files + + Then to load a preset, use ext/draft/preset-load.h. + TODO: create a dedicated repo for other plugin abi preset-load extension. + + The design of this API deliberately does not define a fixed set tags or categories. It is the + plug-in host's job to try to intelligently map the raw list of features that are found for a + preset and to process this list to generate something that makes sense for the host's tagging and + categorization system. The reason for this is to reduce the work for a plug-in developer to add + Preset Discovery support for their existing preset file format and not have to be concerned with + all the different hosts and how they want to receive the metadata. + + VERY IMPORTANT: + - the whole indexing process has to be **fast** + - clap_preset_provider->get_metadata() has to be fast and avoid unnecessary operations + - the whole indexing process must not be interactive + - don't show dialogs, windows, ... + - don't ask for user input +*/ + +#pragma once + +#include "../private/std.h" +#include "../private/macros.h" +#include "../timestamp.h" +#include "../version.h" +#include "../universal-plugin-id.h" + +// Use it to retrieve const clap_preset_discovery_factory_t* from +// clap_plugin_entry.get_factory() +static const CLAP_CONSTEXPR char CLAP_PRESET_DISCOVERY_FACTORY_ID[] = + "clap.preset-discovery-factory/2"; + +// The latest draft is 100% compatible. +// This compat ID may be removed in 2026. +static const CLAP_CONSTEXPR char CLAP_PRESET_DISCOVERY_FACTORY_ID_COMPAT[] = + "clap.preset-discovery-factory/draft-2"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum clap_preset_discovery_location_kind { + // The preset are located in a file on the OS filesystem. + // The location is then a path which works with the OS file system functions (open, stat, ...) + // So both '/' and '\' shall work on Windows as a separator. + CLAP_PRESET_DISCOVERY_LOCATION_FILE = 0, + + // The preset is bundled within the plugin DSO itself. + // The location must then be null, as the preset are within the plugin itself and then the plugin + // will act as a preset container. + CLAP_PRESET_DISCOVERY_LOCATION_PLUGIN = 1, +}; + +enum clap_preset_discovery_flags { + // This is for factory or sound-pack presets. + CLAP_PRESET_DISCOVERY_IS_FACTORY_CONTENT = 1 << 0, + + // This is for user presets. + CLAP_PRESET_DISCOVERY_IS_USER_CONTENT = 1 << 1, + + // This location is meant for demo presets, those are preset which may trigger + // some limitation in the plugin because they require additional features which the user + // needs to purchase or the content itself needs to be bought and is only available in + // demo mode. + CLAP_PRESET_DISCOVERY_IS_DEMO_CONTENT = 1 << 2, + + // This preset is a user's favorite + CLAP_PRESET_DISCOVERY_IS_FAVORITE = 1 << 3, +}; + +// Receiver that receives the metadata for a single preset file. +// The host would define the various callbacks in this interface and the preset parser function +// would then call them. +// +// This interface isn't thread-safe. +typedef struct clap_preset_discovery_metadata_receiver { + void *receiver_data; // reserved pointer for the metadata receiver + + // If there is an error reading metadata from a file this should be called with an error + // message. + // os_error: the operating system error, if applicable. If not applicable set it to a non-error + // value, eg: 0 on unix and Windows. + void(CLAP_ABI *on_error)(const struct clap_preset_discovery_metadata_receiver *receiver, + int32_t os_error, + const char *error_message); + + // This must be called for every preset in the file and before any preset metadata is + // sent with the calls below. + // + // If the preset file is a preset container then name and load_key are mandatory, otherwise + // they are optional. + // + // The load_key is a machine friendly string used to load the preset inside the container via a + // the preset-load plug-in extension. The load_key can also just be the subpath if that's what + // the plugin wants but it could also be some other unique id like a database primary key or a + // binary offset. It's use is entirely up to the plug-in. + // + // If the function returns false, then the provider must stop calling back into the receiver. + bool(CLAP_ABI *begin_preset)(const struct clap_preset_discovery_metadata_receiver *receiver, + const char *name, + const char *load_key); + + // Adds a plug-in id that this preset can be used with. + void(CLAP_ABI *add_plugin_id)(const struct clap_preset_discovery_metadata_receiver *receiver, + const clap_universal_plugin_id_t *plugin_id); + + // Sets the sound pack to which the preset belongs to. + void(CLAP_ABI *set_soundpack_id)(const struct clap_preset_discovery_metadata_receiver *receiver, + const char *soundpack_id); + + // Sets the flags, see clap_preset_discovery_flags. + // If unset, they are then inherited from the location. + void(CLAP_ABI *set_flags)(const struct clap_preset_discovery_metadata_receiver *receiver, + uint32_t flags); + + // Adds a creator name for the preset. + void(CLAP_ABI *add_creator)(const struct clap_preset_discovery_metadata_receiver *receiver, + const char *creator); + + // Sets a description of the preset. + void(CLAP_ABI *set_description)(const struct clap_preset_discovery_metadata_receiver *receiver, + const char *description); + + // Sets the creation time and last modification time of the preset. + // If one of the times isn't known, set it to CLAP_TIMESTAMP_UNKNOWN. + // If this function is not called, then the indexer may look at the file's creation and + // modification time. + void(CLAP_ABI *set_timestamps)(const struct clap_preset_discovery_metadata_receiver *receiver, + clap_timestamp creation_time, + clap_timestamp modification_time); + + // Adds a feature to the preset. + // + // The feature string is arbitrary, it is the indexer's job to understand it and remap it to its + // internal categorization and tagging system. + // + // However, the strings from plugin-features.h should be understood by the indexer and one of the + // plugin category could be provided to determine if the preset will result into an audio-effect, + // instrument, ... + // + // Examples: + // kick, drum, tom, snare, clap, cymbal, bass, lead, metalic, hardsync, crossmod, acid, + // distorted, drone, pad, dirty, etc... + void(CLAP_ABI *add_feature)(const struct clap_preset_discovery_metadata_receiver *receiver, + const char *feature); + + // Adds extra information to the metadata. + void(CLAP_ABI *add_extra_info)(const struct clap_preset_discovery_metadata_receiver *receiver, + const char *key, + const char *value); +} clap_preset_discovery_metadata_receiver_t; + +typedef struct clap_preset_discovery_filetype { + const char *name; + const char *description; // optional + + // `.' isn't included in the string. + // If empty or NULL then every file should be matched. + const char *file_extension; +} clap_preset_discovery_filetype_t; + +// Defines a place in which to search for presets +typedef struct clap_preset_discovery_location { + uint32_t flags; // see enum clap_preset_discovery_flags + const char *name; // name of this location + uint32_t kind; // See clap_preset_discovery_location_kind + + // Actual location in which to crawl presets. + // For FILE kind, the location can be either a path to a directory or a file. + // For PLUGIN kind, the location must be null. + const char *location; +} clap_preset_discovery_location_t; + +// Describes an installed sound pack. +typedef struct clap_preset_discovery_soundpack { + uint32_t flags; // see enum clap_preset_discovery_flags + const char *id; // sound pack identifier + const char *name; // name of this sound pack + const char *description; // optional, reasonably short description of the sound pack + const char *homepage_url; // optional, url to the pack's homepage + const char *vendor; // optional, sound pack's vendor + const char *image_path; // optional, an image on disk + clap_timestamp release_timestamp; // release date, CLAP_TIMESTAMP_UNKNOWN if unavailable +} clap_preset_discovery_soundpack_t; + +// Describes a preset provider +typedef struct clap_preset_discovery_provider_descriptor { + clap_version_t clap_version; // initialized to CLAP_VERSION + const char *id; // see plugin.h for advice on how to choose a good identifier + const char *name; // eg: "Diva's preset provider" + const char *vendor; // optional, eg: u-he +} clap_preset_discovery_provider_descriptor_t; + +// This interface isn't thread-safe. +typedef struct clap_preset_discovery_provider { + const clap_preset_discovery_provider_descriptor_t *desc; + + void *provider_data; // reserved pointer for the provider + + // Initialize the preset provider. + // It should declare all its locations, filetypes and sound packs. + // Returns false if initialization failed. + bool(CLAP_ABI *init)(const struct clap_preset_discovery_provider *provider); + + // Destroys the preset provider + void(CLAP_ABI *destroy)(const struct clap_preset_discovery_provider *provider); + + // reads metadata from the given file and passes them to the metadata receiver + // Returns true on success. + bool(CLAP_ABI *get_metadata)(const struct clap_preset_discovery_provider *provider, + uint32_t location_kind, + const char *location, + const clap_preset_discovery_metadata_receiver_t *metadata_receiver); + + // Query an extension. + // The returned pointer is owned by the provider. + // It is forbidden to call it before provider->init(). + // You can call it within provider->init() call, and after. + const void *(CLAP_ABI *get_extension)(const struct clap_preset_discovery_provider *provider, + const char *extension_id); +} clap_preset_discovery_provider_t; + +// This interface isn't thread-safe +typedef struct clap_preset_discovery_indexer { + clap_version_t clap_version; // initialized to CLAP_VERSION + const char *name; // eg: "Bitwig Studio" + const char *vendor; // optional, eg: "Bitwig GmbH" + const char *url; // optional, eg: "https://bitwig.com" + const char *version; // optional, eg: "4.3", see plugin.h for advice on how to format the version + + void *indexer_data; // reserved pointer for the indexer + + // Declares a preset filetype. + // Don't callback into the provider during this call. + // Returns false if the filetype is invalid. + bool(CLAP_ABI *declare_filetype)(const struct clap_preset_discovery_indexer *indexer, + const clap_preset_discovery_filetype_t *filetype); + + // Declares a preset location. + // Don't callback into the provider during this call. + // Returns false if the location is invalid. + bool(CLAP_ABI *declare_location)(const struct clap_preset_discovery_indexer *indexer, + const clap_preset_discovery_location_t *location); + + // Declares a sound pack. + // Don't callback into the provider during this call. + // Returns false if the sound pack is invalid. + bool(CLAP_ABI *declare_soundpack)(const struct clap_preset_discovery_indexer *indexer, + const clap_preset_discovery_soundpack_t *soundpack); + + // Query an extension. + // The returned pointer is owned by the indexer. + // It is forbidden to call it before provider->init(). + // You can call it within provider->init() call, and after. + const void *(CLAP_ABI *get_extension)(const struct clap_preset_discovery_indexer *indexer, + const char *extension_id); +} clap_preset_discovery_indexer_t; + +// Every methods in this factory must be thread-safe. +// It is encouraged to perform preset indexing in background threads, maybe even in background +// process. +// +// The host may use clap_plugin_invalidation_factory to detect filesystem changes +// which may change the factory's content. +typedef struct clap_preset_discovery_factory { + // Get the number of preset providers available. + // [thread-safe] + uint32_t(CLAP_ABI *count)(const struct clap_preset_discovery_factory *factory); + + // Retrieves a preset provider descriptor by its index. + // Returns null in case of error. + // The descriptor must not be freed. + // [thread-safe] + const clap_preset_discovery_provider_descriptor_t *(CLAP_ABI *get_descriptor)( + const struct clap_preset_discovery_factory *factory, uint32_t index); + + // Create a preset provider by its id. + // The returned pointer must be freed by calling preset_provider->destroy(preset_provider); + // The preset provider is not allowed to use the indexer callbacks in the create method. + // It is forbidden to call back into the indexer before the indexer calls provider->init(). + // Returns null in case of error. + // [thread-safe] + const clap_preset_discovery_provider_t *(CLAP_ABI *create)( + const struct clap_preset_discovery_factory *factory, + const clap_preset_discovery_indexer_t *indexer, + const char *provider_id); +} clap_preset_discovery_factory_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/fixedpoint.h b/third_party/clap/include/clap/fixedpoint.h new file mode 100644 index 0000000..fb042d3 --- /dev/null +++ b/third_party/clap/include/clap/fixedpoint.h @@ -0,0 +1,16 @@ +#pragma once + +#include "private/std.h" +#include "private/macros.h" + +/// We use fixed point representation of beat time and seconds time +/// Usage: +/// double x = ...; // in beats +/// clap_beattime y = round(CLAP_BEATTIME_FACTOR * x); + +// This will never change +static const CLAP_CONSTEXPR int64_t CLAP_BEATTIME_FACTOR = 1LL << 31; +static const CLAP_CONSTEXPR int64_t CLAP_SECTIME_FACTOR = 1LL << 31; + +typedef int64_t clap_beattime; +typedef int64_t clap_sectime; diff --git a/third_party/clap/include/clap/host.h b/third_party/clap/include/clap/host.h new file mode 100644 index 0000000..0a49ca4 --- /dev/null +++ b/third_party/clap/include/clap/host.h @@ -0,0 +1,51 @@ +#pragma once + +#include "version.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_host { + clap_version_t clap_version; // initialized to CLAP_VERSION + + void *host_data; // reserved pointer for the host + + // name and version are mandatory. + const char *name; // eg: "Bitwig Studio" + const char *vendor; // eg: "Bitwig GmbH" + const char *url; // eg: "https://bitwig.com" + const char *version; // eg: "4.3", see plugin.h for advice on how to format the version + + // Query an extension, returns null if not supported. + // The returned pointer is owned by the host and is valid until after the call to plugin->destroy() + // It is forbidden to call it before plugin->init(). + // You can call it within plugin->init() call, and after. + // [thread-safe] + const void *(CLAP_ABI *get_extension)(const struct clap_host *host, const char *extension_id); + + // Request the host to deactivate and then reactivate the plugin. + // The operation may be delayed by the host. + // [thread-safe] + void(CLAP_ABI *request_restart)(const struct clap_host *host); + + // Request the host to activate and start processing the plugin. + // This is useful if you have external IO and need to wake up the plugin from "sleep". + // [thread-safe] + void(CLAP_ABI *request_process)(const struct clap_host *host); + + // Request the host to schedule a call to plugin->on_main_thread(plugin) on the main thread. + // This callback should be called as soon as practicable, usually in the host application's next + // available main thread time slice. Typically callbacks occur within 33ms / 30hz. + // Despite this guidance, plugins should not make assumptions about the exactness of timing for + // a main thread callback, but hosts should endeavour to be prompt. For example, in high load + // situations the environment may starve the gui/main thread in favor of audio processing, + // leading to substantially longer latencies for the callback than the indicative times given + // here. + // [thread-safe] + void(CLAP_ABI *request_callback)(const struct clap_host *host); +} clap_host_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/id.h b/third_party/clap/include/clap/id.h new file mode 100644 index 0000000..3b2b6e6 --- /dev/null +++ b/third_party/clap/include/clap/id.h @@ -0,0 +1,8 @@ +#pragma once + +#include "private/std.h" +#include "private/macros.h" + +typedef uint32_t clap_id; + +static const CLAP_CONSTEXPR clap_id CLAP_INVALID_ID = UINT32_MAX; diff --git a/third_party/clap/include/clap/plugin-features.h b/third_party/clap/include/clap/plugin-features.h new file mode 100644 index 0000000..e5dc18c --- /dev/null +++ b/third_party/clap/include/clap/plugin-features.h @@ -0,0 +1,79 @@ +#pragma once + +// This file provides a set of standard plugin features meant to be used +// within clap_plugin_descriptor.features. +// +// For practical reasons we'll avoid spaces and use `-` instead to facilitate +// scripts that generate the feature array. +// +// Non-standard features should be formatted as follow: "$namespace:$feature" + +///////////////////// +// Plugin category // +///////////////////// + +// Add this feature if your plugin can process note events and then produce audio +#define CLAP_PLUGIN_FEATURE_INSTRUMENT "instrument" + +// Add this feature if your plugin is an audio effect +#define CLAP_PLUGIN_FEATURE_AUDIO_EFFECT "audio-effect" + +// Add this feature if your plugin is a note effect or a note generator/sequencer +#define CLAP_PLUGIN_FEATURE_NOTE_EFFECT "note-effect" + +// Add this feature if your plugin converts audio to notes +#define CLAP_PLUGIN_FEATURE_NOTE_DETECTOR "note-detector" + +// Add this feature if your plugin is an analyzer +#define CLAP_PLUGIN_FEATURE_ANALYZER "analyzer" + +///////////////////////// +// Plugin sub-category // +///////////////////////// + +#define CLAP_PLUGIN_FEATURE_SYNTHESIZER "synthesizer" +#define CLAP_PLUGIN_FEATURE_SAMPLER "sampler" +#define CLAP_PLUGIN_FEATURE_DRUM "drum" // For single drum +#define CLAP_PLUGIN_FEATURE_DRUM_MACHINE "drum-machine" + +#define CLAP_PLUGIN_FEATURE_FILTER "filter" +#define CLAP_PLUGIN_FEATURE_PHASER "phaser" +#define CLAP_PLUGIN_FEATURE_EQUALIZER "equalizer" +#define CLAP_PLUGIN_FEATURE_DEESSER "de-esser" +#define CLAP_PLUGIN_FEATURE_PHASE_VOCODER "phase-vocoder" +#define CLAP_PLUGIN_FEATURE_GRANULAR "granular" +#define CLAP_PLUGIN_FEATURE_FREQUENCY_SHIFTER "frequency-shifter" +#define CLAP_PLUGIN_FEATURE_PITCH_SHIFTER "pitch-shifter" + +#define CLAP_PLUGIN_FEATURE_DISTORTION "distortion" +#define CLAP_PLUGIN_FEATURE_TRANSIENT_SHAPER "transient-shaper" +#define CLAP_PLUGIN_FEATURE_COMPRESSOR "compressor" +#define CLAP_PLUGIN_FEATURE_EXPANDER "expander" +#define CLAP_PLUGIN_FEATURE_GATE "gate" +#define CLAP_PLUGIN_FEATURE_LIMITER "limiter" + +#define CLAP_PLUGIN_FEATURE_FLANGER "flanger" +#define CLAP_PLUGIN_FEATURE_CHORUS "chorus" +#define CLAP_PLUGIN_FEATURE_DELAY "delay" +#define CLAP_PLUGIN_FEATURE_REVERB "reverb" + +#define CLAP_PLUGIN_FEATURE_TREMOLO "tremolo" +#define CLAP_PLUGIN_FEATURE_GLITCH "glitch" + +#define CLAP_PLUGIN_FEATURE_UTILITY "utility" +#define CLAP_PLUGIN_FEATURE_PITCH_CORRECTION "pitch-correction" +#define CLAP_PLUGIN_FEATURE_RESTORATION "restoration" // repair the sound + +#define CLAP_PLUGIN_FEATURE_MULTI_EFFECTS "multi-effects" + +#define CLAP_PLUGIN_FEATURE_MIXING "mixing" +#define CLAP_PLUGIN_FEATURE_MASTERING "mastering" + +//////////////////////// +// Audio Capabilities // +//////////////////////// + +#define CLAP_PLUGIN_FEATURE_MONO "mono" +#define CLAP_PLUGIN_FEATURE_STEREO "stereo" +#define CLAP_PLUGIN_FEATURE_SURROUND "surround" +#define CLAP_PLUGIN_FEATURE_AMBISONIC "ambisonic" diff --git a/third_party/clap/include/clap/plugin.h b/third_party/clap/include/clap/plugin.h new file mode 100644 index 0000000..d9c837a --- /dev/null +++ b/third_party/clap/include/clap/plugin.h @@ -0,0 +1,114 @@ +#pragma once + +#include "private/macros.h" +#include "host.h" +#include "process.h" +#include "plugin-features.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_descriptor { + clap_version_t clap_version; // initialized to CLAP_VERSION + + // Mandatory fields must be set and must not be blank. + // Otherwise the fields can be null or blank, though it is safer to make them blank. + // + // Some indications regarding id and version + // - id is an arbitrary string which should be unique to your plugin, + // we encourage you to use a reverse URI eg: "com.u-he.diva" + // - version is an arbitrary string which describes a plugin, + // it is useful for the host to understand and be able to compare two different + // version strings, so here is a regex like expression which is likely to be + // understood by most hosts: MAJOR(.MINOR(.REVISION)?)?( (Alpha|Beta) XREV)? + const char *id; // eg: "com.u-he.diva", mandatory + const char *name; // eg: "Diva", mandatory + const char *vendor; // eg: "u-he" + const char *url; // eg: "https://u-he.com/products/diva/" + const char *manual_url; // eg: "https://dl.u-he.com/manuals/plugins/diva/Diva-user-guide.pdf" + const char *support_url; // eg: "https://u-he.com/support/" + const char *version; // eg: "1.4.4" + const char *description; // eg: "The spirit of analogue" + + // Arbitrary list of keywords. + // They can be matched by the host indexer and used to classify the plugin. + // The array of pointers must be null terminated. + // For some standard features see plugin-features.h + const char *const *features; +} clap_plugin_descriptor_t; + +typedef struct clap_plugin { + const clap_plugin_descriptor_t *desc; + + void *plugin_data; // reserved pointer for the plugin + + // Must be called after creating the plugin. + // If init returns false, the host must destroy the plugin instance. + // If init returns true, then the plugin is initialized and in the deactivated state. + // Unlike in `plugin-factory::create_plugin`, in init you have complete access to the host + // and host extensions, so clap related setup activities should be done here rather than in + // create_plugin. + // [main-thread] + bool(CLAP_ABI *init)(const struct clap_plugin *plugin); + + // Free the plugin and its resources. + // It is required to deactivate the plugin prior to this call. + // [main-thread & !active] + void(CLAP_ABI *destroy)(const struct clap_plugin *plugin); + + // Activate and deactivate the plugin. + // In this call the plugin may allocate memory and prepare everything needed for the process + // call. The process's sample rate will be constant and process's frame count will included in + // the [min, max] range, which is bounded by [1, INT32_MAX]. + // In this call the plugin may call host-provided methods marked [being-activated]. + // Once activated the latency and port configuration must remain constant, until deactivation. + // Returns true on success. + // [main-thread & !active] + bool(CLAP_ABI *activate)(const struct clap_plugin *plugin, + double sample_rate, + uint32_t min_frames_count, + uint32_t max_frames_count); + // [main-thread & active] + void(CLAP_ABI *deactivate)(const struct clap_plugin *plugin); + + // Call start processing before processing. + // Returns true on success. + // [audio-thread & active & !processing] + bool(CLAP_ABI *start_processing)(const struct clap_plugin *plugin); + + // Call stop processing before sending the plugin to sleep. + // [audio-thread & active & processing] + void(CLAP_ABI *stop_processing)(const struct clap_plugin *plugin); + + // - Clears all buffers, performs a full reset of the processing state (filters, oscillators, + // envelopes, lfo, ...) and kills all voices. + // - The parameter's value remain unchanged. + // - clap_process.steady_time may jump backward. + // + // [audio-thread & active] + void(CLAP_ABI *reset)(const struct clap_plugin *plugin); + + // process audio, events, ... + // All the pointers coming from clap_process_t and its nested attributes, + // are valid until process() returns. + // [audio-thread & active & processing] + clap_process_status(CLAP_ABI *process)(const struct clap_plugin *plugin, + const clap_process_t *process); + + // Query an extension, returns null if not supported. + // The returned pointer is owned by the plugin and is valid until the call to plugin->destroy(). + // It is forbidden to call it before plugin->init(). + // You can call it within plugin->init() call, and after. + // [thread-safe] + const void *(CLAP_ABI *get_extension)(const struct clap_plugin *plugin, const char *id); + + // Called by the host on the main thread in response to a previous call to: + // host->request_callback(host); + // [main-thread] + void(CLAP_ABI *on_main_thread)(const struct clap_plugin *plugin); +} clap_plugin_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/private/macros.h b/third_party/clap/include/clap/private/macros.h new file mode 100644 index 0000000..ba1d665 --- /dev/null +++ b/third_party/clap/include/clap/private/macros.h @@ -0,0 +1,50 @@ +#pragma once + +// Define CLAP_EXPORT +#if !defined(CLAP_EXPORT) +# if defined _WIN32 || defined __CYGWIN__ +# ifdef __GNUC__ +# define CLAP_EXPORT __attribute__((dllexport)) +# else +# define CLAP_EXPORT __declspec(dllexport) +# endif +# else +# if __GNUC__ >= 4 || defined(__clang__) +# define CLAP_EXPORT __attribute__((visibility("default"))) +# else +# define CLAP_EXPORT +# endif +# endif +#endif + +#if !defined(CLAP_ABI) +# if defined _WIN32 || defined __CYGWIN__ +# define CLAP_ABI __cdecl +# else +# define CLAP_ABI +# endif +#endif + +#if defined(_MSVC_LANG) +# define CLAP_CPLUSPLUS _MSVC_LANG +#elif defined(__cplusplus) +# define CLAP_CPLUSPLUS __cplusplus +#endif + +#if defined(CLAP_CPLUSPLUS) && CLAP_CPLUSPLUS >= 201103L +# define CLAP_HAS_CXX11 +# define CLAP_CONSTEXPR constexpr +#else +# define CLAP_CONSTEXPR +#endif + +#if defined(CLAP_CPLUSPLUS) && CLAP_CPLUSPLUS >= 201703L +# define CLAP_HAS_CXX17 +# define CLAP_NODISCARD [[nodiscard]] +#else +# define CLAP_NODISCARD +#endif + +#if defined(CLAP_CPLUSPLUS) && CLAP_CPLUSPLUS >= 202002L +# define CLAP_HAS_CXX20 +#endif diff --git a/third_party/clap/include/clap/private/std.h b/third_party/clap/include/clap/private/std.h new file mode 100644 index 0000000..1c2ffdd --- /dev/null +++ b/third_party/clap/include/clap/private/std.h @@ -0,0 +1,16 @@ +#pragma once + +#include "macros.h" + +#ifdef CLAP_HAS_CXX11 +# include +#else +# include +#endif + +#ifdef __cplusplus +# include +#else +# include +# include +#endif diff --git a/third_party/clap/include/clap/process.h b/third_party/clap/include/clap/process.h new file mode 100644 index 0000000..c9dbf92 --- /dev/null +++ b/third_party/clap/include/clap/process.h @@ -0,0 +1,66 @@ +#pragma once + +#include "events.h" +#include "audio-buffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // Processing failed. The output buffer must be discarded. + CLAP_PROCESS_ERROR = 0, + + // Processing succeeded, keep processing. + CLAP_PROCESS_CONTINUE = 1, + + // Processing succeeded, keep processing if the output is not quiet. + CLAP_PROCESS_CONTINUE_IF_NOT_QUIET = 2, + + // Rely upon the plugin's tail to determine if the plugin should continue to process. + // see clap_plugin_tail + CLAP_PROCESS_TAIL = 3, + + // Processing succeeded, but no more processing is required, + // until the next event or variation in audio input. + CLAP_PROCESS_SLEEP = 4, +}; +typedef int32_t clap_process_status; + +typedef struct clap_process { + // A steady sample time counter. + // This field can be used to calculate the sleep duration between two process calls. + // This value may be specific to this plugin instance and have no relation to what + // other plugin instances may receive. + // + // Set to -1 if not available, otherwise the value must be greater or equal to 0, + // and must be increased by at least `frames_count` for the next call to process. + int64_t steady_time; + + // Number of frames to process + uint32_t frames_count; + + // time info at sample 0 + // If null, then this is a free running host, no transport events will be provided + const clap_event_transport_t *transport; + + // Audio buffers, they must have the same count as specified + // by clap_plugin_audio_ports->count(). + // The index maps to clap_plugin_audio_ports->get(). + // Input buffer and its contents are read-only. + const clap_audio_buffer_t *audio_inputs; + clap_audio_buffer_t *audio_outputs; + uint32_t audio_inputs_count; + uint32_t audio_outputs_count; + + // The input event list can't be modified. + // Input read-only event list. The host will deliver these sorted in sample order. + const clap_input_events_t *in_events; + + // Output event list. The plugin must insert events in sample sorted order when inserting events + const clap_output_events_t *out_events; +} clap_process_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/stream.h b/third_party/clap/include/clap/stream.h new file mode 100644 index 0000000..b9b0b6c --- /dev/null +++ b/third_party/clap/include/clap/stream.h @@ -0,0 +1,38 @@ +#pragma once + +#include "private/std.h" +#include "private/macros.h" + +/// @page Streams +/// +/// ## Notes on using streams +/// +/// When working with `clap_istream` and `clap_ostream` objects to load and save +/// state, it is important to keep in mind that the host may limit the number of +/// bytes that can be read or written at a time. The return values for the +/// stream read and write functions indicate how many bytes were actually read +/// or written. You need to use a loop to ensure that you read or write the +/// entirety of your state. Don't forget to also consider the negative return +/// values for the end of file and IO error codes. + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_istream { + void *ctx; // reserved pointer for the stream + + // returns the number of bytes read; 0 indicates end of file and -1 a read error + int64_t(CLAP_ABI *read)(const struct clap_istream *stream, void *buffer, uint64_t size); +} clap_istream_t; + +typedef struct clap_ostream { + void *ctx; // reserved pointer for the stream + + // returns the number of bytes written; -1 on write error + int64_t(CLAP_ABI *write)(const struct clap_ostream *stream, const void *buffer, uint64_t size); +} clap_ostream_t; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/string-sizes.h b/third_party/clap/include/clap/string-sizes.h new file mode 100644 index 0000000..4334c6d --- /dev/null +++ b/third_party/clap/include/clap/string-sizes.h @@ -0,0 +1,21 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // String capacity for names that can be displayed to the user. + CLAP_NAME_SIZE = 256, + + // String capacity for describing a path, like a parameter in a module hierarchy or path within a + // set of nested track groups. + // + // This is not suited for describing a file path on the disk, as NTFS allows up to 32K long + // paths. + CLAP_PATH_SIZE = 1024, +}; + +#ifdef __cplusplus +} +#endif diff --git a/third_party/clap/include/clap/timestamp.h b/third_party/clap/include/clap/timestamp.h new file mode 100644 index 0000000..63d2cab --- /dev/null +++ b/third_party/clap/include/clap/timestamp.h @@ -0,0 +1,11 @@ +#pragma once + +#include "private/std.h" +#include "private/macros.h" + +// This type defines a timestamp: the number of seconds since UNIX EPOCH. +// See C's time_t time(time_t *). +typedef uint64_t clap_timestamp; + +// Value for unknown timestamp. +static const CLAP_CONSTEXPR clap_timestamp CLAP_TIMESTAMP_UNKNOWN = 0; diff --git a/third_party/clap/include/clap/universal-plugin-id.h b/third_party/clap/include/clap/universal-plugin-id.h new file mode 100644 index 0000000..b039d03 --- /dev/null +++ b/third_party/clap/include/clap/universal-plugin-id.h @@ -0,0 +1,26 @@ +#pragma once + +// Pair of plugin ABI and plugin identifier. +// +// If you want to represent other formats please send us an update to the comment with the +// name of the abi and the representation of the id. +typedef struct clap_universal_plugin_id { + // The plugin ABI name, in lowercase and null-terminated. + // eg: "clap", "vst3", "vst2", "au", ... + const char *abi; + + // The plugin ID, null-terminated and formatted as follows: + // + // CLAP: use the plugin id + // eg: "com.u-he.diva" + // + // AU: format the string like "type:subt:manu" + // eg: "aumu:SgXT:VmbA" + // + // VST2: print the id as a signed 32-bits integer + // eg: "-4382976" + // + // VST3: print the id as a standard UUID + // eg: "123e4567-e89b-12d3-a456-426614174000" + const char *id; +} clap_universal_plugin_id_t; diff --git a/third_party/clap/include/clap/version.h b/third_party/clap/include/clap/version.h new file mode 100644 index 0000000..cfba555 --- /dev/null +++ b/third_party/clap/include/clap/version.h @@ -0,0 +1,42 @@ +#pragma once + +#include "private/macros.h" +#include "private/std.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_version { + // This is the major ABI and API design + // Version 0.X.Y correspond to the development stage, API and ABI are not stable + // Version 1.X.Y correspond to the release stage, API and ABI are stable + uint32_t major; + uint32_t minor; + uint32_t revision; +} clap_version_t; + +#ifdef __cplusplus +} +#endif + +#define CLAP_VERSION_MAJOR 1 +#define CLAP_VERSION_MINOR 2 +#define CLAP_VERSION_REVISION 10 + +#define CLAP_VERSION_INIT \ + { (uint32_t)CLAP_VERSION_MAJOR, (uint32_t)CLAP_VERSION_MINOR, (uint32_t)CLAP_VERSION_REVISION } + +#define CLAP_VERSION_LT(maj,min,rev) ((CLAP_VERSION_MAJOR < (maj)) || \ + ((maj) == CLAP_VERSION_MAJOR && CLAP_VERSION_MINOR < (min)) || \ + ((maj) == CLAP_VERSION_MAJOR && (min) == CLAP_VERSION_MINOR && CLAP_VERSION_REVISION < (rev))) +#define CLAP_VERSION_EQ(maj,min,rev) (((maj) == CLAP_VERSION_MAJOR) && ((min) == CLAP_VERSION_MINOR) && ((rev) == CLAP_VERSION_REVISION)) +#define CLAP_VERSION_GE(maj,min,rev) (!CLAP_VERSION_LT(maj,min,rev)) + +static const CLAP_CONSTEXPR clap_version_t CLAP_VERSION = CLAP_VERSION_INIT; + +CLAP_NODISCARD static inline CLAP_CONSTEXPR bool +clap_version_is_compatible(const clap_version_t v) { + // versions 0.x.y were used during development stage and aren't compatible + return v.major >= 1; +} diff --git a/third_party/vst3/LICENSE.txt b/third_party/vst3/LICENSE.txt new file mode 100644 index 0000000..075933e --- /dev/null +++ b/third_party/vst3/LICENSE.txt @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- +// LICENSE +// (c) 2025, Steinberg Media Technologies GmbH, All Rights Reserved +//----------------------------------------------------------------------------- +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Steinberg Media Technologies nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. +//----------------------------------------------------------------------------- diff --git a/third_party/vst3/vst3_c_api.h b/third_party/vst3/vst3_c_api.h new file mode 100644 index 0000000..19e15c4 --- /dev/null +++ b/third_party/vst3/vst3_c_api.h @@ -0,0 +1,3777 @@ +/*----------------------------------------------------------------------------- + This file is part of a Steinberg SDK. It is subject to the license terms + in the LICENSE file found in the top-level directory of this distribution + and at www.steinberg.net/sdklicenses. + No part of the SDK, including this file, may be copied, modified, propagated, + or distributed except according to the terms contained in the LICENSE file. +-----------------------------------------------------------------------------*/ + +/* This file is the autogenerated C API of the VST3 SDK */ + +#pragma once + +#include + +#if _WIN32 +#define SMTG_STDMETHODCALLTYPE __stdcall +#define SMTG_COM_COMPATIBLE 1 +#else +#define SMTG_STDMETHODCALLTYPE +#define SMTG_COM_COMPATIBLE 0 +#endif + +#ifndef __cplusplus +typedef int16_t char16_t; +#endif + +#if SMTG_COM_COMPATIBLE +#define SMTG_INLINE_UID(l1, l2, l3, l4) \ +{ \ + (Steinberg_int8)(((Steinberg_uint32)(l1) & 0x000000FF) ), (Steinberg_int8)(((Steinberg_uint32)(l1) & 0x0000FF00) >> 8), \ + (Steinberg_int8)(((Steinberg_uint32)(l1) & 0x00FF0000) >> 16), (Steinberg_int8)(((Steinberg_uint32)(l1) & 0xFF000000) >> 24), \ + (Steinberg_int8)(((Steinberg_uint32)(l2) & 0x00FF0000) >> 16), (Steinberg_int8)(((Steinberg_uint32)(l2) & 0xFF000000) >> 24), \ + (Steinberg_int8)(((Steinberg_uint32)(l2) & 0x000000FF) ), (Steinberg_int8)(((Steinberg_uint32)(l2) & 0x0000FF00) >> 8), \ + (Steinberg_int8)(((Steinberg_uint32)(l3) & 0xFF000000) >> 24), (Steinberg_int8)(((Steinberg_uint32)(l3) & 0x00FF0000) >> 16), \ + (Steinberg_int8)(((Steinberg_uint32)(l3) & 0x0000FF00) >> 8), (Steinberg_int8)(((Steinberg_uint32)(l3) & 0x000000FF) ), \ + (Steinberg_int8)(((Steinberg_uint32)(l4) & 0xFF000000) >> 24), (Steinberg_int8)(((Steinberg_uint32)(l4) & 0x00FF0000) >> 16), \ + (Steinberg_int8)(((Steinberg_uint32)(l4) & 0x0000FF00) >> 8), (Steinberg_int8)(((Steinberg_uint32)(l4) & 0x000000FF) ) \ +} +#else +#define SMTG_INLINE_UID(l1, l2, l3, l4) \ +{ \ + (Steinberg_int8)(((Steinberg_uint32)(l1) & 0xFF000000) >> 24), (Steinberg_int8)(((Steinberg_uint32)(l1) & 0x00FF0000) >> 16), \ + (Steinberg_int8)(((Steinberg_uint32)(l1) & 0x0000FF00) >> 8), (Steinberg_int8)(((Steinberg_uint32)(l1) & 0x000000FF) ), \ + (Steinberg_int8)(((Steinberg_uint32)(l2) & 0xFF000000) >> 24), (Steinberg_int8)(((Steinberg_uint32)(l2) & 0x00FF0000) >> 16), \ + (Steinberg_int8)(((Steinberg_uint32)(l2) & 0x0000FF00) >> 8), (Steinberg_int8)(((Steinberg_uint32)(l2) & 0x000000FF) ), \ + (Steinberg_int8)(((Steinberg_uint32)(l3) & 0xFF000000) >> 24), (Steinberg_int8)(((Steinberg_uint32)(l3) & 0x00FF0000) >> 16), \ + (Steinberg_int8)(((Steinberg_uint32)(l3) & 0x0000FF00) >> 8), (Steinberg_int8)(((Steinberg_uint32)(l3) & 0x000000FF) ), \ + (Steinberg_int8)(((Steinberg_uint32)(l4) & 0xFF000000) >> 24), (Steinberg_int8)(((Steinberg_uint32)(l4) & 0x00FF0000) >> 16), \ + (Steinberg_int8)(((Steinberg_uint32)(l4) & 0x0000FF00) >> 8), (Steinberg_int8)(((Steinberg_uint32)(l4) & 0x000000FF) ) \ +} +#endif + +/*---------------------------------------------------------------------------------------------------------------------- +----- Typedefs --------------------------------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------------------*/ + +typedef char Steinberg_int8; +typedef uint8_t Steinberg_uint8; +typedef unsigned char Steinberg_uchar; +typedef int16_t Steinberg_int16; +typedef uint16_t Steinberg_uint16; +typedef int32_t Steinberg_int32; +typedef uint32_t Steinberg_uint32; +typedef int64_t Steinberg_int64; +typedef uint64_t Steinberg_uint64; +typedef Steinberg_int64 Steinberg_TSize; +typedef Steinberg_int32 Steinberg_tresult; +typedef Steinberg_uint64 Steinberg_TPtrInt; +typedef Steinberg_uint8 Steinberg_TBool; +typedef char Steinberg_char8; +typedef char16_t Steinberg_char16; +typedef Steinberg_char16 Steinberg_tchar; +typedef const Steinberg_char8* Steinberg_CStringA; +typedef const Steinberg_char16* Steinberg_CStringW; +typedef const Steinberg_tchar* Steinberg_CString; +typedef const Steinberg_char8* Steinberg_FIDString; +typedef Steinberg_int32 Steinberg_UCoord; +typedef Steinberg_int64 Steinberg_LARGE_INT; +typedef char Steinberg_TUID[16]; +typedef Steinberg_uint64 Steinberg_Linux_TimerInterval; +typedef int Steinberg_Linux_FileDescriptor; +typedef Steinberg_char16 Steinberg_Vst_TChar; +typedef Steinberg_Vst_TChar Steinberg_Vst_String128[128]; +typedef const Steinberg_char8* Steinberg_Vst_CString; +typedef Steinberg_int32 Steinberg_Vst_MediaType; +typedef Steinberg_int32 Steinberg_Vst_BusDirection; +typedef Steinberg_int32 Steinberg_Vst_BusType; +typedef Steinberg_int32 Steinberg_Vst_IoMode; +typedef Steinberg_int32 Steinberg_Vst_UnitID; +typedef double Steinberg_Vst_ParamValue; +typedef Steinberg_uint32 Steinberg_Vst_ParamID; +typedef Steinberg_int32 Steinberg_Vst_ProgramListID; +typedef Steinberg_int16 Steinberg_Vst_CtrlNumber; +typedef double Steinberg_Vst_TQuarterNotes; +typedef Steinberg_int64 Steinberg_Vst_TSamples; +typedef Steinberg_uint32 Steinberg_Vst_ColorSpec; +typedef float Steinberg_Vst_Sample32; +typedef double Steinberg_Vst_Sample64; +typedef double Steinberg_Vst_SampleRate; +typedef Steinberg_uint64 Steinberg_Vst_SpeakerArrangement; +typedef Steinberg_uint64 Steinberg_Vst_Speaker; +typedef Steinberg_uint32 Steinberg_Vst_NoteExpressionTypeID; +typedef double Steinberg_Vst_NoteExpressionValue; +typedef Steinberg_uint32 Steinberg_Vst_KeyswitchTypeID; +typedef Steinberg_uint32 Steinberg_Vst_PhysicalUITypeID; +typedef Steinberg_int32 Steinberg_Vst_KnobMode; +typedef Steinberg_uint32 Steinberg_Vst_ChannelContext_ColorSpec; +typedef Steinberg_uint8 Steinberg_Vst_ChannelContext_ColorComponent; +typedef Steinberg_uint32 Steinberg_Vst_PrefetchableSupport; +typedef Steinberg_uint32 Steinberg_Vst_DataExchangeQueueID; +typedef Steinberg_uint32 Steinberg_Vst_DataExchangeBlockID; +typedef Steinberg_uint32 Steinberg_Vst_DataExchangeUserContextID; +typedef Steinberg_uint8 Steinberg_Vst_MidiGroup; +typedef Steinberg_uint8 Steinberg_Vst_MidiChannel; +typedef Steinberg_int32 Steinberg_Vst_BusIndex; + + +/*---------------------------------------------------------------------------------------------------------------------- +----- Interface forward declarations ----------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------------------*/ + +struct Steinberg_FUnknown; +struct Steinberg_IPlugViewContentScaleSupport; +struct Steinberg_IPlugView; +struct Steinberg_IPlugFrame; +struct Steinberg_Linux_IEventHandler; +struct Steinberg_Linux_ITimerHandler; +struct Steinberg_Linux_IRunLoop; +struct Steinberg_IBStream; +struct Steinberg_ISizeableStream; +struct Steinberg_Vst_INoteExpressionController; +struct Steinberg_Vst_IKeyswitchController; +struct Steinberg_Vst_INoteExpressionPhysicalUIMapping; +struct Steinberg_IPluginBase; +struct Steinberg_IPluginFactory; +struct Steinberg_IPluginFactory2; +struct Steinberg_IPluginFactory3; +struct Steinberg_Vst_IComponent; +struct Steinberg_Vst_IAttributeList; +struct Steinberg_Vst_IStreamAttributes; +struct Steinberg_Vst_IRemapParamID; +struct Steinberg_Vst_IComponentHandler; +struct Steinberg_Vst_IComponentHandler2; +struct Steinberg_Vst_IComponentHandlerBusActivation; +struct Steinberg_Vst_IProgress; +struct Steinberg_Vst_IEditController; +struct Steinberg_Vst_IEditController2; +struct Steinberg_Vst_IMidiMapping; +struct Steinberg_Vst_IEditControllerHostEditing; +struct Steinberg_Vst_IComponentHandlerSystemTime; +struct Steinberg_Vst_IEventList; +struct Steinberg_Vst_IMessage; +struct Steinberg_Vst_IConnectionPoint; +struct Steinberg_Vst_IXmlRepresentationController; +struct Steinberg_Vst_IComponentHandler3; +struct Steinberg_Vst_IContextMenuTarget; +struct Steinberg_Vst_IContextMenu; +struct Steinberg_Vst_IMidiLearn; +struct Steinberg_Vst_ChannelContext_IInfoListener; +struct Steinberg_Vst_IPrefetchableSupport; +struct Steinberg_Vst_IDataExchangeHandler; +struct Steinberg_Vst_IDataExchangeReceiver; +struct Steinberg_Vst_IAutomationState; +struct Steinberg_Vst_IInterAppAudioHost; +struct Steinberg_Vst_IInterAppAudioConnectionNotification; +struct Steinberg_Vst_IInterAppAudioPresetManager; +struct Steinberg_Vst_IAudioProcessor; +struct Steinberg_Vst_IAudioPresentationLatency; +struct Steinberg_Vst_IProcessContextRequirements; +struct Steinberg_Vst_IMidiMapping2; +struct Steinberg_Vst_IMidiLearn2; +struct Steinberg_Vst_IHostApplication; +struct Steinberg_Vst_IVst3ToVst2Wrapper; +struct Steinberg_Vst_IVst3ToAUWrapper; +struct Steinberg_Vst_IVst3ToAAXWrapper; +struct Steinberg_Vst_IVst3WrapperMPESupport; +struct Steinberg_Vst_IParameterFinder; +struct Steinberg_Vst_NoteOnOrchestralArticulation_IInfo; +struct Steinberg_Vst_ITransportControl; +struct Steinberg_Vst_IUnitHandler; +struct Steinberg_Vst_IUnitHandler2; +struct Steinberg_Vst_IUnitInfo; +struct Steinberg_Vst_IProgramListData; +struct Steinberg_Vst_IUnitData; +struct Steinberg_Vst_IPlugInterfaceSupport; +struct Steinberg_Vst_IParameterFunctionName; +struct Steinberg_Vst_IParamValueQueue; +struct Steinberg_Vst_IParameterChanges; + + +/*---------------------------------------------------------------------------------------------------------------------- +----- Struct forward declarations -------------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------------------*/ + +struct Steinberg_ViewRect; +struct Steinberg_Vst_NoteExpressionValueDescription; +struct Steinberg_Vst_NoteExpressionValueEvent; +struct Steinberg_Vst_NoteExpressionIntValueEvent; +struct Steinberg_Vst_NoteExpressionTextEvent; +struct Steinberg_Vst_NoteExpressionTypeInfo; +struct Steinberg_Vst_KeyswitchInfo; +struct Steinberg_Vst_PhysicalUIMap; +struct Steinberg_Vst_PhysicalUIMapList; +struct Steinberg_PFactoryInfo; +struct Steinberg_PClassInfo; +struct Steinberg_PClassInfo2; +struct Steinberg_PClassInfoW; +struct Steinberg_Vst_BusInfo; +struct Steinberg_Vst_RoutingInfo; +struct Steinberg_Vst_ParameterInfo; +struct Steinberg_Vst_FrameRate; +struct Steinberg_Vst_Chord; +struct Steinberg_Vst_ProcessContext; +struct Steinberg_Vst_NoteOnEvent; +struct Steinberg_Vst_NoteOffEvent; +struct Steinberg_Vst_DataEvent; +struct Steinberg_Vst_PolyPressureEvent; +struct Steinberg_Vst_ChordEvent; +struct Steinberg_Vst_ScaleEvent; +struct Steinberg_Vst_LegacyMIDICCOutEvent; +struct Steinberg_Vst_Event; +struct Steinberg_Vst_RepresentationInfo; +struct Steinberg_Vst_IContextMenuItem; +struct Steinberg_Vst_DataExchangeBlock; +struct Steinberg_Vst_ProcessSetup; +struct Steinberg_Vst_AudioBusBuffers; +struct Steinberg_Vst_ProcessData; +struct Steinberg_Vst_Midi2Controller; +struct Steinberg_Vst_Midi2ControllerParamIDAssignment; +struct Steinberg_Vst_Midi2ControllerParamIDAssignmentList; +struct Steinberg_Vst_Midi1ControllerParamIDAssignment; +struct Steinberg_Vst_Midi1ControllerParamIDAssignmentList; +struct Steinberg_Vst_NoteOnOrchestralArticulation_Variations; +struct Steinberg_Vst_NoteOnOrchestralArticulation_ClassificationVariations; +struct Steinberg_Vst_TransportPosition; +struct Steinberg_Vst_UnitInfo; +struct Steinberg_Vst_ProgramListInfo; + + +/*---------------------------------------------------------------------------------------------------------------------- +----- Result value definitions ----------------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------------------*/ + +#if SMTG_COM_COMPATIBLE +static const Steinberg_tresult Steinberg_kNoInterface = 0x80004002L; +static const Steinberg_tresult Steinberg_kResultOk = 0x00000000L; +static const Steinberg_tresult Steinberg_kResultTrue = 0x00000000L; +static const Steinberg_tresult Steinberg_kResultFalse = 0x00000001L; +static const Steinberg_tresult Steinberg_kInvalidArgument = 0x80070057L; +static const Steinberg_tresult Steinberg_kNotImplemented = 0x80004001L; +static const Steinberg_tresult Steinberg_kInternalError = 0x80004005L; +static const Steinberg_tresult Steinberg_kNotInitialized = 0x8000FFFFL; +static const Steinberg_tresult Steinberg_kOutOfMemory = 0x8007000EL; + +#else +static const Steinberg_tresult Steinberg_kNoInterface = -1; +static const Steinberg_tresult Steinberg_kResultOk = 0; +static const Steinberg_tresult Steinberg_kResultTrue = 0; +static const Steinberg_tresult Steinberg_kResultFalse = 1; +static const Steinberg_tresult Steinberg_kInvalidArgument = 2; +static const Steinberg_tresult Steinberg_kNotImplemented = 3; +static const Steinberg_tresult Steinberg_kInternalError = 4; +static const Steinberg_tresult Steinberg_kNotInitialized = 5; +static const Steinberg_tresult Steinberg_kOutOfMemory = 6; +#endif + + +/*---------------------------------------------------------------------------------------------------------------------- +----- Interface typedefs ----------------------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------------------*/ + +typedef float Steinberg_IPlugViewContentScaleSupport_ScaleFactor; +typedef const char* Steinberg_Vst_IAttributeList_AttrID; +typedef Steinberg_uint64 Steinberg_Vst_IProgress_ID; +typedef struct Steinberg_Vst_IContextMenuItem Steinberg_Vst_IContextMenu_Item; + + +/*---------------------------------------------------------------------------------------------------------------------- +----- Enums ------------------------------------------------------------------------------------------------------------ +----------------------------------------------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ibstream.h", line 32 */ + +typedef enum +{ + Steinberg_IBStream_IStreamSeekMode_kIBSeekSet = 0, + Steinberg_IBStream_IStreamSeekMode_kIBSeekCur, + Steinberg_IBStream_IStreamSeekMode_kIBSeekEnd +} Steinberg_IBStream_IStreamSeekMode; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 45 */ + +typedef enum +{ + Steinberg_Vst_NoteExpressionTypeIDs_kVolumeTypeID = 0, + Steinberg_Vst_NoteExpressionTypeIDs_kPanTypeID, + Steinberg_Vst_NoteExpressionTypeIDs_kTuningTypeID, + Steinberg_Vst_NoteExpressionTypeIDs_kVibratoTypeID, + Steinberg_Vst_NoteExpressionTypeIDs_kExpressionTypeID, + Steinberg_Vst_NoteExpressionTypeIDs_kBrightnessTypeID, + Steinberg_Vst_NoteExpressionTypeIDs_kTextTypeID, + Steinberg_Vst_NoteExpressionTypeIDs_kPhonemeTypeID, + Steinberg_Vst_NoteExpressionTypeIDs_kCustomStart = 100000, + Steinberg_Vst_NoteExpressionTypeIDs_kCustomEnd = 200000, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2AssignablePerNoteControllerStart = 201000, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2AssignablePerNoteControllerEnd = 201255, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2RegisteredPerNoteControllerStart = 202000, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2RegisteredPerNoteControllerPlayingPosition = Steinberg_Vst_NoteExpressionTypeIDs_kMidi2RegisteredPerNoteControllerStart + 0x0C, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2RegisteredPerNoteControllerEnd = 202255, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOnAttributeStart = 203000, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOnOrchestralArticulationStart = Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOnAttributeStart + 0x10, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOnOrchestralArticulationEnd = Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOnAttributeStart + 0x1F, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOnAttributeEnd = 203255, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOffAttributeStart = 204000, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOffOrchestralArticulation = Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOffAttributeStart + 0x10, + Steinberg_Vst_NoteExpressionTypeIDs_kMidi2NoteOffAttributeEnd = 204255, + Steinberg_Vst_NoteExpressionTypeIDs_kInvalidTypeID = 0xFFFFFFFF +} Steinberg_Vst_NoteExpressionTypeIDs; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 182 */ + +typedef enum +{ + Steinberg_Vst_NoteExpressionTypeInfo_NoteExpressionTypeFlags_kIsBipolar = 1 << 0, + Steinberg_Vst_NoteExpressionTypeInfo_NoteExpressionTypeFlags_kIsOneShot = 1 << 1, + Steinberg_Vst_NoteExpressionTypeInfo_NoteExpressionTypeFlags_kIsAbsolute = 1 << 2, + Steinberg_Vst_NoteExpressionTypeInfo_NoteExpressionTypeFlags_kAssociatedParameterIDValid = 1 << 3 +} Steinberg_Vst_NoteExpressionTypeInfo_NoteExpressionTypeFlags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 249 */ + +typedef enum +{ + Steinberg_Vst_KeyswitchTypeIDs_kNoteOnKeyswitchTypeID = 0, + Steinberg_Vst_KeyswitchTypeIDs_kOnTheFlyKeyswitchTypeID, + Steinberg_Vst_KeyswitchTypeIDs_kOnReleaseKeyswitchTypeID, + Steinberg_Vst_KeyswitchTypeIDs_kKeyRangeTypeID +} Steinberg_Vst_KeyswitchTypeIDs; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstphysicalui.h", line 41 */ + +typedef enum +{ + Steinberg_Vst_PhysicalUITypeIDs_kPUIXMovement = 0, + Steinberg_Vst_PhysicalUITypeIDs_kPUIYMovement, + Steinberg_Vst_PhysicalUITypeIDs_kPUIPressure, + Steinberg_Vst_PhysicalUITypeIDs_kPUITypeCount, + Steinberg_Vst_PhysicalUITypeIDs_kInvalidPUITypeID = 0xFFFFFFFF +} Steinberg_Vst_PhysicalUITypeIDs; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 65 */ + +typedef enum +{ + Steinberg_PFactoryInfo_FactoryFlags_kNoFlags = 0, + Steinberg_PFactoryInfo_FactoryFlags_kClassesDiscardable = 1 << 0, + Steinberg_PFactoryInfo_FactoryFlags_kLicenseCheck = 1 << 1, + Steinberg_PFactoryInfo_FactoryFlags_kComponentNonDiscardable = 1 << 3, + Steinberg_PFactoryInfo_FactoryFlags_kUnicode = 1 << 4 +} Steinberg_PFactoryInfo_FactoryFlags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 127 */ + +typedef enum +{ + Steinberg_PClassInfo_ClassCardinality_kManyInstances = 0x7FFFFFFF +} Steinberg_PClassInfo_ClassCardinality; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcomponent.h", line 65 */ + +typedef enum +{ + Steinberg_Vst_MediaTypes_kAudio = 0, + Steinberg_Vst_MediaTypes_kEvent, + Steinberg_Vst_MediaTypes_kNumMediaTypes +} Steinberg_Vst_MediaTypes; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcomponent.h", line 74 */ + +typedef enum +{ + Steinberg_Vst_BusDirections_kInput = 0, + Steinberg_Vst_BusDirections_kOutput +} Steinberg_Vst_BusDirections; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcomponent.h", line 82 */ + +typedef enum +{ + Steinberg_Vst_BusTypes_kMain = 0, + Steinberg_Vst_BusTypes_kAux +} Steinberg_Vst_BusTypes; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcomponent.h", line 104 */ + +typedef enum +{ + Steinberg_Vst_BusInfo_BusFlags_kDefaultActive = 1 << 0, + Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage = 1 << 1 +} Steinberg_Vst_BusInfo_BusFlags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcomponent.h", line 122 */ + +typedef enum +{ + Steinberg_Vst_IoModes_kSimple = 0, + Steinberg_Vst_IoModes_kAdvanced, + Steinberg_Vst_IoModes_kOfflineProcessing +} Steinberg_Vst_IoModes; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 67 */ + +typedef enum +{ + Steinberg_Vst_ParameterInfo_ParameterFlags_kNoFlags = 0, + Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate = 1 << 0, + Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly = 1 << 1, + Steinberg_Vst_ParameterInfo_ParameterFlags_kIsWrapAround = 1 << 2, + Steinberg_Vst_ParameterInfo_ParameterFlags_kIsList = 1 << 3, + Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden = 1 << 4, + Steinberg_Vst_ParameterInfo_ParameterFlags_kIsProgramChange = 1 << 15, + Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass = 1 << 16 +} Steinberg_Vst_ParameterInfo_ParameterFlags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 116 */ + +typedef enum +{ + Steinberg_Vst_RestartFlags_kReloadComponent = 1 << 0, + Steinberg_Vst_RestartFlags_kIoChanged = 1 << 1, + Steinberg_Vst_RestartFlags_kParamValuesChanged = 1 << 2, + Steinberg_Vst_RestartFlags_kLatencyChanged = 1 << 3, + Steinberg_Vst_RestartFlags_kParamTitlesChanged = 1 << 4, + Steinberg_Vst_RestartFlags_kMidiCCAssignmentChanged = 1 << 5, + Steinberg_Vst_RestartFlags_kNoteExpressionChanged = 1 << 6, + Steinberg_Vst_RestartFlags_kIoTitlesChanged = 1 << 7, + Steinberg_Vst_RestartFlags_kPrefetchableSupportChanged = 1 << 8, + Steinberg_Vst_RestartFlags_kRoutingInfoChanged = 1 << 9, + Steinberg_Vst_RestartFlags_kKeyswitchChanged = 1 << 10, + Steinberg_Vst_RestartFlags_kParamIDMappingChanged = 1 << 11 +} Steinberg_Vst_RestartFlags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 426 */ + +typedef enum +{ + Steinberg_Vst_IProgress_ProgressType_AsyncStateRestoration = 0, + Steinberg_Vst_IProgress_ProgressType_UIBackgroundTask +} Steinberg_Vst_IProgress_ProgressType; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 555 */ + +typedef enum +{ + Steinberg_Vst_KnobModes_kCircularMode = 0, + Steinberg_Vst_KnobModes_kRelativCircularMode, + Steinberg_Vst_KnobModes_kLinearMode +} Steinberg_Vst_KnobModes; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstprocesscontext.h", line 47 */ + +typedef enum +{ + Steinberg_Vst_FrameRate_FrameRateFlags_kPullDownRate = 1 << 0, + Steinberg_Vst_FrameRate_FrameRateFlags_kDropRate = 1 << 1 +} Steinberg_Vst_FrameRate_FrameRateFlags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstprocesscontext.h", line 79 */ + +typedef enum +{ + Steinberg_Vst_Chord_Masks_kChordMask = 0x0FFF, + Steinberg_Vst_Chord_Masks_kReservedMask = 0xF000 +} Steinberg_Vst_Chord_Masks; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstprocesscontext.h", line 100 */ + +typedef enum +{ + Steinberg_Vst_ProcessContext_StatesAndFlags_kPlaying = 1 << 1, + Steinberg_Vst_ProcessContext_StatesAndFlags_kCycleActive = 1 << 2, + Steinberg_Vst_ProcessContext_StatesAndFlags_kRecording = 1 << 3, + Steinberg_Vst_ProcessContext_StatesAndFlags_kSystemTimeValid = 1 << 8, + Steinberg_Vst_ProcessContext_StatesAndFlags_kContTimeValid = 1 << 17, + Steinberg_Vst_ProcessContext_StatesAndFlags_kProjectTimeMusicValid = 1 << 9, + Steinberg_Vst_ProcessContext_StatesAndFlags_kBarPositionValid = 1 << 11, + Steinberg_Vst_ProcessContext_StatesAndFlags_kCycleValid = 1 << 12, + Steinberg_Vst_ProcessContext_StatesAndFlags_kTempoValid = 1 << 10, + Steinberg_Vst_ProcessContext_StatesAndFlags_kTimeSigValid = 1 << 13, + Steinberg_Vst_ProcessContext_StatesAndFlags_kChordValid = 1 << 18, + Steinberg_Vst_ProcessContext_StatesAndFlags_kSmpteValid = 1 << 14, + Steinberg_Vst_ProcessContext_StatesAndFlags_kClockValid = 1 << 15 +} Steinberg_Vst_ProcessContext_StatesAndFlags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 32 */ + +typedef enum +{ + Steinberg_Vst_NoteIDUserRange_kNoteIDUserRangeLowerBound = -10000, + Steinberg_Vst_NoteIDUserRange_kNoteIDUserRangeUpperBound = -1000 +} Steinberg_Vst_NoteIDUserRange; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 77 */ + +typedef enum +{ + Steinberg_Vst_DataEvent_DataTypes_kMidiSysEx = 0 +} Steinberg_Vst_DataEvent_DataTypes; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 150 */ + +typedef enum +{ + Steinberg_Vst_Event_EventFlags_kIsLive = 1 << 0, + Steinberg_Vst_Event_EventFlags_kUserReserved1 = 1 << 14, + Steinberg_Vst_Event_EventFlags_kUserReserved2 = 1 << 15 +} Steinberg_Vst_Event_EventFlags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 159 */ + +typedef enum +{ + Steinberg_Vst_Event_EventTypes_kNoteOnEvent = 0, + Steinberg_Vst_Event_EventTypes_kNoteOffEvent = 1, + Steinberg_Vst_Event_EventTypes_kDataEvent = 2, + Steinberg_Vst_Event_EventTypes_kPolyPressureEvent = 3, + Steinberg_Vst_Event_EventTypes_kNoteExpressionValueEvent = 4, + Steinberg_Vst_Event_EventTypes_kNoteExpressionTextEvent = 5, + Steinberg_Vst_Event_EventTypes_kChordEvent = 6, + Steinberg_Vst_Event_EventTypes_kScaleEvent = 7, + Steinberg_Vst_Event_EventTypes_kNoteExpressionIntValueEvent = 8, + Steinberg_Vst_Event_EventTypes_kLegacyMIDICCOutEvent = 65535 +} Steinberg_Vst_Event_EventTypes; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcontextmenu.h", line 174 */ + +typedef enum +{ + Steinberg_Vst_IContextMenuItem_Flags_kIsSeparator = 1 << 0, + Steinberg_Vst_IContextMenuItem_Flags_kIsDisabled = 1 << 1, + Steinberg_Vst_IContextMenuItem_Flags_kIsChecked = 1 << 2, + Steinberg_Vst_IContextMenuItem_Flags_kIsGroupStart = 1 << 3 | Steinberg_Vst_IContextMenuItem_Flags_kIsDisabled, + Steinberg_Vst_IContextMenuItem_Flags_kIsGroupEnd = 1 << 4 | Steinberg_Vst_IContextMenuItem_Flags_kIsSeparator +} Steinberg_Vst_IContextMenuItem_Flags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmidicontrollers.h", line 25 */ + +typedef enum +{ + Steinberg_Vst_ControllerNumbers_kCtrlBankSelectMSB = 0, + Steinberg_Vst_ControllerNumbers_kCtrlModWheel = 1, + Steinberg_Vst_ControllerNumbers_kCtrlBreath = 2, + Steinberg_Vst_ControllerNumbers_kCtrlFoot = 4, + Steinberg_Vst_ControllerNumbers_kCtrlPortaTime = 5, + Steinberg_Vst_ControllerNumbers_kCtrlDataEntryMSB = 6, + Steinberg_Vst_ControllerNumbers_kCtrlVolume = 7, + Steinberg_Vst_ControllerNumbers_kCtrlBalance = 8, + Steinberg_Vst_ControllerNumbers_kCtrlPan = 10, + Steinberg_Vst_ControllerNumbers_kCtrlExpression = 11, + Steinberg_Vst_ControllerNumbers_kCtrlEffect1 = 12, + Steinberg_Vst_ControllerNumbers_kCtrlEffect2 = 13, + Steinberg_Vst_ControllerNumbers_kCtrlGPC1 = 16, + Steinberg_Vst_ControllerNumbers_kCtrlGPC2 = 17, + Steinberg_Vst_ControllerNumbers_kCtrlGPC3 = 18, + Steinberg_Vst_ControllerNumbers_kCtrlGPC4 = 19, + Steinberg_Vst_ControllerNumbers_kCtrlBankSelectLSB = 32, + Steinberg_Vst_ControllerNumbers_kCtrlDataEntryLSB = 38, + Steinberg_Vst_ControllerNumbers_kCtrlSustainOnOff = 64, + Steinberg_Vst_ControllerNumbers_kCtrlPortaOnOff = 65, + Steinberg_Vst_ControllerNumbers_kCtrlSustenutoOnOff = 66, + Steinberg_Vst_ControllerNumbers_kCtrlSoftPedalOnOff = 67, + Steinberg_Vst_ControllerNumbers_kCtrlLegatoFootSwOnOff = 68, + Steinberg_Vst_ControllerNumbers_kCtrlHold2OnOff = 69, + Steinberg_Vst_ControllerNumbers_kCtrlSoundVariation = 70, + Steinberg_Vst_ControllerNumbers_kCtrlFilterCutoff = 71, + Steinberg_Vst_ControllerNumbers_kCtrlReleaseTime = 72, + Steinberg_Vst_ControllerNumbers_kCtrlAttackTime = 73, + Steinberg_Vst_ControllerNumbers_kCtrlFilterResonance = 74, + Steinberg_Vst_ControllerNumbers_kCtrlDecayTime = 75, + Steinberg_Vst_ControllerNumbers_kCtrlVibratoRate = 76, + Steinberg_Vst_ControllerNumbers_kCtrlVibratoDepth = 77, + Steinberg_Vst_ControllerNumbers_kCtrlVibratoDelay = 78, + Steinberg_Vst_ControllerNumbers_kCtrlSoundCtrler10 = 79, + Steinberg_Vst_ControllerNumbers_kCtrlGPC5 = 80, + Steinberg_Vst_ControllerNumbers_kCtrlGPC6 = 81, + Steinberg_Vst_ControllerNumbers_kCtrlGPC7 = 82, + Steinberg_Vst_ControllerNumbers_kCtrlGPC8 = 83, + Steinberg_Vst_ControllerNumbers_kCtrlPortaControl = 84, + Steinberg_Vst_ControllerNumbers_kCtrlEff1Depth = 91, + Steinberg_Vst_ControllerNumbers_kCtrlEff2Depth = 92, + Steinberg_Vst_ControllerNumbers_kCtrlEff3Depth = 93, + Steinberg_Vst_ControllerNumbers_kCtrlEff4Depth = 94, + Steinberg_Vst_ControllerNumbers_kCtrlEff5Depth = 95, + Steinberg_Vst_ControllerNumbers_kCtrlDataIncrement = 96, + Steinberg_Vst_ControllerNumbers_kCtrlDataDecrement = 97, + Steinberg_Vst_ControllerNumbers_kCtrlNRPNSelectLSB = 98, + Steinberg_Vst_ControllerNumbers_kCtrlNRPNSelectMSB = 99, + Steinberg_Vst_ControllerNumbers_kCtrlRPNSelectLSB = 100, + Steinberg_Vst_ControllerNumbers_kCtrlRPNSelectMSB = 101, + Steinberg_Vst_ControllerNumbers_kCtrlAllSoundsOff = 120, + Steinberg_Vst_ControllerNumbers_kCtrlResetAllCtrlers = 121, + Steinberg_Vst_ControllerNumbers_kCtrlLocalCtrlOnOff = 122, + Steinberg_Vst_ControllerNumbers_kCtrlAllNotesOff = 123, + Steinberg_Vst_ControllerNumbers_kCtrlOmniModeOff = 124, + Steinberg_Vst_ControllerNumbers_kCtrlOmniModeOn = 125, + Steinberg_Vst_ControllerNumbers_kCtrlPolyModeOnOff = 126, + Steinberg_Vst_ControllerNumbers_kCtrlPolyModeOn = 127, + Steinberg_Vst_ControllerNumbers_kAfterTouch = 128, + Steinberg_Vst_ControllerNumbers_kPitchBend = 129, + Steinberg_Vst_ControllerNumbers_kCountCtrlNumber, + Steinberg_Vst_ControllerNumbers_kCtrlProgramChange = 130, + Steinberg_Vst_ControllerNumbers_kCtrlPolyPressure = 131, + Steinberg_Vst_ControllerNumbers_kCtrlQuarterFrame = 132, + Steinberg_Vst_ControllerNumbers_kSystemSongSelect = 133, + Steinberg_Vst_ControllerNumbers_kSystemSongPointer = 134, + Steinberg_Vst_ControllerNumbers_kSystemCableSelect = 135, + Steinberg_Vst_ControllerNumbers_kSystemTuneRequest = 136, + Steinberg_Vst_ControllerNumbers_kSystemMidiClockStart = 137, + Steinberg_Vst_ControllerNumbers_kSystemMidiClockContinue = 138, + Steinberg_Vst_ControllerNumbers_kSystemMidiClockStop = 139, + Steinberg_Vst_ControllerNumbers_kSystemActiveSensing = 140 +} Steinberg_Vst_ControllerNumbers; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstchannelcontextinfo.h", line 170 */ + +typedef enum +{ + Steinberg_Vst_ChannelContext_ChannelPluginLocation_kPreVolumeFader = 0, + Steinberg_Vst_ChannelContext_ChannelPluginLocation_kPostVolumeFader, + Steinberg_Vst_ChannelContext_ChannelPluginLocation_kUsedAsPanner +} Steinberg_Vst_ChannelContext_ChannelPluginLocation; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstprefetchablesupport.h", line 38 */ + +typedef enum +{ + Steinberg_Vst_ePrefetchableSupport_kIsNeverPrefetchable = 0, + Steinberg_Vst_ePrefetchableSupport_kIsYetPrefetchable, + Steinberg_Vst_ePrefetchableSupport_kIsNotYetPrefetchable, + Steinberg_Vst_ePrefetchableSupport_kNumPrefetchableSupport +} Steinberg_Vst_ePrefetchableSupport; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstautomationstate.h", line 43 */ + +typedef enum +{ + Steinberg_Vst_IAutomationState_AutomationStates_kNoAutomation = 0, + Steinberg_Vst_IAutomationState_AutomationStates_kReadState = 1 << 0, + Steinberg_Vst_IAutomationState_AutomationStates_kWriteState = 1 << 1, + Steinberg_Vst_IAutomationState_AutomationStates_kReadWriteState = Steinberg_Vst_IAutomationState_AutomationStates_kReadState | Steinberg_Vst_IAutomationState_AutomationStates_kWriteState +} Steinberg_Vst_IAutomationState_AutomationStates; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 101 */ + +typedef enum +{ + Steinberg_Vst_ComponentFlags_kDistributable = 1 << 0, + Steinberg_Vst_ComponentFlags_kSimpleModeSupported = 1 << 1 +} Steinberg_Vst_ComponentFlags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 113 */ + +typedef enum +{ + Steinberg_Vst_SymbolicSampleSizes_kSample32, + Steinberg_Vst_SymbolicSampleSizes_kSample64 +} Steinberg_Vst_SymbolicSampleSizes; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 147 */ + +typedef enum +{ + Steinberg_Vst_ProcessModes_kRealtime, + Steinberg_Vst_ProcessModes_kPrefetch, + Steinberg_Vst_ProcessModes_kOffline +} Steinberg_Vst_ProcessModes; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 440 */ + +typedef enum +{ + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedSystemTime = 1 << 0, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedContinousTimeSamples = 1 << 1, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedProjectTimeMusic = 1 << 2, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedBarPositionMusic = 1 << 3, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedCycleMusic = 1 << 4, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedSamplesToNextClock = 1 << 5, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedTempo = 1 << 6, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedTimeSignature = 1 << 7, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedChord = 1 << 8, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedFrameRate = 1 << 9, + Steinberg_Vst_IProcessContextRequirements_Flags_kNeedTransportState = 1 << 10 +} Steinberg_Vst_IProcessContextRequirements_Flags; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteonorchestralarticulationinfo.h", line 70 */ + +typedef enum +{ + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kCoreSoundSustainAndStrikes = 0, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kStaccatosAndShorts = 1, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kSameNoteTrillsRepeats = 2, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kIntervallicTrills = 3, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kAdditionalColors = 4, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kPitchAndDynamicGestures = 5, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kScalesRunsAndArpeggios = 6, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kEffectsAndNoises = 7, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kReserved1 = 8, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kReserved2 = 9, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kCustomNoteOn1 = 10, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kCustomNoteOn2 = 11, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kCustomNoteOn3 = 12, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kCustomNoteOn4 = 13, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kCustomNoteOn5 = 14, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kCustomNoteOn6 = 15, + Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification_kReserved3 = 16 +} Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_Classification; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsttransportcontrol.h", line 32 */ + +typedef enum +{ + Steinberg_Vst_TransportPositionType_Samples, + Steinberg_Vst_TransportPositionType_QuarterNotes +} Steinberg_Vst_TransportPositionType; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsttransportcontrol.h", line 105 */ + +typedef enum +{ + Steinberg_Vst_ITransportControl_Action_Locate = 0, + Steinberg_Vst_ITransportControl_Action_PlaybackStart, + Steinberg_Vst_ITransportControl_Action_PlaybackStop, + Steinberg_Vst_ITransportControl_Action_LocateAndPlaybackStart, + Steinberg_Vst_ITransportControl_Action_PlaybackStopAndLocate, + Steinberg_Vst_ITransportControl_Action_RecordOnPlaybackStart, + Steinberg_Vst_ITransportControl_Action_LocateAndRecordOnPlaybackStart, + Steinberg_Vst_ITransportControl_Action_RecordOff, + Steinberg_Vst_ITransportControl_Action_RecordOffPlaybackStop, + Steinberg_Vst_ITransportControl_Action_RecordOffPlaybackStopAndLocate, + Steinberg_Vst_ITransportControl_Action_SetCycleStart, + Steinberg_Vst_ITransportControl_Action_SetCycleEnd, + Steinberg_Vst_ITransportControl_Action_CycleOn, + Steinberg_Vst_ITransportControl_Action_CycleOff +} Steinberg_Vst_ITransportControl_Action; + + +/*---------------------------------------------------------------------------------------------------------------------- +----- Variable declarations -------------------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------------------*/ + +static const Steinberg_int32 Steinberg_kMaxInt32 = INT32_MAX; +static const Steinberg_int32 Steinberg_kMinInt32 = INT32_MIN; +static const Steinberg_int32 Steinberg_kMaxLong = INT32_MAX; +static const Steinberg_int32 Steinberg_kMinLong = INT32_MIN; +static const Steinberg_uint32 Steinberg_kMaxInt32u = UINT32_MAX; +static const Steinberg_int64 Steinberg_kMaxInt64 = INT64_MAX; +static const Steinberg_int64 Steinberg_kMinInt64 = INT64_MIN; +static const Steinberg_uint64 Steinberg_kMaxInt64u = UINT64_MAX; +static const Steinberg_FIDString Steinberg_kPlatformStringWin = "WIN"; +static const Steinberg_FIDString Steinberg_kPlatformStringMac = "MAC"; +static const Steinberg_FIDString Steinberg_kPlatformStringIOS = "IOS"; +static const Steinberg_FIDString Steinberg_kPlatformStringLinux = "Linux"; +static const Steinberg_FIDString Steinberg_kPlatformString = "MAC"; +static const Steinberg_UCoord Steinberg_kMaxCoord = ((Steinberg_UCoord) 0x7FFFFFFF); +static const Steinberg_UCoord Steinberg_kMinCoord = ((Steinberg_UCoord) -0x7FFFFFFF); +static const Steinberg_FIDString Steinberg_kPlatformTypeHWND = "HWND"; +static const Steinberg_FIDString Steinberg_kPlatformTypeHIView = "HIView"; +static const Steinberg_FIDString Steinberg_kPlatformTypeNSView = "NSView"; +static const Steinberg_FIDString Steinberg_kPlatformTypeUIView = "UIView"; +static const Steinberg_FIDString Steinberg_kPlatformTypeX11EmbedWindowID = "X11EmbedWindowID"; +static const Steinberg_FIDString Steinberg_kPlatformTypeWaylandSurfaceID = "WaylandSurfaceID"; +static const Steinberg_uint32 Steinberg_kPrintfBufferSize = 4096; +static const Steinberg_Vst_ParamID Steinberg_Vst_kNoParamId = 0xFFFFFFFF; +static const Steinberg_Vst_ParamID Steinberg_Vst_kMinParamId = 0; +static const Steinberg_Vst_ParamID Steinberg_Vst_kMaxParamId = 0x7FFFFFFF; +static const Steinberg_int32 Steinberg_Vst_kStepCountContinuous = 0; +static const Steinberg_int32 Steinberg_Vst_kStepCountToggle = 1; +static const Steinberg_FIDString Steinberg_Vst_SDKVersionString = "VST 3.8.1"; +static const Steinberg_uint32 Steinberg_Vst_SDKVersionMajor = 3; +static const Steinberg_uint32 Steinberg_Vst_SDKVersionMinor = 8; +static const Steinberg_uint32 Steinberg_Vst_SDKVersionSub = 1; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion = ((3 << 16) | (8 << 8) | 1); +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_8_0 = 0x030800; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_14 = 0x03070E; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_13 = 0x03070D; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_12 = 0x03070C; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_11 = 0x03070B; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_10 = 0x03070A; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_9 = 0x030709; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_8 = 0x030708; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_7 = 0x030707; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_6 = 0x030706; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_5 = 0x030705; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_4 = 0x030704; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_3 = 0x030703; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_2 = 0x030702; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_1 = 0x030701; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_7_0 = 0x030700; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_14 = 0x03060E; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_13 = 0x03060D; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_12 = 0x03060C; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_11 = 0x03060B; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_10 = 0x03060A; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_9 = 0x030609; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_8 = 0x030608; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_7 = 0x030607; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_6 = 0x030606; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_5 = 0x030605; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_6_0 = 0x030600; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_5_0 = 0x030500; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_1_0 = 0x030100; +static const Steinberg_uint32 Steinberg_Vst_SDKVersion_3_0_0 = 0x030000; +static const Steinberg_int32 Steinberg_Vst_kDefaultFactoryFlags = 1 << 4; +static const Steinberg_Vst_CString Steinberg_Vst_PresetAttributes_kPlugInName = "PlugInName"; +static const Steinberg_Vst_CString Steinberg_Vst_PresetAttributes_kPlugInCategory = "PlugInCategory"; +static const Steinberg_Vst_CString Steinberg_Vst_PresetAttributes_kInstrument = "MusicalInstrument"; +static const Steinberg_Vst_CString Steinberg_Vst_PresetAttributes_kStyle = "MusicalStyle"; +static const Steinberg_Vst_CString Steinberg_Vst_PresetAttributes_kCharacter = "MusicalCharacter"; +static const Steinberg_Vst_CString Steinberg_Vst_PresetAttributes_kStateType = "StateType"; +static const Steinberg_Vst_CString Steinberg_Vst_PresetAttributes_kFilePathStringType = "FilePathString"; +static const Steinberg_Vst_CString Steinberg_Vst_PresetAttributes_kName = "Name"; +static const Steinberg_Vst_CString Steinberg_Vst_PresetAttributes_kFileName = "FileName"; +static const Steinberg_Vst_CString Steinberg_Vst_StateType_kProject = "Project"; +static const Steinberg_Vst_CString Steinberg_Vst_StateType_kDefault = "Default"; +static const Steinberg_Vst_CString Steinberg_Vst_StateType_kTrackPreset = "TrackPreset"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kAccordion = "Accordion"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kAccordionAccordion = "Accordion|Accordion"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kAccordionHarmonica = "Accordion|Harmonica"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kAccordionOther = "Accordion|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBass = "Bass"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBassABass = "Bass|A. Bass"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBassEBass = "Bass|E. Bass"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBassSynthBass = "Bass|Synth Bass"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBassOther = "Bass|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBrass = "Brass"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBrassFrenchHorn = "Brass|French Horn"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBrassTrumpet = "Brass|Trumpet"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBrassTrombone = "Brass|Trombone"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBrassTuba = "Brass|Tuba"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBrassSection = "Brass|Section"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBrassSynth = "Brass|Synth"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kBrassOther = "Brass|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kChromaticPerc = "Chromatic Perc"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kChromaticPercBell = "Chromatic Perc|Bell"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kChromaticPercMallett = "Chromatic Perc|Mallett"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kChromaticPercWood = "Chromatic Perc|Wood"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kChromaticPercPercussion = "Chromatic Perc|Percussion"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kChromaticPercTimpani = "Chromatic Perc|Timpani"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kChromaticPercOther = "Chromatic Perc|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPerc = "Drum&Perc"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercDrumsetGM = "Drum&Perc|Drumset GM"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercDrumset = "Drum&Perc|Drumset"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercDrumMenues = "Drum&Perc|Drum Menues"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercBeats = "Drum&Perc|Beats"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercPercussion = "Drum&Perc|Percussion"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercKickDrum = "Drum&Perc|Kick Drum"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercSnareDrum = "Drum&Perc|Snare Drum"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercToms = "Drum&Perc|Toms"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercHiHats = "Drum&Perc|HiHats"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercCymbals = "Drum&Perc|Cymbals"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kDrumPercOther = "Drum&Perc|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kEthnic = "Ethnic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kEthnicAsian = "Ethnic|Asian"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kEthnicAfrican = "Ethnic|African"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kEthnicEuropean = "Ethnic|European"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kEthnicLatin = "Ethnic|Latin"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kEthnicAmerican = "Ethnic|American"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kEthnicAlien = "Ethnic|Alien"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kEthnicOther = "Ethnic|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kGuitar = "Guitar/Plucked"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kGuitarAGuitar = "Guitar/Plucked|A. Guitar"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kGuitarEGuitar = "Guitar/Plucked|E. Guitar"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kGuitarHarp = "Guitar/Plucked|Harp"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kGuitarEthnic = "Guitar/Plucked|Ethnic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kGuitarOther = "Guitar/Plucked|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kKeyboard = "Keyboard"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kKeyboardClavi = "Keyboard|Clavi"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kKeyboardEPiano = "Keyboard|E. Piano"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kKeyboardHarpsichord = "Keyboard|Harpsichord"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kKeyboardOther = "Keyboard|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kMusicalFX = "Musical FX"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kMusicalFXHitsStabs = "Musical FX|Hits&Stabs"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kMusicalFXMotion = "Musical FX|Motion"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kMusicalFXSweeps = "Musical FX|Sweeps"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kMusicalFXBeepsBlips = "Musical FX|Beeps&Blips"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kMusicalFXScratches = "Musical FX|Scratches"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kMusicalFXOther = "Musical FX|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kOrgan = "Organ"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kOrganElectric = "Organ|Electric"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kOrganPipe = "Organ|Pipe"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kOrganOther = "Organ|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kPiano = "Piano"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kPianoAPiano = "Piano|A. Piano"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kPianoEGrand = "Piano|E. Grand"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kPianoOther = "Piano|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSoundFX = "Sound FX"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSoundFXNature = "Sound FX|Nature"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSoundFXMechanical = "Sound FX|Mechanical"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSoundFXSynthetic = "Sound FX|Synthetic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSoundFXOther = "Sound FX|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kStrings = "Strings"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kStringsViolin = "Strings|Violin"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kStringsViola = "Strings|Viola"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kStringsCello = "Strings|Cello"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kStringsBass = "Strings|Bass"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kStringsSection = "Strings|Section"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kStringsSynth = "Strings|Synth"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kStringsOther = "Strings|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthLead = "Synth Lead"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthLeadAnalog = "Synth Lead|Analog"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthLeadDigital = "Synth Lead|Digital"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthLeadArpeggio = "Synth Lead|Arpeggio"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthLeadOther = "Synth Lead|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthPad = "Synth Pad"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthPadSynthChoir = "Synth Pad|Synth Choir"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthPadAnalog = "Synth Pad|Analog"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthPadDigital = "Synth Pad|Digital"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthPadMotion = "Synth Pad|Motion"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthPadOther = "Synth Pad|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthComp = "Synth Comp"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthCompAnalog = "Synth Comp|Analog"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthCompDigital = "Synth Comp|Digital"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kSynthCompOther = "Synth Comp|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kVocal = "Vocal"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kVocalLeadVocal = "Vocal|Lead Vocal"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kVocalAdlibs = "Vocal|Adlibs"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kVocalChoir = "Vocal|Choir"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kVocalSolo = "Vocal|Solo"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kVocalFX = "Vocal|FX"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kVocalSpoken = "Vocal|Spoken"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kVocalOther = "Vocal|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kWoodwinds = "Woodwinds"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kWoodwindsEthnic = "Woodwinds|Ethnic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kWoodwindsFlute = "Woodwinds|Flute"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kWoodwindsOboe = "Woodwinds|Oboe"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kWoodwindsEnglHorn = "Woodwinds|Engl. Horn"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kWoodwindsClarinet = "Woodwinds|Clarinet"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kWoodwindsSaxophone = "Woodwinds|Saxophone"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kWoodwindsBassoon = "Woodwinds|Bassoon"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalInstrument_kWoodwindsOther = "Woodwinds|Other"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAlternativeIndie = "Alternative/Indie"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAlternativeIndieGothRock = "Alternative/Indie|Goth Rock"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAlternativeIndieGrunge = "Alternative/Indie|Grunge"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAlternativeIndieNewWave = "Alternative/Indie|New Wave"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAlternativeIndiePunk = "Alternative/Indie|Punk"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAlternativeIndieCollegeRock = "Alternative/Indie|College Rock"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAlternativeIndieDarkWave = "Alternative/Indie|Dark Wave"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAlternativeIndieHardcore = "Alternative/Indie|Hardcore"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAmbientChillOut = "Ambient/ChillOut"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAmbientChillOutNewAgeMeditation = "Ambient/ChillOut|New Age/Meditation"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAmbientChillOutDarkAmbient = "Ambient/ChillOut|Dark Ambient"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAmbientChillOutDowntempo = "Ambient/ChillOut|Downtempo"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kAmbientChillOutLounge = "Ambient/ChillOut|Lounge"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kBlues = "Blues"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kBluesAcousticBlues = "Blues|Acoustic Blues"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kBluesCountryBlues = "Blues|Country Blues"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kBluesElectricBlues = "Blues|Electric Blues"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kBluesChicagoBlues = "Blues|Chicago Blues"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassical = "Classical"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalBaroque = "Classical|Baroque"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalChamberMusic = "Classical|Chamber Music"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalMedieval = "Classical|Medieval"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalModernComposition = "Classical|Modern Composition"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalOpera = "Classical|Opera"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalGregorian = "Classical|Gregorian"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalRenaissance = "Classical|Renaissance"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalClassic = "Classical|Classic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalRomantic = "Classical|Romantic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kClassicalSoundtrack = "Classical|Soundtrack"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kCountry = "Country"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kCountryCountryWestern = "Country|Country/Western"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kCountryHonkyTonk = "Country|Honky Tonk"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kCountryUrbanCowboy = "Country|Urban Cowboy"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kCountryBluegrass = "Country|Bluegrass"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kCountryAmericana = "Country|Americana"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kCountrySquaredance = "Country|Squaredance"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kCountryNorthAmericanFolk = "Country|North American Folk"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDance = "Electronica/Dance"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceMinimal = "Electronica/Dance|Minimal"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceClassicHouse = "Electronica/Dance|Classic House"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceElektroHouse = "Electronica/Dance|Elektro House"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceFunkyHouse = "Electronica/Dance|Funky House"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceIndustrial = "Electronica/Dance|Industrial"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceElectronicBodyMusic = "Electronica/Dance|Electronic Body Music"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceTripHop = "Electronica/Dance|Trip Hop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceTechno = "Electronica/Dance|Techno"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceDrumNBassJungle = "Electronica/Dance|Drum'n'Bass/Jungle"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceElektro = "Electronica/Dance|Elektro"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceTrance = "Electronica/Dance|Trance"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceDub = "Electronica/Dance|Dub"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kElectronicaDanceBigBeats = "Electronica/Dance|Big Beats"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kExperimental = "Experimental"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kExperimentalNewMusic = "Experimental|New Music"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kExperimentalFreeImprovisation = "Experimental|Free Improvisation"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kExperimentalElectronicArtMusic = "Experimental|Electronic Art Music"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kExperimentalNoise = "Experimental|Noise"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kJazz = "Jazz"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kJazzNewOrleansJazz = "Jazz|New Orleans Jazz"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kJazzTraditionalJazz = "Jazz|Traditional Jazz"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kJazzOldtimeJazzDixiland = "Jazz|Oldtime Jazz/Dixiland"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kJazzFusion = "Jazz|Fusion"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kJazzAvantgarde = "Jazz|Avantgarde"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kJazzLatinJazz = "Jazz|Latin Jazz"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kJazzFreeJazz = "Jazz|Free Jazz"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kJazzRagtime = "Jazz|Ragtime"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kPop = "Pop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kPopBritpop = "Pop|Britpop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kPopRock = "Pop|Pop/Rock"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kPopTeenPop = "Pop|Teen Pop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kPopChartDance = "Pop|Chart Dance"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kPop80sPop = "Pop|80's Pop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kPopDancehall = "Pop|Dancehall"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kPopDisco = "Pop|Disco"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetal = "Rock/Metal"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalBluesRock = "Rock/Metal|Blues Rock"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalClassicRock = "Rock/Metal|Classic Rock"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalHardRock = "Rock/Metal|Hard Rock"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalRockRoll = "Rock/Metal|Rock & Roll"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalSingerSongwriter = "Rock/Metal|Singer/Songwriter"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalHeavyMetal = "Rock/Metal|Heavy Metal"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalDeathBlackMetal = "Rock/Metal|Death/Black Metal"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalNuMetal = "Rock/Metal|NuMetal"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalReggae = "Rock/Metal|Reggae"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalBallad = "Rock/Metal|Ballad"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalAlternativeRock = "Rock/Metal|Alternative Rock"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalRockabilly = "Rock/Metal|Rockabilly"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalThrashMetal = "Rock/Metal|Thrash Metal"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kRockMetalProgressiveRock = "Rock/Metal|Progressive Rock"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kUrbanHipHopRB = "Urban (Hip-Hop / R&B)"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kUrbanHipHopRBClassic = "Urban (Hip-Hop / R&B)|Classic R&B"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kUrbanHipHopRBModern = "Urban (Hip-Hop / R&B)|Modern R&B"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kUrbanHipHopRBPop = "Urban (Hip-Hop / R&B)|R&B Pop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kUrbanHipHopRBWestCoastHipHop = "Urban (Hip-Hop / R&B)|WestCoast Hip-Hop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kUrbanHipHopRBEastCoastHipHop = "Urban (Hip-Hop / R&B)|EastCoast Hip-Hop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kUrbanHipHopRBRapHipHop = "Urban (Hip-Hop / R&B)|Rap/Hip Hop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kUrbanHipHopRBSoul = "Urban (Hip-Hop / R&B)|Soul"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kUrbanHipHopRBFunk = "Urban (Hip-Hop / R&B)|Funk"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnic = "World/Ethnic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicAfrica = "World/Ethnic|Africa"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicAsia = "World/Ethnic|Asia"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicCeltic = "World/Ethnic|Celtic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicEurope = "World/Ethnic|Europe"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicKlezmer = "World/Ethnic|Klezmer"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicScandinavia = "World/Ethnic|Scandinavia"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicEasternEurope = "World/Ethnic|Eastern Europe"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicIndiaOriental = "World/Ethnic|India/Oriental"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicNorthAmerica = "World/Ethnic|North America"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicSouthAmerica = "World/Ethnic|South America"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalStyle_kWorldEthnicAustralia = "World/Ethnic|Australia"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kMono = "Mono"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kPoly = "Poly"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kSplit = "Split"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kLayer = "Layer"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kGlide = "Glide"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kGlissando = "Glissando"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kMajor = "Major"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kMinor = "Minor"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kSingle = "Single"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kEnsemble = "Ensemble"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kAcoustic = "Acoustic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kElectric = "Electric"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kAnalog = "Analog"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kDigital = "Digital"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kVintage = "Vintage"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kModern = "Modern"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kOld = "Old"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kNew = "New"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kClean = "Clean"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kDistorted = "Distorted"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kDry = "Dry"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kProcessed = "Processed"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kHarmonic = "Harmonic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kDissonant = "Dissonant"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kClear = "Clear"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kNoisy = "Noisy"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kThin = "Thin"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kRich = "Rich"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kDark = "Dark"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kBright = "Bright"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kCold = "Cold"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kWarm = "Warm"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kMetallic = "Metallic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kWooden = "Wooden"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kGlass = "Glass"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kPlastic = "Plastic"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kPercussive = "Percussive"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kSoft = "Soft"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kFast = "Fast"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kSlow = "Slow"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kShort = "Short"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kLong = "Long"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kAttack = "Attack"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kRelease = "Release"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kDecay = "Decay"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kSustain = "Sustain"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kFastAttack = "Fast Attack"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kSlowAttack = "Slow Attack"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kShortRelease = "Short Release"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kLongRelease = "Long Release"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kStatic = "Static"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kMoving = "Moving"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kLoop = "Loop"; +static const Steinberg_Vst_CString Steinberg_Vst_MusicalCharacter_kOneShot = "One Shot"; +static const Steinberg_Vst_CString Steinberg_Vst_ViewType_kEditor = "editor"; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerL = 1 << 0; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerR = 1 << 1; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerC = 1 << 2; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerLfe = 1 << 3; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerLs = 1 << 4; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerRs = 1 << 5; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerLc = 1 << 6; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerRc = 1 << 7; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerS = 1 << 8; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerCs = 1 << 8; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerSl = 1 << 9; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerSr = 1 << 10; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerTc = 1 << 11; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerTfl = 1 << 12; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerTfc = 1 << 13; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerTfr = 1 << 14; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerTrl = 1 << 15; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerTrc = 1 << 16; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerTrr = 1 << 17; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerLfe2 = 1 << 18; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerM = 1 << 19; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN0 = (Steinberg_Vst_Speaker) 1 << 20; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN1 = (Steinberg_Vst_Speaker) 1 << 21; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN2 = (Steinberg_Vst_Speaker) 1 << 22; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN3 = (Steinberg_Vst_Speaker) 1 << 23; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN4 = (Steinberg_Vst_Speaker) 1 << 38; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN5 = (Steinberg_Vst_Speaker) 1 << 39; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN6 = (Steinberg_Vst_Speaker) 1 << 40; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN7 = (Steinberg_Vst_Speaker) 1 << 41; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN8 = (Steinberg_Vst_Speaker) 1 << 42; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN9 = (Steinberg_Vst_Speaker) 1 << 43; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN10 = (Steinberg_Vst_Speaker) 1 << 44; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN11 = (Steinberg_Vst_Speaker) 1 << 45; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN12 = (Steinberg_Vst_Speaker) 1 << 46; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN13 = (Steinberg_Vst_Speaker) 1 << 47; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN14 = (Steinberg_Vst_Speaker) 1 << 48; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN15 = (Steinberg_Vst_Speaker) 1 << 49; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN16 = (Steinberg_Vst_Speaker) 1 << 50; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN17 = (Steinberg_Vst_Speaker) 1 << 51; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN18 = (Steinberg_Vst_Speaker) 1 << 52; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN19 = (Steinberg_Vst_Speaker) 1 << 53; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN20 = (Steinberg_Vst_Speaker) 1 << 54; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN21 = (Steinberg_Vst_Speaker) 1 << 55; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN22 = (Steinberg_Vst_Speaker) 1 << 56; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN23 = (Steinberg_Vst_Speaker) 1 << 57; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerACN24 = (Steinberg_Vst_Speaker) 1 << 58; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerTsl = (Steinberg_Vst_Speaker) 1 << 24; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerTsr = (Steinberg_Vst_Speaker) 1 << 25; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerLcs = (Steinberg_Vst_Speaker) 1 << 26; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerRcs = (Steinberg_Vst_Speaker) 1 << 27; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerBfl = (Steinberg_Vst_Speaker) 1 << 28; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerBfc = (Steinberg_Vst_Speaker) 1 << 29; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerBfr = (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerPl = (Steinberg_Vst_Speaker) 1 << 31; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerPr = (Steinberg_Vst_Speaker) 1 << 32; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerBsl = (Steinberg_Vst_Speaker) 1 << 33; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerBsr = (Steinberg_Vst_Speaker) 1 << 34; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerBrl = (Steinberg_Vst_Speaker) 1 << 35; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerBrc = (Steinberg_Vst_Speaker) 1 << 36; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerBrr = (Steinberg_Vst_Speaker) 1 << 37; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerLw = (Steinberg_Vst_Speaker) 1 << 59; +static const Steinberg_Vst_Speaker Steinberg_Vst_kSpeakerRw = (Steinberg_Vst_Speaker) 1 << 60; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kEmpty = 0; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kMono = 1 << 19; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereo = 1 << 0 | 1 << 1; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereoWide = (Steinberg_Vst_Speaker) 1 << 59 | (Steinberg_Vst_Speaker) 1 << 60; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereoSurround = 1 << 4 | 1 << 5; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereoCenter = 1 << 6 | 1 << 7; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereoSide = 1 << 9 | 1 << 10; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereoCLfe = 1 << 2 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereoTF = 1 << 12 | 1 << 14; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereoTS = (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereoTR = 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kStereoBF = (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kCineFront = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 6 | 1 << 7; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k30Cine = 1 << 0 | 1 << 1 | 1 << 2; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k31Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k30Music = 1 << 0 | 1 << 1 | 1 << 8; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k31Music = 1 << 0 | 1 << 1 | 1 << 8 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k40Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 8; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k41Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 8 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k40Music = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k41Music = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k51 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k60Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 8; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k61Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 8 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k60Music = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k61Music = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71CineFullFront = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70Music = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71Music = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71CineFullRear = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 26 | (Steinberg_Vst_Speaker) 1 << 27; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71CineSideFill = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71Proximity = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 31 | (Steinberg_Vst_Speaker) 1 << 32; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k80Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k81Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k80Music = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 8 | 1 << 9 | 1 << 10; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k81Music = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 8 | 1 << 9 | 1 << 10 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k90Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 9 | 1 << 10; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k91Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 9 | 1 << 10 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k100Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k101Cine = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kAmbi1stOrderACN = (Steinberg_Vst_Speaker) 1 << 20 | (Steinberg_Vst_Speaker) 1 << 21 | (Steinberg_Vst_Speaker) 1 << 22 | (Steinberg_Vst_Speaker) 1 << 23; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kAmbi2cdOrderACN = (Steinberg_Vst_Speaker) 1 << 20 | (Steinberg_Vst_Speaker) 1 << 21 | (Steinberg_Vst_Speaker) 1 << 22 | (Steinberg_Vst_Speaker) 1 << 23 | (Steinberg_Vst_Speaker) 1 << 38 | (Steinberg_Vst_Speaker) 1 << 39 | (Steinberg_Vst_Speaker) 1 << 40 | (Steinberg_Vst_Speaker) 1 << 41 | (Steinberg_Vst_Speaker) 1 << 42; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kAmbi3rdOrderACN = (Steinberg_Vst_Speaker) 1 << 20 | (Steinberg_Vst_Speaker) 1 << 21 | (Steinberg_Vst_Speaker) 1 << 22 | (Steinberg_Vst_Speaker) 1 << 23 | (Steinberg_Vst_Speaker) 1 << 38 | (Steinberg_Vst_Speaker) 1 << 39 | (Steinberg_Vst_Speaker) 1 << 40 | (Steinberg_Vst_Speaker) 1 << 41 | (Steinberg_Vst_Speaker) 1 << 42 | (Steinberg_Vst_Speaker) 1 << 43 | (Steinberg_Vst_Speaker) 1 << 44 | (Steinberg_Vst_Speaker) 1 << 45 | (Steinberg_Vst_Speaker) 1 << 46 | (Steinberg_Vst_Speaker) 1 << 47 | (Steinberg_Vst_Speaker) 1 << 48 | (Steinberg_Vst_Speaker) 1 << 49; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kAmbi4thOrderACN = (Steinberg_Vst_Speaker) 1 << 20 | (Steinberg_Vst_Speaker) 1 << 21 | (Steinberg_Vst_Speaker) 1 << 22 | (Steinberg_Vst_Speaker) 1 << 23 | (Steinberg_Vst_Speaker) 1 << 38 | (Steinberg_Vst_Speaker) 1 << 39 | (Steinberg_Vst_Speaker) 1 << 40 | (Steinberg_Vst_Speaker) 1 << 41 | (Steinberg_Vst_Speaker) 1 << 42 | (Steinberg_Vst_Speaker) 1 << 43 | (Steinberg_Vst_Speaker) 1 << 44 | (Steinberg_Vst_Speaker) 1 << 45 | (Steinberg_Vst_Speaker) 1 << 46 | (Steinberg_Vst_Speaker) 1 << 47 | (Steinberg_Vst_Speaker) 1 << 48 | (Steinberg_Vst_Speaker) 1 << 49 | (Steinberg_Vst_Speaker) 1 << 50 | (Steinberg_Vst_Speaker) 1 << 51 | (Steinberg_Vst_Speaker) 1 << 52 | (Steinberg_Vst_Speaker) 1 << 53 | (Steinberg_Vst_Speaker) 1 << 54 | (Steinberg_Vst_Speaker) 1 << 55 | (Steinberg_Vst_Speaker) 1 << 56 | (Steinberg_Vst_Speaker) 1 << 57 | (Steinberg_Vst_Speaker) 1 << 58; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kAmbi5thOrderACN = 0x000FFFFFFFFF; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kAmbi6thOrderACN = 0x0001FFFFFFFFFFFF; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_kAmbi7thOrderACN = 0xFFFFFFFFFFFFFFFF; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k80Cube = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k40_4 = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71CineTopCenter = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 8 | 1 << 11; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71CineCenterHigh = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 8 | 1 << 13; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70CineFrontHigh = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70MPEG3D = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_2 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71CineFrontHigh = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71MPEG3D = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k51_2 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70CineSideHigh = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_2_TS = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71CineSideHigh = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k51_2_TS = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k81MPEG3D = 1 << 0 | 1 << 1 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 13 | 1 << 14 | (Steinberg_Vst_Speaker) 1 << 29; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k41_4_1 = 1 << 0 | 1 << 1 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 13 | 1 << 14 | (Steinberg_Vst_Speaker) 1 << 29; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k90 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_4 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k91 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k51_4 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_4_1 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 29; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k51_4_1 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 29 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70_2 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71_2 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k91Atmos = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70_2_TF = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71_2_TF = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70_3 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 16; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k72_3 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 16 | 1 << 3 | 1 << 18; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70_4 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71_4 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k111MPEG3D = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70_6 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k71_6 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k90_4 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k91_4 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k90_6 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k91_6 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k90_4_W = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 59 | (Steinberg_Vst_Speaker) 1 << 60 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k91_4_W = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 59 | (Steinberg_Vst_Speaker) 1 << 60 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k90_6_W = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 59 | (Steinberg_Vst_Speaker) 1 << 60 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k91_6_W = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 59 | (Steinberg_Vst_Speaker) 1 << 60 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k100 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 11 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_5 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 11 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k101 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 11 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k101MPEG3D = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 11 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k51_5 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 11 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k102 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 18; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k52_5 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 18; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k110 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_6 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k111 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k51_6 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k122 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 18; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k72_5 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 18; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k130 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k131 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k140 = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30 | (Steinberg_Vst_Speaker) 1 << 35 | (Steinberg_Vst_Speaker) 1 << 37; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k60_4_4 = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30 | (Steinberg_Vst_Speaker) 1 << 35 | (Steinberg_Vst_Speaker) 1 << 37; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k220 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 16 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 29 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k100_9_3 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 16 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 29 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k222 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 16 | 1 << 17 | 1 << 18 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 29 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k102_9_3 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 16 | 1 << 17 | 1 << 18 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 29 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_5_3 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 29 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k51_5_3 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 29 | (Steinberg_Vst_Speaker) 1 << 30 | 1 << 3; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_2_2 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_4_2 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k70_4_2 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 9 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_5_Sony = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k40_2_2 = 1 << 2 | 1 << 9 | 1 << 10 | 1 << 8 | (Steinberg_Vst_Speaker) 1 << 24 | (Steinberg_Vst_Speaker) 1 << 25 | (Steinberg_Vst_Speaker) 1 << 33 | (Steinberg_Vst_Speaker) 1 << 34; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k40_4_2 = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_3_2 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 13 | 1 << 14 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k30_5_2 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 12 | 1 << 13 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k40_4_4 = 1 << 0 | 1 << 1 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30 | (Steinberg_Vst_Speaker) 1 << 35 | (Steinberg_Vst_Speaker) 1 << 37; +static const Steinberg_Vst_SpeakerArrangement Steinberg_Vst_SpeakerArr_k50_4_4 = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 5 | 1 << 12 | 1 << 14 | 1 << 15 | 1 << 17 | (Steinberg_Vst_Speaker) 1 << 28 | (Steinberg_Vst_Speaker) 1 << 30 | (Steinberg_Vst_Speaker) 1 << 35 | (Steinberg_Vst_Speaker) 1 << 37; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringEmpty = ""; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringMono = "Mono"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereo = "Stereo"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoWide = "Stereo (Lw Rw)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoR = "Stereo (Ls Rs)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoC = "Stereo (Lc Rc)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoSide = "Stereo (Sl Sr)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoCLfe = "Stereo (C LFE)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoTF = "Stereo (Tfl Tfr)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoTS = "Stereo (Tsl Tsr)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoTR = "Stereo (Trl Trr)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoBF = "Stereo (Bfl Bfr)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringCineFront = "Cine Front"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString30Cine = "LRC"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString30Music = "LRS"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString31Cine = "LRC+LFE"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString31Music = "LRS+LFE"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40Cine = "LRCS"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40Music = "Quadro"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString41Cine = "LRCS+LFE"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString41Music = "Quadro+LFE"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50 = "5.0"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51 = "5.1"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString60Cine = "6.0 Cine"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString60Music = "6.0 Music"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString61Cine = "6.1 Cine"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString61Music = "6.1 Music"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70Cine = "7.0 SDDS"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70CineOld = "7.0 Cine (SDDS)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70Music = "7.0"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70MusicOld = "7.0 Music (Dolby)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71Cine = "7.1 SDDS"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71CineOld = "7.1 Cine (SDDS)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71Music = "7.1"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71MusicOld = "7.1 Music (Dolby)"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71CineTopCenter = "7.1 Cine Top Center"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71CineCenterHigh = "7.1 Cine Center High"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71CineFullRear = "7.1 Cine Full Rear"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_2 = "5.1.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_2 = "5.0.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_2TopSide = "5.0.2 Top Side"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_2TopSide = "5.1.2 Top Side"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71Proximity = "7.1 Proximity"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString80Cine = "8.0 Cine"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString80Music = "8.0 Music"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40_4 = "8.0 Cube"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString81Cine = "8.1 Cine"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString81Music = "8.1 Music"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90Cine = "9.0 Cine"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91Cine = "9.1 Cine"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString100Cine = "10.0 Cine"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString101Cine = "10.1 Cine"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString52_5 = "5.2.5"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString72_5 = "12.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_4 = "5.0.4"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_4 = "5.1.4"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_4_1 = "5.0.4.1"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_4_1 = "5.1.4.1"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_2 = "7.0.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71_2 = "7.1.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_2_TF = "7.0.2 Top Front"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71_2_TF = "7.1.2 Top Front"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_3 = "7.0.3"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString72_3 = "7.2.3"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_4 = "7.0.4"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71_4 = "7.1.4"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_6 = "7.0.6"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71_6 = "7.1.6"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90_4 = "9.0.4 ITU"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91_4 = "9.1.4 ITU"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90_6 = "9.0.6 ITU"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91_6 = "9.1.6 ITU"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90_4_W = "9.0.4"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91_4_W = "9.1.4"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90_6_W = "9.0.6"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91_6_W = "9.1.6"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_5 = "10.0 Auro-3D"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_5 = "10.1 Auro-3D"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_6 = "11.0 Auro-3D"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_6 = "11.1 Auro-3D"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString130 = "13.0 Auro-3D"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString131 = "13.1 Auro-3D"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString41_4_1 = "8.1 MPEG"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString60_4_4 = "14.0"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString220 = "22.0"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString222 = "22.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_5_3 = "5.0.5.3"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_5_3 = "5.1.5.3"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_2_2 = "5.0.2.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_4_2 = "5.0.4.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_4_2 = "7.0.4.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_5_Sony = "5.0.5 Sony"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40_2_2 = "4.0.3.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40_4_2 = "4.0.4.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_3_2 = "5.0.3.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString30_5_2 = "3.0.5.2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40_4_4 = "4.0.4.4"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_4_4 = "5.0.4.4"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi1stOrder = "1OA"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi2cdOrder = "2OA"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi3rdOrder = "3OA"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi4thOrder = "4OA"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi5thOrder = "5OA"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi6thOrder = "6OA"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi7thOrder = "7OA"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringMonoS = "M"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoS = "L R"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoWideS = "Lw Rw"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoRS = "Ls Rs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoCS = "Lc Rc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoSS = "Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoCLfeS = "C LFE"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoTFS = "Tfl Tfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoTSS = "Tsl Tsr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoTRS = "Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringStereoBFS = "Bfl Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringCineFrontS = "L R C Lc Rc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString30CineS = "L R C"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString30MusicS = "L R S"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString31CineS = "L R C LFE"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString31MusicS = "L R LFE S"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40CineS = "L R C S"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40MusicS = "L R Ls Rs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString41CineS = "L R C LFE S"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString41MusicS = "L R LFE Ls Rs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50S = "L R C Ls Rs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51S = "L R C LFE Ls Rs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString60CineS = "L R C Ls Rs Cs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString60MusicS = "L R Ls Rs Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString61CineS = "L R C LFE Ls Rs Cs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString61MusicS = "L R LFE Ls Rs Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70CineS = "L R C Ls Rs Lc Rc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70MusicS = "L R C Ls Rs Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71CineS = "L R C LFE Ls Rs Lc Rc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71MusicS = "L R C LFE Ls Rs Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString80CineS = "L R C Ls Rs Lc Rc Cs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString80MusicS = "L R C Ls Rs Cs Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString81CineS = "L R C LFE Ls Rs Lc Rc Cs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString81MusicS = "L R C LFE Ls Rs Cs Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40_4S = "L R Ls Rs Tfl Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71CineTopCenterS = "L R C LFE Ls Rs Cs Tc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71CineCenterHighS = "L R C LFE Ls Rs Cs Tfc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71CineFullRearS = "L R C LFE Ls Rs Lcs Rcs"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_2S = "L R C Ls Rs Tfl Tfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_2S = "L R C LFE Ls Rs Tfl Tfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_2TopSideS = "L R C Ls Rs Tsl Tsr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_2TopSideS = "L R C LFE Ls Rs Tsl Tsr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71ProximityS = "L R C LFE Ls Rs Pl Pr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90CineS = "L R C Ls Rs Lc Rc Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91CineS = "L R C LFE Ls Rs Lc Rc Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString100CineS = "L R C Ls Rs Lc Rc Cs Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString101CineS = "L R C LFE Ls Rs Lc Rc Cs Sl Sr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_4S = "L R C Ls Rs Tfl Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_4S = "L R C LFE Ls Rs Tfl Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_4_1S = "L R C Ls Rs Tfl Tfr Trl Trr Bfc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_4_1S = "L R C LFE Ls Rs Tfl Tfr Trl Trr Bfc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_2S = "L R C Ls Rs Sl Sr Tsl Tsr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71_2S = "L R C LFE Ls Rs Sl Sr Tsl Tsr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_2_TFS = "L R C Ls Rs Sl Sr Tfl Tfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71_2_TFS = "L R C LFE Ls Rs Sl Sr Tfl Tfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_3S = "L R C Ls Rs Sl Sr Tfl Tfr Trc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString72_3S = "L R C LFE Ls Rs Sl Sr Tfl Tfr Trc LFE2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_4S = "L R C Ls Rs Sl Sr Tfl Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71_4S = "L R C LFE Ls Rs Sl Sr Tfl Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_6S = "L R C Ls Rs Sl Sr Tfl Tfr Trl Trr Tsl Tsr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString71_6S = "L R C LFE Ls Rs Sl Sr Tfl Tfr Trl Trr Tsl Tsr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90_4S = "L R C Ls Rs Lc Rc Sl Sr Tfl Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91_4S = "L R C LFE Ls Rs Lc Rc Sl Sr Tfl Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90_6S = "L R C Ls Rs Lc Rc Sl Sr Tfl Tfr Trl Trr Tsl Tsr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91_6S = "L R C LFE Ls Rs Lc Rc Sl Sr Tfl Tfr Trl Trr Tsl Tsr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90_4_WS = "L R C Ls Rs Sl Sr Tfl Tfr Trl Trr Lw Rw"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91_4_WS = "L R C LFE Ls Rs Sl Sr Tfl Tfr Trl Trr Lw Rw"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString90_6_WS = "L R C Ls Rs Sl Sr Tfl Tfr Trl Trr Tsl Tsr Lw Rw"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString91_6_WS = "L R C LFE Ls Rs Sl Sr Tfl Tfr Trl Trr Tsl Tsr Lw Rw"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_5S = "L R C Ls Rs Tc Tfl Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_5S = "L R C LFE Ls Rs Tc Tfl Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_5_SonyS = "L R C Ls Rs Tfl Tfc Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_6S = "L R C Ls Rs Tc Tfl Tfc Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_6S = "L R C LFE Ls Rs Tc Tfl Tfc Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString130S = "L R C Ls Rs Sl Sr Tc Tfl Tfc Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString131S = "L R C LFE Ls Rs Sl Sr Tc Tfl Tfc Tfr Trl Trr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString52_5S = "L R C LFE Ls Rs Tfl Tfc Tfr Trl Trr LFE2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString72_5S = "L R C LFE Ls Rs Lc Rc Tfl Tfc Tfr Trl Trr LFE2"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString41_4_1S = "L R LFE Ls Rs Tfl Tfc Tfr Bfc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString30_5_2S = "L R C Tfl Tfc Tfr Trl Trr Bfl Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40_2_2S = "C Sl Sr Cs Tfc Tsl Tsr Trc"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40_4_2S = "L R Ls Rs Tfl Tfr Trl Trr Bfl Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString40_4_4S = "L R Ls Rs Tfl Tfr Trl Trr Bfl Bfr Brl Brr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_4_4S = "L R C Ls Rs Tfl Tfr Trl Trr Bfl Bfr Brl Brr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString60_4_4S = "L R Ls Rs Sl Sr Tfl Tfr Trl Trr Bfl Bfr Brl Brr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_5_3S = "L R C Ls Rs Tfl Tfc Tfr Trl Trr Bfl Bfc Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString51_5_3S = "L R C LFE Ls Rs Tfl Tfc Tfr Trl Trr Bfl Bfc Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_2_2S = "L R C Ls Rs Tsl Tsr Bfl Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_3_2S = "L R C Ls Rs Tfl Tfc Tfr Bfl Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString50_4_2S = "L R C Ls Rs Tfl Tfr Trl Trr Bfl Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString70_4_2S = "L R C Ls Rs Sl Sr Tfl Tfr Trl Trr Bfl Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString222S = "L R C LFE Ls Rs Lc Rc Cs Sl Sr Tc Tfl Tfc Tfr Trl Trc Trr LFE2 Tsl Tsr Bfl Bfc Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kString220S = "L R C Ls Rs Lc Rc Cs Sl Sr Tc Tfl Tfc Tfr Trl Trc Trr Tsl Tsr Bfl Bfc Bfr"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi1stOrderS = "0 1 2 3"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi2cdOrderS = "0 1 2 3 4 5 6 7 8"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi3rdOrderS = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi4thOrderS = "0..24"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi5thOrderS = "0..35"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi6thOrderS = "0..48"; +static const Steinberg_Vst_CString Steinberg_Vst_SpeakerArr_kStringAmbi7thOrderS = "0..63"; +static const Steinberg_Vst_CString Steinberg_Vst_CurveType_kSegment = "segment"; +static const Steinberg_Vst_CString Steinberg_Vst_CurveType_kValueList = "valueList"; +static const Steinberg_Vst_CString Steinberg_Vst_Attributes_kStyle = "style"; +static const Steinberg_Vst_CString Steinberg_Vst_Attributes_kLEDStyle = "ledStyle"; +static const Steinberg_Vst_CString Steinberg_Vst_Attributes_kSwitchStyle = "switchStyle"; +static const Steinberg_Vst_CString Steinberg_Vst_Attributes_kKnobTurnsPerFullRange = "turnsPerFullRange"; +static const Steinberg_Vst_CString Steinberg_Vst_Attributes_kFunction = "function"; +static const Steinberg_Vst_CString Steinberg_Vst_Attributes_kFlags = "flags"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanPosCenterXFunc = "PanPosCenterX"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanPosCenterYFunc = "PanPosCenterY"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanPosFrontLeftXFunc = "PanPosFrontLeftX"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanPosFrontLeftYFunc = "PanPosFrontLeftY"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanPosFrontRightXFunc = "PanPosFrontRightX"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanPosFrontRightYFunc = "PanPosFrontRightY"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanRotationFunc = "PanRotation"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanLawFunc = "PanLaw"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanMirrorModeFunc = "PanMirrorMode"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kPanLfeGainFunc = "PanLfeGain"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kGainReductionFunc = "GainReduction"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kSoloFunc = "Solo"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kMuteFunc = "Mute"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFunction_kVolumeFunc = "Volume"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kInverseStyle = "inverse"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kLEDWrapLeftStyle = "wrapLeft"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kLEDWrapRightStyle = "wrapRight"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kLEDSpreadStyle = "spread"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kLEDBoostCutStyle = "boostCut"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kLEDSingleDotStyle = "singleDot"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kSwitchPushStyle = "push"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kSwitchPushIncLoopedStyle = "pushIncLooped"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kSwitchPushDecLoopedStyle = "pushDecLooped"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kSwitchPushIncStyle = "pushInc"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kSwitchPushDecStyle = "pushDec"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesStyle_kSwitchLatchStyle = "latch"; +static const Steinberg_Vst_CString Steinberg_Vst_AttributesFlags_kHideableFlag = "hideable"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelUIDKey = "channel uid"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelUIDLengthKey = "channel uid length"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelRuntimeIDKey = "channel runtime id"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelNameKey = "channel name"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelNameLengthKey = "channel name length"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelColorKey = "channel color"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelIndexKey = "channel index"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelIndexNamespaceOrderKey = "channel index namespace order"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelIndexNamespaceKey = "channel index namespace"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelIndexNamespaceLengthKey = "channel index namespace length"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelImageKey = "channel image"; +static const Steinberg_Vst_CString Steinberg_Vst_ChannelContext_kChannelPluginLocationKey = "channel plugin location"; +static const Steinberg_Vst_DataExchangeQueueID Steinberg_Vst_InvalidDataExchangeQueueID = INT32_MAX; +static const Steinberg_Vst_DataExchangeBlockID Steinberg_Vst_InvalidDataExchangeBlockID = INT32_MAX; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFx = "Fx"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxAnalyzer = "Fx|Analyzer"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxBass = "Fx|Bass"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxChannelStrip = "Fx|Channel Strip"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxDelay = "Fx|Delay"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxDistortion = "Fx|Distortion"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxDrums = "Fx|Drums"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxDynamics = "Fx|Dynamics"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxEQ = "Fx|EQ"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxFilter = "Fx|Filter"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxGenerator = "Fx|Generator"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxGuitar = "Fx|Guitar"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxInstrument = "Fx|Instrument"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxInstrumentExternal = "Fx|Instrument|External"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxMastering = "Fx|Mastering"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxMicrophone = "Fx|Microphone"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxModulation = "Fx|Modulation"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxNetwork = "Fx|Network"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxPitchShift = "Fx|Pitch Shift"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxRestoration = "Fx|Restoration"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxReverb = "Fx|Reverb"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxSpatial = "Fx|Spatial"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxSurround = "Fx|Surround"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxTools = "Fx|Tools"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kFxVocals = "Fx|Vocals"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kInstrument = "Instrument"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kInstrumentDrum = "Instrument|Drum"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kInstrumentExternal = "Instrument|External"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kInstrumentPiano = "Instrument|Piano"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kInstrumentSampler = "Instrument|Sampler"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kInstrumentSynth = "Instrument|Synth"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kInstrumentSynthSampler = "Instrument|Synth|Sampler"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kAmbisonics = "Ambisonics"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kAnalyzer = "Analyzer"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kNoOfflineProcess = "NoOfflineProcess"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kOnlyARA = "OnlyARA"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kOnlyOfflineProcess = "OnlyOfflineProcess"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kOnlyRealTime = "OnlyRT"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kSpatial = "Spatial"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kSpatialFx = "Spatial|Fx"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kUpDownMix = "Up-Downmix"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kMono = "Mono"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kStereo = "Stereo"; +static const Steinberg_Vst_CString Steinberg_Vst_PlugType_kSurround = "Surround"; +static const Steinberg_uint32 Steinberg_Vst_kNoTail = 0; +static const Steinberg_uint32 Steinberg_Vst_kInfiniteTail = UINT32_MAX; +static const Steinberg_Vst_UnitID Steinberg_Vst_kRootUnitId = 0; +static const Steinberg_Vst_UnitID Steinberg_Vst_kNoParentUnitId = -1; +static const Steinberg_Vst_ProgramListID Steinberg_Vst_kNoProgramListId = -1; +static const Steinberg_int32 Steinberg_Vst_kAllProgramInvalid = -1; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kCompGainReduction = "Comp:GainReduction"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kCompGainReductionMax = "Comp:GainReductionMax"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kCompGainReductionPeakHold = "Comp:GainReductionPeakHold"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kCompResetGainReductionMax = "Comp:ResetGainReductionMax"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kLowLatencyMode = "LowLatencyMode"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kDryWetMix = "DryWetMix"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kRandomize = "Randomize"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kRandomizeAroundCurrent = "RandomizeAroundCurrent"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kPanPosCenterX = "PanPosCenterX"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kPanPosCenterY = "PanPosCenterY"; +static const Steinberg_Vst_CString Steinberg_Vst_FunctionNameType_kPanPosCenterZ = "PanPosCenterZ"; + + +/*---------------------------------------------------------------------------------------------------------------------- +----- Structs ---------------------------------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/gui/iplugview.h", line 34 */ + +struct Steinberg_ViewRect +{ + Steinberg_int32 left; + Steinberg_int32 top; + Steinberg_int32 right; + Steinberg_int32 bottom; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 102 */ + +struct Steinberg_Vst_NoteExpressionValueDescription +{ + Steinberg_Vst_NoteExpressionValue defaultValue; + Steinberg_Vst_NoteExpressionValue minimum; + Steinberg_Vst_NoteExpressionValue maximum; + Steinberg_int32 stepCount; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 123 */ + +struct Steinberg_Vst_NoteExpressionValueEvent +{ + Steinberg_Vst_NoteExpressionTypeID typeId; + Steinberg_int32 noteId; + Steinberg_Vst_NoteExpressionValue value; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 137 */ + +struct Steinberg_Vst_NoteExpressionIntValueEvent +{ + Steinberg_Vst_NoteExpressionTypeID typeId; + Steinberg_int32 noteId; + Steinberg_uint64 value; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 151 */ + +struct Steinberg_Vst_NoteExpressionTextEvent +{ + Steinberg_Vst_NoteExpressionTypeID typeId; + Steinberg_int32 noteId; + Steinberg_uint32 textLen; + const Steinberg_Vst_TChar* text; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 171 */ + +struct Steinberg_Vst_NoteExpressionTypeInfo +{ + Steinberg_Vst_NoteExpressionTypeID typeId; + Steinberg_Vst_String128 title; + Steinberg_Vst_String128 shortTitle; + Steinberg_Vst_String128 units; + Steinberg_int32 unitId; + struct Steinberg_Vst_NoteExpressionValueDescription valueDesc; + Steinberg_Vst_ParamID associatedParameterId; + Steinberg_int32 flags; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 265 */ + +struct Steinberg_Vst_KeyswitchInfo +{ + Steinberg_Vst_KeyswitchTypeID typeId; + Steinberg_Vst_String128 title; + Steinberg_Vst_String128 shortTitle; + Steinberg_int32 keyswitchMin; + Steinberg_int32 keyswitchMax; + Steinberg_int32 keyRemapped; + Steinberg_int32 unitId; + Steinberg_int32 flags; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstphysicalui.h", line 60 */ + +struct Steinberg_Vst_PhysicalUIMap +{ + Steinberg_Vst_PhysicalUITypeID physicalUITypeID; + Steinberg_Vst_NoteExpressionTypeID noteExpressionTypeID; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstphysicalui.h", line 76 */ + +struct Steinberg_Vst_PhysicalUIMapList +{ + Steinberg_uint32 count; + struct Steinberg_Vst_PhysicalUIMap* map; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 62 */ + +struct Steinberg_PFactoryInfo +{ + Steinberg_char8 vendor[64]; + Steinberg_char8 url[256]; + Steinberg_char8 email[128]; + Steinberg_int32 flags; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 124 */ + +struct Steinberg_PClassInfo +{ + Steinberg_TUID cid; + Steinberg_int32 cardinality; + Steinberg_char8 category[32]; + Steinberg_char8 name[64]; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 222 */ + +struct Steinberg_PClassInfo2 +{ + Steinberg_TUID cid; + Steinberg_int32 cardinality; + Steinberg_char8 category[32]; + Steinberg_char8 name[64]; + Steinberg_uint32 classFlags; + Steinberg_char8 subCategories[128]; + Steinberg_char8 vendor[64]; + Steinberg_char8 version[64]; + Steinberg_char8 sdkVersion[64]; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 337 */ + +struct Steinberg_PClassInfoW +{ + Steinberg_TUID cid; + Steinberg_int32 cardinality; + Steinberg_char8 category[32]; + Steinberg_char16 name[64]; + Steinberg_uint32 classFlags; + Steinberg_char8 subCategories[128]; + Steinberg_char16 vendor[64]; + Steinberg_char16 version[64]; + Steinberg_char16 sdkVersion[64]; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcomponent.h", line 93 */ + +struct Steinberg_Vst_BusInfo +{ + Steinberg_Vst_MediaType mediaType; + Steinberg_Vst_BusDirection direction; + Steinberg_int32 channelCount; + Steinberg_Vst_String128 name; + Steinberg_Vst_BusType busType; + Steinberg_uint32 flags; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcomponent.h", line 136 */ + +struct Steinberg_Vst_RoutingInfo +{ + Steinberg_Vst_MediaType mediaType; + Steinberg_int32 busIndex; + Steinberg_int32 channel; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 46 */ + +struct Steinberg_Vst_ParameterInfo +{ + Steinberg_Vst_ParamID id; + Steinberg_Vst_String128 title; + Steinberg_Vst_String128 shortTitle; + Steinberg_Vst_String128 units; + Steinberg_int32 stepCount; + Steinberg_Vst_ParamValue defaultNormalizedValue; + Steinberg_Vst_UnitID unitId; + Steinberg_int32 flags; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstprocesscontext.h", line 44 */ + +struct Steinberg_Vst_FrameRate +{ + Steinberg_uint32 framesPerSecond; + Steinberg_uint32 flags; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstprocesscontext.h", line 64 */ + +struct Steinberg_Vst_Chord +{ + Steinberg_uint8 keyNote; + Steinberg_uint8 rootNote; + Steinberg_int16 chordMask; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstprocesscontext.h", line 96 */ + +struct Steinberg_Vst_ProcessContext +{ + Steinberg_uint32 state; + double sampleRate; + Steinberg_Vst_TSamples projectTimeSamples; + Steinberg_int64 systemTime; + Steinberg_Vst_TSamples continousTimeSamples; + Steinberg_Vst_TQuarterNotes projectTimeMusic; + Steinberg_Vst_TQuarterNotes barPositionMusic; + Steinberg_Vst_TQuarterNotes cycleStartMusic; + Steinberg_Vst_TQuarterNotes cycleEndMusic; + double tempo; + Steinberg_int32 timeSigNumerator; + Steinberg_int32 timeSigDenominator; + struct Steinberg_Vst_Chord chord; + Steinberg_int32 smpteOffsetSubframes; + struct Steinberg_Vst_FrameRate frameRate; + Steinberg_int32 samplesToNextClock; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 43 */ + +struct Steinberg_Vst_NoteOnEvent +{ + Steinberg_int16 channel; + Steinberg_int16 pitch; + float tuning; + float velocity; + Steinberg_int32 length; + Steinberg_int32 noteId; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 57 */ + +struct Steinberg_Vst_NoteOffEvent +{ + Steinberg_int16 channel; + Steinberg_int16 pitch; + float velocity; + Steinberg_int32 noteId; + float tuning; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 70 */ + +struct Steinberg_Vst_DataEvent +{ + Steinberg_uint32 size; + Steinberg_uint32 type; + const Steinberg_uint8* bytes; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 87 */ + +struct Steinberg_Vst_PolyPressureEvent +{ + Steinberg_int16 channel; + Steinberg_int16 pitch; + float pressure; + Steinberg_int32 noteId; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 99 */ + +struct Steinberg_Vst_ChordEvent +{ + Steinberg_int16 root; + Steinberg_int16 bassNote; + Steinberg_int16 mask; + Steinberg_uint16 textLen; + const Steinberg_Vst_TChar* text; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 113 */ + +struct Steinberg_Vst_ScaleEvent +{ + Steinberg_int16 root; + Steinberg_int16 mask; + Steinberg_uint16 textLen; + const Steinberg_Vst_TChar* text; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 129 */ + +struct Steinberg_Vst_LegacyMIDICCOutEvent +{ + Steinberg_uint8 controlNumber; + Steinberg_int8 channel; + Steinberg_int8 value; + Steinberg_int8 value2; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 142 */ + +struct Steinberg_Vst_Event +{ + Steinberg_int32 busIndex; + Steinberg_int32 sampleOffset; + Steinberg_Vst_TQuarterNotes ppqPosition; + Steinberg_uint16 flags; + Steinberg_uint16 type; + union + { + struct Steinberg_Vst_NoteOnEvent Steinberg_Vst_Event_noteOn; + struct Steinberg_Vst_NoteOffEvent Steinberg_Vst_Event_noteOff; + struct Steinberg_Vst_DataEvent Steinberg_Vst_Event_data; + struct Steinberg_Vst_PolyPressureEvent Steinberg_Vst_Event_polyPressure; + struct Steinberg_Vst_NoteExpressionValueEvent Steinberg_Vst_Event_noteExpressionValue; + struct Steinberg_Vst_NoteExpressionTextEvent Steinberg_Vst_Event_noteExpressionText; + struct Steinberg_Vst_NoteExpressionIntValueEvent Steinberg_Vst_Event_noteExpressionIntValue; + struct Steinberg_Vst_ChordEvent Steinberg_Vst_Event_chord; + struct Steinberg_Vst_ScaleEvent Steinberg_Vst_Event_scale; + struct Steinberg_Vst_LegacyMIDICCOutEvent Steinberg_Vst_Event_midiCCOut; + }; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstrepresentation.h", line 37 */ + +struct Steinberg_Vst_RepresentationInfo +{ + Steinberg_char8 vendor[64]; + Steinberg_char8 name[64]; + Steinberg_char8 version[64]; + Steinberg_char8 host[64]; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcontextmenu.h", line 168 */ + +struct Steinberg_Vst_IContextMenuItem +{ + Steinberg_Vst_String128 name; + Steinberg_int32 tag; + Steinberg_int32 flags; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstdataexchange.h", line 45 */ + +struct Steinberg_Vst_DataExchangeBlock +{ + void* data; + Steinberg_uint32 size; + Steinberg_Vst_DataExchangeBlockID blockID; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 174 */ + +struct Steinberg_Vst_ProcessSetup +{ + Steinberg_int32 processMode; + Steinberg_int32 symbolicSampleSize; + Steinberg_int32 maxSamplesPerBlock; + Steinberg_Vst_SampleRate sampleRate; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 202 */ + +struct Steinberg_Vst_AudioBusBuffers +{ + Steinberg_int32 numChannels; + Steinberg_uint64 silenceFlags; + union + { + Steinberg_Vst_Sample32** Steinberg_Vst_AudioBusBuffers_channelBuffers32; + Steinberg_Vst_Sample64** Steinberg_Vst_AudioBusBuffers_channelBuffers64; + }; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 224 */ + +struct Steinberg_Vst_ProcessData +{ + Steinberg_int32 processMode; + Steinberg_int32 symbolicSampleSize; + Steinberg_int32 numSamples; + Steinberg_int32 numInputs; + Steinberg_int32 numOutputs; + struct Steinberg_Vst_AudioBusBuffers* inputs; + struct Steinberg_Vst_AudioBusBuffers* outputs; + struct Steinberg_Vst_IParameterChanges* inputParameterChanges; + struct Steinberg_Vst_IParameterChanges* outputParameterChanges; + struct Steinberg_Vst_IEventList* inputEvents; + struct Steinberg_Vst_IEventList* outputEvents; + struct Steinberg_Vst_ProcessContext* processContext; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmidimapping2.h", line 41 */ + +struct Steinberg_Vst_Midi2Controller +{ + Steinberg_uint8 byte1; + Steinberg_uint8 byte2; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmidimapping2.h", line 81 */ + +struct Steinberg_Vst_Midi2ControllerParamIDAssignment +{ + Steinberg_Vst_ParamID pId; + Steinberg_Vst_BusIndex busIndex; + Steinberg_Vst_MidiChannel channel; + struct Steinberg_Vst_Midi2Controller controller; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmidimapping2.h", line 90 */ + +struct Steinberg_Vst_Midi2ControllerParamIDAssignmentList +{ + Steinberg_uint32 count; + struct Steinberg_Vst_Midi2ControllerParamIDAssignment* map; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmidimapping2.h", line 97 */ + +struct Steinberg_Vst_Midi1ControllerParamIDAssignment +{ + Steinberg_Vst_ParamID pId; + Steinberg_Vst_BusIndex busIndex; + Steinberg_Vst_MidiChannel channel; + Steinberg_Vst_CtrlNumber controller; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmidimapping2.h", line 106 */ + +struct Steinberg_Vst_Midi1ControllerParamIDAssignmentList +{ + Steinberg_uint32 count; + struct Steinberg_Vst_Midi1ControllerParamIDAssignment* map; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteonorchestralarticulationinfo.h", line 33 */ + +struct Steinberg_Vst_NoteOnOrchestralArticulation_Variations +{ + Steinberg_uint8 variation[16]; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteonorchestralarticulationinfo.h", line 43 */ + +struct Steinberg_Vst_NoteOnOrchestralArticulation_ClassificationVariations +{ + struct Steinberg_Vst_NoteOnOrchestralArticulation_Variations classification[17]; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsttransportcontrol.h", line 51 */ + +struct Steinberg_Vst_TransportPosition +{ + Steinberg_Vst_TransportPositionType type; + union + { + Steinberg_Vst_TSamples Steinberg_Vst_TransportPosition_samples; + Steinberg_Vst_TQuarterNotes Steinberg_Vst_TransportPosition_quarterNotes; + }; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstunits.h", line 44 */ + +struct Steinberg_Vst_UnitInfo +{ + Steinberg_Vst_UnitID id; + Steinberg_Vst_UnitID parentUnitId; + Steinberg_Vst_String128 name; + Steinberg_Vst_ProgramListID programListId; +}; + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstunits.h", line 56 */ + +struct Steinberg_Vst_ProgramListInfo +{ + Steinberg_Vst_ProgramListID id; + Steinberg_Vst_String128 name; + Steinberg_int32 programCount; +}; + + +/*---------------------------------------------------------------------------------------------------------------------- +----- Interfaces ------------------------------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/funknown.h", line 374 */ + +typedef struct Steinberg_FUnknownVtbl +{ + /* methods defined in "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + +} Steinberg_FUnknownVtbl; + +typedef struct Steinberg_FUnknown +{ + struct Steinberg_FUnknownVtbl* lpVtbl; +} Steinberg_FUnknown; + +static const Steinberg_TUID Steinberg_FUnknown_iid = SMTG_INLINE_UID (0x00000000, 0x00000000, 0xC0000000, 0x00000046); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/gui/iplugviewcontentscalesupport.h", line 57 */ + +typedef struct Steinberg_IPlugViewContentScaleSupportVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_IPlugViewContentScaleSupport": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setContentScaleFactor) (void* thisInterface, Steinberg_IPlugViewContentScaleSupport_ScaleFactor factor); + +} Steinberg_IPlugViewContentScaleSupportVtbl; + +typedef struct Steinberg_IPlugViewContentScaleSupport +{ + struct Steinberg_IPlugViewContentScaleSupportVtbl* lpVtbl; +} Steinberg_IPlugViewContentScaleSupport; + +static const Steinberg_TUID Steinberg_IPlugViewContentScaleSupport_iid = SMTG_INLINE_UID (0x65ED9690, 0x8AC44525, 0x8AADEF7A, 0x72EA703F); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/gui/iplugview.h", line 134 */ + +typedef struct Steinberg_IPlugViewVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_IPlugView": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* isPlatformTypeSupported) (void* thisInterface, Steinberg_FIDString type); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* attached) (void* thisInterface, void* parent, Steinberg_FIDString type); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* removed) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onWheel) (void* thisInterface, float distance); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onKeyDown) (void* thisInterface, Steinberg_char16 key, Steinberg_int16 keyCode, Steinberg_int16 modifiers); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onKeyUp) (void* thisInterface, Steinberg_char16 key, Steinberg_int16 keyCode, Steinberg_int16 modifiers); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getSize) (void* thisInterface, struct Steinberg_ViewRect* size); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onSize) (void* thisInterface, struct Steinberg_ViewRect* newSize); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onFocus) (void* thisInterface, Steinberg_TBool state); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setFrame) (void* thisInterface, struct Steinberg_IPlugFrame* frame); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* canResize) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* checkSizeConstraint) (void* thisInterface, struct Steinberg_ViewRect* rect); + +} Steinberg_IPlugViewVtbl; + +typedef struct Steinberg_IPlugView +{ + struct Steinberg_IPlugViewVtbl* lpVtbl; +} Steinberg_IPlugView; + +static const Steinberg_TUID Steinberg_IPlugView_iid = SMTG_INLINE_UID (0x5BC32507, 0xD06049EA, 0xA6151B52, 0x2B755B29); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/gui/iplugview.h", line 208 */ + +typedef struct Steinberg_IPlugFrameVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_IPlugFrame": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* resizeView) (void* thisInterface, struct Steinberg_IPlugView* view, struct Steinberg_ViewRect* newSize); + +} Steinberg_IPlugFrameVtbl; + +typedef struct Steinberg_IPlugFrame +{ + struct Steinberg_IPlugFrameVtbl* lpVtbl; +} Steinberg_IPlugFrame; + +static const Steinberg_TUID Steinberg_IPlugFrame_iid = SMTG_INLINE_UID (0x367FAF01, 0xAFA94693, 0x8D4DA2A0, 0xED0882A3); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/gui/iplugview.h", line 234 */ + +typedef struct Steinberg_Linux_IEventHandlerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Linux_IEventHandler": */ + void (SMTG_STDMETHODCALLTYPE* onFDIsSet) (void* thisInterface, Steinberg_Linux_FileDescriptor fd); + +} Steinberg_Linux_IEventHandlerVtbl; + +typedef struct Steinberg_Linux_IEventHandler +{ + struct Steinberg_Linux_IEventHandlerVtbl* lpVtbl; +} Steinberg_Linux_IEventHandler; + +static const Steinberg_TUID Steinberg_Linux_IEventHandler_iid = SMTG_INLINE_UID (0x561E65C9, 0x13A0496F, 0x813A2C35, 0x654D7983); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/gui/iplugview.h", line 250 */ + +typedef struct Steinberg_Linux_ITimerHandlerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Linux_ITimerHandler": */ + void (SMTG_STDMETHODCALLTYPE* onTimer) (void* thisInterface); + +} Steinberg_Linux_ITimerHandlerVtbl; + +typedef struct Steinberg_Linux_ITimerHandler +{ + struct Steinberg_Linux_ITimerHandlerVtbl* lpVtbl; +} Steinberg_Linux_ITimerHandler; + +static const Steinberg_TUID Steinberg_Linux_ITimerHandler_iid = SMTG_INLINE_UID (0x10BDD94F, 0x41424774, 0x821FAD8F, 0xECA72CA9); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/gui/iplugview.h", line 278 */ + +typedef struct Steinberg_Linux_IRunLoopVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Linux_IRunLoop": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* registerEventHandler) (void* thisInterface, struct Steinberg_Linux_IEventHandler* handler, Steinberg_Linux_FileDescriptor fd); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* unregisterEventHandler) (void* thisInterface, struct Steinberg_Linux_IEventHandler* handler); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* registerTimer) (void* thisInterface, struct Steinberg_Linux_ITimerHandler* handler, Steinberg_Linux_TimerInterval milliseconds); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* unregisterTimer) (void* thisInterface, struct Steinberg_Linux_ITimerHandler* handler); + +} Steinberg_Linux_IRunLoopVtbl; + +typedef struct Steinberg_Linux_IRunLoop +{ + struct Steinberg_Linux_IRunLoopVtbl* lpVtbl; +} Steinberg_Linux_IRunLoop; + +static const Steinberg_TUID Steinberg_Linux_IRunLoop_iid = SMTG_INLINE_UID (0x18C35366, 0x97764F1A, 0x9C5B8385, 0x7A871389); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ibstream.h", line 29 */ + +typedef struct Steinberg_IBStreamVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_IBStream": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* read) (void* thisInterface, void* buffer, Steinberg_int32 numBytes, Steinberg_int32* numBytesRead); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* write) (void* thisInterface, void* buffer, Steinberg_int32 numBytes, Steinberg_int32* numBytesWritten); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* seek) (void* thisInterface, Steinberg_int64 pos, Steinberg_int32 mode, Steinberg_int64* result); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* tell) (void* thisInterface, Steinberg_int64* pos); + +} Steinberg_IBStreamVtbl; + +typedef struct Steinberg_IBStream +{ + struct Steinberg_IBStreamVtbl* lpVtbl; +} Steinberg_IBStream; + +static const Steinberg_TUID Steinberg_IBStream_iid = SMTG_INLINE_UID (0xC3BF6EA2, 0x30994752, 0x9B6BF990, 0x1EE33E9B); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ibstream.h", line 72 */ + +typedef struct Steinberg_ISizeableStreamVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_ISizeableStream": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getStreamSize) (void* thisInterface, Steinberg_int64* size); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setStreamSize) (void* thisInterface, Steinberg_int64 size); + +} Steinberg_ISizeableStreamVtbl; + +typedef struct Steinberg_ISizeableStream +{ + struct Steinberg_ISizeableStreamVtbl* lpVtbl; +} Steinberg_ISizeableStream; + +static const Steinberg_TUID Steinberg_ISizeableStream_iid = SMTG_INLINE_UID (0x04F9549E, 0xE02F4E6E, 0x87E86A87, 0x47F4E17F); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 212 */ + +typedef struct Steinberg_Vst_INoteExpressionControllerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_INoteExpressionController": */ + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getNoteExpressionCount) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getNoteExpressionInfo) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel, Steinberg_int32 noteExpressionIndex, struct Steinberg_Vst_NoteExpressionTypeInfo* info); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getNoteExpressionStringByValue) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel, Steinberg_Vst_NoteExpressionTypeID id, Steinberg_Vst_NoteExpressionValue valueNormalized, Steinberg_Vst_String128 string); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getNoteExpressionValueByString) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel, Steinberg_Vst_NoteExpressionTypeID id, const Steinberg_Vst_TChar* string, Steinberg_Vst_NoteExpressionValue* valueNormalized); + +} Steinberg_Vst_INoteExpressionControllerVtbl; + +typedef struct Steinberg_Vst_INoteExpressionController +{ + struct Steinberg_Vst_INoteExpressionControllerVtbl* lpVtbl; +} Steinberg_Vst_INoteExpressionController; + +static const Steinberg_TUID Steinberg_Vst_INoteExpressionController_iid = SMTG_INLINE_UID (0xB7F8F859, 0x41234872, 0x91169581, 0x4F3721A3); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteexpression.h", line 294 */ + +typedef struct Steinberg_Vst_IKeyswitchControllerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IKeyswitchController": */ + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getKeyswitchCount) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getKeyswitchInfo) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel, Steinberg_int32 keySwitchIndex, struct Steinberg_Vst_KeyswitchInfo* info); + +} Steinberg_Vst_IKeyswitchControllerVtbl; + +typedef struct Steinberg_Vst_IKeyswitchController +{ + struct Steinberg_Vst_IKeyswitchControllerVtbl* lpVtbl; +} Steinberg_Vst_IKeyswitchController; + +static const Steinberg_TUID Steinberg_Vst_IKeyswitchController_iid = SMTG_INLINE_UID (0x1F2F76D3, 0xBFFB4B96, 0xB99527A5, 0x5EBCCEF4); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstphysicalui.h", line 148 */ + +typedef struct Steinberg_Vst_INoteExpressionPhysicalUIMappingVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_INoteExpressionPhysicalUIMapping": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getPhysicalUIMapping) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel, struct Steinberg_Vst_PhysicalUIMapList* list); + +} Steinberg_Vst_INoteExpressionPhysicalUIMappingVtbl; + +typedef struct Steinberg_Vst_INoteExpressionPhysicalUIMapping +{ + struct Steinberg_Vst_INoteExpressionPhysicalUIMappingVtbl* lpVtbl; +} Steinberg_Vst_INoteExpressionPhysicalUIMapping; + +static const Steinberg_TUID Steinberg_Vst_INoteExpressionPhysicalUIMapping_iid = SMTG_INLINE_UID (0xB03078FF, 0x94D24AC8, 0x90CCD303, 0xD4133324); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 36 */ + +typedef struct Steinberg_IPluginBaseVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_IPluginBase": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* initialize) (void* thisInterface, struct Steinberg_FUnknown* context); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* terminate) (void* thisInterface); + +} Steinberg_IPluginBaseVtbl; + +typedef struct Steinberg_IPluginBase +{ + struct Steinberg_IPluginBaseVtbl* lpVtbl; +} Steinberg_IPluginBase; + +static const Steinberg_TUID Steinberg_IPluginBase_iid = SMTG_INLINE_UID (0x22888DDB, 0x156E45AE, 0x8358B348, 0x08190625); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 192 */ + +typedef struct Steinberg_IPluginFactoryVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_IPluginFactory": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getFactoryInfo) (void* thisInterface, struct Steinberg_PFactoryInfo* info); + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* countClasses) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getClassInfo) (void* thisInterface, Steinberg_int32 index, struct Steinberg_PClassInfo* info); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* createInstance) (void* thisInterface, Steinberg_FIDString cid, Steinberg_FIDString iid, void** obj); + +} Steinberg_IPluginFactoryVtbl; + +typedef struct Steinberg_IPluginFactory +{ + struct Steinberg_IPluginFactoryVtbl* lpVtbl; +} Steinberg_IPluginFactory; + +static const Steinberg_TUID Steinberg_IPluginFactory_iid = SMTG_INLINE_UID (0x7A4D811C, 0x52114A1F, 0xAED9D2EE, 0x0B43BF9F); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 321 */ + +typedef struct Steinberg_IPluginFactory2Vtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods derived from "Steinberg_IPluginFactory": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getFactoryInfo) (void* thisInterface, struct Steinberg_PFactoryInfo* info); + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* countClasses) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getClassInfo) (void* thisInterface, Steinberg_int32 index, struct Steinberg_PClassInfo* info); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* createInstance) (void* thisInterface, Steinberg_FIDString cid, Steinberg_FIDString iid, void** obj); + + /* methods defined in "Steinberg_IPluginFactory2": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getClassInfo2) (void* thisInterface, Steinberg_int32 index, struct Steinberg_PClassInfo2* info); + +} Steinberg_IPluginFactory2Vtbl; + +typedef struct Steinberg_IPluginFactory2 +{ + struct Steinberg_IPluginFactory2Vtbl* lpVtbl; +} Steinberg_IPluginFactory2; + +static const Steinberg_TUID Steinberg_IPluginFactory2_iid = SMTG_INLINE_UID (0x0007B650, 0xF24B4C0B, 0xA464EDB9, 0xF00B2ABB); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/base/ipluginbase.h", line 447 */ + +typedef struct Steinberg_IPluginFactory3Vtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods derived from "Steinberg_IPluginFactory": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getFactoryInfo) (void* thisInterface, struct Steinberg_PFactoryInfo* info); + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* countClasses) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getClassInfo) (void* thisInterface, Steinberg_int32 index, struct Steinberg_PClassInfo* info); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* createInstance) (void* thisInterface, Steinberg_FIDString cid, Steinberg_FIDString iid, void** obj); + + /* methods derived from "Steinberg_IPluginFactory2": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getClassInfo2) (void* thisInterface, Steinberg_int32 index, struct Steinberg_PClassInfo2* info); + + /* methods defined in "Steinberg_IPluginFactory3": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getClassInfoUnicode) (void* thisInterface, Steinberg_int32 index, struct Steinberg_PClassInfoW* info); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setHostContext) (void* thisInterface, struct Steinberg_FUnknown* context); + +} Steinberg_IPluginFactory3Vtbl; + +typedef struct Steinberg_IPluginFactory3 +{ + struct Steinberg_IPluginFactory3Vtbl* lpVtbl; +} Steinberg_IPluginFactory3; + +static const Steinberg_TUID Steinberg_IPluginFactory3_iid = SMTG_INLINE_UID (0x4555A2AB, 0xC1234E57, 0x9B122910, 0x36878931); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcomponent.h", line 158 */ + +typedef struct Steinberg_Vst_IComponentVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods derived from "Steinberg_IPluginBase": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* initialize) (void* thisInterface, struct Steinberg_FUnknown* context); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* terminate) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IComponent": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getControllerClassId) (void* thisInterface, Steinberg_TUID classId); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setIoMode) (void* thisInterface, Steinberg_Vst_IoMode mode); + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getBusCount) (void* thisInterface, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getBusInfo) (void* thisInterface, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, struct Steinberg_Vst_BusInfo* bus); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getRoutingInfo) (void* thisInterface, struct Steinberg_Vst_RoutingInfo* inInfo, struct Steinberg_Vst_RoutingInfo* outInfo); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* activateBus) (void* thisInterface, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, Steinberg_TBool state); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setActive) (void* thisInterface, Steinberg_TBool state); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setState) (void* thisInterface, struct Steinberg_IBStream* state); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getState) (void* thisInterface, struct Steinberg_IBStream* state); + +} Steinberg_Vst_IComponentVtbl; + +typedef struct Steinberg_Vst_IComponent +{ + struct Steinberg_Vst_IComponentVtbl* lpVtbl; +} Steinberg_Vst_IComponent; + +static const Steinberg_TUID Steinberg_Vst_IComponent_iid = SMTG_INLINE_UID (0xE831FF31, 0xF2D54301, 0x928EBBEE, 0x25697802); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstattributes.h", line 40 */ + +typedef struct Steinberg_Vst_IAttributeListVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IAttributeList": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setInt) (void* thisInterface, Steinberg_Vst_IAttributeList_AttrID id, Steinberg_int64 value); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getInt) (void* thisInterface, Steinberg_Vst_IAttributeList_AttrID id, Steinberg_int64* value); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setFloat) (void* thisInterface, Steinberg_Vst_IAttributeList_AttrID id, double value); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getFloat) (void* thisInterface, Steinberg_Vst_IAttributeList_AttrID id, double* value); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setString) (void* thisInterface, Steinberg_Vst_IAttributeList_AttrID id, const Steinberg_Vst_TChar* string); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getString) (void* thisInterface, Steinberg_Vst_IAttributeList_AttrID id, Steinberg_Vst_TChar* string, Steinberg_uint32 sizeInBytes); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setBinary) (void* thisInterface, Steinberg_Vst_IAttributeList_AttrID id, const void* data, Steinberg_uint32 sizeInBytes); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getBinary) (void* thisInterface, Steinberg_Vst_IAttributeList_AttrID id, const void** data, Steinberg_uint32* sizeInBytes); + +} Steinberg_Vst_IAttributeListVtbl; + +typedef struct Steinberg_Vst_IAttributeList +{ + struct Steinberg_Vst_IAttributeListVtbl* lpVtbl; +} Steinberg_Vst_IAttributeList; + +static const Steinberg_TUID Steinberg_Vst_IAttributeList_iid = SMTG_INLINE_UID (0x1E5F0AEB, 0xCC7F4533, 0xA2544011, 0x38AD5EE4); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstattributes.h", line 135 */ + +typedef struct Steinberg_Vst_IStreamAttributesVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IStreamAttributes": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getFileName) (void* thisInterface, Steinberg_Vst_String128 name); + struct Steinberg_Vst_IAttributeList* (SMTG_STDMETHODCALLTYPE* getAttributes) (void* thisInterface); + +} Steinberg_Vst_IStreamAttributesVtbl; + +typedef struct Steinberg_Vst_IStreamAttributes +{ + struct Steinberg_Vst_IStreamAttributesVtbl* lpVtbl; +} Steinberg_Vst_IStreamAttributes; + +static const Steinberg_TUID Steinberg_Vst_IStreamAttributes_iid = SMTG_INLINE_UID (0xD6CE2FFC, 0xEFAF4B8C, 0x9E74F1BB, 0x12DA44B4); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstremapparamid.h", line 46 */ + +typedef struct Steinberg_Vst_IRemapParamIDVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IRemapParamID": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getCompatibleParamID) (void* thisInterface, const Steinberg_TUID pluginToReplaceUID, Steinberg_Vst_ParamID oldParamID, Steinberg_Vst_ParamID* newParamID); + +} Steinberg_Vst_IRemapParamIDVtbl; + +typedef struct Steinberg_Vst_IRemapParamID +{ + struct Steinberg_Vst_IRemapParamIDVtbl* lpVtbl; +} Steinberg_Vst_IRemapParamID; + +static const Steinberg_TUID Steinberg_Vst_IRemapParamID_iid = SMTG_INLINE_UID (0x2B88021E, 0x6286B646, 0xB49DF76A, 0x5663061C); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 217 */ + +typedef struct Steinberg_Vst_IComponentHandlerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IComponentHandler": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* beginEdit) (void* thisInterface, Steinberg_Vst_ParamID id); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* performEdit) (void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue valueNormalized); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* endEdit) (void* thisInterface, Steinberg_Vst_ParamID id); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* restartComponent) (void* thisInterface, Steinberg_int32 flags); + +} Steinberg_Vst_IComponentHandlerVtbl; + +typedef struct Steinberg_Vst_IComponentHandler +{ + struct Steinberg_Vst_IComponentHandlerVtbl* lpVtbl; +} Steinberg_Vst_IComponentHandler; + +static const Steinberg_TUID Steinberg_Vst_IComponentHandler_iid = SMTG_INLINE_UID (0x93A0BEA3, 0x0BD045DB, 0x8E890B0C, 0xC1E46AC6); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 307 */ + +typedef struct Steinberg_Vst_IComponentHandler2Vtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IComponentHandler2": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setDirty) (void* thisInterface, Steinberg_TBool state); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* requestOpenEditor) (void* thisInterface, Steinberg_FIDString name); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* startGroupEdit) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* finishGroupEdit) (void* thisInterface); + +} Steinberg_Vst_IComponentHandler2Vtbl; + +typedef struct Steinberg_Vst_IComponentHandler2 +{ + struct Steinberg_Vst_IComponentHandler2Vtbl* lpVtbl; +} Steinberg_Vst_IComponentHandler2; + +static const Steinberg_TUID Steinberg_Vst_IComponentHandler2_iid = SMTG_INLINE_UID (0xF040B4B3, 0xA36045EC, 0xABCDC045, 0xB4D5A2CC); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 365 */ + +typedef struct Steinberg_Vst_IComponentHandlerBusActivationVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IComponentHandlerBusActivation": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* requestBusActivation) (void* thisInterface, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, Steinberg_TBool state); + +} Steinberg_Vst_IComponentHandlerBusActivationVtbl; + +typedef struct Steinberg_Vst_IComponentHandlerBusActivation +{ + struct Steinberg_Vst_IComponentHandlerBusActivationVtbl* lpVtbl; +} Steinberg_Vst_IComponentHandlerBusActivation; + +static const Steinberg_TUID Steinberg_Vst_IComponentHandlerBusActivation_iid = SMTG_INLINE_UID (0x067D02C1, 0x5B4E274D, 0xA92D90FD, 0x6EAF7240); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 422 */ + +typedef struct Steinberg_Vst_IProgressVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IProgress": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* start) (void* thisInterface, Steinberg_Vst_IProgress_ProgressType type, const Steinberg_tchar* optionalDescription, Steinberg_Vst_IProgress_ID* outID); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* update) (void* thisInterface, Steinberg_Vst_IProgress_ID id, Steinberg_Vst_ParamValue normValue); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* finish) (void* thisInterface, Steinberg_Vst_IProgress_ID id); + +} Steinberg_Vst_IProgressVtbl; + +typedef struct Steinberg_Vst_IProgress +{ + struct Steinberg_Vst_IProgressVtbl* lpVtbl; +} Steinberg_Vst_IProgress; + +static const Steinberg_TUID Steinberg_Vst_IProgress_iid = SMTG_INLINE_UID (0x00C9DC5B, 0x9D904254, 0x91A388C8, 0xB4E91B69); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 468 */ + +typedef struct Steinberg_Vst_IEditControllerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods derived from "Steinberg_IPluginBase": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* initialize) (void* thisInterface, struct Steinberg_FUnknown* context); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* terminate) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IEditController": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setComponentState) (void* thisInterface, struct Steinberg_IBStream* state); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setState) (void* thisInterface, struct Steinberg_IBStream* state); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getState) (void* thisInterface, struct Steinberg_IBStream* state); + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getParameterCount) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getParameterInfo) (void* thisInterface, Steinberg_int32 paramIndex, struct Steinberg_Vst_ParameterInfo* info); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getParamStringByValue) (void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue valueNormalized, Steinberg_Vst_String128 string); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getParamValueByString) (void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_TChar* string, Steinberg_Vst_ParamValue* valueNormalized); + Steinberg_Vst_ParamValue (SMTG_STDMETHODCALLTYPE* normalizedParamToPlain) (void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue valueNormalized); + Steinberg_Vst_ParamValue (SMTG_STDMETHODCALLTYPE* plainParamToNormalized) (void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue plainValue); + Steinberg_Vst_ParamValue (SMTG_STDMETHODCALLTYPE* getParamNormalized) (void* thisInterface, Steinberg_Vst_ParamID id); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setParamNormalized) (void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue value); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setComponentHandler) (void* thisInterface, struct Steinberg_Vst_IComponentHandler* handler); + struct Steinberg_IPlugView* (SMTG_STDMETHODCALLTYPE* createView) (void* thisInterface, Steinberg_FIDString name); + +} Steinberg_Vst_IEditControllerVtbl; + +typedef struct Steinberg_Vst_IEditController +{ + struct Steinberg_Vst_IEditControllerVtbl* lpVtbl; +} Steinberg_Vst_IEditController; + +static const Steinberg_TUID Steinberg_Vst_IEditController_iid = SMTG_INLINE_UID (0xDCD7BBE3, 0x7742448D, 0xA874AACC, 0x979C759E); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 575 */ + +typedef struct Steinberg_Vst_IEditController2Vtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IEditController2": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setKnobMode) (void* thisInterface, Steinberg_Vst_KnobMode mode); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* openHelp) (void* thisInterface, Steinberg_TBool onlyCheck); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* openAboutBox) (void* thisInterface, Steinberg_TBool onlyCheck); + +} Steinberg_Vst_IEditController2Vtbl; + +typedef struct Steinberg_Vst_IEditController2 +{ + struct Steinberg_Vst_IEditController2Vtbl* lpVtbl; +} Steinberg_Vst_IEditController2; + +static const Steinberg_TUID Steinberg_Vst_IEditController2_iid = SMTG_INLINE_UID (0x7F4EFE59, 0xF3204967, 0xAC27A3AE, 0xAFB63038); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 659 */ + +typedef struct Steinberg_Vst_IMidiMappingVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IMidiMapping": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getMidiControllerAssignment) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel, Steinberg_Vst_CtrlNumber midiControllerNumber, Steinberg_Vst_ParamID* id); + +} Steinberg_Vst_IMidiMappingVtbl; + +typedef struct Steinberg_Vst_IMidiMapping +{ + struct Steinberg_Vst_IMidiMappingVtbl* lpVtbl; +} Steinberg_Vst_IMidiMapping; + +static const Steinberg_TUID Steinberg_Vst_IMidiMapping_iid = SMTG_INLINE_UID (0xDF0FF9F7, 0x49B74669, 0xB63AB732, 0x7ADBF5E5); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 708 */ + +typedef struct Steinberg_Vst_IEditControllerHostEditingVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IEditControllerHostEditing": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* beginEditFromHost) (void* thisInterface, Steinberg_Vst_ParamID paramID); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* endEditFromHost) (void* thisInterface, Steinberg_Vst_ParamID paramID); + +} Steinberg_Vst_IEditControllerHostEditingVtbl; + +typedef struct Steinberg_Vst_IEditControllerHostEditing +{ + struct Steinberg_Vst_IEditControllerHostEditingVtbl* lpVtbl; +} Steinberg_Vst_IEditControllerHostEditing; + +static const Steinberg_TUID Steinberg_Vst_IEditControllerHostEditing_iid = SMTG_INLINE_UID (0xC1271208, 0x70594098, 0xB9DD34B3, 0x6BB0195E); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsteditcontroller.h", line 735 */ + +typedef struct Steinberg_Vst_IComponentHandlerSystemTimeVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IComponentHandlerSystemTime": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getSystemTime) (void* thisInterface, Steinberg_int64* systemTime); + +} Steinberg_Vst_IComponentHandlerSystemTimeVtbl; + +typedef struct Steinberg_Vst_IComponentHandlerSystemTime +{ + struct Steinberg_Vst_IComponentHandlerSystemTimeVtbl* lpVtbl; +} Steinberg_Vst_IComponentHandlerSystemTime; + +static const Steinberg_TUID Steinberg_Vst_IComponentHandlerSystemTime_iid = SMTG_INLINE_UID (0xF9E53056, 0xD1554CD5, 0xB7695E1B, 0x7B0F7745); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstevents.h", line 198 */ + +typedef struct Steinberg_Vst_IEventListVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IEventList": */ + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getEventCount) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getEvent) (void* thisInterface, Steinberg_int32 index, struct Steinberg_Vst_Event* e); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* addEvent) (void* thisInterface, struct Steinberg_Vst_Event* e); + +} Steinberg_Vst_IEventListVtbl; + +typedef struct Steinberg_Vst_IEventList +{ + struct Steinberg_Vst_IEventListVtbl* lpVtbl; +} Steinberg_Vst_IEventList; + +static const Steinberg_TUID Steinberg_Vst_IEventList_iid = SMTG_INLINE_UID (0x3A2C4214, 0x346349FE, 0xB2C4F397, 0xB9695A44); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmessage.h", line 40 */ + +typedef struct Steinberg_Vst_IMessageVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IMessage": */ + Steinberg_FIDString (SMTG_STDMETHODCALLTYPE* getMessageID) (void* thisInterface); + void (SMTG_STDMETHODCALLTYPE* setMessageID) (void* thisInterface, Steinberg_FIDString id); + struct Steinberg_Vst_IAttributeList* (SMTG_STDMETHODCALLTYPE* getAttributes) (void* thisInterface); + +} Steinberg_Vst_IMessageVtbl; + +typedef struct Steinberg_Vst_IMessage +{ + struct Steinberg_Vst_IMessageVtbl* lpVtbl; +} Steinberg_Vst_IMessage; + +static const Steinberg_TUID Steinberg_Vst_IMessage_iid = SMTG_INLINE_UID (0x936F033B, 0xC6C047DB, 0xBB0882F8, 0x13C1E613); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmessage.h", line 73 */ + +typedef struct Steinberg_Vst_IConnectionPointVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IConnectionPoint": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* connect) (void* thisInterface, struct Steinberg_Vst_IConnectionPoint* other); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* disconnect) (void* thisInterface, struct Steinberg_Vst_IConnectionPoint* other); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* notify) (void* thisInterface, struct Steinberg_Vst_IMessage* message); + +} Steinberg_Vst_IConnectionPointVtbl; + +typedef struct Steinberg_Vst_IConnectionPoint +{ + struct Steinberg_Vst_IConnectionPointVtbl* lpVtbl; +} Steinberg_Vst_IConnectionPoint; + +static const Steinberg_TUID Steinberg_Vst_IConnectionPoint_iid = SMTG_INLINE_UID (0x70A4156F, 0x6E6E4026, 0x989148BF, 0xAA60D8D1); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstrepresentation.h", line 180 */ + +typedef struct Steinberg_Vst_IXmlRepresentationControllerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IXmlRepresentationController": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getXmlRepresentationStream) (void* thisInterface, struct Steinberg_Vst_RepresentationInfo* info, struct Steinberg_IBStream* stream); + +} Steinberg_Vst_IXmlRepresentationControllerVtbl; + +typedef struct Steinberg_Vst_IXmlRepresentationController +{ + struct Steinberg_Vst_IXmlRepresentationControllerVtbl* lpVtbl; +} Steinberg_Vst_IXmlRepresentationController; + +static const Steinberg_TUID Steinberg_Vst_IXmlRepresentationController_iid = SMTG_INLINE_UID (0xA81A0471, 0x48C34DC4, 0xAC30C9E1, 0x3C8393D5); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcontextmenu.h", line 124 */ + +typedef struct Steinberg_Vst_IComponentHandler3Vtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IComponentHandler3": */ + struct Steinberg_Vst_IContextMenu* (SMTG_STDMETHODCALLTYPE* createContextMenu) (void* thisInterface, struct Steinberg_IPlugView* plugView, const Steinberg_Vst_ParamID* paramID); + +} Steinberg_Vst_IComponentHandler3Vtbl; + +typedef struct Steinberg_Vst_IComponentHandler3 +{ + struct Steinberg_Vst_IComponentHandler3Vtbl* lpVtbl; +} Steinberg_Vst_IComponentHandler3; + +static const Steinberg_TUID Steinberg_Vst_IComponentHandler3_iid = SMTG_INLINE_UID (0x69F11617, 0xD26B400D, 0xA4B6B964, 0x7B6EBBAB); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcontextmenu.h", line 154 */ + +typedef struct Steinberg_Vst_IContextMenuTargetVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IContextMenuTarget": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* executeMenuItem) (void* thisInterface, Steinberg_int32 tag); + +} Steinberg_Vst_IContextMenuTargetVtbl; + +typedef struct Steinberg_Vst_IContextMenuTarget +{ + struct Steinberg_Vst_IContextMenuTargetVtbl* lpVtbl; +} Steinberg_Vst_IContextMenuTarget; + +static const Steinberg_TUID Steinberg_Vst_IContextMenuTarget_iid = SMTG_INLINE_UID (0x3CDF2E75, 0x85D34144, 0xBF86D36B, 0xD7C4894D); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstcontextmenu.h", line 196 */ + +typedef struct Steinberg_Vst_IContextMenuVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IContextMenu": */ + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getItemCount) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getItem) (void* thisInterface, Steinberg_int32 index, Steinberg_Vst_IContextMenu_Item* item, struct Steinberg_Vst_IContextMenuTarget** target); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* addItem) (void* thisInterface, const Steinberg_Vst_IContextMenu_Item* item, struct Steinberg_Vst_IContextMenuTarget* target); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* removeItem) (void* thisInterface, const Steinberg_Vst_IContextMenu_Item* item, struct Steinberg_Vst_IContextMenuTarget* target); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* popup) (void* thisInterface, Steinberg_UCoord x, Steinberg_UCoord y); + +} Steinberg_Vst_IContextMenuVtbl; + +typedef struct Steinberg_Vst_IContextMenu +{ + struct Steinberg_Vst_IContextMenuVtbl* lpVtbl; +} Steinberg_Vst_IContextMenu; + +static const Steinberg_TUID Steinberg_Vst_IContextMenu_iid = SMTG_INLINE_UID (0x2E93C863, 0x0C9C4588, 0x97DBECF5, 0xAD17817D); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmidilearn.h", line 90 */ + +typedef struct Steinberg_Vst_IMidiLearnVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IMidiLearn": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onLiveMIDIControllerInput) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel, Steinberg_Vst_CtrlNumber midiCC); + +} Steinberg_Vst_IMidiLearnVtbl; + +typedef struct Steinberg_Vst_IMidiLearn +{ + struct Steinberg_Vst_IMidiLearnVtbl* lpVtbl; +} Steinberg_Vst_IMidiLearn; + +static const Steinberg_TUID Steinberg_Vst_IMidiLearn_iid = SMTG_INLINE_UID (0x6B2449CC, 0x419740B5, 0xAB3C79DA, 0xC5FE5C86); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstchannelcontextinfo.h", line 155 */ + +typedef struct Steinberg_Vst_ChannelContext_IInfoListenerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_ChannelContext_IInfoListener": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setChannelContextInfos) (void* thisInterface, struct Steinberg_Vst_IAttributeList* list); + +} Steinberg_Vst_ChannelContext_IInfoListenerVtbl; + +typedef struct Steinberg_Vst_ChannelContext_IInfoListener +{ + struct Steinberg_Vst_ChannelContext_IInfoListenerVtbl* lpVtbl; +} Steinberg_Vst_ChannelContext_IInfoListener; + +static const Steinberg_TUID Steinberg_Vst_ChannelContext_IInfoListener_iid = SMTG_INLINE_UID (0x0F194781, 0x8D984ADA, 0xBBA0C1EF, 0xC011D8D0); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstprefetchablesupport.h", line 78 */ + +typedef struct Steinberg_Vst_IPrefetchableSupportVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IPrefetchableSupport": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getPrefetchableSupport) (void* thisInterface, Steinberg_Vst_PrefetchableSupport* prefetchable); + +} Steinberg_Vst_IPrefetchableSupportVtbl; + +typedef struct Steinberg_Vst_IPrefetchableSupport +{ + struct Steinberg_Vst_IPrefetchableSupportVtbl* lpVtbl; +} Steinberg_Vst_IPrefetchableSupport; + +static const Steinberg_TUID Steinberg_Vst_IPrefetchableSupport_iid = SMTG_INLINE_UID (0x8AE54FDA, 0xE93046B9, 0xA28555BC, 0xDC98E21E); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstdataexchange.h", line 96 */ + +typedef struct Steinberg_Vst_IDataExchangeHandlerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IDataExchangeHandler": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* openQueue) (void* thisInterface, struct Steinberg_Vst_IAudioProcessor* processor, Steinberg_uint32 blockSize, Steinberg_uint32 numBlocks, Steinberg_uint32 alignment, Steinberg_Vst_DataExchangeUserContextID userContextID, Steinberg_Vst_DataExchangeQueueID* outID); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* closeQueue) (void* thisInterface, Steinberg_Vst_DataExchangeQueueID queueID); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* lockBlock) (void* thisInterface, Steinberg_Vst_DataExchangeQueueID queueId, struct Steinberg_Vst_DataExchangeBlock* block); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* freeBlock) (void* thisInterface, Steinberg_Vst_DataExchangeQueueID queueId, Steinberg_Vst_DataExchangeBlockID blockID, Steinberg_TBool sendToController); + +} Steinberg_Vst_IDataExchangeHandlerVtbl; + +typedef struct Steinberg_Vst_IDataExchangeHandler +{ + struct Steinberg_Vst_IDataExchangeHandlerVtbl* lpVtbl; +} Steinberg_Vst_IDataExchangeHandler; + +static const Steinberg_TUID Steinberg_Vst_IDataExchangeHandler_iid = SMTG_INLINE_UID (0x36D551BD, 0x6FF54F08, 0xB48E830D, 0x8BD5A03B); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstdataexchange.h", line 171 */ + +typedef struct Steinberg_Vst_IDataExchangeReceiverVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IDataExchangeReceiver": */ + void (SMTG_STDMETHODCALLTYPE* queueOpened) (void* thisInterface, Steinberg_Vst_DataExchangeUserContextID userContextID, Steinberg_uint32 blockSize, Steinberg_TBool* dispatchOnBackgroundThread); + void (SMTG_STDMETHODCALLTYPE* queueClosed) (void* thisInterface, Steinberg_Vst_DataExchangeUserContextID userContextID); + void (SMTG_STDMETHODCALLTYPE* onDataExchangeBlocksReceived) (void* thisInterface, Steinberg_Vst_DataExchangeUserContextID userContextID, Steinberg_uint32 numBlocks, struct Steinberg_Vst_DataExchangeBlock* blocks, Steinberg_TBool onBackgroundThread); + +} Steinberg_Vst_IDataExchangeReceiverVtbl; + +typedef struct Steinberg_Vst_IDataExchangeReceiver +{ + struct Steinberg_Vst_IDataExchangeReceiverVtbl* lpVtbl; +} Steinberg_Vst_IDataExchangeReceiver; + +static const Steinberg_TUID Steinberg_Vst_IDataExchangeReceiver_iid = SMTG_INLINE_UID (0x45A759DC, 0x84FA4907, 0xABCB6175, 0x2FC786B6); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstautomationstate.h", line 39 */ + +typedef struct Steinberg_Vst_IAutomationStateVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IAutomationState": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setAutomationState) (void* thisInterface, Steinberg_int32 state); + +} Steinberg_Vst_IAutomationStateVtbl; + +typedef struct Steinberg_Vst_IAutomationState +{ + struct Steinberg_Vst_IAutomationStateVtbl* lpVtbl; +} Steinberg_Vst_IAutomationState; + +static const Steinberg_TUID Steinberg_Vst_IAutomationState_iid = SMTG_INLINE_UID (0xB4E8287F, 0x1BB346AA, 0x83A46667, 0x68937BAB); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstinterappaudio.h", line 38 */ + +typedef struct Steinberg_Vst_IInterAppAudioHostVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IInterAppAudioHost": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getScreenSize) (void* thisInterface, struct Steinberg_ViewRect* size, float* scale); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* connectedToHost) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* switchToHost) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* sendRemoteControlEvent) (void* thisInterface, Steinberg_uint32 event); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getHostIcon) (void* thisInterface, void** icon); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* scheduleEventFromUI) (void* thisInterface, struct Steinberg_Vst_Event* event); + struct Steinberg_Vst_IInterAppAudioPresetManager* (SMTG_STDMETHODCALLTYPE* createPresetManager) (void* thisInterface, const Steinberg_TUID* cid); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* showSettingsView) (void* thisInterface); + +} Steinberg_Vst_IInterAppAudioHostVtbl; + +typedef struct Steinberg_Vst_IInterAppAudioHost +{ + struct Steinberg_Vst_IInterAppAudioHostVtbl* lpVtbl; +} Steinberg_Vst_IInterAppAudioHost; + +static const Steinberg_TUID Steinberg_Vst_IInterAppAudioHost_iid = SMTG_INLINE_UID (0x0CE5743D, 0x68DF415E, 0xAE285BD4, 0xE2CDC8FD); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstinterappaudio.h", line 101 */ + +typedef struct Steinberg_Vst_IInterAppAudioConnectionNotificationVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IInterAppAudioConnectionNotification": */ + void (SMTG_STDMETHODCALLTYPE* onInterAppAudioConnectionStateChange) (void* thisInterface, Steinberg_TBool newState); + +} Steinberg_Vst_IInterAppAudioConnectionNotificationVtbl; + +typedef struct Steinberg_Vst_IInterAppAudioConnectionNotification +{ + struct Steinberg_Vst_IInterAppAudioConnectionNotificationVtbl* lpVtbl; +} Steinberg_Vst_IInterAppAudioConnectionNotification; + +static const Steinberg_TUID Steinberg_Vst_IInterAppAudioConnectionNotification_iid = SMTG_INLINE_UID (0x6020C72D, 0x5FC24AA1, 0xB0950DB5, 0xD7D6D5CF); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstinterappaudio.h", line 122 */ + +typedef struct Steinberg_Vst_IInterAppAudioPresetManagerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IInterAppAudioPresetManager": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* runLoadPresetBrowser) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* runSavePresetBrowser) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* loadNextPreset) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* loadPreviousPreset) (void* thisInterface); + +} Steinberg_Vst_IInterAppAudioPresetManagerVtbl; + +typedef struct Steinberg_Vst_IInterAppAudioPresetManager +{ + struct Steinberg_Vst_IInterAppAudioPresetManagerVtbl* lpVtbl; +} Steinberg_Vst_IInterAppAudioPresetManager; + +static const Steinberg_TUID Steinberg_Vst_IInterAppAudioPresetManager_iid = SMTG_INLINE_UID (0xADE6FCC4, 0x46C94E1D, 0xB3B49A80, 0xC93FEFDD); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 269 */ + +typedef struct Steinberg_Vst_IAudioProcessorVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IAudioProcessor": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setBusArrangements) (void* thisInterface, Steinberg_Vst_SpeakerArrangement* inputs, Steinberg_int32 numIns, Steinberg_Vst_SpeakerArrangement* outputs, Steinberg_int32 numOuts); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getBusArrangement) (void* thisInterface, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, Steinberg_Vst_SpeakerArrangement* arr); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* canProcessSampleSize) (void* thisInterface, Steinberg_int32 symbolicSampleSize); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* getLatencySamples) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setupProcessing) (void* thisInterface, struct Steinberg_Vst_ProcessSetup* setup); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setProcessing) (void* thisInterface, Steinberg_TBool state); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* process) (void* thisInterface, struct Steinberg_Vst_ProcessData* data); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* getTailSamples) (void* thisInterface); + +} Steinberg_Vst_IAudioProcessorVtbl; + +typedef struct Steinberg_Vst_IAudioProcessor +{ + struct Steinberg_Vst_IAudioProcessorVtbl* lpVtbl; +} Steinberg_Vst_IAudioProcessor; + +static const Steinberg_TUID Steinberg_Vst_IAudioProcessor_iid = SMTG_INLINE_UID (0x42043F99, 0xB7DA453C, 0xA569E79D, 0x9AAEC33D); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 400 */ + +typedef struct Steinberg_Vst_IAudioPresentationLatencyVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IAudioPresentationLatency": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setAudioPresentationLatencySamples) (void* thisInterface, Steinberg_Vst_BusDirection dir, Steinberg_int32 busIndex, Steinberg_uint32 latencyInSamples); + +} Steinberg_Vst_IAudioPresentationLatencyVtbl; + +typedef struct Steinberg_Vst_IAudioPresentationLatency +{ + struct Steinberg_Vst_IAudioPresentationLatencyVtbl* lpVtbl; +} Steinberg_Vst_IAudioPresentationLatency; + +static const Steinberg_TUID Steinberg_Vst_IAudioPresentationLatency_iid = SMTG_INLINE_UID (0x309ECE78, 0xEB7D4fae, 0x8B2225D9, 0x09FD08B6); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstaudioprocessor.h", line 437 */ + +typedef struct Steinberg_Vst_IProcessContextRequirementsVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IProcessContextRequirements": */ + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* getProcessContextRequirements) (void* thisInterface); + +} Steinberg_Vst_IProcessContextRequirementsVtbl; + +typedef struct Steinberg_Vst_IProcessContextRequirements +{ + struct Steinberg_Vst_IProcessContextRequirementsVtbl* lpVtbl; +} Steinberg_Vst_IProcessContextRequirements; + +static const Steinberg_TUID Steinberg_Vst_IProcessContextRequirements_iid = SMTG_INLINE_UID (0x2A654303, 0xEF764E3D, 0x95B5FE83, 0x730EF6D0); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmidimapping2.h", line 128 */ + +typedef struct Steinberg_Vst_IMidiMapping2Vtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IMidiMapping2": */ + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* getNumMidi2ControllerAssignments) (void* thisInterface, Steinberg_Vst_BusDirections direction); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getMidi2ControllerAssignments) (void* thisInterface, Steinberg_Vst_BusDirections direction, const struct Steinberg_Vst_Midi2ControllerParamIDAssignmentList* list); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* getNumMidi1ControllerAssignments) (void* thisInterface, Steinberg_Vst_BusDirections direction); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getMidi1ControllerAssignments) (void* thisInterface, Steinberg_Vst_BusDirections direction, const struct Steinberg_Vst_Midi1ControllerParamIDAssignmentList* list); + +} Steinberg_Vst_IMidiMapping2Vtbl; + +typedef struct Steinberg_Vst_IMidiMapping2 +{ + struct Steinberg_Vst_IMidiMapping2Vtbl* lpVtbl; +} Steinberg_Vst_IMidiMapping2; + +static const Steinberg_TUID Steinberg_Vst_IMidiMapping2_iid = SMTG_INLINE_UID (0x6DE14B88, 0x03F94F09, 0xA2552F0F, 0x9326593E); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstmidimapping2.h", line 188 */ + +typedef struct Steinberg_Vst_IMidiLearn2Vtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IMidiLearn2": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onLiveMidi2ControllerInput) (void* thisInterface, Steinberg_Vst_BusIndex index, Steinberg_Vst_MidiChannel channel, struct Steinberg_Vst_Midi2Controller midiCC); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onLiveMidi1ControllerInput) (void* thisInterface, Steinberg_Vst_BusIndex index, Steinberg_Vst_MidiChannel channel, Steinberg_Vst_CtrlNumber midiCC); + +} Steinberg_Vst_IMidiLearn2Vtbl; + +typedef struct Steinberg_Vst_IMidiLearn2 +{ + struct Steinberg_Vst_IMidiLearn2Vtbl* lpVtbl; +} Steinberg_Vst_IMidiLearn2; + +static const Steinberg_TUID Steinberg_Vst_IMidiLearn2_iid = SMTG_INLINE_UID (0xF07E498A, 0x78864327, 0x8B431CED, 0xA3C553FC); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsthostapplication.h", line 35 */ + +typedef struct Steinberg_Vst_IHostApplicationVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IHostApplication": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getName) (void* thisInterface, Steinberg_Vst_String128 name); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* createInstance) (void* thisInterface, Steinberg_TUID cid, Steinberg_TUID iid, void** obj); + +} Steinberg_Vst_IHostApplicationVtbl; + +typedef struct Steinberg_Vst_IHostApplication +{ + struct Steinberg_Vst_IHostApplicationVtbl* lpVtbl; +} Steinberg_Vst_IHostApplication; + +static const Steinberg_TUID Steinberg_Vst_IHostApplication_iid = SMTG_INLINE_UID (0x58E595CC, 0xDB2D4969, 0x8B6AAF8C, 0x36A664E5); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsthostapplication.h", line 76 */ + +typedef struct Steinberg_Vst_IVst3ToVst2WrapperVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + +} Steinberg_Vst_IVst3ToVst2WrapperVtbl; + +typedef struct Steinberg_Vst_IVst3ToVst2Wrapper +{ + struct Steinberg_Vst_IVst3ToVst2WrapperVtbl* lpVtbl; +} Steinberg_Vst_IVst3ToVst2Wrapper; + +static const Steinberg_TUID Steinberg_Vst_IVst3ToVst2Wrapper_iid = SMTG_INLINE_UID (0x29633AEC, 0x1D1C47E2, 0xBB85B97B, 0xD36EAC61); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsthostapplication.h", line 96 */ + +typedef struct Steinberg_Vst_IVst3ToAUWrapperVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + +} Steinberg_Vst_IVst3ToAUWrapperVtbl; + +typedef struct Steinberg_Vst_IVst3ToAUWrapper +{ + struct Steinberg_Vst_IVst3ToAUWrapperVtbl* lpVtbl; +} Steinberg_Vst_IVst3ToAUWrapper; + +static const Steinberg_TUID Steinberg_Vst_IVst3ToAUWrapper_iid = SMTG_INLINE_UID (0xA3B8C6C5, 0xC0954688, 0xB0916F0B, 0xB697AA44); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsthostapplication.h", line 116 */ + +typedef struct Steinberg_Vst_IVst3ToAAXWrapperVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + +} Steinberg_Vst_IVst3ToAAXWrapperVtbl; + +typedef struct Steinberg_Vst_IVst3ToAAXWrapper +{ + struct Steinberg_Vst_IVst3ToAAXWrapperVtbl* lpVtbl; +} Steinberg_Vst_IVst3ToAAXWrapper; + +static const Steinberg_TUID Steinberg_Vst_IVst3ToAAXWrapper_iid = SMTG_INLINE_UID (0x6D319DC6, 0x60C56242, 0xB32C951B, 0x93BEF4C6); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsthostapplication.h", line 140 */ + +typedef struct Steinberg_Vst_IVst3WrapperMPESupportVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IVst3WrapperMPESupport": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* enableMPEInputProcessing) (void* thisInterface, Steinberg_TBool state); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setMPEInputDeviceSettings) (void* thisInterface, Steinberg_int32 masterChannel, Steinberg_int32 memberBeginChannel, Steinberg_int32 memberEndChannel); + +} Steinberg_Vst_IVst3WrapperMPESupportVtbl; + +typedef struct Steinberg_Vst_IVst3WrapperMPESupport +{ + struct Steinberg_Vst_IVst3WrapperMPESupportVtbl* lpVtbl; +} Steinberg_Vst_IVst3WrapperMPESupport; + +static const Steinberg_TUID Steinberg_Vst_IVst3WrapperMPESupport_iid = SMTG_INLINE_UID (0x44149067, 0x42CF4BF9, 0x8800B750, 0xF7359FE3); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstplugview.h", line 44 */ + +typedef struct Steinberg_Vst_IParameterFinderVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IParameterFinder": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* findParameter) (void* thisInterface, Steinberg_int32 xPos, Steinberg_int32 yPos, Steinberg_Vst_ParamID* resultTag); + +} Steinberg_Vst_IParameterFinderVtbl; + +typedef struct Steinberg_Vst_IParameterFinder +{ + struct Steinberg_Vst_IParameterFinderVtbl* lpVtbl; +} Steinberg_Vst_IParameterFinder; + +static const Steinberg_TUID Steinberg_Vst_IParameterFinder_iid = SMTG_INLINE_UID (0x0F618302, 0x215D4587, 0xA512073C, 0x77B9D383); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstnoteonorchestralarticulationinfo.h", line 65 */ + +typedef struct Steinberg_Vst_NoteOnOrchestralArticulation_IInfoVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_NoteOnOrchestralArticulation_IInfo": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getVariationsInfo) (void* thisInterface, Steinberg_int32 busIndex, Steinberg_int16 channel, struct Steinberg_Vst_NoteOnOrchestralArticulation_ClassificationVariations* info); + +} Steinberg_Vst_NoteOnOrchestralArticulation_IInfoVtbl; + +typedef struct Steinberg_Vst_NoteOnOrchestralArticulation_IInfo +{ + struct Steinberg_Vst_NoteOnOrchestralArticulation_IInfoVtbl* lpVtbl; +} Steinberg_Vst_NoteOnOrchestralArticulation_IInfo; + +static const Steinberg_TUID Steinberg_Vst_NoteOnOrchestralArticulation_IInfo_iid = SMTG_INLINE_UID (0x7D34A9B4, 0x89CA45F4, 0x9284A9FD, 0x4DD9C906); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivsttransportcontrol.h", line 100 */ + +typedef struct Steinberg_Vst_ITransportControlVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_ITransportControl": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* requestAction) (void* thisInterface, Steinberg_int32 action, struct Steinberg_Vst_TransportPosition* position); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* isActionSupported) (void* thisInterface, Steinberg_int32 action); + +} Steinberg_Vst_ITransportControlVtbl; + +typedef struct Steinberg_Vst_ITransportControl +{ + struct Steinberg_Vst_ITransportControlVtbl* lpVtbl; +} Steinberg_Vst_ITransportControl; + +static const Steinberg_TUID Steinberg_Vst_ITransportControl_iid = SMTG_INLINE_UID (0xD752F52D, 0x004348A0, 0xB431B045, 0xF0DCA49C); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstunits.h", line 80 */ + +typedef struct Steinberg_Vst_IUnitHandlerVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IUnitHandler": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* notifyUnitSelection) (void* thisInterface, Steinberg_Vst_UnitID unitId); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* notifyProgramListChange) (void* thisInterface, Steinberg_Vst_ProgramListID listId, Steinberg_int32 programIndex); + +} Steinberg_Vst_IUnitHandlerVtbl; + +typedef struct Steinberg_Vst_IUnitHandler +{ + struct Steinberg_Vst_IUnitHandlerVtbl* lpVtbl; +} Steinberg_Vst_IUnitHandler; + +static const Steinberg_TUID Steinberg_Vst_IUnitHandler_iid = SMTG_INLINE_UID (0x4B5147F8, 0x4654486B, 0x8DAB30BA, 0x163A3C56); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstunits.h", line 121 */ + +typedef struct Steinberg_Vst_IUnitHandler2Vtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IUnitHandler2": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* notifyUnitByBusChange) (void* thisInterface); + +} Steinberg_Vst_IUnitHandler2Vtbl; + +typedef struct Steinberg_Vst_IUnitHandler2 +{ + struct Steinberg_Vst_IUnitHandler2Vtbl* lpVtbl; +} Steinberg_Vst_IUnitHandler2; + +static const Steinberg_TUID Steinberg_Vst_IUnitHandler2_iid = SMTG_INLINE_UID (0xF89F8CDF, 0x699E4BA5, 0x96AAC9A4, 0x81452B01); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstunits.h", line 151 */ + +typedef struct Steinberg_Vst_IUnitInfoVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IUnitInfo": */ + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getUnitCount) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getUnitInfo) (void* thisInterface, Steinberg_int32 unitIndex, struct Steinberg_Vst_UnitInfo* info); + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getProgramListCount) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getProgramListInfo) (void* thisInterface, Steinberg_int32 listIndex, struct Steinberg_Vst_ProgramListInfo* info); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getProgramName) (void* thisInterface, Steinberg_Vst_ProgramListID listId, Steinberg_int32 programIndex, Steinberg_Vst_String128 name); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getProgramInfo) (void* thisInterface, Steinberg_Vst_ProgramListID listId, Steinberg_int32 programIndex, Steinberg_Vst_CString attributeId, Steinberg_Vst_String128 attributeValue); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* hasProgramPitchNames) (void* thisInterface, Steinberg_Vst_ProgramListID listId, Steinberg_int32 programIndex); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getProgramPitchName) (void* thisInterface, Steinberg_Vst_ProgramListID listId, Steinberg_int32 programIndex, Steinberg_int16 midiPitch, Steinberg_Vst_String128 name); + Steinberg_Vst_UnitID (SMTG_STDMETHODCALLTYPE* getSelectedUnit) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* selectUnit) (void* thisInterface, Steinberg_Vst_UnitID unitId); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getUnitByBus) (void* thisInterface, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir, Steinberg_int32 busIndex, Steinberg_int32 channel, Steinberg_Vst_UnitID* unitId); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setUnitProgramData) (void* thisInterface, Steinberg_int32 listOrUnitId, Steinberg_int32 programIndex, struct Steinberg_IBStream* data); + +} Steinberg_Vst_IUnitInfoVtbl; + +typedef struct Steinberg_Vst_IUnitInfo +{ + struct Steinberg_Vst_IUnitInfoVtbl* lpVtbl; +} Steinberg_Vst_IUnitInfo; + +static const Steinberg_TUID Steinberg_Vst_IUnitInfo_iid = SMTG_INLINE_UID (0x3D4BD6B5, 0x913A4FD2, 0xA886E768, 0xA5EB92C1); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstunits.h", line 242 */ + +typedef struct Steinberg_Vst_IProgramListDataVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IProgramListData": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* programDataSupported) (void* thisInterface, Steinberg_Vst_ProgramListID listId); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getProgramData) (void* thisInterface, Steinberg_Vst_ProgramListID listId, Steinberg_int32 programIndex, struct Steinberg_IBStream* data); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setProgramData) (void* thisInterface, Steinberg_Vst_ProgramListID listId, Steinberg_int32 programIndex, struct Steinberg_IBStream* data); + +} Steinberg_Vst_IProgramListDataVtbl; + +typedef struct Steinberg_Vst_IProgramListData +{ + struct Steinberg_Vst_IProgramListDataVtbl* lpVtbl; +} Steinberg_Vst_IProgramListData; + +static const Steinberg_TUID Steinberg_Vst_IProgramListData_iid = SMTG_INLINE_UID (0x8683B01F, 0x7B354F70, 0xA2651DEC, 0x353AF4FF); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstunits.h", line 279 */ + +typedef struct Steinberg_Vst_IUnitDataVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IUnitData": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* unitDataSupported) (void* thisInterface, Steinberg_Vst_UnitID unitID); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getUnitData) (void* thisInterface, Steinberg_Vst_UnitID unitId, struct Steinberg_IBStream* data); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* setUnitData) (void* thisInterface, Steinberg_Vst_UnitID unitId, struct Steinberg_IBStream* data); + +} Steinberg_Vst_IUnitDataVtbl; + +typedef struct Steinberg_Vst_IUnitData +{ + struct Steinberg_Vst_IUnitDataVtbl* lpVtbl; +} Steinberg_Vst_IUnitData; + +static const Steinberg_TUID Steinberg_Vst_IUnitData_iid = SMTG_INLINE_UID (0x6C389611, 0xD391455D, 0xB870B833, 0x94A0EFDD); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstpluginterfacesupport.h", line 53 */ + +typedef struct Steinberg_Vst_IPlugInterfaceSupportVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IPlugInterfaceSupport": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* isPlugInterfaceSupported) (void* thisInterface, const Steinberg_TUID iid); + +} Steinberg_Vst_IPlugInterfaceSupportVtbl; + +typedef struct Steinberg_Vst_IPlugInterfaceSupport +{ + struct Steinberg_Vst_IPlugInterfaceSupportVtbl* lpVtbl; +} Steinberg_Vst_IPlugInterfaceSupport; + +static const Steinberg_TUID Steinberg_Vst_IPlugInterfaceSupport_iid = SMTG_INLINE_UID (0x4FB58B9E, 0x9EAA4E0F, 0xAB361C1C, 0xCCB56FEA); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstparameterfunctionname.h", line 141 */ + +typedef struct Steinberg_Vst_IParameterFunctionNameVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IParameterFunctionName": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getParameterIDFromFunctionName) (void* thisInterface, Steinberg_Vst_UnitID unitID, Steinberg_FIDString functionName, Steinberg_Vst_ParamID* paramID); + +} Steinberg_Vst_IParameterFunctionNameVtbl; + +typedef struct Steinberg_Vst_IParameterFunctionName +{ + struct Steinberg_Vst_IParameterFunctionNameVtbl* lpVtbl; +} Steinberg_Vst_IParameterFunctionName; + +static const Steinberg_TUID Steinberg_Vst_IParameterFunctionName_iid = SMTG_INLINE_UID (0x6D21E1DC, 0x91199D4B, 0xA2A02FEF, 0x6C1AE55C); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstparameterchanges.h", line 84 */ + +typedef struct Steinberg_Vst_IParamValueQueueVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IParamValueQueue": */ + Steinberg_Vst_ParamID (SMTG_STDMETHODCALLTYPE* getParameterId) (void* thisInterface); + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getPointCount) (void* thisInterface); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* getPoint) (void* thisInterface, Steinberg_int32 index, Steinberg_int32* sampleOffset, Steinberg_Vst_ParamValue* value); + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* addPoint) (void* thisInterface, Steinberg_int32 sampleOffset, Steinberg_Vst_ParamValue value, Steinberg_int32* index); + +} Steinberg_Vst_IParamValueQueueVtbl; + +typedef struct Steinberg_Vst_IParamValueQueue +{ + struct Steinberg_Vst_IParamValueQueueVtbl* lpVtbl; +} Steinberg_Vst_IParamValueQueue; + +static const Steinberg_TUID Steinberg_Vst_IParamValueQueue_iid = SMTG_INLINE_UID (0x01263A18, 0xED074F6F, 0x98C9D356, 0x4686F9BA); + +/*---------------------------------------------------------------------------------------------------------------------- +Source: "pluginterfaces/vst/ivstparameterchanges.h", line 121 */ + +typedef struct Steinberg_Vst_IParameterChangesVtbl +{ + /* methods derived from "Steinberg_FUnknown": */ + Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface); + Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface); + + /* methods defined in "Steinberg_Vst_IParameterChanges": */ + Steinberg_int32 (SMTG_STDMETHODCALLTYPE* getParameterCount) (void* thisInterface); + struct Steinberg_Vst_IParamValueQueue* (SMTG_STDMETHODCALLTYPE* getParameterData) (void* thisInterface, Steinberg_int32 index); + struct Steinberg_Vst_IParamValueQueue* (SMTG_STDMETHODCALLTYPE* addParameterData) (void* thisInterface, const Steinberg_Vst_ParamID* id, Steinberg_int32* index); + +} Steinberg_Vst_IParameterChangesVtbl; + +typedef struct Steinberg_Vst_IParameterChanges +{ + struct Steinberg_Vst_IParameterChangesVtbl* lpVtbl; +} Steinberg_Vst_IParameterChanges; + +static const Steinberg_TUID Steinberg_Vst_IParameterChanges_iid = SMTG_INLINE_UID (0xA4779663, 0x0BB64A56, 0xB44384A8, 0x466FEB9D); + diff --git a/tools/analyze.py b/tools/analyze.py index aa71627..8f8af4c 100644 --- a/tools/analyze.py +++ b/tools/analyze.py @@ -10,6 +10,8 @@ if not shutil.which("clang"): jack = subprocess.run(["pkg-config", "--cflags", "jack"], capture_output=True, text=True) if shutil.which("pkg-config") else None for source in sys.argv[1:]: flags = [] + if source == "src/plugin/modern.c": + flags = ["-isystem", "third_party/clap/include", "-isystem", "third_party/vst3"] if source == "src/backend/jack_backend.c" and jack and jack.returncode == 0: import shlex flags = ["-DXTC_HAVE_JACK", *shlex.split(jack.stdout)] diff --git a/tools/install_layout.py b/tools/install_layout.py index 81db6c7..ff1ce27 100644 --- a/tools/install_layout.py +++ b/tools/install_layout.py @@ -32,6 +32,8 @@ def inventory(source, paths): ('bindir', 'xtc-check', None), ('bindir', 'xtc', None), ('desktopdir', 'xtc.desktop', source / 'packaging/xtc.desktop'), ('licensedir', 'LICENSE', source / 'LICENSE'), + ('licensedir', 'CLAP-LICENSE', source / 'third_party/clap/LICENSE'), + ('licensedir', 'VST3-C-API-LICENSE', source / 'third_party/vst3/LICENSE.txt'), ('docdir', 'README.md', source / 'README.md'), ('docdir', 'BINARY_MANIFEST.json', None)] entries += [('includedir', 'xtc/' + p.name, p) for p in sorted((source / 'include/xtc').glob('*.h'))]