1 /**
2 Dynamic bindings to the AudioUnit and AudioToolbox frameworks.
3 
4 Copyright: Guillaume Piolat 2015.
5 License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
6 */
7 module derelict.carbon.audiounit;
8 
9 // AudioUnit and AudioToolbox frameworks loader
10 // Not strictly in Carbon, this is technical debt
11 
12 import core.stdc.config;
13 
14 import dplug.core.sharedlib;
15 import dplug.core.nogc;
16 import derelict.carbon.corefoundation;
17 import derelict.carbon.coreaudio;
18 import derelict.carbon.coreservices;
19 
20 version(OSX)
21     enum libNames = "/System/Library/Frameworks/AudioUnit.framework/AudioUnit";
22 else
23     enum libNames = "";
24 
25 
26 class DerelictAudioUnitLoader : SharedLibLoader
27 {
28     public
29     {
30         this() nothrow @nogc
31         {
32             super(libNames);
33         }
34 
35         override void loadSymbols() nothrow @nogc
36         {
37             bindFunc(cast(void**)&AudioUnitGetProperty, "AudioUnitGetProperty");
38             bindFunc(cast(void**)&AudioUnitRender, "AudioUnitRender");
39         }
40     }
41 }
42 
43 
44 private __gshared DerelictAudioUnitLoader DerelictAudioUnit;
45 
46 private __gshared loaderCounterAU = 0;
47 
48 // Call this each time a novel owner uses these functions
49 // TODO: hold a mutex, because this isn't thread-safe
50 void acquireAudioUnitFunctions() nothrow @nogc
51 {
52     if (DerelictAudioUnit is null)  // You only live once
53     {
54         DerelictAudioUnit = mallocNew!DerelictAudioUnitLoader();
55         DerelictAudioUnit.load();
56     }
57 }
58 
59 // Call this each time a novel owner releases a Cocoa functions
60 // TODO: hold a mutex, because this isn't thread-safe
61 void releaseAudioUnitFunctions() nothrow @nogc
62 {
63     /*if (--loaderCounterAU == 0)
64     {
65         DerelictAudioUnit.unload();
66         DerelictAudioUnit.destroyFree();
67     }*/
68 }
69 
70 
71 unittest
72 {
73     version(OSX)
74     {
75         acquireAudioUnitFunctions();
76         releaseAudioUnitFunctions();
77     }
78 }
79 
80 
81 enum : int
82 {
83     kAudioUnitRange                                    = 0x0000,
84     kAudioUnitInitializeSelect                         = 0x0001,
85     kAudioUnitUninitializeSelect                       = 0x0002,
86     kAudioUnitGetPropertyInfoSelect                    = 0x0003,
87     kAudioUnitGetPropertySelect                        = 0x0004,
88     kAudioUnitSetPropertySelect                        = 0x0005,
89     kAudioUnitAddPropertyListenerSelect                = 0x000A,
90     kAudioUnitRemovePropertyListenerSelect             = 0x000B,
91     kAudioUnitRemovePropertyListenerWithUserDataSelect = 0x0012,
92     kAudioUnitAddRenderNotifySelect                    = 0x000F,
93     kAudioUnitRemoveRenderNotifySelect                 = 0x0010,
94     kAudioUnitGetParameterSelect                       = 0x0006,
95     kAudioUnitSetParameterSelect                       = 0x0007,
96     kAudioUnitScheduleParametersSelect                 = 0x0011,
97     kAudioUnitRenderSelect                             = 0x000E,
98     kAudioUnitResetSelect                              = 0x0009,
99     kAudioUnitComplexRenderSelect                      = 0x0013,
100     kAudioUnitProcessSelect                            = 0x0014,
101     kAudioUnitProcessMultipleSelect                    = 0x0015
102 }
103 
104 // AUComponent.h
105 
106 alias AudioComponentInstance = void*;
107 alias AudioUnit = AudioComponentInstance;
108 
109 alias AudioUnitPropertyID = uint;
110 alias AudioUnitScope = uint;
111 alias AudioUnitElement = uint;
112 alias AudioUnitParameterID = uint;
113 alias AudioUnitParameterValue = float;
114 
115 extern(C) nothrow @nogc
116 {
117     alias AURenderCallback = OSStatus function(void *                          inRefCon,
118                                                AudioUnitRenderActionFlags *    ioActionFlags,
119                                                const(AudioTimeStamp)*          inTimeStamp,
120                                                UInt32                          inBusNumber,
121                                                UInt32                          inNumberFrames,
122                                                AudioBufferList *               ioData);
123 
124     alias AudioUnitPropertyListenerProc = void function(void *              inRefCon,
125                                                         AudioUnit           inUnit,
126                                                         AudioUnitPropertyID inID,
127                                                         AudioUnitScope      inScope,
128                                                         AudioUnitElement    inElement);
129 }
130 
131 alias AudioUnitRenderActionFlags = uint;
132 enum : AudioUnitRenderActionFlags
133 {
134     kAudioUnitRenderAction_PreRender            = (1 << 2),
135     kAudioUnitRenderAction_PostRender           = (1 << 3),
136     kAudioUnitRenderAction_OutputIsSilence      = (1 << 4),
137     kAudioOfflineUnitRenderAction_Preflight     = (1 << 5),
138     kAudioOfflineUnitRenderAction_Render        = (1 << 6),
139     kAudioOfflineUnitRenderAction_Complete      = (1 << 7),
140     kAudioUnitRenderAction_PostRenderError      = (1 << 8),
141     kAudioUnitRenderAction_DoNotCheckRenderArgs = (1 << 9)
142 }
143 
144 enum : OSStatus
145 {
146     kAudioUnitErr_InvalidProperty           = -10879,
147     kAudioUnitErr_InvalidParameter          = -10878,
148     kAudioUnitErr_InvalidElement            = -10877,
149     kAudioUnitErr_NoConnection              = -10876,
150     kAudioUnitErr_FailedInitialization      = -10875,
151     kAudioUnitErr_TooManyFramesToProcess    = -10874,
152     kAudioUnitErr_InvalidFile               = -10871,
153     kAudioUnitErr_UnknownFileType           = -10870,
154     kAudioUnitErr_FileNotSpecified          = -10869,
155     kAudioUnitErr_FormatNotSupported        = -10868,
156     kAudioUnitErr_Uninitialized             = -10867,
157     kAudioUnitErr_InvalidScope              = -10866,
158     kAudioUnitErr_PropertyNotWritable       = -10865,
159     kAudioUnitErr_CannotDoInCurrentContext  = -10863,
160     kAudioUnitErr_InvalidPropertyValue      = -10851,
161     kAudioUnitErr_PropertyNotInUse          = -10850,
162     kAudioUnitErr_Initialized               = -10849,
163     kAudioUnitErr_InvalidOfflineRender      = -10848,
164     kAudioUnitErr_Unauthorized              = -10847,
165     kAudioComponentErr_InstanceInvalidated  = -66749,
166 }
167 
168 alias AUParameterEventType = uint;
169 
170 enum : AUParameterEventType
171 {
172     kParameterEvent_Immediate   = 1,
173     kParameterEvent_Ramped      = 2
174 }
175 
176 struct AudioUnitParameterEvent
177 {
178     AudioUnitScope          scope_;
179     AudioUnitElement        element;
180     AudioUnitParameterID    parameter;
181 
182     AUParameterEventType    eventType;
183 
184     static union EventValues
185     {
186         static struct Ramp
187         {
188             SInt32                      startBufferOffset;
189             UInt32                      durationInFrames;
190             AudioUnitParameterValue     startValue;
191             AudioUnitParameterValue     endValue;
192         }                   ;
193         Ramp ramp;
194 
195         static struct Immediate
196         {
197             UInt32                      bufferOffset;
198             AudioUnitParameterValue     value;
199         }
200         Immediate immediate;
201 
202     }
203     EventValues eventValues;
204 }
205 
206 struct AudioUnitParameter
207 {
208     AudioUnit               mAudioUnit;
209     AudioUnitParameterID    mParameterID;
210     AudioUnitScope          mScope;
211     AudioUnitElement        mElement;
212 }
213 
214 struct AudioUnitProperty
215 {
216     AudioUnit               mAudioUnit;
217     AudioUnitPropertyID     mPropertyID;
218     AudioUnitScope          mScope;
219     AudioUnitElement        mElement;
220 }
221 
222 extern(C) nothrow @nogc
223 {
224     alias AudioUnitGetParameterProc = OSStatus function(
225                                 void *                      inComponentStorage,
226                                 AudioUnitParameterID        inID,
227                                 AudioUnitScope              inScope,
228                                 AudioUnitElement            inElement,
229                                 AudioUnitParameterValue *   outValue);
230 
231     alias AudioUnitSetParameterProc = OSStatus function(
232                                 void *                      inComponentStorage,
233                                 AudioUnitParameterID        inID,
234                                 AudioUnitScope              inScope,
235                                 AudioUnitElement            inElement,
236                                 AudioUnitParameterValue     inValue,
237                                 UInt32                      inBufferOffsetInFrames);
238 
239     alias AudioUnitRenderProc = OSStatus function(
240                                 void *                          inComponentStorage,
241                                 AudioUnitRenderActionFlags *    ioActionFlags,
242                                 const(AudioTimeStamp)*          inTimeStamp,
243                                 UInt32                          inOutputBusNumber,
244                                 UInt32                          inNumberFrames,
245                                 AudioBufferList *               ioData);
246 }
247 
248 __gshared
249 {
250     AudioUnitRenderProc AudioUnitRender;
251 }
252 
253 extern(C) nothrow @nogc
254 {
255     alias AudioUnitGetPropertyProc = OSStatus function(
256                                     AudioUnit               inUnit,
257                                     AudioUnitPropertyID     inID,
258                                     AudioUnitScope          inScope,
259                                     AudioUnitElement        inElement,
260                                     void *                  outData,
261                                     UInt32 *                ioDataSize);
262 }
263 
264 __gshared
265 {
266     AudioUnitGetPropertyProc AudioUnitGetProperty;
267 }
268 
269 // AudioUnitCarbonView.h
270 
271 enum
272 {
273     kAudioUnitCarbonViewRange                  = 0x0300,
274     kAudioUnitCarbonViewCreateSelect           = 0x0301,
275     kAudioUnitCarbonViewSetEventListenerSelect = 0x0302
276 }
277 
278 enum
279 {
280     kAudioUnitCarbonViewComponentType   = CCONST('a', 'u', 'v', 'w'),
281     kAUCarbonViewSubType_Generic        = CCONST('g', 'n', 'r', 'c')
282 }
283 
284 // AudioUnitProperties.h
285 
286 enum : AudioUnitScope
287 {
288     kAudioUnitScope_Global      = 0,
289     kAudioUnitScope_Input       = 1,
290     kAudioUnitScope_Output      = 2,
291     kAudioUnitScope_Group       = 3,
292     kAudioUnitScope_Part        = 4,
293     kAudioUnitScope_Note        = 5,
294     kAudioUnitScope_Layer       = 6,
295     kAudioUnitScope_LayerItem   = 7
296 }
297 
298 enum : AudioUnitPropertyID
299 {
300     kAudioUnitProperty_ClassInfo                    = 0,
301     kAudioUnitProperty_MakeConnection               = 1,
302     kAudioUnitProperty_SampleRate                   = 2,
303     kAudioUnitProperty_ParameterList                = 3,
304     kAudioUnitProperty_ParameterInfo                = 4,
305     kAudioUnitProperty_FastDispatch                 = 5,
306     kAudioUnitProperty_CPULoad                      = 6,
307     kAudioUnitProperty_StreamFormat                 = 8,
308     kAudioUnitProperty_ElementCount                 = 11,
309     kAudioUnitProperty_Latency                      = 12,
310     kAudioUnitProperty_SupportedNumChannels         = 13,
311     kAudioUnitProperty_MaximumFramesPerSlice        = 14,
312     kAudioUnitProperty_ParameterValueStrings        = 16,
313     kAudioUnitProperty_AudioChannelLayout           = 19,
314     kAudioUnitProperty_TailTime                     = 20,
315     kAudioUnitProperty_BypassEffect                 = 21,
316     kAudioUnitProperty_LastRenderError              = 22,
317     kAudioUnitProperty_SetRenderCallback            = 23,
318     kAudioUnitProperty_FactoryPresets               = 24,
319     kAudioUnitProperty_RenderQuality                = 26,
320     kAudioUnitProperty_HostCallbacks                = 27,
321     kAudioUnitProperty_InPlaceProcessing            = 29,
322     kAudioUnitProperty_ElementName                  = 30,
323     kAudioUnitProperty_SupportedChannelLayoutTags   = 32,
324     kAudioUnitProperty_PresentPreset                = 36,
325     kAudioUnitProperty_DependentParameters          = 45,
326     kAudioUnitProperty_InputSamplesInOutput         = 49,
327     kAudioUnitProperty_ShouldAllocateBuffer         = 51,
328     kAudioUnitProperty_FrequencyResponse            = 52,
329     kAudioUnitProperty_ParameterHistoryInfo         = 53,
330     kAudioUnitProperty_NickName                     = 54,
331     kAudioUnitProperty_OfflineRender                = 37,
332     kAudioUnitProperty_ParameterIDName              = 34,
333     kAudioUnitProperty_ParameterStringFromValue     = 33,
334     kAudioUnitProperty_ParameterClumpName           = 35,
335     kAudioUnitProperty_ParameterValueFromString     = 38,
336     kAudioUnitProperty_ContextName                  = 25,
337     kAudioUnitProperty_PresentationLatency          = 40,
338     kAudioUnitProperty_ClassInfoFromDocument        = 50,
339     kAudioUnitProperty_RequestViewController        = 56,
340     kAudioUnitProperty_ParametersForOverview        = 57,
341     kAudioUnitProperty_SetExternalBuffer            = 15,
342     kAudioUnitProperty_GetUIComponentList           = 18,
343     kAudioUnitProperty_CocoaUI                      = 31,
344     kAudioUnitProperty_IconLocation                 = 39,
345     kAudioUnitProperty_AUHostIdentifier             = 46,
346     kAudioUnitProperty_MIDIOutputCallbackInfo       = 47,
347     kAudioUnitProperty_MIDIOutputCallback           = 48,
348 }
349 
350 enum : AudioUnitPropertyID
351 {
352     kMusicDeviceProperty_InstrumentCount            = 1000,
353     kMusicDeviceProperty_BankName                   = 1007,
354     kMusicDeviceProperty_SoundBankURL               = 1100
355 }
356 
357 static immutable string
358     kAUPresetVersionKey       = "version",
359     kAUPresetTypeKey          = "type",
360     kAUPresetSubtypeKey       = "subtype",
361     kAUPresetManufacturerKey  = "manufacturer",
362     kAUPresetDataKey          = "data",
363     kAUPresetNameKey          = "name",
364     kAUPresetRenderQualityKey = "render-quality",
365     kAUPresetCPULoadKey       = "cpu-load",
366     kAUPresetElementNameKey   = "element-name",
367     kAUPresetExternalFileRefs = "file-references",
368     kAUPresetVSTDataKey       = "vstdata",
369     kAUPresetVSTPresetKey     = "vstpreset",
370     kAUPresetMASDataKey       = "masdata",
371     kAUPresetPartKey          = "part";
372 
373 version(BigEndian)
374     struct AUNumVersion
375     {
376         UInt8               majorRev;
377         UInt8               minorAndBugRev;
378         UInt8               stage;
379         UInt8               nonRelRev;
380     }
381 
382 version(LittleEndian)
383     struct AUNumVersion
384     {
385         UInt8               nonRelRev;
386         UInt8               stage;
387         UInt8               minorAndBugRev;
388         UInt8               majorRev;
389     }
390 
391 struct AUHostIdentifier
392 {
393     CFStringRef         hostName;
394     AUNumVersion        hostVersion;
395 }
396 
397 struct AudioUnitConnection
398 {
399     AudioUnit   sourceAudioUnit;
400     UInt32      sourceOutputNumber;
401     UInt32      destInputNumber;
402 }
403 
404 struct AUChannelInfo
405 {
406     SInt16      inChannels;
407     SInt16      outChannels;
408 }
409 
410 struct AURenderCallbackStruct
411 {
412     AURenderCallback inputProc;
413     void* inputProcRefCon;
414 }
415 
416 
417 
418 struct AUPreset
419 {
420     SInt32      presetNumber;
421     CFStringRef presetName;
422 }
423 
424 enum : AudioUnitPropertyID
425 {
426     kAudioUnitProperty_SRCAlgorithm             = 9, // see kAudioUnitProperty_SampleRateConverterComplexity
427     kAudioUnitProperty_MIDIControlMapping       = 17, // see ParameterMIDIMapping Properties
428     kAudioUnitProperty_CurrentPreset            = 28, // see PresentPreset
429 
430     kAudioUnitProperty_ParameterValueName       = kAudioUnitProperty_ParameterStringFromValue,
431     kAudioUnitProperty_BusCount                 = kAudioUnitProperty_ElementCount,
432 }
433 
434 
435 extern(C) nothrow @nogc
436 {
437     alias HostCallback_GetBeatAndTempo = OSStatus function(void * inHostUserData,
438                                                 Float64 *   outCurrentBeat,
439                                                 Float64 *   outCurrentTempo);
440 
441     alias HostCallback_GetMusicalTimeLocation = OSStatus function(void *  inHostUserData,
442                                                     UInt32 *        outDeltaSampleOffsetToNextBeat,
443                                                     Float32 *       outTimeSig_Numerator,
444                                                     UInt32 *        outTimeSig_Denominator,
445                                                     Float64 *       outCurrentMeasureDownBeat);
446     alias HostCallback_GetTransportState = OSStatus function(void *   inHostUserData,
447                                             Boolean *           outIsPlaying,
448                                             Boolean *           outTransportStateChanged,
449                                             Float64 *           outCurrentSampleInTimeLine,
450                                             Boolean *           outIsCycling,
451                                             Float64 *           outCycleStartBeat,
452                                             Float64 *           outCycleEndBeat);
453     alias HostCallback_GetTransportState2 = OSStatus function(void * inHostUserData,
454                                             Boolean *           outIsPlaying,
455                                             Boolean *           outIsRecording,
456                                             Boolean *           outTransportStateChanged,
457                                             Float64 *           outCurrentSampleInTimeLine,
458                                             Boolean *           outIsCycling,
459                                             Float64 *           outCycleStartBeat,
460                                             Float64 *           outCycleEndBeat);
461 }
462 
463 struct HostCallbackInfo
464 {
465     void *                                    hostUserData;
466     HostCallback_GetBeatAndTempo              beatAndTempoProc;
467     HostCallback_GetMusicalTimeLocation       musicalTimeLocationProc;
468     HostCallback_GetTransportState            transportStateProc;
469     HostCallback_GetTransportState2           transportStateProc2;
470 }
471 
472 struct AudioUnitCocoaViewInfo
473 {
474     CFURLRef    mCocoaAUViewBundleLocation;
475     CFStringRef[1] mCocoaAUViewClass;
476 }
477 
478 extern(C) nothrow @nogc
479 {
480     alias AUMIDIOutputCallback = OSStatus function(void* userData,
481                                                    const(AudioTimeStamp)* timeStamp,
482                                                    UInt32 midiOutNum,
483                                                    const(MIDIPacketList)* pktlist);
484 }
485 
486 struct AUMIDIOutputCallbackStruct
487 {
488     AUMIDIOutputCallback midiOutputCallback;
489     void* userData;
490 }
491 
492 struct AudioUnitParameterInfo
493 {
494     char[52]                    name;
495     CFStringRef                 unitName;
496     UInt32                      clumpID;
497     CFStringRef                 cfNameString;
498     AudioUnitParameterUnit      unit;
499     AudioUnitParameterValue     minValue;
500     AudioUnitParameterValue     maxValue;
501     AudioUnitParameterValue     defaultValue;
502     AudioUnitParameterOptions   flags;
503 }
504 
505 alias AudioUnitParameterUnit = UInt32;
506 enum : AudioUnitParameterUnit
507 {
508     kAudioUnitParameterUnit_Generic             = 0,
509     kAudioUnitParameterUnit_Indexed             = 1,
510     kAudioUnitParameterUnit_Boolean             = 2,
511     kAudioUnitParameterUnit_Percent             = 3,
512     kAudioUnitParameterUnit_Seconds             = 4,
513     kAudioUnitParameterUnit_SampleFrames        = 5,
514     kAudioUnitParameterUnit_Phase               = 6,
515     kAudioUnitParameterUnit_Rate                = 7,
516     kAudioUnitParameterUnit_Hertz               = 8,
517     kAudioUnitParameterUnit_Cents               = 9,
518     kAudioUnitParameterUnit_RelativeSemiTones   = 10,
519     kAudioUnitParameterUnit_MIDINoteNumber      = 11,
520     kAudioUnitParameterUnit_MIDIController      = 12,
521     kAudioUnitParameterUnit_Decibels            = 13,
522     kAudioUnitParameterUnit_LinearGain          = 14,
523     kAudioUnitParameterUnit_Degrees             = 15,
524     kAudioUnitParameterUnit_EqualPowerCrossfade = 16,
525     kAudioUnitParameterUnit_MixerFaderCurve1    = 17,
526     kAudioUnitParameterUnit_Pan                 = 18,
527     kAudioUnitParameterUnit_Meters              = 19,
528     kAudioUnitParameterUnit_AbsoluteCents       = 20,
529     kAudioUnitParameterUnit_Octaves             = 21,
530     kAudioUnitParameterUnit_BPM                 = 22,
531     kAudioUnitParameterUnit_Beats               = 23,
532     kAudioUnitParameterUnit_Milliseconds        = 24,
533     kAudioUnitParameterUnit_Ratio               = 25,
534     kAudioUnitParameterUnit_CustomUnit          = 26
535 }
536 
537 alias AudioUnitParameterOptions = UInt32;
538 enum : AudioUnitParameterOptions
539 {
540     kAudioUnitParameterFlag_CFNameRelease       = (1UL << 4),
541 
542     kAudioUnitParameterFlag_OmitFromPresets     = (1UL << 13),
543     kAudioUnitParameterFlag_PlotHistory         = (1UL << 14),
544     kAudioUnitParameterFlag_MeterReadOnly       = (1UL << 15),
545 
546     // bit positions 18,17,16 are set aside for display scales. bit 19 is reserved.
547     kAudioUnitParameterFlag_DisplayMask         = (7UL << 16) | (1UL << 22),
548     kAudioUnitParameterFlag_DisplaySquareRoot   = (1UL << 16),
549     kAudioUnitParameterFlag_DisplaySquared      = (2UL << 16),
550     kAudioUnitParameterFlag_DisplayCubed        = (3UL << 16),
551     kAudioUnitParameterFlag_DisplayCubeRoot     = (4UL << 16),
552     kAudioUnitParameterFlag_DisplayExponential  = (5UL << 16),
553 
554     kAudioUnitParameterFlag_HasClump            = (1UL << 20),
555     kAudioUnitParameterFlag_ValuesHaveStrings   = (1UL << 21),
556 
557     kAudioUnitParameterFlag_DisplayLogarithmic  = (1UL << 22),
558 
559     kAudioUnitParameterFlag_IsHighResolution    = (1UL << 23),
560     // parameter is non-automatable
561     kAudioUnitParameterFlag_NonRealTime         = (1UL << 24),
562     kAudioUnitParameterFlag_CanRamp             = (1UL << 25),
563     kAudioUnitParameterFlag_ExpertMode          = (1UL << 26),
564     kAudioUnitParameterFlag_HasCFNameString     = (1UL << 27),
565     kAudioUnitParameterFlag_IsGlobalMeta        = (1UL << 28),
566     kAudioUnitParameterFlag_IsElementMeta       = (1UL << 29),
567     kAudioUnitParameterFlag_IsReadable          = (1UL << 30),
568     kAudioUnitParameterFlag_IsWritable          = (1UL << 31)
569 }
570 
571 struct AudioUnitParameterNameInfo
572 {
573     AudioUnitParameterID    inID;
574     SInt32                  inDesiredLength;
575     CFStringRef             outName;
576 }
577 alias AudioUnitParameterIDName = AudioUnitParameterNameInfo;
578 
579 struct AudioUnitParameterStringFromValue
580 {
581     AudioUnitParameterID                inParamID;
582     const(AudioUnitParameterValue)*     inValue;
583     CFStringRef                         outString;
584 }
585 
586 struct AudioUnitParameterValueFromString
587 {
588     AudioUnitParameterID        inParamID;
589     CFStringRef                 inString;
590     AudioUnitParameterValue     outValue;
591 }
592 
593 
594 
595 // AudioToolbox framework
596 
597 version(OSX)
598     enum libNamesToolbox = "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox";
599 else
600     enum libNamesToolbox = "";
601 
602 
603 class DerelictAudioToolboxLoader : SharedLibLoader
604 {
605     public
606     {
607         nothrow @nogc:
608         this()
609         {
610             super(libNamesToolbox);
611         }
612 
613         override void loadSymbols()
614         {
615             bindFunc(cast(void**)&AUEventListenerNotify, "AUEventListenerNotify");
616         }
617     }
618 }
619 
620 
621 private __gshared DerelictAudioToolboxLoader DerelictAudioToolbox;
622 
623 private __gshared loaderCounterATB = 0;
624 
625 // Call this each time a novel owner uses these functions
626 // TODO: hold a mutex, because this isn't thread-safe
627 void acquireAudioToolboxFunctions() nothrow @nogc
628 {
629     if (DerelictAudioToolbox is null)  // You only live once
630     {
631         DerelictAudioToolbox = mallocNew!DerelictAudioToolboxLoader();
632         DerelictAudioToolbox.load();
633     }
634 }
635 
636 // Call this each time a novel owner releases a Cocoa functions
637 // TODO: hold a mutex, because this isn't thread-safe
638 void releaseAudioToolboxFunctions() nothrow @nogc
639 {
640     /*if (--loaderCounterATB == 0)
641     {
642         DerelictAudioToolbox.unload();
643         DerelictAudioToolbox.destroyFree();
644     }*/
645 }
646 
647 unittest
648 {
649     version(OSX)
650     {
651         acquireAudioToolboxFunctions();
652         releaseAudioToolboxFunctions();
653     }
654 }
655 
656 
657 alias AudioUnitEventType = UInt32;
658 enum : AudioUnitEventType
659 {
660     kAudioUnitEvent_ParameterValueChange        = 0,
661     kAudioUnitEvent_BeginParameterChangeGesture = 1,
662     kAudioUnitEvent_EndParameterChangeGesture   = 2,
663     kAudioUnitEvent_PropertyChange              = 3
664 }
665 
666 alias AUEventListenerRef = void*;
667 
668 struct AudioUnitEvent
669 {
670     AudioUnitEventType                  mEventType;
671     union Argument
672     {
673         AudioUnitParameter  mParameter; // for parameter value change, begin and end gesture
674         AudioUnitProperty   mProperty;  // for kAudioUnitEvent_PropertyChange
675     }
676     Argument mArgument;
677 }
678 
679 extern(C) nothrow @nogc
680 {
681     alias da_AUEventListenerNotify = OSStatus function(AUEventListenerRef inSendingListener, void* inSendingObject, const(AudioUnitEvent)* inEvent);
682 }
683 
684 __gshared
685 {
686     da_AUEventListenerNotify AUEventListenerNotify;
687 }
688 
689 enum
690 {
691     kMusicDeviceRange = 0x0100,
692     kMusicDeviceMIDIEventSelect = 0x0101,
693     kMusicDeviceSysExSelect = 0x0102,
694     kMusicDevicePrepareInstrumentSelect = 0x0103,
695     kMusicDeviceReleaseInstrumentSelect = 0x0104,
696     kMusicDeviceStartNoteSelect = 0x0105,
697     kMusicDeviceStopNoteSelect = 0x0106,
698 }
699 
700 alias MusicDeviceInstrumentID = uint;
701 alias MusicDeviceGroupID = uint;
702 alias NoteInstanceID = uint;
703 
704 struct MusicDeviceNoteParams
705 {
706     UInt32 argCount;
707     Float32 mPitch;
708     Float32 mVelocity;
709     //NoteParamsControlValue[1] mControls;               /* arbitrary length */
710 }
711 
712 //
713 // AUDIO COMPONENT API
714 //
715 // AudioComponent.h
716 
717 
718 alias AudioComponentFlags = UInt32;
719 enum : AudioComponentFlags
720 {
721     kAudioComponentFlag_Unsearchable = 1,  // available: OSX 10.7
722     kAudioComponentFlag_SandboxSafe = 2    // available: OSX 10.8
723 }
724 
725 struct AudioComponentDescription
726 {
727     OSType componentType;
728     OSType componentSubType;
729     OSType componentManufacturer;
730     UInt32 componentFlags;
731     UInt32 componentFlagsMask;
732 }
733 
734 alias AudioComponent = void*;
735 
736 extern(C) nothrow
737 {
738     alias AudioComponentMethod = OSStatus function(void *self,...);
739 }
740 
741 struct AudioComponentPlugInInterface
742 {
743     extern(C) nothrow OSStatus function(void *self, AudioComponentInstance mInstance) Open;
744     extern(C) nothrow OSStatus function(void *self) Close;
745     extern(C) nothrow AudioComponentMethod function(SInt16 selector) Lookup;
746     void*                reserved;
747 }
748 
749 extern(C) nothrow
750 {
751     alias AudioComponentFactoryFunction = AudioComponentPlugInInterface* function(const(AudioComponentDescription)* inDesc);
752 }
753 
754 
755 // <CoreMIDI/MIDIServices.h>
756 
757 alias MIDITimeStamp = ulong;
758 
759 struct MIDIPacket
760 {
761     MIDITimeStamp       timeStamp;
762     UInt16              length;
763     byte[256]           data;
764 }
765 static assert(MIDIPacket.sizeof == 8 + 2 + 6 + 256); // verified with c++ Godbolt
766 
767 const(MIDIPacket)* MIDIPacketNext(const(MIDIPacket)* pkt)
768 {
769     version(ARM)
770     {
771         ptrdiff_t mask = ~3;
772         size_t p = cast(size_t)(pkt.data.ptr + pkt.length);
773         p = (p + 3) & mask;
774         return cast(const(MIDIPacket)*)p;
775     }
776     else version(AArch64)
777     {
778         ptrdiff_t mask = ~3;
779         size_t p = cast(size_t)(pkt.data.ptr + pkt.length);
780         p = (p + 3) & mask;
781         return cast(const(MIDIPacket)*)p;
782     }
783     else
784     {
785         return cast(const(MIDIPacket)*)(pkt.data.ptr + pkt.length);
786     }
787 }
788 
789 struct MIDIPacketList
790 {
791     UInt32              numPackets;
792     MIDIPacket[1]           packet;
793 }
794 static assert(MIDIPacketList.sizeof == 4 + 4 + MIDIPacket.sizeof); // verified with C++ Godbolt