2 File: AUPlugInDispatch.cpp
3 Abstract: AUPlugInDispatch.h
6 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 Inc. ("Apple") in consideration of your agreement to the following
8 terms, and your use, installation, modification or redistribution of
9 this Apple software constitutes acceptance of these terms. If you do
10 not agree with these terms, please do not use, install, modify or
11 redistribute this Apple software.
13 In consideration of your agreement to abide by the following terms, and
14 subject to these terms, Apple grants you a personal, non-exclusive
15 license, under Apple's copyrights in this original Apple software (the
16 "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 Software, with or without modifications, in source and/or binary forms;
18 provided that if you redistribute the Apple Software in its entirety and
19 without modifications, you must retain this notice and the following
20 text and disclaimers in all such redistributions of the Apple Software.
21 Neither the name, trademarks, service marks or logos of Apple Inc. may
22 be used to endorse or promote products derived from the Apple Software
23 without specific prior written permission from Apple. Except as
24 expressly stated in this notice, no other rights or licenses, express or
25 implied, are granted by Apple herein, including but not limited to any
26 patent rights that may be infringed by your derivative works or by other
27 works in which the Apple Software may be incorporated.
29 The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
35 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 POSSIBILITY OF SUCH DAMAGE.
44 Copyright (C) 2014 Apple Inc. All Rights Reserved.
47 #include "AUPlugInDispatch.h"
48 #include "CAXException.h"
49 #include "ComponentBase.h"
52 #define ACPI ((AudioComponentPlugInInstance *)self)
53 #define AUI ((AUBase *)&ACPI->mInstanceStorage)
55 #define AUI_LOCK CAMutex::Locker auLock(AUI->GetMutex());
57 // ------------------------------------------------------------------------------------------------
58 static OSStatus AUMethodInitialize(void *self)
60 OSStatus result = noErr;
63 result = AUI->DoInitialize();
69 static OSStatus AUMethodUninitialize(void *self)
71 OSStatus result = noErr;
80 static OSStatus AUMethodGetPropertyInfo(void *self, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32 *outDataSize, Boolean *outWritable)
82 OSStatus result = noErr;
84 UInt32 dataSize = 0; // 13517289 GetPropetyInfo was returning an uninitialized value when there is an error. This is a problem for auval.
85 Boolean writable = false;
88 result = AUI->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable);
89 if (outDataSize != NULL)
90 *outDataSize = dataSize;
91 if (outWritable != NULL)
92 *outWritable = writable;
98 static OSStatus AUMethodGetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void *outData, UInt32 *ioDataSize)
100 OSStatus result = noErr;
102 UInt32 actualPropertySize, clientBufferSize;
108 if (ioDataSize == NULL) {
109 ca_debug_string("AudioUnitGetProperty: null size pointer");
110 result = kAudio_ParamError;
111 goto finishGetProperty;
113 if (outData == NULL) {
116 result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, dataSize, writable);
117 *ioDataSize = dataSize;
118 goto finishGetProperty;
121 clientBufferSize = *ioDataSize;
122 if (clientBufferSize == 0)
124 ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
125 // $$$ or should we allow this as a shortcut for finding the size?
126 result = kAudio_ParamError;
127 goto finishGetProperty;
130 result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, actualPropertySize, writable);
132 goto finishGetProperty;
134 if (clientBufferSize < actualPropertySize)
136 tempBuffer = new char[actualPropertySize];
137 destBuffer = tempBuffer;
140 destBuffer = outData;
143 result = AUI->DispatchGetProperty(inID, inScope, inElement, destBuffer);
145 if (result == noErr) {
146 if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
148 memcpy(outData, tempBuffer, clientBufferSize);
150 // ioDataSize remains correct, the number of bytes we wrote
152 *ioDataSize = actualPropertySize;
161 static OSStatus AUMethodSetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void *inData, UInt32 inDataSize)
163 OSStatus result = noErr;
166 if (inData && inDataSize)
167 result = AUI->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize);
169 if (inData == NULL && inDataSize == 0) {
170 result = AUI->DispatchRemovePropertyValue(inID, inScope, inElement);
172 if (inData == NULL) {
173 ca_debug_string("AudioUnitSetProperty: inData == NULL");
174 result = kAudio_ParamError;
175 goto finishSetProperty;
178 if (inDataSize == 0) {
179 ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
180 result = kAudio_ParamError;
181 goto finishSetProperty;
191 static OSStatus AUMethodAddPropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
193 OSStatus result = noErr;
196 result = AUI->AddPropertyListener(prop, proc, userData);
202 static OSStatus AUMethodRemovePropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
204 OSStatus result = noErr;
207 result = AUI->RemovePropertyListener(prop, proc, NULL, false);
213 static OSStatus AUMethodRemovePropertyListenerWithUserData(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
215 OSStatus result = noErr;
218 result = AUI->RemovePropertyListener(prop, proc, userData, true);
224 static OSStatus AUMethodAddRenderNotify(void *self, AURenderCallback proc, void *userData)
226 OSStatus result = noErr;
229 result = AUI->SetRenderNotification(proc, userData);
235 static OSStatus AUMethodRemoveRenderNotify(void *self, AURenderCallback proc, void *userData)
237 OSStatus result = noErr;
240 result = AUI->RemoveRenderNotification(proc, userData);
246 static OSStatus AUMethodGetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value)
248 OSStatus result = noErr;
251 result = (value == NULL ? kAudio_ParamError : AUI->GetParameter(param, scope, elem, *value));
257 static OSStatus AUMethodSetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
259 OSStatus result = noErr;
261 // this is a (potentially) realtime method; no lock
262 result = AUI->SetParameter(param, scope, elem, value, bufferOffset);
268 static OSStatus AUMethodScheduleParameters(void *self, const AudioUnitParameterEvent *events, UInt32 numEvents)
270 OSStatus result = noErr;
272 // this is a (potentially) realtime method; no lock
273 result = AUI->ScheduleParameter(events, numEvents);
279 static OSStatus AUMethodRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
281 OSStatus result = noErr;
283 #if !TARGET_OS_IPHONE
286 // this is a processing method; no lock
287 AudioUnitRenderActionFlags tempFlags;
289 if (inTimeStamp == NULL || ioData == NULL)
290 result = kAudio_ParamError;
292 if (ioActionFlags == NULL) {
294 ioActionFlags = &tempFlags;
296 result = AUI->DoRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData);
299 #if !TARGET_OS_IPHONE
307 static OSStatus AUMethodComplexRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberOfPackets, UInt32 *outNumberOfPackets, AudioStreamPacketDescription *outPacketDescriptions, AudioBufferList *ioData, void *outMetadata, UInt32 *outMetadataByteSize)
309 OSStatus result = noErr;
311 #if !TARGET_OS_IPHONE
314 // this is a processing method; no lock
315 AudioUnitRenderActionFlags tempFlags;
317 if (inTimeStamp == NULL || ioData == NULL)
318 result = kAudio_ParamError;
320 if (ioActionFlags == NULL) {
322 ioActionFlags = &tempFlags;
324 result = AUI->ComplexRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions, *ioData, outMetadata, outMetadataByteSize);
327 #if !TARGET_OS_IPHONE
335 static OSStatus AUMethodReset(void *self, AudioUnitScope scope, AudioUnitElement elem)
337 OSStatus result = noErr;
340 result = AUI->Reset(scope, elem);
346 static OSStatus AUMethodProcess (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList *ioData)
348 OSStatus result = noErr;
350 #if !TARGET_OS_IPHONE
353 // this is a processing method; no lock
354 bool doParamCheck = true;
356 AudioUnitRenderActionFlags tempFlags;
358 if (ioActionFlags == NULL) {
360 ioActionFlags = &tempFlags;
362 if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
363 doParamCheck = false;
366 if (doParamCheck && (inTimeStamp == NULL || ioData == NULL))
367 result = kAudio_ParamError;
369 result = AUI->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData);
372 #if !TARGET_OS_IPHONE
380 static OSStatus AUMethodProcessMultiple (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, UInt32 inNumberInputBufferLists, const AudioBufferList **inInputBufferLists, UInt32 inNumberOutputBufferLists, AudioBufferList **ioOutputBufferLists)
382 OSStatus result = noErr;
384 #if !TARGET_OS_IPHONE
387 // this is a processing method; no lock
388 bool doParamCheck = true;
390 AudioUnitRenderActionFlags tempFlags;
392 if (ioActionFlags == NULL) {
394 ioActionFlags = &tempFlags;
396 if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
397 doParamCheck = false;
400 if (doParamCheck && (inTimeStamp == NULL || inInputBufferLists == NULL || ioOutputBufferLists == NULL))
401 result = kAudio_ParamError;
403 result = AUI->DoProcessMultiple(*ioActionFlags, *inTimeStamp, inNumberFrames, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
406 #if !TARGET_OS_IPHONE
413 // ------------------------------------------------------------------------------------------------
415 static OSStatus AUMethodStart(void *self)
417 OSStatus result = noErr;
420 result = AUI->Start();
426 static OSStatus AUMethodStop(void *self)
428 OSStatus result = noErr;
431 result = AUI->Stop();
437 // ------------------------------------------------------------------------------------------------
439 #if !CA_BASIC_AU_FEATURES
440 // I don't know what I'm doing here; conflicts with the multiple inheritence in MusicDeviceBase.
441 static OSStatus AUMethodMIDIEvent(void *self, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
443 OSStatus result = noErr;
445 // this is a potential render-time method; no lock
446 result = AUI->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
452 static OSStatus AUMethodSysEx(void *self, const UInt8 *inData, UInt32 inLength)
454 OSStatus result = noErr;
456 // this is a potential render-time method; no lock
457 result = AUI->SysEx(inData, inLength);
463 static OSStatus AUMethodStartNote(void *self, MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams)
465 OSStatus result = noErr;
467 // this is a potential render-time method; no lock
468 if (inParams == NULL || outNoteInstanceID == NULL)
469 result = kAudio_ParamError;
471 result = AUI->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
477 static OSStatus AUMethodStopNote(void *self, MusicDeviceGroupID inGroupID, NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame)
479 OSStatus result = noErr;
481 // this is a potential render-time method; no lock
482 result = AUI->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
488 #if !TARGET_OS_IPHONE
489 static OSStatus AUMethodPrepareInstrument (void *self, MusicDeviceInstrumentID inInstrument)
491 OSStatus result = noErr;
493 // this is a potential render-time method; no lock
494 result = AUI->PrepareInstrument(inInstrument);
500 static OSStatus AUMethodReleaseInstrument (void *self, MusicDeviceInstrumentID inInstrument)
502 OSStatus result = noErr;
504 // this is a potential render-time method; no lock
505 result = AUI->ReleaseInstrument(inInstrument);
510 #endif // TARGET_OS_IPHONE
511 #endif // CA_BASIC_AU_FEATURES
514 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
516 #pragma mark Lookup Methods
518 AudioComponentMethod AUBaseLookup::Lookup (SInt16 selector)
521 case kAudioUnitInitializeSelect: return (AudioComponentMethod)AUMethodInitialize;
522 case kAudioUnitUninitializeSelect: return (AudioComponentMethod)AUMethodUninitialize;
523 case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
524 case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
525 case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
526 case kAudioUnitAddPropertyListenerSelect:return (AudioComponentMethod)AUMethodAddPropertyListener;
527 case kAudioUnitRemovePropertyListenerSelect:
528 return (AudioComponentMethod)AUMethodRemovePropertyListener;
529 case kAudioUnitRemovePropertyListenerWithUserDataSelect:
530 return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData;
531 case kAudioUnitAddRenderNotifySelect: return (AudioComponentMethod)AUMethodAddRenderNotify;
532 case kAudioUnitRemoveRenderNotifySelect:return (AudioComponentMethod)AUMethodRemoveRenderNotify;
533 case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
534 case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;
535 case kAudioUnitScheduleParametersSelect:return (AudioComponentMethod)AUMethodScheduleParameters;
536 case kAudioUnitRenderSelect: return (AudioComponentMethod)AUMethodRender;
537 case kAudioUnitResetSelect: return (AudioComponentMethod)AUMethodReset;
544 AudioComponentMethod AUOutputLookup::Lookup (SInt16 selector)
546 AudioComponentMethod method = AUBaseLookup::Lookup(selector);
547 if (method) return method;
550 case kAudioOutputUnitStartSelect: return (AudioComponentMethod)AUMethodStart;
551 case kAudioOutputUnitStopSelect: return (AudioComponentMethod)AUMethodStop;
558 AudioComponentMethod AUComplexOutputLookup::Lookup (SInt16 selector)
560 AudioComponentMethod method = AUBaseLookup::Lookup(selector);
561 if (method) return method;
563 method = AUOutputLookup::Lookup(selector);
564 if (method) return method;
566 if (selector == kAudioUnitComplexRenderSelect)
567 return (AudioComponentMethod)AUMethodComplexRender;
571 AudioComponentMethod AUBaseProcessLookup::Lookup (SInt16 selector)
573 AudioComponentMethod method = AUBaseLookup::Lookup(selector);
574 if (method) return method;
576 if (selector == kAudioUnitProcessSelect)
577 return (AudioComponentMethod)AUMethodProcess;
582 AudioComponentMethod AUBaseProcessMultipleLookup::Lookup (SInt16 selector)
584 AudioComponentMethod method = AUBaseLookup::Lookup(selector);
585 if (method) return method;
587 if (selector == kAudioUnitProcessMultipleSelect)
588 return (AudioComponentMethod)AUMethodProcessMultiple;
593 AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup (SInt16 selector)
595 AudioComponentMethod method = AUBaseLookup::Lookup(selector);
596 if (method) return method;
598 method = AUBaseProcessMultipleLookup::Lookup(selector);
599 if (method) return method;
601 method = AUBaseProcessLookup::Lookup(selector);
602 if (method) return method;
607 #if !CA_BASIC_AU_FEATURES
608 inline AudioComponentMethod MIDI_Lookup (SInt16 selector)
611 case kMusicDeviceMIDIEventSelect: return (AudioComponentMethod)AUMethodMIDIEvent;
612 case kMusicDeviceSysExSelect: return (AudioComponentMethod)AUMethodSysEx;
619 AudioComponentMethod AUMIDILookup::Lookup (SInt16 selector)
621 AudioComponentMethod method = AUBaseLookup::Lookup(selector);
622 if (method) return method;
624 return MIDI_Lookup(selector);
627 AudioComponentMethod AUMIDIProcessLookup::Lookup (SInt16 selector)
629 AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector);
630 if (method) return method;
632 return MIDI_Lookup(selector);
635 AudioComponentMethod AUMusicLookup::Lookup (SInt16 selector)
637 AudioComponentMethod method = AUBaseLookup::Lookup(selector);
638 if (method) return method;
641 case kMusicDeviceStartNoteSelect: return (AudioComponentMethod)AUMethodStartNote;
642 case kMusicDeviceStopNoteSelect: return (AudioComponentMethod)AUMethodStopNote;
643 #if !TARGET_OS_IPHONE
644 case kMusicDevicePrepareInstrumentSelect: return (AudioComponentMethod)AUMethodPrepareInstrument;
645 case kMusicDeviceReleaseInstrumentSelect: return (AudioComponentMethod)AUMethodReleaseInstrument;
650 return MIDI_Lookup (selector);
653 AudioComponentMethod AUAuxBaseLookup::Lookup (SInt16 selector)
656 case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
657 case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
658 case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
660 case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
661 case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;