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