in Source/AUBase.cpp [683:882]
OSStatus AUBase::DispatchSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize)
{
OSStatus result = noErr;
switch (inID) {
case kAudioUnitProperty_MakeConnection: {
AUSDK_Require(
inDataSize >= sizeof(AudioUnitConnection), kAudioUnitErr_InvalidPropertyValue);
const auto& connection = *static_cast<const AudioUnitConnection*>(inData);
result = SetConnection(connection);
break;
}
case kAudioUnitProperty_SetRenderCallback: {
AUSDK_Require(
inDataSize >= sizeof(AURenderCallbackStruct), kAudioUnitErr_InvalidPropertyValue);
const auto& callback = *static_cast<const AURenderCallbackStruct*>(inData);
result = SetInputCallback(kAudioUnitProperty_SetRenderCallback, inElement,
callback.inputProc, callback.inputProcRefCon);
break;
}
case kAudioUnitProperty_ElementCount:
AUSDK_Require(inDataSize == sizeof(UInt32), kAudioUnitErr_InvalidPropertyValue);
AUSDK_Require(BusCountWritable(inScope), kAudioUnitErr_PropertyNotWritable);
result = SetBusCount(inScope, *static_cast<const UInt32*>(inData));
if (result == noErr) {
PropertyChanged(inID, inScope, inElement);
}
break;
case kAudioUnitProperty_MaximumFramesPerSlice:
AUSDK_Require(inDataSize == sizeof(UInt32), kAudioUnitErr_InvalidPropertyValue);
AUSDK_Require_noerr(CanSetMaxFrames());
SetMaxFramesPerSlice(*static_cast<const UInt32*>(inData));
break;
case kAudioUnitProperty_StreamFormat: {
constexpr static UInt32 kMinimumValidASBDSize = 36;
AUSDK_Require(inDataSize >= kMinimumValidASBDSize, kAudioUnitErr_InvalidPropertyValue);
AUSDK_Require(GetElement(inScope, inElement) != nullptr, kAudioUnitErr_InvalidElement);
AudioStreamBasicDescription newDesc = {};
// now we're going to be ultra conservative! because of discrepancies between
// sizes of this struct based on aligment padding inconsistencies
memcpy(&newDesc, inData, kMinimumValidASBDSize);
AUSDK_Require(ASBD::MinimalSafetyCheck(newDesc), kAudioUnitErr_FormatNotSupported);
AUSDK_Require(ValidFormat(inScope, inElement, newDesc), kAudioUnitErr_FormatNotSupported);
const AudioStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
if (!ASBD::IsEqual(curDesc, newDesc)) {
AUSDK_Require(
IsStreamFormatWritable(inScope, inElement), kAudioUnitErr_PropertyNotWritable);
result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
}
break;
}
case kAudioUnitProperty_SampleRate: {
AUSDK_Require(inDataSize == sizeof(Float64), kAudioUnitErr_InvalidPropertyValue);
AUSDK_Require(GetElement(inScope, inElement) != nullptr, kAudioUnitErr_InvalidElement);
const AudioStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
AudioStreamBasicDescription newDesc = curDesc;
newDesc.mSampleRate = *static_cast<const Float64*>(inData);
AUSDK_Require(ValidFormat(inScope, inElement, newDesc), kAudioUnitErr_FormatNotSupported);
if (!ASBD::IsEqual(curDesc, newDesc)) {
AUSDK_Require(
IsStreamFormatWritable(inScope, inElement), kAudioUnitErr_PropertyNotWritable);
result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
}
break;
}
case kAudioUnitProperty_AudioChannelLayout: {
const auto& layout = *static_cast<const AudioChannelLayout*>(inData);
constexpr size_t headerSize = sizeof(AudioChannelLayout) - sizeof(AudioChannelDescription);
AUSDK_Require(inDataSize >= offsetof(AudioChannelLayout, mNumberChannelDescriptions) +
sizeof(AudioChannelLayout::mNumberChannelDescriptions),
kAudioUnitErr_InvalidPropertyValue);
AUSDK_Require(inDataSize >= headerSize + layout.mNumberChannelDescriptions *
sizeof(AudioChannelDescription),
kAudioUnitErr_InvalidPropertyValue);
result = SetAudioChannelLayout(inScope, inElement, &layout);
if (result == noErr) {
PropertyChanged(inID, inScope, inElement);
}
break;
}
case kAudioUnitProperty_ClassInfo:
AUSDK_Require(inDataSize == sizeof(CFPropertyListRef*), kAudioUnitErr_InvalidPropertyValue);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
result = RestoreState(*static_cast<const CFPropertyListRef*>(inData));
break;
case kAudioUnitProperty_PresentPreset: {
AUSDK_Require(inDataSize == sizeof(AUPreset), kAudioUnitErr_InvalidPropertyValue);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
const auto& newPreset = *static_cast<const AUPreset*>(inData);
if (newPreset.presetNumber >= 0) {
result = NewFactoryPresetSet(newPreset);
// NewFactoryPresetSet SHOULD call SetAFactoryPreset if the preset is valid
// from its own list of preset number->name
if (result == noErr) {
PropertyChanged(inID, inScope, inElement);
}
} else if (newPreset.presetName != nullptr) {
result = NewCustomPresetSet(newPreset);
if (result == noErr) {
PropertyChanged(inID, inScope, inElement);
}
} else {
result = kAudioUnitErr_InvalidPropertyValue;
}
break;
}
case kAudioUnitProperty_ElementName: {
AUSDK_Require(GetElement(inScope, inElement) != nullptr, kAudioUnitErr_InvalidElement);
AUSDK_Require(inDataSize == sizeof(CFStringRef), kAudioUnitErr_InvalidPropertyValue);
const auto element = GetScope(inScope).GetElement(inElement);
const CFStringRef inStr = *static_cast<const CFStringRef*>(inData);
element->SetName(inStr);
PropertyChanged(inID, inScope, inElement);
break;
}
case kAudioUnitProperty_ShouldAllocateBuffer: {
AUSDK_Require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output),
kAudioUnitErr_InvalidScope);
AUSDK_Require(GetElement(inScope, inElement) != nullptr, kAudioUnitErr_InvalidElement);
AUSDK_Require(inDataSize == sizeof(UInt32), kAudioUnitErr_InvalidPropertyValue);
AUSDK_Require(!IsInitialized(), kAudioUnitErr_Initialized);
auto& element = IOElement(inScope, inElement);
element.SetWillAllocateBuffer(*static_cast<const UInt32*>(inData) != 0);
break;
}
case kAudioUnitProperty_HostCallbacks: {
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
const UInt32 availSize =
std::min(inDataSize, static_cast<UInt32>(sizeof(HostCallbackInfo)));
const bool hasChanged = memcmp(&mHostCallbackInfo, inData, availSize) == 0;
mHostCallbackInfo = {};
memcpy(&mHostCallbackInfo, inData, availSize);
if (hasChanged) {
PropertyChanged(inID, inScope, inElement);
}
break;
}
case kAudioUnitProperty_ContextName: {
AUSDK_Require(inDataSize == sizeof(CFStringRef), kAudioUnitErr_InvalidPropertyValue);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
const CFStringRef inStr = *static_cast<const CFStringRef*>(inData);
mContextName = inStr;
PropertyChanged(inID, inScope, inElement);
break;
}
case kAudioUnitProperty_NickName: {
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inDataSize == sizeof(CFStringRef), kAudioUnitErr_InvalidPropertyValue);
const CFStringRef inStr = *static_cast<const CFStringRef*>(inData);
mNickName = inStr;
PropertyChanged(inID, inScope, inElement);
break;
}
#if AUSDK_MIDI2_AVAILABLE
case kAudioUnitProperty_HostMIDIProtocol: {
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inDataSize == sizeof(MIDIProtocolID), kAudioUnitErr_InvalidPropertyValue);
mHostMIDIProtocol = *static_cast<const MIDIProtocolID*>(inData);
PropertyChanged(inID, inScope, inElement);
break;
}
#endif
default:
result = SetProperty(inID, inScope, inElement, inData, inDataSize);
if (result == noErr) {
PropertyChanged(inID, inScope, inElement);
}
break;
}
return result;
}