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