AUPublic/AUBase/AUPlugInDispatch.cpp
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Part of Core Audio AUBase Classes |
*/ |
#include "AUPlugInDispatch.h" |
#include "CAXException.h" |
#include "ComponentBase.h" |
#include "AUBase.h" |
#define ACPI ((AudioComponentPlugInInstance *)self) |
#define AUI ((AUBase *)&ACPI->mInstanceStorage) |
#define AUI_LOCK CAMutex::Locker auLock(AUI->GetMutex()); |
// ------------------------------------------------------------------------------------------------ |
static OSStatus AUMethodInitialize(void *self) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = AUI->DoInitialize(); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodUninitialize(void *self) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
AUI->DoCleanup(); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodGetPropertyInfo(void *self, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32 *outDataSize, Boolean *outWritable) |
{ |
OSStatus result = noErr; |
try { |
UInt32 dataSize = 0; // 13517289 GetPropetyInfo was returning an uninitialized value when there is an error. This is a problem for auval. |
Boolean writable = false; |
AUI_LOCK |
result = AUI->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable); |
if (outDataSize != NULL) |
*outDataSize = dataSize; |
if (outWritable != NULL) |
*outWritable = writable; |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodGetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void *outData, UInt32 *ioDataSize) |
{ |
OSStatus result = noErr; |
try { |
UInt32 actualPropertySize, clientBufferSize; |
Boolean writable; |
char *tempBuffer; |
void *destBuffer; |
AUI_LOCK |
if (ioDataSize == NULL) { |
ca_debug_string("AudioUnitGetProperty: null size pointer"); |
result = kAudio_ParamError; |
goto finishGetProperty; |
} |
if (outData == NULL) { |
UInt32 dataSize; |
result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, dataSize, writable); |
*ioDataSize = dataSize; |
goto finishGetProperty; |
} |
clientBufferSize = *ioDataSize; |
if (clientBufferSize == 0) |
{ |
ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry"); |
// $$$ or should we allow this as a shortcut for finding the size? |
result = kAudio_ParamError; |
goto finishGetProperty; |
} |
result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, actualPropertySize, writable); |
if (result != noErr) |
goto finishGetProperty; |
if (clientBufferSize < actualPropertySize) |
{ |
tempBuffer = new char[actualPropertySize]; |
destBuffer = tempBuffer; |
} else { |
tempBuffer = NULL; |
destBuffer = outData; |
} |
result = AUI->DispatchGetProperty(inID, inScope, inElement, destBuffer); |
if (result == noErr) { |
if (clientBufferSize < actualPropertySize && tempBuffer != NULL) |
{ |
memcpy(outData, tempBuffer, clientBufferSize); |
delete[] tempBuffer; |
// ioDataSize remains correct, the number of bytes we wrote |
} else |
*ioDataSize = actualPropertySize; |
} else |
*ioDataSize = 0; |
} |
COMPONENT_CATCH |
finishGetProperty: |
return result; |
} |
static OSStatus AUMethodSetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void *inData, UInt32 inDataSize) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
if (inData && inDataSize) |
result = AUI->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize); |
else { |
if (inData == NULL && inDataSize == 0) { |
result = AUI->DispatchRemovePropertyValue(inID, inScope, inElement); |
} else { |
if (inData == NULL) { |
ca_debug_string("AudioUnitSetProperty: inData == NULL"); |
result = kAudio_ParamError; |
goto finishSetProperty; |
} |
if (inDataSize == 0) { |
ca_debug_string("AudioUnitSetProperty: inDataSize == 0"); |
result = kAudio_ParamError; |
goto finishSetProperty; |
} |
} |
} |
} |
COMPONENT_CATCH |
finishSetProperty: |
return result; |
} |
static OSStatus AUMethodAddPropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = AUI->AddPropertyListener(prop, proc, userData); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodRemovePropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = AUI->RemovePropertyListener(prop, proc, NULL, false); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodRemovePropertyListenerWithUserData(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = AUI->RemovePropertyListener(prop, proc, userData, true); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodAddRenderNotify(void *self, AURenderCallback proc, void *userData) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = AUI->SetRenderNotification(proc, userData); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodRemoveRenderNotify(void *self, AURenderCallback proc, void *userData) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = AUI->RemoveRenderNotification(proc, userData); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodGetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = (value == NULL ? kAudio_ParamError : AUI->GetParameter(param, scope, elem, *value)); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodSetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset) |
{ |
OSStatus result = noErr; |
try { |
// this is a (potentially) realtime method; no lock |
result = AUI->SetParameter(param, scope, elem, value, bufferOffset); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodScheduleParameters(void *self, const AudioUnitParameterEvent *events, UInt32 numEvents) |
{ |
OSStatus result = noErr; |
try { |
// this is a (potentially) realtime method; no lock |
result = AUI->ScheduleParameter(events, numEvents); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) |
{ |
OSStatus result = noErr; |
#if !TARGET_OS_IPHONE |
try { |
#endif |
// this is a processing method; no lock |
AudioUnitRenderActionFlags tempFlags; |
if (inTimeStamp == NULL || ioData == NULL) |
result = kAudio_ParamError; |
else { |
if (ioActionFlags == NULL) { |
tempFlags = 0; |
ioActionFlags = &tempFlags; |
} |
result = AUI->DoRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData); |
} |
#if !TARGET_OS_IPHONE |
} |
COMPONENT_CATCH |
#endif |
return result; |
} |
static OSStatus AUMethodComplexRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberOfPackets, UInt32 *outNumberOfPackets, AudioStreamPacketDescription *outPacketDescriptions, AudioBufferList *ioData, void *outMetadata, UInt32 *outMetadataByteSize) |
{ |
OSStatus result = noErr; |
#if !TARGET_OS_IPHONE |
try { |
#endif |
// this is a processing method; no lock |
AudioUnitRenderActionFlags tempFlags; |
if (inTimeStamp == NULL || ioData == NULL) |
result = kAudio_ParamError; |
else { |
if (ioActionFlags == NULL) { |
tempFlags = 0; |
ioActionFlags = &tempFlags; |
} |
result = AUI->ComplexRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions, *ioData, outMetadata, outMetadataByteSize); |
} |
#if !TARGET_OS_IPHONE |
} |
COMPONENT_CATCH |
#endif |
return result; |
} |
static OSStatus AUMethodReset(void *self, AudioUnitScope scope, AudioUnitElement elem) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = AUI->Reset(scope, elem); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodProcess (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList *ioData) |
{ |
OSStatus result = noErr; |
#if !TARGET_OS_IPHONE |
try { |
#endif |
// this is a processing method; no lock |
bool doParamCheck = true; |
AudioUnitRenderActionFlags tempFlags; |
if (ioActionFlags == NULL) { |
tempFlags = 0; |
ioActionFlags = &tempFlags; |
} else { |
if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/) |
doParamCheck = false; |
} |
if (doParamCheck && (inTimeStamp == NULL || ioData == NULL)) |
result = kAudio_ParamError; |
else { |
result = AUI->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData); |
} |
#if !TARGET_OS_IPHONE |
} |
COMPONENT_CATCH |
#endif |
return result; |
} |
static OSStatus AUMethodProcessMultiple (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, UInt32 inNumberInputBufferLists, const AudioBufferList **inInputBufferLists, UInt32 inNumberOutputBufferLists, AudioBufferList **ioOutputBufferLists) |
{ |
OSStatus result = noErr; |
#if !TARGET_OS_IPHONE |
try { |
#endif |
// this is a processing method; no lock |
bool doParamCheck = true; |
AudioUnitRenderActionFlags tempFlags; |
if (ioActionFlags == NULL) { |
tempFlags = 0; |
ioActionFlags = &tempFlags; |
} else { |
if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/) |
doParamCheck = false; |
} |
if (doParamCheck && (inTimeStamp == NULL || inInputBufferLists == NULL || ioOutputBufferLists == NULL)) |
result = kAudio_ParamError; |
else { |
result = AUI->DoProcessMultiple(*ioActionFlags, *inTimeStamp, inNumberFrames, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists); |
} |
#if !TARGET_OS_IPHONE |
} |
COMPONENT_CATCH |
#endif |
return result; |
} |
// ------------------------------------------------------------------------------------------------ |
static OSStatus AUMethodStart(void *self) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = AUI->Start(); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodStop(void *self) |
{ |
OSStatus result = noErr; |
try { |
AUI_LOCK |
result = AUI->Stop(); |
} |
COMPONENT_CATCH |
return result; |
} |
// ------------------------------------------------------------------------------------------------ |
#if !CA_BASIC_AU_FEATURES |
// I don't know what I'm doing here; conflicts with the multiple inheritence in MusicDeviceBase. |
static OSStatus AUMethodMIDIEvent(void *self, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame) |
{ |
OSStatus result = noErr; |
try { |
// this is a potential render-time method; no lock |
result = AUI->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodSysEx(void *self, const UInt8 *inData, UInt32 inLength) |
{ |
OSStatus result = noErr; |
try { |
// this is a potential render-time method; no lock |
result = AUI->SysEx(inData, inLength); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodStartNote(void *self, MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams) |
{ |
OSStatus result = noErr; |
try { |
// this is a potential render-time method; no lock |
if (inParams == NULL || outNoteInstanceID == NULL) |
result = kAudio_ParamError; |
else |
result = AUI->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodStopNote(void *self, MusicDeviceGroupID inGroupID, NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame) |
{ |
OSStatus result = noErr; |
try { |
// this is a potential render-time method; no lock |
result = AUI->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame); |
} |
COMPONENT_CATCH |
return result; |
} |
#if !TARGET_OS_IPHONE |
static OSStatus AUMethodPrepareInstrument (void *self, MusicDeviceInstrumentID inInstrument) |
{ |
OSStatus result = noErr; |
try { |
// this is a potential render-time method; no lock |
result = AUI->PrepareInstrument(inInstrument); |
} |
COMPONENT_CATCH |
return result; |
} |
static OSStatus AUMethodReleaseInstrument (void *self, MusicDeviceInstrumentID inInstrument) |
{ |
OSStatus result = noErr; |
try { |
// this is a potential render-time method; no lock |
result = AUI->ReleaseInstrument(inInstrument); |
} |
COMPONENT_CATCH |
return result; |
} |
#endif // TARGET_OS_IPHONE |
#endif // CA_BASIC_AU_FEATURES |
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
#pragma mark - |
#pragma mark Lookup Methods |
AudioComponentMethod AUBaseLookup::Lookup (SInt16 selector) |
{ |
switch (selector) { |
case kAudioUnitInitializeSelect: return (AudioComponentMethod)AUMethodInitialize; |
case kAudioUnitUninitializeSelect: return (AudioComponentMethod)AUMethodUninitialize; |
case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo; |
case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty; |
case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty; |
case kAudioUnitAddPropertyListenerSelect:return (AudioComponentMethod)AUMethodAddPropertyListener; |
case kAudioUnitRemovePropertyListenerSelect: |
return (AudioComponentMethod)AUMethodRemovePropertyListener; |
case kAudioUnitRemovePropertyListenerWithUserDataSelect: |
return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData; |
case kAudioUnitAddRenderNotifySelect: return (AudioComponentMethod)AUMethodAddRenderNotify; |
case kAudioUnitRemoveRenderNotifySelect:return (AudioComponentMethod)AUMethodRemoveRenderNotify; |
case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter; |
case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter; |
case kAudioUnitScheduleParametersSelect:return (AudioComponentMethod)AUMethodScheduleParameters; |
case kAudioUnitRenderSelect: return (AudioComponentMethod)AUMethodRender; |
case kAudioUnitResetSelect: return (AudioComponentMethod)AUMethodReset; |
default: |
break; |
} |
return NULL; |
} |
AudioComponentMethod AUOutputLookup::Lookup (SInt16 selector) |
{ |
AudioComponentMethod method = AUBaseLookup::Lookup(selector); |
if (method) return method; |
switch (selector) { |
case kAudioOutputUnitStartSelect: return (AudioComponentMethod)AUMethodStart; |
case kAudioOutputUnitStopSelect: return (AudioComponentMethod)AUMethodStop; |
default: |
break; |
} |
return NULL; |
} |
AudioComponentMethod AUComplexOutputLookup::Lookup (SInt16 selector) |
{ |
AudioComponentMethod method = AUBaseLookup::Lookup(selector); |
if (method) return method; |
method = AUOutputLookup::Lookup(selector); |
if (method) return method; |
if (selector == kAudioUnitComplexRenderSelect) |
return (AudioComponentMethod)AUMethodComplexRender; |
return NULL; |
} |
AudioComponentMethod AUBaseProcessLookup::Lookup (SInt16 selector) |
{ |
AudioComponentMethod method = AUBaseLookup::Lookup(selector); |
if (method) return method; |
if (selector == kAudioUnitProcessSelect) |
return (AudioComponentMethod)AUMethodProcess; |
return NULL; |
} |
AudioComponentMethod AUBaseProcessMultipleLookup::Lookup (SInt16 selector) |
{ |
AudioComponentMethod method = AUBaseLookup::Lookup(selector); |
if (method) return method; |
if (selector == kAudioUnitProcessMultipleSelect) |
return (AudioComponentMethod)AUMethodProcessMultiple; |
return NULL; |
} |
AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup (SInt16 selector) |
{ |
AudioComponentMethod method = AUBaseLookup::Lookup(selector); |
if (method) return method; |
method = AUBaseProcessMultipleLookup::Lookup(selector); |
if (method) return method; |
method = AUBaseProcessLookup::Lookup(selector); |
if (method) return method; |
return NULL; |
} |
#if !CA_BASIC_AU_FEATURES |
inline AudioComponentMethod MIDI_Lookup (SInt16 selector) |
{ |
switch (selector) { |
case kMusicDeviceMIDIEventSelect: return (AudioComponentMethod)AUMethodMIDIEvent; |
case kMusicDeviceSysExSelect: return (AudioComponentMethod)AUMethodSysEx; |
default: |
break; |
} |
return NULL; |
} |
AudioComponentMethod AUMIDILookup::Lookup (SInt16 selector) |
{ |
AudioComponentMethod method = AUBaseLookup::Lookup(selector); |
if (method) return method; |
return MIDI_Lookup(selector); |
} |
AudioComponentMethod AUMIDIProcessLookup::Lookup (SInt16 selector) |
{ |
AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector); |
if (method) return method; |
return MIDI_Lookup(selector); |
} |
AudioComponentMethod AUMusicLookup::Lookup (SInt16 selector) |
{ |
AudioComponentMethod method = AUBaseLookup::Lookup(selector); |
if (method) return method; |
switch (selector) { |
case kMusicDeviceStartNoteSelect: return (AudioComponentMethod)AUMethodStartNote; |
case kMusicDeviceStopNoteSelect: return (AudioComponentMethod)AUMethodStopNote; |
#if !TARGET_OS_IPHONE |
case kMusicDevicePrepareInstrumentSelect: return (AudioComponentMethod)AUMethodPrepareInstrument; |
case kMusicDeviceReleaseInstrumentSelect: return (AudioComponentMethod)AUMethodReleaseInstrument; |
#endif |
default: |
break; |
} |
return MIDI_Lookup (selector); |
} |
AudioComponentMethod AUAuxBaseLookup::Lookup (SInt16 selector) |
{ |
switch (selector) { |
case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo; |
case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty; |
case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty; |
case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter; |
case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter; |
default: |
break; |
} |
return NULL; |
} |
#endif |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-02-19