in Source/AUBase.cpp [1845:1968]
OSStatus AUBase::RestoreState(CFPropertyListRef plist)
{
if (CFGetTypeID(plist) != CFDictionaryGetTypeID()) {
return kAudioUnitErr_InvalidPropertyValue;
}
const AudioComponentDescription desc = GetComponentDescription();
const auto* const dict = static_cast<CFDictionaryRef>(plist);
// zeroeth step - make sure the Part key is NOT present, as this method is used
// to restore the GLOBAL state of the dictionary
if (CFDictionaryContainsKey(dict, kPartString)) {
return kAudioUnitErr_InvalidPropertyValue;
}
// first step -> check the saved version in the data ref
// at this point we're only dealing with version==0
const auto* cfnum = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kVersionString));
if (cfnum == nullptr) {
return kAudioUnitErr_InvalidPropertyValue;
}
SInt32 value = 0;
CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value);
if (value != kCurrentSavedStateVersion) {
return kAudioUnitErr_InvalidPropertyValue;
}
// second step -> check that this data belongs to this kind of audio unit
// by checking the component subtype and manuID
// We're not checking the type, since there may be different versions (effect, format-converter,
// offline) of essentially the same AU
cfnum = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kSubtypeString));
if (cfnum == nullptr) {
return kAudioUnitErr_InvalidPropertyValue;
}
CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value);
if (static_cast<UInt32>(value) != desc.componentSubType) {
return kAudioUnitErr_InvalidPropertyValue;
}
cfnum = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kManufacturerString));
if (cfnum == nullptr) {
return kAudioUnitErr_InvalidPropertyValue;
}
CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value);
if (static_cast<UInt32>(value) != desc.componentManufacturer) {
return kAudioUnitErr_InvalidPropertyValue;
}
// fourth step -> restore the state of all of the parameters for each scope and element
const auto* const data = static_cast<CFDataRef>(CFDictionaryGetValue(dict, kDataString));
if (data != nullptr) {
const UInt8* p = CFDataGetBytePtr(data);
const UInt8* const pend = p + CFDataGetLength(data); // NOLINT
// we have a zero length data, which may just mean there were no parameters to save!
// if (p >= pend) return noErr;
while (p < pend) {
const UInt32 scopeIdx =
CFSwapInt32BigToHost(*reinterpret_cast<const UInt32*>(p)); // NOLINT
p += sizeof(UInt32); // NOLINT
const auto& scope = GetScope(scopeIdx);
p = scope.RestoreState(p);
}
}
// OK - now we're going to do some properties
// restore the preset name...
const auto* const name = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kNameString));
if (mCurrentPreset.presetName != nullptr) {
CFRelease(mCurrentPreset.presetName);
}
if (name != nullptr) {
mCurrentPreset.presetName = name;
mCurrentPreset.presetNumber = -1;
} else { // no name entry make the default one
mCurrentPreset.presetName = kUntitledString;
mCurrentPreset.presetNumber = -1;
}
CFRetain(mCurrentPreset.presetName);
PropertyChanged(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0);
// Does the dict contain render quality information?
if (CFDictionaryGetValueIfPresent(
dict, kRenderQualityString, reinterpret_cast<const void**>(&cfnum))) { // NOLINT
CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value);
DispatchSetProperty(
kAudioUnitProperty_RenderQuality, kAudioUnitScope_Global, 0, &value, sizeof(value));
}
// Does the unit support the CPULoad Quality property - if so, save it...
if (CFDictionaryGetValueIfPresent(
dict, kCPULoadString, reinterpret_cast<const void**>(&cfnum))) { // NOLINT
auto floatValue = std::numeric_limits<Float32>::quiet_NaN;
CFNumberGetValue(cfnum, kCFNumberFloatType, &floatValue);
DispatchSetProperty(
kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &floatValue, sizeof(floatValue));
}
// Do we have any element names for any of our scopes?
CFDictionaryRef nameDict = nullptr;
if (CFDictionaryGetValueIfPresent(
dict, kElementNameString, reinterpret_cast<const void**>(&nameDict))) { // NOLINT
for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
const CFStringRef key = CFStringCreateWithFormat(
nullptr, nullptr, CFSTR("%u"), static_cast<unsigned>(i)); // NOLINT
CFDictionaryRef elementDict = nullptr;
if (CFDictionaryGetValueIfPresent(
nameDict, key, reinterpret_cast<const void**>(&elementDict))) { // NOLINT
const bool didAddElements = GetScope(i).RestoreElementNames(elementDict);
if (didAddElements) {
PropertyChanged(kAudioUnitProperty_ElementCount, i, 0);
}
}
CFRelease(key);
}
}
return noErr;
}