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 }