in Source/AUBase.cpp [1760:1840]
OSStatus AUBase::SaveState(CFPropertyListRef* outData)
{
const AudioComponentDescription desc = GetComponentDescription();
auto dict = Owned<CFMutableDictionaryRef>::from_create(CFDictionaryCreateMutable(
nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
// first step -> save the version to the data ref
SInt32 value = kCurrentSavedStateVersion;
AddNumToDictionary(*dict, kVersionString, value);
// second step -> save the component type, subtype, manu to the data ref
value = static_cast<SInt32>(desc.componentType);
AddNumToDictionary(*dict, kTypeString, value);
value = static_cast<SInt32>(desc.componentSubType);
AddNumToDictionary(*dict, kSubtypeString, value);
value = static_cast<SInt32>(desc.componentManufacturer);
AddNumToDictionary(*dict, kManufacturerString, value);
// fourth step -> save the state of all parameters on all scopes and elements
auto data = Owned<CFMutableDataRef>::from_create(CFDataCreateMutable(nullptr, 0));
for (AudioUnitScope iscope = 0; iscope < 3; ++iscope) {
const auto& scope = GetScope(iscope);
scope.SaveState(*data);
}
SaveExtendedScopes(*data);
// save all this in the data section of the dictionary
CFDictionarySetValue(*dict, kDataString, *data);
data = nullptr; // data can be large-ish, so destroy it now.
// OK - now we're going to do some properties
// save the preset name...
CFDictionarySetValue(*dict, kNameString, mCurrentPreset.presetName);
// Does the unit support the RenderQuality property - if so, save it...
OSStatus result =
DispatchGetProperty(kAudioUnitProperty_RenderQuality, kAudioUnitScope_Global, 0, &value);
if (result == noErr) {
AddNumToDictionary(*dict, kRenderQualityString, value);
}
// Does the unit support the CPULoad Quality property - if so, save it...
Float32 cpuLoad = 0.0f;
result = DispatchGetProperty(kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &cpuLoad);
if (result == noErr) {
CFNumberRef num = CFNumberCreate(nullptr, kCFNumberFloatType, &cpuLoad);
CFDictionarySetValue(*dict, kCPULoadString, num);
CFRelease(num);
}
// Do we have any element names for any of our scopes?
// first check to see if we have any names...
bool foundName = false;
for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
foundName = GetScope(i).HasElementWithName();
if (foundName) {
break;
}
}
// OK - we found a name away we go...
if (foundName) {
auto nameDict = Owned<CFMutableDictionaryRef>::from_create(CFDictionaryCreateMutable(
nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
GetScope(i).AddElementNamesToDict(*nameDict);
}
CFDictionarySetValue(*dict, kElementNameString, *nameDict);
}
// we're done!!!
*outData = static_cast<CFPropertyListRef>(dict.release()); // transfer ownership
return noErr;
}