CoreAudio/PublicUtility/CAPersistence.cpp
/* |
File: CAPersistence.cpp |
Abstract: CAPersistence.h |
Version: 1.1 |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple |
Inc. ("Apple") in consideration of your agreement to the following |
terms, and your use, installation, modification or redistribution of |
this Apple software constitutes acceptance of these terms. If you do |
not agree with these terms, please do not use, install, modify or |
redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. may |
be used to endorse or promote products derived from the Apple Software |
without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or |
implied, are granted by Apple herein, including but not limited to any |
patent rights that may be infringed by your derivative works or by other |
works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
Copyright (C) 2014 Apple Inc. All Rights Reserved. |
*/ |
#include "CACFArray.h" |
#include "CACFDictionary.h" |
#include "CAAudioUnit.h" |
#include "CACFString.h" |
#include "CAAudioChannelLayout.h" |
#include "CAAUParameter.h" |
#include "CAAUMIDIMap.h" |
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h> |
#pragma mark __CAStreamBasicDescription |
static const CFStringRef kSampleRate = CFSTR("sample rate"); |
static const CFStringRef kFormat = CFSTR("format"); |
static const CFStringRef kFormatFlags = CFSTR("format flags"); |
static const CFStringRef kPacketBytes = CFSTR("packet bytes"); |
static const CFStringRef kFramePackets = CFSTR("frame packets"); |
static const CFStringRef kFrameBytes = CFSTR("frame bytes"); |
static const CFStringRef kFrameChannels = CFSTR("frame channels"); |
static const CFStringRef kChannelBits = CFSTR("channel bits"); |
// This will return a value that should be used as the key for this struct |
// and a CFData object that contains the current state of this object |
OSStatus CAStreamBasicDescription::Save (CFPropertyListRef *outData) const |
{ |
CACFDictionary dict(false); |
if (!dict.AddFloat64 (kSampleRate, mSampleRate)) goto error; |
if (!dict.AddUInt32 (kFormat, mFormatID)) goto error; |
if (!dict.AddUInt32 (kFormatFlags, mFormatFlags)) goto error; |
if (!dict.AddUInt32 (kPacketBytes, mBytesPerPacket)) goto error; |
if (!dict.AddUInt32 (kFramePackets, mFramesPerPacket)) goto error; |
if (!dict.AddUInt32 (kFrameBytes, mBytesPerFrame)) goto error; |
if (!dict.AddUInt32 (kFrameChannels, mChannelsPerFrame)) goto error; |
if (!dict.AddUInt32 (kChannelBits, mBitsPerChannel)) goto error; |
*outData = dict.GetDict(); |
return noErr; |
error: |
dict.ShouldRelease (true); |
return paramErr; |
} |
// Given a CFData object generated by the save command, this will re-establish |
// the CAStreamBasicDescription |
OSStatus CAStreamBasicDescription::Restore (CFPropertyListRef& inData) |
{ |
if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr; |
CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false); |
if (!dict.GetFloat64 (kSampleRate, mSampleRate)) return paramErr; |
if (!dict.GetUInt32 (kFormat, mFormatID)) return paramErr; |
if (!dict.GetUInt32 (kFormatFlags, mFormatFlags)) return paramErr; |
if (!dict.GetUInt32 (kPacketBytes, mBytesPerPacket)) return paramErr; |
if (!dict.GetUInt32 (kFramePackets, mFramesPerPacket)) return paramErr; |
if (!dict.GetUInt32 (kFrameBytes, mBytesPerFrame)) return paramErr; |
if (!dict.GetUInt32 (kFrameChannels, mChannelsPerFrame)) return paramErr; |
if (!dict.GetUInt32 (kChannelBits, mBitsPerChannel)) return paramErr; |
return noErr; |
} |
#pragma mark __CAComponentDescription |
static const CFStringRef kType = CFSTR("type"); |
static const CFStringRef kSubType = CFSTR("subtype"); |
static const CFStringRef kManu = CFSTR("manufacturer"); |
OSStatus CAComponentDescription::Save (CFPropertyListRef *outData) const |
{ |
CACFDictionary dict(false); |
if (!dict.AddUInt32 (kType, componentType)) goto error; |
if (!dict.AddUInt32 (kSubType, componentSubType)) goto error; |
if (!dict.AddUInt32 (kManu, componentManufacturer)) goto error; |
*outData = dict.GetDict(); |
return 0; |
error: |
dict.ShouldRelease (true); |
return paramErr; |
} |
OSStatus CAComponentDescription::Restore (CFPropertyListRef &inData) |
{ |
if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr; |
CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false); |
if (!dict.GetUInt32 (kType, componentType)) return paramErr; |
if (!dict.GetUInt32 (kSubType, componentSubType)) return paramErr; |
if (!dict.GetUInt32 (kManu, componentManufacturer)) return paramErr; |
componentFlags = 0; |
componentFlagsMask = 0; |
return 0; |
} |
#pragma mark __CAComponent |
OSStatus CAComponent::Save (CFPropertyListRef *outData) const |
{ |
OSStatus result = mDesc.Save (outData); |
if (result) return result; |
//add the name string of the component for a human readable name... |
// this name string is *not* restored when restoring the component |
CFStringRef name = GetCompName (); |
if (name && *outData) |
CFDictionarySetValue ((CFMutableDictionaryRef)(*outData), CFSTR("name"), name); |
return noErr; |
} |
OSStatus CAComponent::Restore (CFPropertyListRef &inData) |
{ |
if (mDesc.Restore (inData)) return paramErr; |
Clear(); |
mComp = AudioComponentFindNext (NULL, &mDesc); |
// this will restore the current flags... |
if (mComp) |
AudioComponentGetDescription (Comp(), &mDesc); |
return noErr; |
} |
#pragma mark __CAAudioChannelLayout |
static const CFStringRef kACLTagKey = CFSTR("acl tag"); |
static const CFStringRef kACLBitmapKey = CFSTR("chan bitmap"); |
static const CFStringRef kACLLabelKey = CFSTR("label"); |
static const CFStringRef kACLFlagsKey = CFSTR("flags"); |
static const CFStringRef kACLCoords0Key = CFSTR("coords 0"); |
static const CFStringRef kACLCoords1Key = CFSTR("coords 1"); |
static const CFStringRef kACLCoords2Key = CFSTR("coords 2"); |
static const CFStringRef kACLDescsKey = CFSTR("descriptions"); |
OSStatus CAAudioChannelLayout::Save (CFPropertyListRef *outData) const |
{ |
const AudioChannelLayout& layout = Layout(); |
CACFDictionary dict (false); |
if (!dict.AddUInt32 (kACLTagKey, layout.mChannelLayoutTag)) |
goto badadd; |
if (layout.mChannelBitmap && !dict.AddUInt32 (kACLBitmapKey, layout.mChannelBitmap)) |
goto badadd; |
if (layout.mNumberChannelDescriptions) |
{ |
CFMutableArrayRef descs = CFArrayCreateMutable (NULL, layout.mNumberChannelDescriptions, &kCFTypeArrayCallBacks); |
const AudioChannelDescription *desc = layout.mChannelDescriptions; |
for (unsigned int i = 0; i < layout.mNumberChannelDescriptions; ++i, ++desc) |
{ |
CACFDictionary descDict (true); |
if (!descDict.AddUInt32 (kACLLabelKey, desc->mChannelLabel)) |
{ CFRelease (descs); goto badadd; } |
if (!descDict.AddUInt32 (kACLFlagsKey, desc->mChannelFlags)) |
{ CFRelease (descs); goto badadd; } |
if (!descDict.AddFloat32 (kACLCoords0Key, desc->mCoordinates[0])) |
{ CFRelease (descs); goto badadd; } |
if (!descDict.AddFloat32 (kACLCoords1Key, desc->mCoordinates[1])) |
{ CFRelease (descs); goto badadd; } |
if (!descDict.AddFloat32 (kACLCoords2Key, desc->mCoordinates[2])) |
{ CFRelease (descs); goto badadd; } |
CFArrayAppendValue (descs, descDict.AsPropertyList()); |
} |
dict.AddArray (kACLDescsKey, descs); |
CFRelease (descs); |
} |
*outData = dict.GetDict(); |
return noErr; |
badadd: |
dict.ShouldRelease(true); |
return paramErr; |
} |
OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData) |
{ |
if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr; |
CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false); |
RefCountedLayout *temp = NULL; |
AudioChannelLayout* layout; |
CFArrayRef descs = NULL; |
UInt32 numDescs = 0; |
if (dict.GetArray (kACLDescsKey, descs)) { |
numDescs = static_cast<OSStatus>(CFArrayGetCount (descs)); |
} |
temp = RefCountedLayout::CreateWithNumberChannelDescriptions(numDescs); |
layout = temp->GetLayout(); |
if (!dict.GetUInt32 (kACLTagKey, layout->mChannelLayoutTag)) |
goto badget; |
if (dict.HasKey (kACLBitmapKey)) { |
if (!dict.GetUInt32 (kACLBitmapKey, layout->mChannelBitmap)) |
goto badget; |
} else |
layout->mChannelBitmap = 0; |
layout->mNumberChannelDescriptions = numDescs; |
if (numDescs) |
{ |
AudioChannelDescription *desc = layout->mChannelDescriptions; |
for (unsigned int i = 0; i < numDescs; ++i, ++desc) |
{ |
CFDictionaryRef descDict = (CFDictionaryRef)CFArrayGetValueAtIndex (descs, i); |
CACFDictionary theDesc (descDict, false); |
if (!theDesc.GetUInt32 (kACLLabelKey, desc->mChannelLabel)) |
goto badget; |
if (!theDesc.GetUInt32 (kACLFlagsKey, desc->mChannelFlags)) |
goto badget; |
if (!theDesc.GetFloat32 (kACLCoords0Key, desc->mCoordinates[0])) |
goto badget; |
if (!theDesc.GetFloat32 (kACLCoords1Key, desc->mCoordinates[1])) |
goto badget; |
if (!theDesc.GetFloat32 (kACLCoords2Key, desc->mCoordinates[2])) |
goto badget; |
} |
} |
if (mLayout) |
mLayout->release(); |
mLayout = temp; |
return noErr; |
badget: |
delete temp; |
return paramErr; |
} |
#pragma mark __AudioUnitParameter |
static const CFStringRef kAUScopeStr = CFSTR("scope"); |
static const CFStringRef kAUElementIDStr = CFSTR("element ID"); |
static const CFStringRef kAUParameterIDStr = CFSTR("paramID"); |
void CAAUParameter::Save (CFPropertyListRef &outData) const |
{ |
return CAAUParameter::Save (*this, outData); |
} |
// static functions to save/restore AudioUnitParameter |
void CAAUParameter::Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData) |
{ |
CACFDictionary dict(false); |
dict.AddUInt32 (kAUScopeStr, inParam.mScope); |
dict.AddUInt32 (kAUElementIDStr, inParam.mElement); |
dict.AddUInt32 (kAUParameterIDStr, inParam.mParameterID); |
outData = dict.AsPropertyList(); |
} |
OSStatus CAAUParameter::Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam) |
{ |
if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr; |
CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false); |
if (!dict.GetUInt32 (kAUScopeStr, outParam.mScope)) return paramErr; |
if (!dict.GetUInt32 (kAUElementIDStr, outParam.mElement)) return paramErr; |
if (!dict.GetUInt32 (kAUParameterIDStr, outParam.mParameterID)) return paramErr; |
return noErr; |
} |
#pragma mark __MIDIMap |
const CFStringRef kParamMIDIStr = CFSTR("param maps"); |
const CFStringRef kMIDIFlagsStr = CFSTR("flags"); |
const CFStringRef kMIDISubMinStr = CFSTR("sub min"); |
const CFStringRef kMIDISubMaxStr = CFSTR("sub max"); |
const CFStringRef kMIDIStatusStr = CFSTR("midi status byte"); |
const CFStringRef kMIDIDataByteStr = CFSTR("midi data1 byte"); |
const CFStringRef kAUStr = CFSTR("unit"); |
static const CFStringRef kLocalElementIDStr = CFSTR("element ID"); |
static const CFStringRef kLocalScopeStr = CFSTR("scope"); |
static const CFStringRef kLocalParameterIDStr = CFSTR("paramID"); |
void CAAUMIDIMap::Save(CFPropertyListRef &outData) const |
{ |
CACFDictionary paramDict(false); |
paramDict.AddUInt32 (kLocalScopeStr, mScope); |
paramDict.AddUInt32 (kLocalElementIDStr, mElement); |
paramDict.AddUInt32 (kLocalParameterIDStr, mParameterID); |
paramDict.AddUInt32 (kMIDIFlagsStr, mFlags); |
paramDict.AddFloat32 (kMIDISubMinStr, mSubRangeMin); |
paramDict.AddFloat32 (kMIDISubMaxStr, mSubRangeMax); |
UInt32 data = mStatus; |
paramDict.AddUInt32 (kMIDIStatusStr, data); |
data = mData1; |
paramDict.AddUInt32 (kMIDIDataByteStr, data); |
outData = paramDict.GetCFDictionary(); |
} |
void CAAUMIDIMap::Restore(CFDictionaryRef inData) |
{ |
CACFDictionary paramDict (inData, false); |
if (!paramDict.GetUInt32 (kLocalScopeStr, mScope)) return; |
if (!paramDict.GetUInt32 (kLocalElementIDStr, mElement)) return; |
if (!paramDict.GetUInt32 (kLocalParameterIDStr, mParameterID)) return; |
if (!paramDict.GetUInt32 (kMIDIFlagsStr, mFlags)) return; |
if (!paramDict.GetFloat32 (kMIDISubMinStr, mSubRangeMin)) return; |
if (!paramDict.GetFloat32 (kMIDISubMaxStr, mSubRangeMax)) return; |
UInt32 data; |
if (!paramDict.GetUInt32 (kMIDIStatusStr, data)) return; |
mStatus = data; |
if (!paramDict.GetUInt32 (kMIDIDataByteStr, data)) return; |
mData1 = data; |
} |
void CAAUMIDIMap::SaveAsMapPList (AudioUnit inUnit, const AUParameterMIDIMapping* inMappings, UInt32 inNumMappings, CFPropertyListRef &outData, CFStringRef inName) |
{ |
CACFDictionary mappingDict (false); |
CACFArray maps (true); |
for (UInt32 i = 0; i< inNumMappings; ++i) |
{ |
CFPropertyListRef data; |
CAAUMIDIMap paramMap(inMappings[i]); |
paramMap.Save (data); |
if (data) |
{ |
maps.AppendCFType (data); |
CFRelease(data); |
} |
} |
if (maps.GetNumberItems()) { |
mappingDict.AddCFType (kParamMIDIStr, maps.GetCFArray()); |
// Add the AU info here - where this map came from |
CAAudioUnit au (inUnit); |
CFPropertyListRef data; |
au.Comp().Save (&data); |
mappingDict.AddCFType (kAUStr, data); |
CFRelease(data); |
if (!inName) inName = CFSTR("Untitled"); |
mappingDict.AddString (CFSTR("name"), inName); |
mappingDict.AddUInt32 (CFSTR("version"), 1); |
outData = mappingDict.AsPropertyList(); |
} else { |
mappingDict.ShouldRelease(true); |
outData = NULL; |
} |
} |
UInt32 CAAUMIDIMap::NumberOfMaps (const CFDictionaryRef inData) |
{ |
CACFDictionary dict (inData, false); |
if (dict.HasKey (kParamMIDIStr)) |
{ |
CFArrayRef cfArray; |
dict.GetArray (kParamMIDIStr, cfArray); |
CACFArray array (cfArray, false); |
return array.GetNumberItems(); |
} |
return 0; |
} |
void CAAUMIDIMap::RestoreFromMapPList (const CFDictionaryRef inData, AUParameterMIDIMapping* outMappings, UInt32 inNumMappings) |
{ |
CACFDictionary dict (inData, false); |
if (dict.HasKey (kParamMIDIStr)) |
{ |
CFArrayRef cfArray; |
dict.GetArray (kParamMIDIStr, cfArray); |
CACFArray array (cfArray, false); |
UInt32 count = array.GetNumberItems(); |
if (count > inNumMappings) |
count = inNumMappings; |
for (unsigned int i = 0; i < count; ++i) |
{ |
CFDictionaryRef paramsDictRef; |
if (!array.GetDictionary(i, paramsDictRef)) |
return; |
CAAUMIDIMap parameterMap; |
parameterMap.Restore(paramsDictRef); |
outMappings[i] = parameterMap; |
} |
} |
} |
Copyright © 2014 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2014-07-08