Bug in saving user presets
Bug in saving user presets
- Subject: Bug in saving user presets
- From: Robert Abernathy <email@hidden>
- Date: Wed, 25 Jan 2006 21:39:56 +0000
I'm tracking down a bug in user presets in an AU I'm working on.
I've tracked it down to being in AUBase::SaveState or
AUElement::SaveState.
The parameter data is being gathered correctly in
AUElement::SaveState. If I print it here as it is being pulled from
mParameters or mIndexedParameters, it is correct.
If I take the, the dictionary that is built in AUBase::SaveState and
print it out immediately after the parameter data is added, I can see
that the data is wrong at this point. (See code below, the function
TestState is where the data is checked. It mimics the read data in
AUElement::RestoreState to do the dictionary/data read.)
The parameter data is offset by two indices. As the parameters are
read back in AUElement::PrintState, the zeroth and first elements are
garbage (close to zero). The 2nd entry contains the value of the
zeroth parameter. The 3rd entry contains the value of the first
parameter and so forth, up to the 90th entry containing the value of
the 88th parameter. The 89th and 90th parameters are missing.
If I print the data out as it is being read back in
AUElement::RestoreState, the pattern above is the same. Shifted off
by two with the first two entries garbage.
The code I used for testing is below.
Any help would be much appreciated as I'm kinda stuck here.
Thanks,
Rob
Code
below-------------------------------------------------------------------
-----------
ComponentResult AUBase::SaveState( CFPropertyListRef * outData)
{
ComponentDescription desc;
OSStatus result = GetComponentInfo((Component)GetComponentInstance
(), &desc, NULL, NULL, NULL);
if (result) return result;
CFMutableDictionaryRef dict = CFDictionaryCreateMutable (NULL, 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 = desc.componentType;
AddNumToDictionary (dict, kTypeString, value);
value = desc.componentSubType;
AddNumToDictionary (dict, kSubtypeString, value);
value = desc.componentManufacturer;
AddNumToDictionary (dict, kManufacturerString, value);
// fourth step -> save the state of all parameters on all scopes and
elements
CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
for (AudioUnitScope iscope = 0; iscope < 4; ++iscope) {
if (iscope == kAudioUnitScope_Group)
continue;
AUScope &scope = GetScope(iscope);
AudioUnitElement nElems = scope.GetNumberOfElements();
for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
AUElement *element = scope.GetElement(ielem);
UInt32 nparams = element->GetNumberOfParameters();
if (nparams > 0) {
struct {
UInt32 scope;
UInt32 element;
} hdr;
hdr.scope = EndianU32_NtoB(iscope);
hdr.element = EndianU32_NtoB(ielem);
CFDataAppendBytes(data, (UInt8 *)&hdr, sizeof(hdr));
element->SaveState(data);
}
}
}
// save all this in the data section of the dictionary
CFDictionarySetValue(dict, kDataString, data);
CFRelease (data);
TestState(dict); // my added function to print out the data
//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...
value = 0;
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;
result = DispatchGetProperty (kAudioUnitProperty_CPULoad,
kAudioUnitScope_Global,
0,
&cpuLoad);
if (result == noErr) {
CFNumberRef num = CFNumberCreate (NULL, 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) {
CFMutableDictionaryRef nameDict = CFDictionaryCreateMutable (NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
GetScope (i).AddElementNamesToDict (nameDict);
}
CFDictionarySetValue (dict, kElementNameString, nameDict);
CFRelease (nameDict);
}
// we're done!!!
*outData = dict;
return noErr;
}
// -------------------------------------
// little function to test the data in the preset
void AUBase::TestState(CFMutableDictionaryRef dict) {
std::cout << "AUBase::TestState() . Count " << CFDictionaryGetCount
(dict) << "\n";
CFDataRef data = reinterpret_cast<CFDataRef>(CFDictionaryGetValue
(dict, kDataString));
if (data != NULL)
{
const UInt8 *p, *pend;
p = CFDataGetBytePtr(data);
pend = p + CFDataGetLength(data);
// we have a zero length data, which may just mean there were no
parameters to save!
// if (p >= pend) return noErr;
while (p < pend) {
struct {
UInt32 scope;
UInt32 element;
} hdr;
hdr.scope = EndianU32_BtoN(*(UInt32 *)p); p += sizeof(UInt32);
hdr.element = EndianU32_BtoN(*(UInt32 *)p); p += sizeof(UInt32);
AUScope &scope = GetScope(hdr.scope);
AUElement *element = scope.GetElement(hdr.element);
// $$$ order of operations issue: what if the element does not
yet exist?
// then we just break out of the loop
if (!element)
break;
p = element->PrintState(p);
}
}
}
// My added routine
// It mimicks AUElement::RestoreState
const UInt8 * AUElement::PrintState(const UInt8 *state)
{
const UInt8 *p = state;
UInt32 nparams = EndianU32_BtoN(*(UInt32 *)p);
std::cout << "Print state ... NParams = " << nparams << "\n";
p += sizeof(UInt32);
for (UInt32 i = 0; i < nparams; ++i) {
struct {
UInt32 paramID;
Float32 value;
} entry;
entry.paramID = EndianU32_BtoN(*(UInt32 *)p);
p += sizeof(UInt32);
UInt32 temp = EndianU32_BtoN(*(UInt32 *)p);
entry.value = *(Float32 *)&temp;
p += sizeof(Float32);
std::cout << "Print - Element: id = " << entry.paramID << " value =
" << entry.value << "\n";
}
return p;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden