1 /* 2 MIT License 3 4 Copyright (c) 2021 Alexandre BIQUE 5 Copyright (c) 2024 Guillaume PIOLAT 6 7 Permission is hereby granted, free of charge, to any person obtaining 8 a copy of this software and associated documentation files (the 9 "Software"), to deal in the Software without restriction, including 10 without limitation the rights to use, copy, modify, merge, publish, 11 distribute, sublicense, and/or sell copies of the Software, and to 12 permit persons to whom the Software is furnished to do so, subject to 13 the following conditions: 14 15 The above copyright notice and this permission notice shall be 16 included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 module dplug.clap.types; 27 28 nothrow @nogc: 29 version(CLAP): 30 31 import core.stdc.string; 32 import core.stdc.config; 33 import core.stdc.stdio; 34 import dplug.core.runtime; 35 import dplug.core.nogc; 36 import dplug.core.sync; 37 import dplug.client.client; 38 import dplug.client.daw; 39 import dplug.clap.client; 40 import dplug.clap; 41 import dplug.clap.clapversion; 42 43 44 // CLAP has lots of unsigned integers, meaning we must in theory 45 // check for overflows 46 int assumeNoOverflow(uint x) pure @safe 47 { 48 assert(x <= int.max); 49 return x; 50 } 51 52 void toBufZ(char[] buf, const(char)[] source) 53 { 54 snprintf(buf.ptr, buf.length, "%.*s", 55 cast(int)(source.length), source.ptr); 56 } 57 58 // id.h 59 60 alias clap_id = uint; 61 enum clap_id CLAP_INVALID_ID = uint.max; 62 /* 63 void printfemergency(const(char)* s) 64 { 65 import core.stdc.stdio; 66 FILE* fio = fopen(`C:\Users\guill\Desktop\output.txt`, "a"); 67 fprintf(fio, "%s", s); 68 fflush(fio); 69 fclose(fio); 70 }*/ 71 72 73 // string-sizes.h 74 75 // String capacity for names that can be displayed to the user. 76 enum CLAP_NAME_SIZE = 256; 77 78 // String capacity for describing a path, like a parameter in a module hierarchy or path within a 79 // set of nested track groups. 80 // 81 // This is not suited for describing a file path on the disk, as NTFS allows up to 32K long 82 // paths. 83 enum CLAP_PATH_SIZE = 1024; 84 85 86 // fixed-point.h 87 88 /// We use fixed point representation of beat time and seconds time 89 /// Usage: 90 /// double x = ...; // in beats 91 /// clap_beattime y = round(CLAP_BEATTIME_FACTOR * x); 92 // This will never change 93 enum long CLAP_BEATTIME_FACTOR = (cast(long)1) << 31; 94 enum long CLAP_SECTIME_FACTOR = (cast(long)1) << 31; 95 96 alias clap_beattime = long; 97 alias clap_sectime = long; 98 99 100 // plugin-features.h 101 102 // Add this feature if your plugin can process note events and then produce audio 103 static immutable CLAP_PLUGIN_FEATURE_INSTRUMENT = "instrument"; 104 105 // Add this feature if your plugin is an audio effect 106 static immutable CLAP_PLUGIN_FEATURE_AUDIO_EFFECT = "audio-effect"; 107 108 // Add this feature if your plugin is a note effect or a note generator/sequencer 109 static immutable CLAP_PLUGIN_FEATURE_NOTE_EFFECT = "note-effect"; 110 111 // Add this feature if your plugin converts audio to notes 112 static immutable CLAP_PLUGIN_FEATURE_NOTE_DETECTOR = "note-detector"; 113 114 // Add this feature if your plugin is an analyzer 115 static immutable CLAP_PLUGIN_FEATURE_ANALYZER = "analyzer"; 116 117 // Audio Capabilities 118 119 static immutable CLAP_PLUGIN_FEATURE_MONO = "mono"; 120 static immutable CLAP_PLUGIN_FEATURE_STEREO = "stereo"; 121 static immutable CLAP_PLUGIN_FEATURE_SURROUND = "surround"; 122 static immutable CLAP_PLUGIN_FEATURE_AMBISONIC = "ambisonic"; 123 124 125 126 // version.h 127 128 __gshared UncheckedMutex g_factoryMutex; // FUTURE: sounds like... leaked? 129 130 // Get the pointer to a factory. See factory/plugin-factory.h for an example. 131 // 132 // Returns null if the factory is not provided. 133 // The returned pointer must *not* be freed by the caller. 134 const(void)* clap_factory_templated(ClientClass)(const(char)* factory_id) 135 { 136 ScopedForeignCallback!(false, true) scopedCallback; 137 scopedCallback.enter(); 138 if (strcmp(factory_id, "clap.plugin-factory") == 0) 139 { 140 static immutable __gshared clap_plugin_factory_t g_factory 141 = clap_plugin_factory_t(&factory_get_plugin_count, 142 &factory_get_plugin_descriptor!ClientClass, 143 &factory_create_plugin!ClientClass); 144 return &g_factory; 145 } 146 147 if ( (strcmp(factory_id, CLAP_PRESET_DISCOVERY_FACTORY_ID.ptr) == 0) 148 || (strcmp(factory_id, CLAP_PRESET_DISCOVERY_FACTORY_ID_COMPAT.ptr) == 0) ) 149 { 150 static immutable __gshared clap_preset_discovery_factory_t g_presetfactory 151 = clap_preset_discovery_factory_t(&preset_discovery_count, 152 &preset_discovery_get_descriptor!ClientClass, 153 &preset_discovery_create!ClientClass); 154 return &g_presetfactory; 155 } 156 return null; 157 } 158 159 extern(C) 160 { 161 // plugin factory impl 162 163 uint factory_get_plugin_count(const(clap_plugin_factory_t)* factory) 164 { 165 return 1; 166 } 167 168 const(clap_plugin_descriptor_t)* get_descriptor_from_client(Client client) 169 { 170 // Fill with information from PluginClass 171 __gshared clap_plugin_descriptor_t desc; 172 173 desc.clap_version = CLAP_VERSION; 174 175 __gshared char[128] idZ; 176 __gshared char[128] nameZ; 177 __gshared char[128] vendorZ; 178 __gshared char[256] urlZ; 179 toBufZ(idZ, client.CLAPIdentifier); 180 toBufZ(nameZ, client.pluginName); 181 toBufZ(vendorZ, client.vendorName); 182 toBufZ(urlZ, client.pluginHomepage); 183 desc.id = idZ.ptr; 184 desc.name = nameZ.ptr; 185 desc.vendor = vendorZ.ptr; 186 desc.url = urlZ.ptr; 187 188 // FUTURE: Dplug doesn't have that, same URL as homepage 189 desc.manual_url = desc.url; 190 191 // FUTURE: provide that support URL 192 desc.support_url = desc.url; 193 194 // Can be __shared, since there is a single plugin in our CLAP client, 195 // with a single version. 196 __gshared char[64] versionBuf; 197 PluginVersion ver = client.getPublicVersion(); 198 ver.toCLAPVersionString(versionBuf.ptr, 64); 199 desc.version_ = versionBuf.ptr; 200 desc.description = "No description.".ptr; 201 202 // Build a global array of features. 203 enum MAX_FEATURES = 8; 204 int nFeatures = 0; 205 __gshared const(char)*[MAX_FEATURES] g_features; 206 void addFeature(immutable(char)[] feature) 207 { 208 g_features[nFeatures++] = feature.ptr; 209 } 210 bool isSynth = client.isSynth; 211 bool isEffect = !client.isSynth; 212 if (isSynth) addFeature(CLAP_PLUGIN_FEATURE_INSTRUMENT); 213 if (isSynth && client.isLegalIO(0, 1)) addFeature( CLAP_PLUGIN_FEATURE_MONO ); 214 if (isSynth && client.isLegalIO(0, 2)) addFeature( CLAP_PLUGIN_FEATURE_STEREO ); 215 if (isEffect) addFeature(CLAP_PLUGIN_FEATURE_AUDIO_EFFECT); 216 if (isEffect && client.isLegalIO(1, 1)) addFeature( CLAP_PLUGIN_FEATURE_MONO ); 217 if (isEffect && client.isLegalIO(2, 2)) addFeature( CLAP_PLUGIN_FEATURE_STEREO ); 218 219 string clapCategory; 220 final switch(client.pluginCategory()) with (PluginCategory) 221 { 222 case effectAnalysisAndMetering: clapCategory = "analyzer"; break; 223 case effectDelay: clapCategory = "delay"; break; 224 case effectDistortion: clapCategory = "distortion"; break; 225 case effectDynamics: clapCategory = "compressor"; break; // Note: CLAP has 3: compressor, expander, transient shaper 226 case effectEQ: clapCategory = "equalizer"; break; 227 case effectImaging: clapCategory = "utility"; break; // No imaging categiry in CLAP 228 case effectModulation: clapCategory = "chorus"; break; // Note: CLAP has chorus and flanger 229 case effectPitch: clapCategory = "pitch-correction"; break; 230 case effectReverb: clapCategory = "reverb"; break; 231 case effectOther: clapCategory = null; break; 232 case instrumentDrums: clapCategory = "drum-machine"; break; 233 case instrumentSampler: clapCategory = "sampler"; break; 234 case instrumentSynthesizer: clapCategory = "synthesizer"; break; 235 case instrumentOther: clapCategory = null; break; 236 case invalid: assert(false); 237 } 238 addFeature(clapCategory); 239 addFeature(null); 240 desc.features = g_features.ptr; 241 return &desc; 242 } 243 244 const(clap_plugin_descriptor_t)* factory_get_plugin_descriptor(ClientClass)(const(clap_plugin_factory_t)* factory, uint index) 245 { 246 ScopedForeignCallback!(false, true) sfc; 247 sfc.enter(); 248 249 // Only one plug-in supported by CLAP wrapper in Dplug. 250 if (index != 0) 251 return null; 252 253 g_factoryMutex.lockLazy(); 254 scope(exit) g_factoryMutex.unlock(); 255 256 // Create a client just for the purpose of describing the plug-in 257 ClientClass client = mallocNew!ClientClass(); 258 scope(exit) client.destroyFree(); 259 return get_descriptor_from_client(client); 260 } 261 262 const(clap_plugin_t)* factory_create_plugin(ClientClass)(const(clap_plugin_factory_t)*factory, 263 const(clap_host_t)* host, 264 const(char)* plugin_id) 265 { 266 ScopedForeignCallback!(false, true) sfc; 267 sfc.enter(); 268 269 // Note: I don't see what would NOT be thread-safe here. 270 271 // Create a Client and a CLAPClient, who hold that and the CLAP structure 272 ClientClass client = mallocNew!ClientClass(); 273 274 // Verify that ID match, this is a clap-validator check. 275 const(clap_plugin_descriptor_t)* desc = get_descriptor_from_client(client); 276 if (strcmp(desc.id, plugin_id) != 0) 277 { 278 destroyFree(client); 279 return null; 280 } 281 282 CLAPClient clapClient = mallocNew!CLAPClient(client, host); 283 284 return clapClient.get_clap_plugin(); 285 } 286 287 288 // preset factory impl 289 290 uint preset_discovery_count(const(clap_preset_discovery_factory_t)* factory) 291 { 292 return 1; // always one preset provider 293 } 294 295 const(clap_preset_discovery_provider_descriptor_t)* get_preset_dicovery_from_client(Client client) 296 { 297 __gshared char[128] idFZ; 298 __gshared char[128] vendorZ; 299 toBufZ(idFZ, client.CLAPIdentifierFactory); 300 toBufZ(vendorZ, client.vendorName); 301 302 // ID is globally unique, why not. Apparently you can 303 // provide presets for other people's products that way. 304 __gshared clap_preset_discovery_provider_descriptor_t desc; 305 desc.clap_version = CLAP_VERSION; 306 desc.id = idFZ.ptr; 307 desc.name = "Dplug preset provider"; // what an annoying thing to name 308 desc.vendor = vendorZ.ptr; 309 return &desc; 310 } 311 312 // Retrieves a preset provider descriptor by its index. 313 // Returns null in case of error. 314 // The descriptor must not be freed. 315 // [thread-safe] 316 const(clap_preset_discovery_provider_descriptor_t)* 317 preset_discovery_get_descriptor(ClientClass)(const(clap_preset_discovery_factory_t)* factory, uint index) 318 { 319 ScopedForeignCallback!(false, true) sfc; 320 sfc.enter(); 321 322 if (index != 0) 323 return null; 324 325 // Create a client just for the purpose of describing its "preset provider" 326 ClientClass client = mallocNew!ClientClass(); 327 scope(exit) client.destroyFree(); 328 return get_preset_dicovery_from_client(client); 329 } 330 331 const(clap_preset_discovery_provider_t)* 332 preset_discovery_create(ClientClass)(const(clap_preset_discovery_factory_t)* factory, 333 const(clap_preset_discovery_indexer_t)* indexer, 334 const(char)* provider_id) 335 { 336 ScopedForeignCallback!(false, true) sfc; 337 sfc.enter(); 338 339 // Create a client yet again for the purpose of creating its 340 // "preset provider" 341 ClientClass client = mallocNew!ClientClass(); 342 const(clap_preset_discovery_provider_descriptor_t)* desc = get_preset_dicovery_from_client(client); 343 344 if (strcmp(provider_id, desc.id) != 0) 345 { 346 destroyFree(client); 347 return null; 348 } 349 350 // Note: take ownership of that Client 351 CLAPPresetProvider provider = mallocNew!CLAPPresetProvider(client, indexer); 352 __gshared clap_preset_discovery_provider_t provdesc; 353 provdesc.desc = desc; 354 provdesc.provider_data = cast(void*)provider; 355 provdesc.init_ = &provider_init; 356 provdesc.destroy = &provider_destroy; 357 provdesc.get_metadata = &provider_get_metadata; 358 provdesc.get_extension = &provider_get_extension; 359 return &provdesc; 360 } 361 } 362 363 // factory.h 364 365 // Every method must be thread-safe. 366 // It is very important to be able to scan the plugin as quickly as possible. 367 // 368 // The host may use clap_plugin_invalidation_factory to detect filesystem changes 369 // which may change the factory's content. 370 struct clap_plugin_factory_t 371 { 372 nothrow @nogc extern(C): 373 374 // Get the number of plugins available. 375 // [thread-safe] 376 uint function(const(clap_plugin_factory_t)*) get_plugin_count; 377 378 // Retrieves a plugin descriptor by its index. 379 // Returns null in case of error. 380 // The descriptor must not be freed. 381 // [thread-safe] 382 const(clap_plugin_descriptor_t)* function(const(clap_plugin_factory_t)*, uint) get_plugin_descriptor; 383 384 // Create a clap_plugin by its plugin_id. 385 // The returned pointer must be freed by calling plugin->destroy(plugin); 386 // The plugin is not allowed to use the host callbacks in the create method. 387 // Returns null in case of error. 388 // [thread-safe] 389 const(clap_plugin_t)* function(const(clap_plugin_factory_t)*, 390 const(clap_host_t)*, const(char)*) create_plugin; 391 } 392 393 394 // plugin.h 395 396 struct clap_plugin_descriptor_t 397 { 398 clap_version_t clap_version; // initialized to CLAP_VERSION 399 400 // Mandatory fields must be set and must not be blank. 401 // Otherwise the fields can be null or blank, though it is safer to make them blank. 402 // 403 // Some indications regarding id and version 404 // - id is an arbitrary string which should be unique to your plugin, 405 // we encourage you to use a reverse URI eg: "com.u-he.diva" 406 // - version is an arbitrary string which describes a plugin, 407 // it is useful for the host to understand and be able to compare two different 408 // version strings, so here is a regex like expression which is likely to be 409 // understood by most hosts: MAJOR(.MINOR(.REVISION)?)?( (Alpha|Beta) XREV)? 410 const(char)* id; // eg: "com.u-he.diva", mandatory 411 const(char)* name; // eg: "Diva", mandatory 412 const(char)* vendor; // eg: "u-he" 413 const(char)* url; // eg: "https://u-he.com/products/diva/" 414 const(char)* manual_url; // eg: "https://dl.u-he.com/manuals/plugins/diva/Diva-user-guide.pdf" 415 const(char)* support_url; // eg: "https://u-he.com/support/" 416 const(char)* version_; // eg: "1.4.4" 417 const(char)* description; // eg: "The spirit of analogue" 418 419 // Arbitrary list of keywords. 420 // They can be matched by the host indexer and used to classify the plugin. 421 // The array of pointers must be null terminated. 422 // For some standard features see plugin-features.h 423 // Dlang Note: this is a null-terminated array of null-terminated strings. 424 const(char)** features; 425 } 426 427 428 struct clap_plugin_t 429 { 430 nothrow @nogc extern(C): 431 432 const(clap_plugin_descriptor_t)* desc; 433 void *plugin_data; // reserved pointer for the plugin 434 435 // Must be called after creating the plugin. 436 // If init returns false, the host must destroy the plugin instance. 437 // If init returns true, then the plugin is initialized and in the deactivated state. 438 // Unlike in `plugin-factory::create_plugin`, in init you have complete access to the host 439 // and host extensions, so clap related setup activities should be done here rather than in 440 // create_plugin. 441 // [main-thread] 442 bool function(const(clap_plugin_t)* plugin) init; 443 444 // Free the plugin and its resources. 445 // It is required to deactivate the plugin prior to this call. 446 // [main-thread & !active] 447 void function(const(clap_plugin_t)* plugin) destroy; 448 449 // Activate and deactivate the plugin. 450 // In this call the plugin may allocate memory and prepare 451 // everything needed for the process call. The process's sample 452 // rate will be constant and process's frame count will included 453 // in the [min, max] range, which is bounded by [1, INT32_MAX]. 454 // Once activated the latency and port configuration must remain 455 // constant, until deactivation. 456 // Returns true on success. 457 // [main-thread & !active] 458 bool function(const(clap_plugin_t)* plugin, 459 double sample_rate, 460 uint min_frames_count, 461 uint max_frames_count) activate; 462 463 // [main-thread & active] 464 void function(const(clap_plugin_t)*plugin) deactivate; 465 466 // Call start processing before processing. 467 // Returns true on success. 468 // [audio-thread & active & !processing] 469 bool function(const(clap_plugin_t)*plugin) start_processing; 470 471 // Call stop processing before sending the plugin to sleep. 472 // [audio-thread & active & processing] 473 void function(const(clap_plugin_t)* plugin) stop_processing; 474 475 // - Clears all buffers, performs a full reset of the processing state (filters, oscillators, 476 // envelopes, lfo, ...) and kills all voices. 477 // - The parameter's value remain unchanged. 478 // - clap_process.steady_time may jump backward. 479 // 480 // [audio-thread & active] 481 void function(const(clap_plugin_t)* plugin) reset; 482 483 // process audio, events, ... 484 // All the pointers coming from clap_process_t and its nested attributes, 485 // are valid until process() returns. 486 // [audio-thread & active & processing] 487 clap_process_status function(const(clap_plugin_t)*plugin, 488 const(clap_process_t)* processParams) process; 489 490 // Query an extension. 491 // The returned pointer is owned by the plugin. 492 // It is forbidden to call it before plugin->init(). 493 // You can call it within plugin->init() call, and after. 494 // [thread-safe] 495 const(void)* function(const(clap_plugin_t)*plugin, const char *id) get_extension; 496 497 // Called by the host on the main thread in response to a previous call to: 498 // host->request_callback(host); 499 // [main-thread] 500 void function(const(clap_plugin_t)*plugin) on_main_thread; 501 } 502 503 504 // color.h 505 506 struct clap_color 507 { 508 ubyte alpha; 509 ubyte red; 510 ubyte green; 511 ubyte blue; 512 } 513 514 // process.h 515 516 alias clap_process_status = int; 517 enum : clap_process_status 518 { 519 // Processing failed. The output buffer must be discarded. 520 CLAP_PROCESS_ERROR = 0, 521 522 // Processing succeeded, keep processing. 523 CLAP_PROCESS_CONTINUE = 1, 524 525 // Processing succeeded, keep processing if the output is not quiet. 526 CLAP_PROCESS_CONTINUE_IF_NOT_QUIET = 2, 527 528 // Rely upon the plugin's tail to determine if the plugin should continue to process. 529 // see clap_plugin_tail 530 CLAP_PROCESS_TAIL = 3, 531 532 // Processing succeeded, but no more processing is required, 533 // until the next event or variation in audio input. 534 CLAP_PROCESS_SLEEP = 4, 535 } 536 537 struct clap_process_t 538 { 539 // A steady sample time counter. 540 // This field can be used to calculate the sleep duration between two process calls. 541 // This value may be specific to this plugin instance and have no relation to what 542 // other plugin instances may receive. 543 // 544 // Set to -1 if not available, otherwise the value must be greater or equal to 0, 545 // and must be increased by at least `frames_count` for the next call to process. 546 ulong steady_time; 547 548 // Number of frames to process 549 uint frames_count; 550 551 // time info at sample 0 552 // If null, then this is a free running host, no transport events will be provided 553 // Port: CLAP spec doesn't say when *transport contradict an event 554 // in in_events. 555 const(clap_event_transport_t) *transport; 556 557 // Audio buffers, they must have the same count as specified 558 // by clap_plugin_audio_ports->count(). 559 // The index maps to clap_plugin_audio_ports->get(). 560 // Input buffer and its contents are read-only. 561 const(clap_audio_buffer_t)*audio_inputs; 562 clap_audio_buffer_t *audio_outputs; 563 uint audio_inputs_count; 564 uint audio_outputs_count; 565 566 // The input event list can't be modified. 567 // Input read-only event list. The host will deliver these sorted in sample order. 568 const(clap_input_events_t)* in_events; 569 570 // Output event list. The plugin must insert events in sample sorted order when inserting events 571 const(clap_output_events_t)* out_events; 572 } 573 574 // audiobuffer.h 575 576 // Sample code for reading a stereo buffer: 577 // 578 // bool isLeftConstant = (buffer->constant_mask & (1 << 0)) != 0; 579 // bool isRightConstant = (buffer->constant_mask & (1 << 1)) != 0; 580 // 581 // for (int i = 0; i < N; ++i) { 582 // float l = data32[0][isLeftConstant ? 0 : i]; 583 // float r = data32[1][isRightConstant ? 0 : i]; 584 // } 585 // 586 // Note: checking the constant mask is optional, and this implies that 587 // the buffer must be filled with the constant value. 588 // Rationale: if a buffer reader doesn't check the constant mask, then it may 589 // process garbage samples and in result, garbage samples may be transmitted 590 // to the audio interface with all the bad consequences it can have. 591 // 592 // The constant mask is a hint. 593 struct clap_audio_buffer_t 594 { 595 // Either data32 or data64 pointer will be set. 596 float **data32; 597 double **data64; 598 uint channel_count; 599 uint latency; // latency from/to the audio interface 600 ulong constant_mask; 601 } 602 603 604 // params.h 605 606 alias clap_param_info_flags = uint; 607 enum : clap_param_info_flags 608 { 609 // Is this param stepped? (integer values only) 610 // if so the double value is converted to integer using a cast (equivalent to trunc). 611 CLAP_PARAM_IS_STEPPED = 1 << 0, 612 613 // Useful for periodic parameters like a phase 614 CLAP_PARAM_IS_PERIODIC = 1 << 1, 615 616 // The parameter should not be shown to the user, because it is currently not used. 617 // It is not necessary to process automation for this parameter. 618 CLAP_PARAM_IS_HIDDEN = 1 << 2, 619 620 // The parameter can't be changed by the host. 621 CLAP_PARAM_IS_READONLY = 1 << 3, 622 623 // This parameter is used to merge the plugin and host bypass button. 624 // It implies that the parameter is stepped. 625 // min: 0 -> bypass off 626 // max: 1 -> bypass on 627 CLAP_PARAM_IS_BYPASS = 1 << 4, 628 629 // When set: 630 // - automation can be recorded 631 // - automation can be played back 632 // 633 // The host can send live user changes for this parameter regardless of this flag. 634 // 635 // If this parameter affects the internal processing structure of the plugin, ie: max delay, fft 636 // size, ... and the plugins needs to re-allocate its working buffers, then it should call 637 // host->request_restart(), and perform the change once the plugin is re-activated. 638 CLAP_PARAM_IS_AUTOMATABLE = 1 << 5, 639 640 // Does this parameter support the modulation signal? 641 CLAP_PARAM_IS_MODULATABLE = 1 << 10, 642 643 // Does this parameter support per note modulations? 644 CLAP_PARAM_IS_MODULATABLE_PER_NOTE_ID = 1 << 11, 645 646 // Does this parameter support per key modulations? 647 CLAP_PARAM_IS_MODULATABLE_PER_KEY = 1 << 12, 648 649 // Does this parameter support per channel modulations? 650 CLAP_PARAM_IS_MODULATABLE_PER_CHANNEL = 1 << 13, 651 652 // Does this parameter support per port modulations? 653 CLAP_PARAM_IS_MODULATABLE_PER_PORT = 1 << 14, 654 655 // Any change to this parameter will affect the plugin output and requires to be done via 656 // process() if the plugin is active. 657 // 658 // A simple example would be a DC Offset, changing it will change the output signal and must be 659 // processed. 660 CLAP_PARAM_REQUIRES_PROCESS = 1 << 15, 661 662 // This parameter represents an enumerated value. 663 // If you set this flag, then you must set CLAP_PARAM_IS_STEPPED too. 664 // All values from min to max must not have a blank value_to_text(). 665 CLAP_PARAM_IS_ENUM = 1 << 16, 666 } 667 668 struct clap_param_info_t 669 { 670 // Stable parameter identifier, it must never change. 671 clap_id id; 672 673 clap_param_info_flags flags; 674 675 // This value is optional and set by the plugin. 676 // Its purpose is to provide fast access to the plugin parameter object by caching its pointer. 677 // For instance: 678 // 679 // in clap_plugin_params.get_info(): 680 // Parameter *p = findParameter(param_id); 681 // param_info->cookie = p; 682 // 683 // later, in clap_plugin.process(): 684 // 685 // Parameter *p = (Parameter *)event->cookie; 686 // if (!p) [[unlikely]] 687 // p = findParameter(event->param_id); 688 // 689 // where findParameter() is a function the plugin implements to map parameter ids to internal 690 // objects. 691 // 692 // Important: 693 // - The cookie is invalidated by a call to clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) or 694 // when the plugin is destroyed. 695 // - The host will either provide the cookie as issued or nullptr in events addressing 696 // parameters. 697 // - The plugin must gracefully handle the case of a cookie which is nullptr. 698 // - Many plugins will process the parameter events more quickly if the host can provide the 699 // cookie in a faster time than a hashmap lookup per param per event. 700 void *cookie; 701 702 // The display name. eg: "Volume". This does not need to be unique. Do not include the module 703 // text in this. The host should concatenate/format the module + name in the case where showing 704 // the name alone would be too vague. 705 char[CLAP_NAME_SIZE] name; 706 707 // The module path containing the param, eg: "Oscillators/Wavetable 1". 708 // '/' will be used as a separator to show a tree-like structure. 709 char[CLAP_PATH_SIZE] module_; 710 711 double min_value; // Minimum plain value 712 double max_value; // Maximum plain value 713 double default_value; // Default plain value 714 } 715 716 struct clap_plugin_params_t 717 { 718 extern(C) nothrow @nogc: 719 // Returns the number of parameters. 720 // [main-thread] 721 uint function (const(clap_plugin_t)*plugin) count; 722 723 // Copies the parameter's info to param_info. 724 // Returns true on success. 725 // [main-thread] 726 bool function(const(clap_plugin_t)*plugin, 727 uint param_index, 728 clap_param_info_t *param_info) get_info; 729 730 // Writes the parameter's current value to out_value. 731 // Returns true on success. 732 // [main-thread] 733 bool function(const clap_plugin_t *plugin, clap_id param_id, double *out_value) get_value; 734 735 // Fills out_buffer with a null-terminated UTF-8 string that represents the parameter at the 736 // given 'value' argument. eg: "2.3 kHz". The host should always use this to format parameter 737 // values before displaying it to the user. 738 // Returns true on success. 739 // [main-thread] 740 bool function(const(clap_plugin_t)*plugin, 741 clap_id param_id, 742 double value, 743 char *out_buffer, 744 uint out_buffer_capacity) value_to_text; 745 746 // Converts the null-terminated UTF-8 param_value_text into a double and writes it to out_value. 747 // The host can use this to convert user input into a parameter value. 748 // Returns true on success. 749 // [main-thread] 750 bool function(const clap_plugin_t *plugin, 751 clap_id param_id, 752 const(char) *param_value_text, 753 double *out_value) text_to_value; 754 755 // Flushes a set of parameter changes. 756 // This method must not be called concurrently to clap_plugin->process(). 757 // 758 // Note: if the plugin is processing, then the process() call will already achieve the 759 // parameter update (bi-directional), so a call to flush isn't required, also be aware 760 // that the plugin may use the sample offset in process(), while this information would be 761 // lost within flush(). 762 // 763 // [active ? audio-thread : main-thread] 764 void function(const(clap_plugin_t) *plugin, 765 const(clap_input_events_t) *in_, 766 const(clap_output_events_t) *out_) flush; 767 } 768 769 alias clap_param_rescan_flags = uint; 770 enum : clap_param_rescan_flags 771 { 772 // The parameter values did change, eg. after loading a preset. 773 // The host will scan all the parameters value. 774 // The host will not record those changes as automation points. 775 // New values takes effect immediately. 776 CLAP_PARAM_RESCAN_VALUES = 1 << 0, 777 778 // The value to text conversion changed, and the text needs to be rendered again. 779 CLAP_PARAM_RESCAN_TEXT = 1 << 1, 780 781 // The parameter info did change, use this flag for: 782 // - name change 783 // - module change 784 // - is_periodic (flag) 785 // - is_hidden (flag) 786 // New info takes effect immediately. 787 CLAP_PARAM_RESCAN_INFO = 1 << 2, 788 789 // Invalidates everything the host knows about parameters. 790 // It can only be used while the plugin is deactivated. 791 // If the plugin is activated use clap_host->restart() and delay any change until the host calls 792 // clap_plugin->deactivate(). 793 // 794 // You must use this flag if: 795 // - some parameters were added or removed. 796 // - some parameters had critical changes: 797 // - is_per_note (flag) 798 // - is_per_key (flag) 799 // - is_per_channel (flag) 800 // - is_per_port (flag) 801 // - is_readonly (flag) 802 // - is_bypass (flag) 803 // - is_stepped (flag) 804 // - is_modulatable (flag) 805 // - min_value 806 // - max_value 807 // - cookie 808 CLAP_PARAM_RESCAN_ALL = 1 << 3, 809 } 810 811 alias clap_param_clear_flags = uint; 812 enum : clap_param_clear_flags 813 { 814 // Clears all possible references to a parameter 815 CLAP_PARAM_CLEAR_ALL = 1 << 0, 816 817 // Clears all automations to a parameter 818 CLAP_PARAM_CLEAR_AUTOMATIONS = 1 << 1, 819 820 // Clears all modulations to a parameter 821 CLAP_PARAM_CLEAR_MODULATIONS = 1 << 2, 822 } 823 824 struct clap_host_params_t 825 { 826 extern(C) nothrow @nogc: 827 // Rescan the full list of parameters according to the flags. 828 // [main-thread] 829 void function(const(clap_host_t)* host, clap_param_rescan_flags flags) rescan; 830 831 // Clears references to a parameter. 832 // [main-thread] 833 void function(const(clap_host_t)* host, clap_id param_id, clap_param_clear_flags flags) clear; 834 835 // Request a parameter flush. 836 // 837 // The host will then schedule a call to either: 838 // - clap_plugin.process() 839 // - clap_plugin_params.flush() 840 // 841 // This function is always safe to use and should not be called from an [audio-thread] as the 842 // plugin would already be within process() or flush(). 843 // 844 // [thread-safe,!audio-thread] 845 void function(const(clap_host_t)* host) request_flush; 846 } 847 848 849 // events.h 850 851 // event header 852 // must be the first attribute of the event 853 struct clap_event_header_t 854 { 855 uint size; // event size including this header, eg: sizeof (clap_event_note) 856 uint time; // sample offset within the buffer for this event 857 ushort space_id; // event space, see clap_host_event_registry 858 ushort type; // event type 859 uint flags; // see clap_event_flags 860 } 861 862 // The clap core event space 863 enum ushort CLAP_CORE_EVENT_SPACE_ID = 0; 864 865 alias clap_event_flags = int; 866 enum : clap_event_flags 867 { 868 // Indicate a live user event, for example a user turning a physical knob 869 // or playing a physical key. 870 CLAP_EVENT_IS_LIVE = 1 << 0, 871 872 // Indicate that the event should not be recorded. 873 // For example this is useful when a parameter changes because of a MIDI CC, 874 // because if the host records both the MIDI CC automation and the parameter 875 // automation there will be a conflict. 876 CLAP_EVENT_DONT_RECORD = 1 << 1, 877 } 878 879 // Some of the following events overlap, a note on can be expressed with: 880 // - CLAP_EVENT_NOTE_ON 881 // - CLAP_EVENT_MIDI 882 // - CLAP_EVENT_MIDI2 883 // 884 // The preferred way of sending a note event is to use CLAP_EVENT_NOTE_*. 885 // 886 // The same event must not be sent twice: it is forbidden to send a the same note on 887 // encoded with both CLAP_EVENT_NOTE_ON and CLAP_EVENT_MIDI. 888 // 889 // The plugins are encouraged to be able to handle note events encoded as raw midi or midi2, 890 // or implement clap_plugin_event_filter and reject raw midi and midi2 events. 891 enum 892 { 893 // NOTE_ON and NOTE_OFF represent a key pressed and key released event, respectively. 894 // A NOTE_ON with a velocity of 0 is valid and should not be interpreted as a NOTE_OFF. 895 // 896 // NOTE_CHOKE is meant to choke the voice(s), like in a drum machine when a closed hihat 897 // chokes an open hihat. This event can be sent by the host to the plugin. Here are two use 898 // cases: 899 // - a plugin is inside a drum pad in Bitwig Studio's drum machine, and this pad is choked by 900 // another one 901 // - the user double-clicks the DAW's stop button in the transport which then stops the sound on 902 // every track 903 // 904 // NOTE_END is sent by the plugin to the host. The port, channel, key and note_id are those given 905 // by the host in the NOTE_ON event. In other words, this event is matched against the 906 // plugin's note input port. 907 // NOTE_END is useful to help the host to match the plugin's voice life time. 908 // 909 // When using polyphonic modulations, the host has to allocate and release voices for its 910 // polyphonic modulator. Yet only the plugin effectively knows when the host should terminate 911 // a voice. NOTE_END solves that issue in a non-intrusive and cooperative way. 912 // 913 // CLAP assumes that the host will allocate a unique voice on NOTE_ON event for a given port, 914 // channel and key. This voice will run until the plugin will instruct the host to terminate 915 // it by sending a NOTE_END event. 916 // 917 // Consider the following sequence: 918 // - process() 919 // Host->Plugin NoteOn(port:0, channel:0, key:16, time:t0) 920 // Host->Plugin NoteOn(port:0, channel:0, key:64, time:t0) 921 // Host->Plugin NoteOff(port:0, channel:0, key:16, t1) 922 // Host->Plugin NoteOff(port:0, channel:0, key:64, t1) 923 // # on t2, both notes did terminate 924 // Host->Plugin NoteOn(port:0, channel:0, key:64, t3) 925 // # Here the plugin finished processing all the frames and will tell the host 926 // # to terminate the voice on key 16 but not 64, because a note has been started at t3 927 // Plugin->Host NoteEnd(port:0, channel:0, key:16, time:ignored) 928 // 929 // These four events use clap_event_note. 930 CLAP_EVENT_NOTE_ON = 0, 931 CLAP_EVENT_NOTE_OFF = 1, 932 CLAP_EVENT_NOTE_CHOKE = 2, 933 CLAP_EVENT_NOTE_END = 3, 934 935 // Represents a note expression. 936 // Uses clap_event_note_expression. 937 CLAP_EVENT_NOTE_EXPRESSION = 4, 938 939 // PARAM_VALUE sets the parameter's value; uses clap_event_param_value. 940 // PARAM_MOD sets the parameter's modulation amount; uses clap_event_param_mod. 941 // 942 // The value heard is: param_value + param_mod. 943 // 944 // In case of a concurrent global value/modulation versus a polyphonic one, 945 // the voice should only use the polyphonic one and the polyphonic modulation 946 // amount will already include the monophonic signal. 947 CLAP_EVENT_PARAM_VALUE = 5, 948 CLAP_EVENT_PARAM_MOD = 6, 949 950 // Indicates that the user started or finished adjusting a knob. 951 // This is not mandatory to wrap parameter changes with gesture events, but this improves 952 // the user experience a lot when recording automation or overriding automation playback. 953 // Uses clap_event_param_gesture. 954 CLAP_EVENT_PARAM_GESTURE_BEGIN = 7, 955 CLAP_EVENT_PARAM_GESTURE_END = 8, 956 957 CLAP_EVENT_TRANSPORT = 9, // update the transport info; clap_event_transport 958 CLAP_EVENT_MIDI = 10, // raw midi event; clap_event_midi 959 CLAP_EVENT_MIDI_SYSEX = 11, // raw midi sysex event; clap_event_midi_sysex 960 CLAP_EVENT_MIDI2 = 12, // raw midi 2 event; clap_event_midi2 961 } 962 963 // Note on, off, end and choke events. 964 // 965 // Clap addresses notes and voices using the 4-value tuple 966 // (port, channel, key, note_id). Note on/off/end/choke 967 // events and parameter modulation messages are delivered with 968 // these values populated. 969 // 970 // Values in a note and voice address are either >= 0 if they 971 // are specified, or -1 to indicate a wildcard. A wildcard 972 // means a voice with any value in that part of the tuple 973 // matches the message. 974 // 975 // For instance, a (PCKN) of (0, 3, -1, -1) will match all voices 976 // on channel 3 of port 0. And a PCKN of (-1, 0, 60, -1) will match 977 // all channel 0 key 60 voices, independent of port or note id. 978 // 979 // Especially in the case of note-on note-off pairs, and in the 980 // absence of voice stacking or polyphonic modulation, a host may 981 // choose to issue a note id only at note on. So you may see a 982 // message stream like 983 // 984 // CLAP_EVENT_NOTE_ON [0,0,60,184] 985 // CLAP_EVENT_NOTE_OFF [0,0,60,-1] 986 // 987 // and the host will expect the first voice to be released. 988 // Well constructed plugins will search for voices and notes using 989 // the entire tuple. 990 // 991 // In the case of note on events: 992 // - The port, channel and key must be specified with a value >= 0 993 // - A note-on event with a '-1' for port, channel or key is invalid and 994 // can be rejected or ignored by a plugin or host. 995 // - A host which does not support note ids should set the note id to -1. 996 // 997 // In the case of note choke or end events: 998 // - the velocity is ignored. 999 // - key and channel are used to match active notes 1000 // - note_id is optionally provided by the host 1001 struct clap_event_note_t 1002 { 1003 clap_event_header_t header; 1004 int note_id; // host provided note id >= 0, or -1 if unspecified or wildcard 1005 short port_index; // port index from ext/note-ports; -1 for wildcard 1006 short channel; // 0..15, same as MIDI1 Channel Number, -1 for wildcard 1007 short key; // 0..127, same as MIDI1 Key Number (60==Middle C), -1 for wildcard 1008 double velocity; // 0..1 1009 } 1010 1011 // Note Expressions are well named modifications of a voice targeted to 1012 // voices using the same wildcard rules described above. Note Expressions are delivered 1013 // as sample accurate events and should be applied at the sample when received. 1014 // 1015 // Note expressions are a statement of value, not cumulative. A PAN event of 0 followed by 1 1016 // followed by 0.5 would pan hard left, hard right, and center. They are intended as 1017 // an offset from the non-note-expression voice default. A voice which had a volume of 1018 // -20db absent note expressions which received a +4db note expression would move the 1019 // voice to -16db. 1020 // 1021 // A plugin which receives a note expression at the same sample as a NOTE_ON event 1022 // should apply that expression to all generated samples. A plugin which receives 1023 // a note expression after a NOTE_ON event should initiate the voice with default 1024 // values and then apply the note expression when received. A plugin may make a choice 1025 // to smooth note expression streams. 1026 enum 1027 { 1028 // with 0 < x <= 4, plain = 20 * log(x) 1029 CLAP_NOTE_EXPRESSION_VOLUME = 0, 1030 1031 // pan, 0 left, 0.5 center, 1 right 1032 CLAP_NOTE_EXPRESSION_PAN = 1, 1033 1034 // Relative tuning in semitones, from -120 to +120. Semitones are in 1035 // equal temperament and are doubles; the resulting note would be 1036 // retuned by `100 * evt->value` cents. 1037 CLAP_NOTE_EXPRESSION_TUNING = 2, 1038 1039 // 0..1 1040 CLAP_NOTE_EXPRESSION_VIBRATO = 3, 1041 CLAP_NOTE_EXPRESSION_EXPRESSION = 4, 1042 CLAP_NOTE_EXPRESSION_BRIGHTNESS = 5, 1043 CLAP_NOTE_EXPRESSION_PRESSURE = 6, 1044 } 1045 alias clap_note_expression = int; 1046 1047 struct clap_event_note_expression_t 1048 { 1049 clap_event_header_t header; 1050 1051 clap_note_expression expression_id; 1052 1053 // target a specific note_id, port, key and channel, with 1054 // -1 meaning wildcard, per the wildcard discussion above 1055 int note_id; 1056 short port_index; 1057 short channel; 1058 short key; 1059 1060 double value; // see expression for the range 1061 } 1062 1063 struct clap_event_param_value_t 1064 { 1065 clap_event_header_t header; 1066 1067 // target parameter 1068 clap_id param_id; // @ref clap_param_info.id 1069 void *cookie; // @ref clap_param_info.cookie 1070 1071 // target a specific note_id, port, key and channel, with 1072 // -1 meaning wildcard, per the wildcard discussion above 1073 int note_id; 1074 short port_index; 1075 short channel; 1076 short key; 1077 1078 double value; 1079 } 1080 1081 struct clap_event_param_mod_t 1082 { 1083 clap_event_header_t header; 1084 1085 // target parameter 1086 clap_id param_id; // @ref clap_param_info.id 1087 void *cookie; // @ref clap_param_info.cookie 1088 1089 // target a specific note_id, port, key and channel, with 1090 // -1 meaning wildcard, per the wildcard discussion above 1091 int note_id; 1092 short port_index; 1093 short channel; 1094 short key; 1095 1096 double amount; // modulation amount 1097 } 1098 1099 struct clap_event_param_gesture_t 1100 { 1101 clap_event_header_t header; 1102 1103 // target parameter 1104 clap_id param_id; // @ref clap_param_info.id 1105 } 1106 1107 alias clap_transport_flags = int; 1108 enum : clap_transport_flags 1109 { 1110 CLAP_TRANSPORT_HAS_TEMPO = 1 << 0, 1111 CLAP_TRANSPORT_HAS_BEATS_TIMELINE = 1 << 1, 1112 CLAP_TRANSPORT_HAS_SECONDS_TIMELINE = 1 << 2, 1113 CLAP_TRANSPORT_HAS_TIME_SIGNATURE = 1 << 3, 1114 CLAP_TRANSPORT_IS_PLAYING = 1 << 4, 1115 CLAP_TRANSPORT_IS_RECORDING = 1 << 5, 1116 CLAP_TRANSPORT_IS_LOOP_ACTIVE = 1 << 6, 1117 CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL = 1 << 7, 1118 } 1119 1120 struct clap_event_transport_t 1121 { 1122 clap_event_header_t header; 1123 1124 uint flags; // see clap_transport_flags 1125 1126 clap_beattime song_pos_beats; // position in beats 1127 clap_sectime song_pos_seconds; // position in seconds 1128 1129 double tempo; // in bpm 1130 double tempo_inc; // tempo increment for each sample and until the next 1131 // time info event 1132 1133 clap_beattime loop_start_beats; 1134 clap_beattime loop_end_beats; 1135 clap_sectime loop_start_seconds; 1136 clap_sectime loop_end_seconds; 1137 1138 clap_beattime bar_start; // start pos of the current bar 1139 int bar_number; // bar at song pos 0 has the number 0 1140 1141 ushort tsig_num; // time signature numerator 1142 ushort tsig_denom; // time signature denominator 1143 } 1144 1145 struct clap_event_midi_t 1146 { 1147 clap_event_header_t header; 1148 1149 ushort port_index; 1150 ubyte[3] data; 1151 } 1152 1153 struct clap_event_midi_sysex_t 1154 { 1155 clap_event_header_t header; 1156 ushort port_index; 1157 const(ubyte)* buffer; // midi buffer 1158 uint size; 1159 } 1160 1161 // While it is possible to use a series of midi2 event to send a sysex, 1162 // prefer clap_event_midi_sysex if possible for efficiency. 1163 struct clap_event_midi2_t 1164 { 1165 clap_event_header_t header; 1166 ushort port_index; 1167 uint[4] data; 1168 } 1169 1170 // A CLAP event that is a union of any type of event 1171 union clap_event_any_t 1172 { 1173 clap_event_note_t event_note; 1174 clap_event_note_expression_t note_expression; 1175 clap_event_param_value_t param_value; 1176 clap_event_param_mod_t param_mod; 1177 clap_event_param_gesture_t param_gesture; 1178 clap_event_transport_t transport; 1179 clap_event_midi_t midi; 1180 clap_event_midi_sysex_t midi_sysex; 1181 clap_event_midi2_t midi2; 1182 } 1183 1184 // A.Bique said: "If you are using non standard events, you should 1185 // make the event a single block of memory if possible, and use 1186 // relative pointers instead, I mean offsets from the start of the 1187 // struct. 1188 // Cross process events could happen, for example if we have an intel 1189 // 32 bits plugin and a 64 bits one, and one plugin is sending an 1190 // output event, we'd have to pass it to the other plugin host, via 1191 // IPC, so it has to work with memcpy()" 1192 1193 1194 // Input event list. The host will deliver these sorted in sample order. 1195 struct clap_input_events_t 1196 { 1197 extern(C) nothrow @nogc: 1198 void *ctx; // reserved pointer for the list 1199 1200 // returns the number of events in the list 1201 uint function(const(clap_input_events_t) *list) size; 1202 1203 // Don't free the returned event, it belongs to the list 1204 const(clap_event_header_t)* function(const(clap_input_events_t)*list, uint index) get; 1205 } 1206 1207 // Output event list. The plugin must insert events in sample sorted order when inserting events 1208 struct clap_output_events_t 1209 { 1210 extern(C) nothrow @nogc: 1211 void *ctx; // reserved pointer for the list 1212 1213 // Pushes a copy of the event 1214 // returns false if the event could not be pushed to the queue (out of memory?) 1215 bool function(const(clap_output_events_t)* list, 1216 const(clap_event_header_t)* event) try_push; 1217 } 1218 1219 1220 // audio-ports 1221 // another name for "buses" 1222 1223 // 1224 // This extension provides a way for the plugin to describe its current audio ports. 1225 // 1226 // If the plugin does not implement this extension, it won't have audio ports. 1227 // 1228 // 32 bits support is required for both host and plugins. 64 bits audio is optional. 1229 // 1230 // The plugin is only allowed to change its ports configuration while it is deactivated. 1231 1232 static immutable string CLAP_EXT_AUDIO_PORTS = "clap.audio-ports"; 1233 static immutable string CLAP_PORT_MONO = "mono"; 1234 static immutable string CLAP_PORT_STEREO = "stereo"; 1235 1236 enum 1237 { 1238 // This port is the main audio input or output. 1239 // There can be only one main input and main output. 1240 // Main port must be at index 0. 1241 CLAP_AUDIO_PORT_IS_MAIN = 1 << 0, 1242 1243 // This port can be used with 64 bits audio 1244 CLAP_AUDIO_PORT_SUPPORTS_64BITS = 1 << 1, 1245 1246 // 64 bits audio is preferred with this port 1247 CLAP_AUDIO_PORT_PREFERS_64BITS = 1 << 2, 1248 1249 // This port must be used with the same sample size as all the other ports which have this flag. 1250 // In other words if all ports have this flag then the plugin may either be used entirely with 1251 // 64 bits audio or 32 bits audio, but it can't be mixed. 1252 CLAP_AUDIO_PORT_REQUIRES_COMMON_SAMPLE_SIZE = 1 << 3, 1253 } 1254 1255 struct clap_audio_port_info_t 1256 { 1257 // id identifies a port and must be stable. 1258 // id may overlap between input and output ports. 1259 clap_id id; 1260 char[CLAP_NAME_SIZE] name; // displayable name 1261 1262 uint flags; 1263 uint channel_count; 1264 1265 // If null or empty then it is unspecified (arbitrary audio). 1266 // This field can be compared against: 1267 // - CLAP_PORT_MONO 1268 // - CLAP_PORT_STEREO 1269 // - CLAP_PORT_SURROUND (defined in the surround extension) 1270 // - CLAP_PORT_AMBISONIC (defined in the ambisonic extension) 1271 // 1272 // An extension can provide its own port type and way to inspect the channels. 1273 const(char)* port_type; 1274 1275 // in-place processing: allow the host to use the same buffer for input and output 1276 // if supported set the pair port id. 1277 // if not supported set to CLAP_INVALID_ID 1278 clap_id in_place_pair; 1279 } 1280 1281 // The audio ports scan has to be done while the plugin is deactivated. 1282 struct clap_plugin_audio_ports_t 1283 { 1284 extern(C) nothrow @nogc: 1285 1286 // Number of ports, for either input or output 1287 // [main-thread] 1288 uint function(const(clap_plugin_t)* plugin, bool is_input) count; 1289 1290 // Get info about an audio port. 1291 // Returns true on success and stores the result into info. 1292 // [main-thread] 1293 bool function(const(clap_plugin_t)* plugin, 1294 uint index, 1295 bool is_input, 1296 clap_audio_port_info_t *info) get; 1297 } 1298 1299 // gui.h 1300 1301 /// @page GUI 1302 /// 1303 /// This extension defines how the plugin will present its GUI. 1304 /// 1305 /// There are two approaches: 1306 /// 1. the plugin creates a window and embeds it into the host's window 1307 /// 2. the plugin creates a floating window 1308 /// 1309 /// Embedding the window gives more control to the host, and feels more integrated. 1310 /// Floating window are sometimes the only option due to technical limitations. 1311 /// 1312 /// Showing the GUI works as follow: 1313 /// 1. clap_plugin_gui->is_api_supported(), check what can work 1314 /// 2. clap_plugin_gui->create(), allocates gui resources 1315 /// 3. if the plugin window is floating 1316 /// 4. -> clap_plugin_gui->set_transient() 1317 /// 5. -> clap_plugin_gui->suggest_title() 1318 /// 6. else 1319 /// 7. -> clap_plugin_gui->set_scale() 1320 /// 8. -> clap_plugin_gui->can_resize() 1321 /// 9. -> if resizable and has known size from previous session, clap_plugin_gui->set_size() 1322 /// 10. -> else clap_plugin_gui->get_size(), gets initial size 1323 /// 11. -> clap_plugin_gui->set_parent() 1324 /// 12. clap_plugin_gui->show() 1325 /// 13. clap_plugin_gui->hide()/show() ... 1326 /// 14. clap_plugin_gui->destroy() when done with the gui 1327 /// 1328 /// Resizing the window (initiated by the plugin, if embedded): 1329 /// 1. Plugins calls clap_host_gui->request_resize() 1330 /// 2. If the host returns true the new size is accepted, 1331 /// the host doesn't have to call clap_plugin_gui->set_size(). 1332 /// If the host returns false, the new size is rejected. 1333 /// 1334 /// Resizing the window (drag, if embedded)): 1335 /// 1. Only possible if clap_plugin_gui->can_resize() returns true 1336 /// 2. Mouse drag -> new_size 1337 /// 3. clap_plugin_gui->adjust_size(new_size) -> working_size 1338 /// 4. clap_plugin_gui->set_size(working_size) 1339 1340 // If your windowing API is not listed here, please open an issue and we'll figure it out. 1341 // https://github.com/free-audio/clap/issues/new 1342 1343 // uses physical size 1344 // embed using https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent 1345 static immutable string CLAP_WINDOW_API_WIN32 = "win32"; 1346 1347 // uses logical size, don't call clap_plugin_gui->set_scale() 1348 static immutable string CLAP_WINDOW_API_COCOA = "cocoa"; 1349 1350 // uses physical size 1351 // embed using https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html 1352 static immutable string CLAP_WINDOW_API_X11 = "x11"; 1353 1354 // uses physical size 1355 // embed is currently not supported, use floating windows 1356 static immutable string CLAP_WINDOW_API_WAYLAND = "wayland"; 1357 1358 alias clap_hwnd = void*; 1359 alias clap_nsview = void*; 1360 alias clap_xwnd = c_ulong; 1361 1362 // Represent a window reference. 1363 struct clap_window_t 1364 { 1365 const(char) *api; // one of CLAP_WINDOW_API_XXX 1366 union 1367 { 1368 clap_nsview cocoa; 1369 clap_xwnd x11; 1370 clap_hwnd win32; 1371 void *ptr; // for anything defined outside of clap 1372 } 1373 } 1374 1375 // Information to improve window resizing when initiated by the host or window manager. 1376 struct clap_gui_resize_hints_t 1377 { 1378 bool can_resize_horizontally; 1379 bool can_resize_vertically; 1380 1381 // only if can resize horizontally and vertically 1382 bool preserve_aspect_ratio; 1383 uint aspect_ratio_width; 1384 uint aspect_ratio_height; 1385 } 1386 1387 // Size (width, height) is in pixels; the corresponding windowing system extension is 1388 // responsible for defining if it is physical pixels or logical pixels. 1389 struct clap_plugin_gui_t 1390 { 1391 extern(C) nothrow @nogc: 1392 1393 // Returns true if the requested gui api is supported 1394 // [main-thread] 1395 bool function(const clap_plugin_t *plugin, const char *api, bool is_floating) is_api_supported; 1396 1397 // Returns true if the plugin has a preferred api. 1398 // The host has no obligation to honor the plugin preference, this is just a hint. 1399 // The const char **api variable should be explicitly assigned as a pointer to 1400 // one of the CLAP_WINDOW_API_ constants defined above, not strcopied. 1401 // [main-thread] 1402 bool function(const clap_plugin_t *plugin, 1403 const(char) **api, 1404 bool *is_floating) get_preferred_api; 1405 1406 // Create and allocate all resources necessary for the gui. 1407 // 1408 // If is_floating is true, then the window will not be managed by the host. The plugin 1409 // can set its window to stays above the parent window, see set_transient(). 1410 // api may be null or blank for floating window. 1411 // 1412 // If is_floating is false, then the plugin has to embed its window into the parent window, see 1413 // set_parent(). 1414 // 1415 // After this call, the GUI may not be visible yet; don't forget to call show(). 1416 // 1417 // Returns true if the GUI is successfully created. 1418 // [main-thread] 1419 bool function(const clap_plugin_t *plugin, const char *api, bool is_floating) create; 1420 1421 // Free all resources associated with the gui. 1422 // [main-thread] 1423 void function(const clap_plugin_t *plugin) destroy; 1424 1425 // Set the absolute GUI scaling factor, and override any OS info. 1426 // Should not be used if the windowing api relies upon logical pixels. 1427 // 1428 // If the plugin prefers to work out the scaling factor itself by querying the OS directly, 1429 // then ignore the call. 1430 // 1431 // scale = 2 means 200% scaling. 1432 // 1433 // Returns true if the scaling could be applied 1434 // Returns false if the call was ignored, or the scaling could not be applied. 1435 // [main-thread] 1436 bool function(const clap_plugin_t *plugin, double scale) set_scale; 1437 1438 // Get the current size of the plugin UI. 1439 // clap_plugin_gui->create() must have been called prior to asking the size. 1440 // 1441 // Returns true if the plugin could get the size. 1442 // [main-thread] 1443 bool function(const clap_plugin_t *plugin, uint *width, uint *height) get_size; 1444 1445 // Returns true if the window is resizeable (mouse drag). 1446 // [main-thread & !floating] 1447 bool function(const clap_plugin_t *plugin) can_resize; 1448 1449 // Returns true if the plugin can provide hints on how to resize the window. 1450 // [main-thread & !floating] 1451 bool function(const clap_plugin_t *plugin, clap_gui_resize_hints_t *hints) get_resize_hints; 1452 1453 // If the plugin gui is resizable, then the plugin will calculate the closest 1454 // usable size which fits in the given size. 1455 // This method does not change the size. 1456 // 1457 // Returns true if the plugin could adjust the given size. 1458 // [main-thread & !floating] 1459 bool function(const clap_plugin_t *plugin, uint *width, uint *height) adjust_size; 1460 1461 // Sets the window size. 1462 // 1463 // Returns true if the plugin could resize its window to the given size. 1464 // [main-thread & !floating] 1465 bool function(const clap_plugin_t *plugin, uint width, uint height) set_size; 1466 1467 // Embeds the plugin window into the given window. 1468 // 1469 // Returns true on success. 1470 // [main-thread & !floating] 1471 bool function(const clap_plugin_t *plugin, const clap_window_t *window) set_parent; 1472 1473 // Set the plugin floating window to stay above the given window. 1474 // 1475 // Returns true on success. 1476 // [main-thread & floating] 1477 bool function(const clap_plugin_t *plugin, const clap_window_t *window) set_transient; 1478 1479 // Suggests a window title. Only for floating windows. 1480 // 1481 // [main-thread & floating] 1482 void function(const clap_plugin_t *plugin, const char *title) suggest_title; 1483 1484 // Show the window. 1485 // 1486 // Returns true on success. 1487 // [main-thread] 1488 bool function(const clap_plugin_t *plugin) show; 1489 1490 // Hide the window, this method does not free the resources, it just hides 1491 // the window content. Yet it may be a good idea to stop painting timers. 1492 // 1493 // Returns true on success. 1494 // [main-thread] 1495 bool function(const clap_plugin_t *plugin) hide; 1496 } 1497 1498 struct clap_host_gui_t 1499 { 1500 extern(C) nothrow @nogc: 1501 1502 // The host should call get_resize_hints() again. 1503 // [thread-safe & !floating] 1504 void function(const clap_host_t *host) resize_hints_changed; 1505 1506 // Request the host to resize the client area to width, height. 1507 // Return true if the new size is accepted, false otherwise. 1508 // The host doesn't have to call set_size(). 1509 // 1510 // Note: if not called from the main thread, then a return value simply means that the host 1511 // acknowledged the request and will process it asynchronously. If the request then can't be 1512 // satisfied then the host will call set_size() to revert the operation. 1513 // [thread-safe & !floating] 1514 bool function(const clap_host_t *host, uint width, uint height) request_resize; 1515 1516 // Request the host to show the plugin gui. 1517 // Return true on success, false otherwise. 1518 // [thread-safe] 1519 bool function(const clap_host_t *host) request_show; 1520 1521 // Request the host to hide the plugin gui. 1522 // Return true on success, false otherwise. 1523 // [thread-safe] 1524 bool function(const clap_host_t *host) request_hide; 1525 1526 // The floating window has been closed, or the connection to the gui has been lost. 1527 // 1528 // If was_destroyed is true, then the host must call clap_plugin_gui->destroy() to acknowledge 1529 // the gui destruction. 1530 // [thread-safe] 1531 void function(const clap_host_t *host, bool was_destroyed) closed; 1532 } 1533 1534 // host.h 1535 1536 struct clap_host_t 1537 { 1538 extern(C) nothrow @nogc: 1539 clap_version_t clap_version; // initialized to CLAP_VERSION 1540 1541 void* host_data; // reserved pointer for the host 1542 1543 // name and version are mandatory. 1544 const(char) *name; // eg: "Bitwig Studio" 1545 const(char) *vendor; // eg: "Bitwig GmbH" 1546 const(char) *url; // eg: "https://bitwig.com" 1547 const(char) *version_; // eg: "4.3", see plugin.h for advice on how to format the version 1548 1549 // Query an extension. 1550 // The returned pointer is owned by the host. 1551 // It is forbidden to call it before plugin->init(). 1552 // You can call it within plugin->init() call, and after. 1553 // [thread-safe] 1554 const(void)* function(const(clap_host_t) *host, const(char)* extension_id) get_extension; 1555 1556 // Request the host to deactivate and then reactivate the plugin. 1557 // The operation may be delayed by the host. 1558 // [thread-safe] 1559 void function(const(clap_host_t)*host) request_restart; 1560 1561 // Request the host to activate and start processing the plugin. 1562 // This is useful if you have external IO and need to wake up the plugin from "sleep". 1563 // [thread-safe] 1564 void function(const(clap_host_t)*host) request_process; 1565 1566 // Request the host to schedule a call to plugin->on_main_thread(plugin) on the main thread. 1567 // [thread-safe] 1568 void function(const(clap_host_t)*host) request_callback; 1569 } 1570 1571 // latency.h 1572 1573 struct clap_plugin_latency_t 1574 { 1575 extern(C) nothrow @nogc: 1576 // Returns the plugin latency in samples. 1577 // [main-thread & (being-activated | active)] 1578 uint function(const(clap_plugin_t)* plugin) get; 1579 } 1580 1581 struct clap_host_latency_t 1582 { 1583 extern(C) nothrow @nogc: 1584 // Tell the host that the latency changed. 1585 // The latency is only allowed to change during plugin->activate. 1586 // If the plugin is activated, call host->request_restart() 1587 // [main-thread & being-activated] 1588 void function(const(clap_host_t)* host) changed; 1589 } 1590 1591 // state.h 1592 1593 struct clap_plugin_state_t 1594 { 1595 extern(C) nothrow @nogc: 1596 // Saves the plugin state into stream. 1597 // Returns true if the state was correctly saved. 1598 // [main-thread] 1599 bool function(const(clap_plugin_t)* plugin, const(clap_ostream_t)* stream) save; 1600 1601 // Loads the plugin state from stream. 1602 // Returns true if the state was correctly restored. 1603 // [main-thread] 1604 bool function(const(clap_plugin_t)* plugin, const(clap_istream_t)* stream) load; 1605 } 1606 1607 struct clap_host_state_t 1608 { 1609 extern(C) nothrow @nogc: 1610 // Tell the host that the plugin state has changed and should be saved again. 1611 // If a parameter value changes, then it is implicit that the state is dirty. 1612 // [main-thread] 1613 void function(const(clap_host_t)* host) mark_dirty; 1614 } 1615 1616 1617 // stream.h 1618 1619 /// @page Streams 1620 /// 1621 /// ## Notes on using streams 1622 /// 1623 /// When working with `clap_istream` and `clap_ostream` objects to load and save 1624 /// state, it is important to keep in mind that the host may limit the number of 1625 /// bytes that can be read or written at a time. The return values for the 1626 /// stream read and write functions indicate how many bytes were actually read 1627 /// or written. You need to use a loop to ensure that you read or write the 1628 /// entirety of your state. Don't forget to also consider the negative return 1629 /// values for the end of file and IO error codes. 1630 1631 struct clap_istream_t 1632 { 1633 extern(C) nothrow @nogc: 1634 void *ctx; // reserved pointer for the stream 1635 1636 // returns the number of bytes read; 0 indicates end of file and -1 a read error 1637 long function(const(clap_istream_t)* stream, void *buffer, ulong size) read; 1638 } 1639 1640 struct clap_ostream_t 1641 { 1642 extern(C) nothrow @nogc: 1643 void *ctx; // reserved pointer for the stream 1644 1645 // returns the number of bytes written; -1 on write error 1646 long function(const(clap_ostream_t)* stream, const(void)* buffer, ulong size) write; 1647 } 1648 1649 // Helper function to perform a whole read in a loop. 1650 // Return `size` if `size` bytes were read. 1651 // -1 on error or if less bytes were read than `size`. 1652 // There is no end-of-file indication. 1653 long readExactly(const(clap_istream_t)* stream, void *buffer, ulong size) 1654 { 1655 ulong remain = size; 1656 ubyte* bbuf = cast(ubyte*) buffer; 1657 while (remain > 0) 1658 { 1659 long read = stream.read(stream, bbuf, remain); 1660 if (read == -1) 1661 return -1; 1662 1663 remain -= read; 1664 assert(remain >= 0); 1665 bbuf += read; 1666 1667 if (read == 0) // end of file 1668 break; 1669 } 1670 return (remain == 0) ? size : -1; 1671 } 1672 1673 // Helper function to perform a whole read in a loop. 1674 // Return `size` if `size` bytes were read. 1675 // -1 on error or if less bytes were read than `size`. 1676 // There is no end-of-file indication. 1677 long writeExactly(const(clap_ostream_t)* stream, void *buffer, ulong size) 1678 { 1679 ulong remain = size; 1680 ubyte* bbuf = cast(ubyte*) buffer; 1681 while (remain > 0) 1682 { 1683 long written = stream.write(stream, bbuf, remain); 1684 if (written == -1) 1685 return -1; 1686 1687 remain -= written; 1688 assert(remain >= 0); 1689 bbuf += written; 1690 1691 if (written == 0) // nothing written, exit 1692 break; 1693 } 1694 return (remain == 0) ? size : -1; 1695 } 1696 1697 1698 // tail.h 1699 1700 struct clap_plugin_tail_t 1701 { 1702 extern(C) nothrow @nogc: 1703 // Returns tail length in samples. 1704 // Any value greater or equal to INT32_MAX implies infinite tail. 1705 // [main-thread,audio-thread] 1706 uint function(const(clap_plugin_t)* plugin) get; 1707 } 1708 1709 struct clap_host_tail_t 1710 { 1711 extern(C) nothrow @nogc: 1712 // Tell the host that the tail has changed. 1713 // [audio-thread] 1714 void function(const(clap_host_t)* host) changed; 1715 } 1716 1717 1718 // universal-id.h 1719 1720 // Pair of plugin ABI and plugin identifier. 1721 // 1722 // If you want to represent other formats please send us an update to the comment with the 1723 // name of the abi and the representation of the id. 1724 struct clap_universal_plugin_id_t 1725 { 1726 // The plugin ABI name, in lowercase and null-terminated. 1727 // eg: "clap", "vst3", "vst2", "au", ... 1728 const(char)* abi; 1729 1730 // The plugin ID, null-terminated and formatted as follows: 1731 // 1732 // CLAP: use the plugin id 1733 // eg: "com.u-he.diva" 1734 // 1735 // AU: format the string like "type:subt:manu" 1736 // eg: "aumu:SgXT:VmbA" 1737 // 1738 // VST2: print the id as a signed 32-bits integer 1739 // eg: "-4382976" 1740 // 1741 // VST3: print the id as a standard UUID 1742 // eg: "123e4567-e89b-12d3-a456-426614174000" 1743 const(char)* id; 1744 } 1745 1746 // timestamp.h 1747 1748 // This type defines a timestamp: the number of seconds since UNIX EPOCH. 1749 // See C's time_t time(time_t *). 1750 alias clap_timestamp = ulong; 1751 1752 1753 // preset-discovery.h 1754 1755 /* 1756 Preset Discovery API. 1757 1758 Preset Discovery enables a plug-in host to identify where presets are found, what 1759 extensions they have, which plug-ins they apply to, and other metadata associated with the 1760 presets so that they can be indexed and searched for quickly within the plug-in host's browser. 1761 1762 This has a number of advantages for the user: 1763 - it allows them to browse for presets from one central location in a consistent way 1764 - the user can browse for presets without having to commit to a particular plug-in first 1765 1766 The API works as follow to index presets and presets metadata: 1767 1. clap_plugin_entry.get_factory(CLAP_PRESET_DISCOVERY_FACTORY_ID) 1768 2. clap_preset_discovery_factory_t.create(...) 1769 3. clap_preset_discovery_provider.init() (only necessary the first time, declarations 1770 can be cached) 1771 `-> clap_preset_discovery_indexer.declare_filetype() 1772 `-> clap_preset_discovery_indexer.declare_location() 1773 `-> clap_preset_discovery_indexer.declare_soundpack() (optional) 1774 `-> clap_preset_discovery_indexer.set_invalidation_watch_file() (optional) 1775 4. crawl the given locations and monitor file system changes 1776 `-> clap_preset_discovery_indexer.get_metadata() for each presets files 1777 1778 Then to load a preset, use ext/draft/preset-load.h. 1779 TODO: create a dedicated repo for other plugin abi preset-load extension. 1780 1781 The design of this API deliberately does not define a fixed set tags or categories. It is the 1782 plug-in host's job to try to intelligently map the raw list of features that are found for a 1783 preset and to process this list to generate something that makes sense for the host's tagging and 1784 categorization system. The reason for this is to reduce the work for a plug-in developer to add 1785 Preset Discovery support for their existing preset file format and not have to be concerned with 1786 all the different hosts and how they want to receive the metadata. 1787 1788 VERY IMPORTANT: 1789 - the whole indexing process has to be **fast** 1790 - clap_preset_provider->get_metadata() has to be fast and avoid unnecessary operations 1791 - the whole indexing process must not be interactive 1792 - don't show dialogs, windows, ... 1793 - don't ask for user input 1794 */ 1795 1796 // Use it to retrieve const clap_preset_discovery_factory_t* from 1797 // clap_plugin_entry.get_factory() 1798 enum string CLAP_PRESET_DISCOVERY_FACTORY_ID = "clap.preset-discovery-factory/2"; 1799 1800 // The latest draft is 100% compatible. 1801 // This compat ID may be removed in 2026. 1802 enum string CLAP_PRESET_DISCOVERY_FACTORY_ID_COMPAT = "clap.preset-discovery-factory/draft-2"; 1803 1804 alias clap_preset_discovery_location_kind = int; 1805 enum : clap_preset_discovery_location_kind 1806 { 1807 // The preset are located in a file on the OS filesystem. 1808 // The location is then a path which works with the OS file system functions (open, stat, ...) 1809 // So both '/' and '\' shall work on Windows as a separator. 1810 CLAP_PRESET_DISCOVERY_LOCATION_FILE = 0, 1811 1812 // The preset is bundled within the plugin DSO itself. 1813 // The location must then be null, as the preset are within the plugin itself and then the plugin 1814 // will act as a preset container. 1815 CLAP_PRESET_DISCOVERY_LOCATION_PLUGIN = 1, 1816 } 1817 1818 alias clap_preset_discovery_flags = int; 1819 enum : clap_preset_discovery_flags 1820 { 1821 // This is for factory or sound-pack presets. 1822 CLAP_PRESET_DISCOVERY_IS_FACTORY_CONTENT = 1 << 0, 1823 1824 // This is for user presets. 1825 CLAP_PRESET_DISCOVERY_IS_USER_CONTENT = 1 << 1, 1826 1827 // This location is meant for demo presets, those are preset which may trigger 1828 // some limitation in the plugin because they require additional features which the user 1829 // needs to purchase or the content itself needs to be bought and is only available in 1830 // demo mode. 1831 CLAP_PRESET_DISCOVERY_IS_DEMO_CONTENT = 1 << 2, 1832 1833 // This preset is a user's favorite 1834 CLAP_PRESET_DISCOVERY_IS_FAVORITE = 1 << 3, 1835 } 1836 1837 1838 // Receiver that receives the metadata for a single preset file. 1839 // The host would define the various callbacks in this interface and the preset parser function 1840 // would then call them. 1841 // 1842 // This interface isn't thread-safe. 1843 struct clap_preset_discovery_metadata_receiver_t 1844 { 1845 extern(C) nothrow @nogc: 1846 1847 void *receiver_data; // reserved pointer for the metadata receiver 1848 1849 // If there is an error reading metadata from a file this should be called with an error 1850 // message. 1851 // os_error: the operating system error, if applicable. If not applicable set it to a non-error 1852 // value, eg: 0 on unix and Windows. 1853 void function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1854 int os_error, 1855 const(char) *error_message) on_error; 1856 1857 // This must be called for every preset in the file and before any preset metadata is 1858 // sent with the calls below. 1859 // 1860 // If the preset file is a preset container then name and load_key are mandatory, otherwise 1861 // they are optional. 1862 // 1863 // The load_key is a machine friendly string used to load the preset inside the container via a 1864 // the preset-load plug-in extension. The load_key can also just be the subpath if that's what 1865 // the plugin wants but it could also be some other unique id like a database primary key or a 1866 // binary offset. It's use is entirely up to the plug-in. 1867 // 1868 // If the function returns false, then the provider must stop calling back into the receiver. 1869 bool function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1870 const(char)*name, 1871 const(char)*load_key) begin_preset; 1872 1873 // Adds a plug-in id that this preset can be used with. 1874 void function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1875 const(clap_universal_plugin_id_t)* plugin_id) add_plugin_id; 1876 1877 // Sets the sound pack to which the preset belongs to. 1878 void function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1879 const(char)* soundpack_id) set_soundpack_id; 1880 1881 // Sets the flags, see clap_preset_discovery_flags. 1882 // If unset, they are then inherited from the location. 1883 void function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1884 uint flags) set_flags; 1885 1886 // Adds a creator name for the preset. 1887 void function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1888 const(char)* creator) add_creator; 1889 1890 // Sets a description of the preset. 1891 void function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1892 const(char)* description) set_description; 1893 1894 // Sets the creation time and last modification time of the preset. 1895 // If one of the times isn't known, set it to CLAP_TIMESTAMP_UNKNOWN. 1896 // If this function is not called, then the indexer may look at the file's creation and 1897 // modification time. 1898 void function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1899 clap_timestamp creation_time, 1900 clap_timestamp modification_time) set_timestamps; 1901 1902 // Adds a feature to the preset. 1903 // 1904 // The feature string is arbitrary, it is the indexer's job to understand it and remap it to its 1905 // internal categorization and tagging system. 1906 // 1907 // However, the strings from plugin-features.h should be understood by the indexer and one of the 1908 // plugin category could be provided to determine if the preset will result into an audio-effect, 1909 // instrument, ... 1910 // 1911 // Examples: 1912 // kick, drum, tom, snare, clap, cymbal, bass, lead, metalic, hardsync, crossmod, acid, 1913 // distorted, drone, pad, dirty, etc... 1914 void function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1915 const(char)* feature) add_feature; 1916 1917 // Adds extra information to the metadata. 1918 void function(const(clap_preset_discovery_metadata_receiver_t)* receiver, 1919 const(char)* key, 1920 const(char)* value) add_extra_info; 1921 } 1922 1923 struct clap_preset_discovery_filetype_t 1924 { 1925 const(char)* name; 1926 const(char)* description; // optional 1927 1928 // `.' isn't included in the string. 1929 // If empty or NULL then every file should be matched. 1930 const(char)* file_extension; 1931 } 1932 1933 // Defines a place in which to search for presets 1934 struct clap_preset_discovery_location_t 1935 { 1936 uint flags; // see enum clap_preset_discovery_flags 1937 const(char)* name; // name of this location 1938 uint kind; // See clap_preset_discovery_location_kind 1939 1940 // Actual location in which to crawl presets. 1941 // For FILE kind, the location can be either a path to a directory or a file. 1942 // For PLUGIN kind, the location must be null. 1943 const(char)* location; 1944 } 1945 1946 // Describes an installed sound pack. 1947 struct clap_preset_discovery_soundpack_t 1948 { 1949 uint flags; // see enum clap_preset_discovery_flags 1950 const(char) *id; // sound pack identifier 1951 const(char) *name; // name of this sound pack 1952 const(char) *description; // optional, reasonably short description of the sound pack 1953 const(char) *homepage_url; // optional, url to the pack's homepage 1954 const(char) *vendor; // optional, sound pack's vendor 1955 const(char) *image_path; // optional, an image on disk 1956 clap_timestamp release_timestamp; // release date, CLAP_TIMESTAMP_UNKNOWN if unavailable 1957 } 1958 1959 // Describes a preset provider 1960 struct clap_preset_discovery_provider_descriptor_t 1961 { 1962 clap_version_t clap_version; // initialized to CLAP_VERSION 1963 const(char) *id; // see plugin.h for advice on how to choose a good identifier 1964 const(char) *name; // eg: "Diva's preset provider" 1965 const(char) *vendor; // optional, eg: u-he 1966 } 1967 1968 // This interface isn't thread-safe. 1969 struct clap_preset_discovery_provider_t 1970 { 1971 extern(C) nothrow @nogc: 1972 1973 const(clap_preset_discovery_provider_descriptor_t)* desc; 1974 1975 void* provider_data; // reserved pointer for the provider 1976 1977 // Initialize the preset provider. 1978 // It should declare all its locations, filetypes and sound packs. 1979 // Returns false if initialization failed. 1980 bool function(const(clap_preset_discovery_provider_t)* provider) init_; 1981 1982 // Destroys the preset provider 1983 void function(const(clap_preset_discovery_provider_t)* provider) destroy; 1984 1985 // reads metadata from the given file and passes them to the metadata receiver 1986 // Returns true on success. 1987 bool function(const(clap_preset_discovery_provider_t)* provider, 1988 uint location_kind, 1989 const(char)* location, 1990 const(clap_preset_discovery_metadata_receiver_t)* metadata_receiver) get_metadata; 1991 1992 // Query an extension. 1993 // The returned pointer is owned by the provider. 1994 // It is forbidden to call it before provider->init(). 1995 // You can call it within provider->init() call, and after. 1996 const(void)* function(const(clap_preset_discovery_provider_t)* provider, 1997 const(char)* extension_id) get_extension; 1998 } 1999 2000 // This interface isn't thread-safe 2001 struct clap_preset_discovery_indexer_t 2002 { 2003 extern(C) nothrow @nogc: 2004 2005 clap_version_t clap_version; // initialized to CLAP_VERSION 2006 const(char) *name; // eg: "Bitwig Studio" 2007 const(char) *vendor; // optional, eg: "Bitwig GmbH" 2008 const(char) *url; // optional, eg: "https://bitwig.com" 2009 const(char) *version_; // optional, eg: "4.3", see plugin.h for advice on how to format the version 2010 2011 void *indexer_data; // reserved pointer for the indexer 2012 2013 // Declares a preset filetype. 2014 // Don't callback into the provider during this call. 2015 // Returns false if the filetype is invalid. 2016 bool function(const(clap_preset_discovery_indexer_t)* indexer, 2017 const(clap_preset_discovery_filetype_t)* filetype) declare_filetype; 2018 2019 // Declares a preset location. 2020 // Don't callback into the provider during this call. 2021 // Returns false if the location is invalid. 2022 bool function(const(clap_preset_discovery_indexer_t)* indexer, 2023 const(clap_preset_discovery_location_t)* location) declare_location; 2024 2025 // Declares a sound pack. 2026 // Don't callback into the provider during this call. 2027 // Returns false if the sound pack is invalid. 2028 bool function(const(clap_preset_discovery_indexer_t)* indexer, 2029 const(clap_preset_discovery_soundpack_t)* soundpack) declare_soundpack; 2030 2031 // Query an extension. 2032 // The returned pointer is owned by the indexer. 2033 // It is forbidden to call it before provider->init(). 2034 // You can call it within provider->init() call, and after. 2035 const(void)* function(const(clap_preset_discovery_indexer_t)* indexer, 2036 const(char)* extension_id) get_extension; 2037 } 2038 2039 // Every methods in this factory must be thread-safe. 2040 // It is encouraged to perform preset indexing in background threads, maybe even in background 2041 // process. 2042 // 2043 // The host may use clap_plugin_invalidation_factory to detect filesystem changes 2044 // which may change the factory's content. 2045 struct clap_preset_discovery_factory_t 2046 { 2047 extern(C) nothrow @nogc: 2048 2049 // Get the number of preset providers available. 2050 // [thread-safe] 2051 uint function(const(clap_preset_discovery_factory_t)* factory) count; 2052 2053 // Retrieves a preset provider descriptor by its index. 2054 // Returns null in case of error. 2055 // The descriptor must not be freed. 2056 // [thread-safe] 2057 const(clap_preset_discovery_provider_descriptor_t)* 2058 function(const(clap_preset_discovery_factory_t)* factory, uint index) get_descriptor; 2059 2060 // Create a preset provider by its id. 2061 // The returned pointer must be freed by calling preset_provider->destroy(preset_provider); 2062 // The preset provider is not allowed to use the indexer callbacks in the create method. 2063 // It is forbidden to call back into the indexer before the indexer calls provider->init(). 2064 // Returns null in case of error. 2065 // [thread-safe] 2066 const(clap_preset_discovery_provider_t)* 2067 function(const(clap_preset_discovery_factory_t)* factory, 2068 const(clap_preset_discovery_indexer_t)* indexer, 2069 const(char)* provider_id) create; 2070 } 2071 2072 2073 // preset-load.h 2074 2075 enum string CLAP_EXT_PRESET_LOAD = "clap.preset-load/2"; 2076 2077 // The latest draft is 100% compatible. 2078 // This compat ID may be removed in 2026. 2079 enum string CLAP_EXT_PRESET_LOAD_COMPAT = "clap.preset-load.draft/2"; 2080 2081 struct clap_plugin_preset_load_t 2082 { 2083 extern(C) nothrow @nogc: 2084 2085 // Loads a preset in the plugin native preset file format from a location. 2086 // The preset discovery provider defines the location and load_key to be passed to this function. 2087 // Returns true on success. 2088 // [main-thread] 2089 bool function(const(clap_plugin_t)*plugin, 2090 uint location_kind, 2091 const(char) *location, 2092 const(char) *load_key) from_location; 2093 } 2094 2095 struct clap_host_preset_load_t 2096 { 2097 extern(C) nothrow @nogc: 2098 2099 // Called if clap_plugin_preset_load.load() failed. 2100 // os_error: the operating system error, if applicable. If not applicable set it to a non-error 2101 // value, eg: 0 on unix and Windows. 2102 // 2103 // [main-thread] 2104 void function(const(clap_host_t)*host, 2105 uint location_kind, 2106 const(char) *location, 2107 const(char) *load_key, 2108 int os_error, 2109 const(char) *msg) on_error; 2110 2111 // Informs the host that the following preset has been loaded. 2112 // This contributes to keep in sync the host preset browser and plugin preset browser. 2113 // If the preset was loaded from a container file, then the load_key must be set, otherwise it 2114 // must be null. 2115 // 2116 // [main-thread] 2117 void function(const(clap_host_t)*host, 2118 uint location_kind, 2119 const(char) *location, 2120 const(char) *load_key) loaded; 2121 } 2122 2123 // audio-port-config.h 2124 2125 /// @page Audio Ports Config 2126 /// 2127 /// This extension let the plugin provide port configurations presets. 2128 /// For example mono, stereo, surround, ambisonic, ... 2129 /// 2130 /// After the plugin initialization, the host may scan the list of configurations and eventually 2131 /// select one that fits the plugin context. The host can only select a configuration if the plugin 2132 /// is deactivated. 2133 /// 2134 /// A configuration is a very simple description of the audio ports: 2135 /// - it describes the main input and output ports 2136 /// - it has a name that can be displayed to the user 2137 /// 2138 /// The idea behind the configurations, is to let the user choose one via a menu. 2139 /// 2140 /// Plugins with very complex configuration possibilities should let the user configure the ports 2141 /// from the plugin GUI, and call @ref clap_host_audio_ports.rescan(CLAP_AUDIO_PORTS_RESCAN_ALL). 2142 /// 2143 /// To inquire the exact bus layout, the plugin implements the clap_plugin_audio_ports_config_info_t 2144 /// extension where all busses can be retrieved in the same way as in the audio-port extension. 2145 2146 enum string CLAP_EXT_AUDIO_PORTS_CONFIG = "clap.audio-ports-config"; 2147 2148 enum string CLAP_EXT_AUDIO_PORTS_CONFIG_INFO = "clap.audio-ports-config-info/1"; 2149 2150 // The latest draft is 100% compatible. 2151 // This compat ID may be removed in 2026. 2152 enum string CLAP_EXT_AUDIO_PORTS_CONFIG_INFO_COMPAT = 2153 "clap.audio-ports-config-info/draft-0"; 2154 2155 // Minimalistic description of ports configuration 2156 struct clap_audio_ports_config_t 2157 { 2158 clap_id id; 2159 char[CLAP_NAME_SIZE] name; 2160 2161 uint input_port_count; 2162 uint output_port_count; 2163 2164 // main input info 2165 bool has_main_input; 2166 uint main_input_channel_count; 2167 const(char)*main_input_port_type; 2168 2169 // main output info 2170 bool has_main_output; 2171 uint main_output_channel_count; 2172 const(char)*main_output_port_type; 2173 } 2174 2175 // The audio ports config scan has to be done while the plugin is deactivated. 2176 struct clap_plugin_audio_ports_config_t 2177 { 2178 extern(C) nothrow @nogc: 2179 // Gets the number of available configurations 2180 // [main-thread] 2181 uint function(const(clap_plugin_t)* plugin) count; 2182 2183 // Gets information about a configuration 2184 // Returns true on success and stores the result into config. 2185 // [main-thread] 2186 bool function(const(clap_plugin_t)* plugin, 2187 uint index, 2188 clap_audio_ports_config_t* config) get; 2189 2190 // Selects the configuration designated by id 2191 // Returns true if the configuration could be applied. 2192 // Once applied the host should scan again the audio ports. 2193 // [main-thread & plugin-deactivated] 2194 bool function(const(clap_plugin_t)* plugin, clap_id config_id) select; 2195 } 2196 2197 // Extended config info 2198 struct clap_plugin_audio_ports_config_info_t 2199 { 2200 extern(C) nothrow @nogc: 2201 // Gets the id of the currently selected config, or CLAP_INVALID_ID if the current port 2202 // layout isn't part of the config list. 2203 // 2204 // [main-thread] 2205 clap_id function(const clap_plugin_t *plugin) current_config; 2206 2207 // Get info about an audio port, for a given config_id. 2208 // This is analogous to clap_plugin_audio_ports.get(). 2209 // Returns true on success and stores the result into info. 2210 // [main-thread] 2211 bool function(const(clap_plugin_t)* plugin, 2212 clap_id config_id, 2213 uint port_index, 2214 bool is_input, 2215 clap_audio_port_info_t *info) get; 2216 } 2217 2218 struct clap_host_audio_ports_config_t 2219 { 2220 extern(C) nothrow @nogc: 2221 // Rescan the full list of configs. 2222 // [main-thread] 2223 void function(const(clap_host_t)*host) rescan; 2224 } 2225 2226 2227 // note-ports.h 2228 2229 /// The plugin is only allowed to change its note ports configuration while it is deactivated. 2230 2231 enum string CLAP_EXT_NOTE_PORTS = "clap.note-ports"; 2232 2233 2234 alias clap_note_dialect = int; 2235 enum : clap_note_dialect 2236 { 2237 // Uses clap_event_note and clap_event_note_expression. 2238 CLAP_NOTE_DIALECT_CLAP = 1 << 0, 2239 2240 // Uses clap_event_midi, no polyphonic expression 2241 CLAP_NOTE_DIALECT_MIDI = 1 << 1, 2242 2243 // Uses clap_event_midi, with polyphonic expression (MPE) 2244 CLAP_NOTE_DIALECT_MIDI_MPE = 1 << 2, 2245 2246 // Uses clap_event_midi2 2247 CLAP_NOTE_DIALECT_MIDI2 = 1 << 3, 2248 } 2249 2250 struct clap_note_port_info_t 2251 { 2252 // id identifies a port and must be stable. 2253 // id may overlap between input and output ports. 2254 clap_id id; 2255 uint supported_dialects; // bitfield, see clap_note_dialect 2256 uint preferred_dialect; // one value of clap_note_dialect 2257 char[CLAP_NAME_SIZE] name; // displayable name, i18n? 2258 } 2259 2260 // The note ports scan has to be done while the plugin is deactivated. 2261 struct clap_plugin_note_ports_t 2262 { 2263 extern(C) nothrow @nogc: 2264 // Number of ports, for either input or output. 2265 // [main-thread] 2266 uint function(const(clap_plugin_t)* plugin, bool is_input) count; 2267 2268 // Get info about a note port. 2269 // Returns true on success and stores the result into info. 2270 // [main-thread] 2271 bool function(const(clap_plugin_t)* plugin, 2272 uint index, 2273 bool is_input, 2274 clap_note_port_info_t *info) get; 2275 } 2276 2277 enum 2278 { 2279 // The ports have changed, the host shall perform a full scan of the ports. 2280 // This flag can only be used if the plugin is not active. 2281 // If the plugin active, call host->request_restart() and then call rescan() 2282 // when the host calls deactivate() 2283 CLAP_NOTE_PORTS_RESCAN_ALL = 1 << 0, 2284 2285 // The ports name did change, the host can scan them right away. 2286 CLAP_NOTE_PORTS_RESCAN_NAMES = 1 << 1, 2287 } 2288 2289 struct clap_host_note_ports_t 2290 { 2291 extern(C) nothrow @nogc: 2292 // Query which dialects the host supports 2293 // [main-thread] 2294 uint function(const(clap_host_t)* host) supported_dialects; 2295 2296 // Rescan the full list of note ports according to the flags. 2297 // [main-thread] 2298 void function(const(clap_host_t)* host, uint flags) rescan; 2299 } 2300 2301 // configurable-audio-ports.h 2302 2303 // This extension lets the host configure the plugin's input and output audio ports. 2304 // This is a "push" approach to audio ports configuration. 2305 2306 enum string CLAP_EXT_CONFIGURABLE_AUDIO_PORTS = "clap.configurable-audio-ports/1"; 2307 2308 // The latest draft is 100% compatible. 2309 // This compat ID may be removed in 2026. 2310 enum string CLAP_EXT_CONFIGURABLE_AUDIO_PORTS_COMPAT = "clap.configurable-audio-ports.draft1"; 2311 2312 struct clap_audio_port_configuration_request_t 2313 { 2314 // Identifies the port by is_input and port_index 2315 bool is_input; 2316 uint port_index; 2317 2318 // The requested number of channels. 2319 uint channel_count; 2320 2321 // The port type, see audio-ports.h, clap_audio_port_info.port_type for interpretation. 2322 const(char)*port_type; 2323 2324 // cast port_details according to port_type: 2325 // - CLAP_PORT_MONO: (discard) 2326 // - CLAP_PORT_STEREO: (discard) 2327 // - CLAP_PORT_SURROUND: const uint8_t *channel_map 2328 // - CLAP_PORT_AMBISONIC: const clap_ambisonic_config_t *info 2329 const(void)* port_details; 2330 } 2331 2332 struct clap_plugin_configurable_audio_ports_t 2333 { 2334 extern(C) nothrow @nogc: 2335 // Returns true if the given configurations can be applied using apply_configuration(). 2336 // [main-thread && !active] 2337 bool function(const(clap_plugin_t)* plugin, 2338 const(clap_audio_port_configuration_request_t)* requests, 2339 uint request_count) can_apply_configuration; 2340 2341 // Submit a bunch of configuration requests which will atomically be applied together, 2342 // or discarded together. 2343 // 2344 // Once the configuration is successfully applied, it isn't necessary for the plugin to call 2345 // clap_host_audio_ports->changed(); and it isn't necessary for the host to scan the 2346 // audio ports. 2347 // 2348 // Returns true if applied. 2349 // [main-thread && !active] 2350 bool function(const(clap_plugin_t)* plugin, 2351 const(clap_audio_port_configuration_request_t)* requests, 2352 uint request_count) apply_configuration; 2353 }