2 File: CAPersistence.cpp
3 Abstract: CAPersistence.h
6 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 Inc. ("Apple") in consideration of your agreement to the following
8 terms, and your use, installation, modification or redistribution of
9 this Apple software constitutes acceptance of these terms. If you do
10 not agree with these terms, please do not use, install, modify or
11 redistribute this Apple software.
13 In consideration of your agreement to abide by the following terms, and
14 subject to these terms, Apple grants you a personal, non-exclusive
15 license, under Apple's copyrights in this original Apple software (the
16 "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 Software, with or without modifications, in source and/or binary forms;
18 provided that if you redistribute the Apple Software in its entirety and
19 without modifications, you must retain this notice and the following
20 text and disclaimers in all such redistributions of the Apple Software.
21 Neither the name, trademarks, service marks or logos of Apple Inc. may
22 be used to endorse or promote products derived from the Apple Software
23 without specific prior written permission from Apple. Except as
24 expressly stated in this notice, no other rights or licenses, express or
25 implied, are granted by Apple herein, including but not limited to any
26 patent rights that may be infringed by your derivative works or by other
27 works in which the Apple Software may be incorporated.
29 The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
35 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 POSSIBILITY OF SUCH DAMAGE.
44 Copyright (C) 2014 Apple Inc. All Rights Reserved.
47 #include "CACFArray.h"
48 #include "CACFDictionary.h"
50 #include "CAAudioUnit.h"
51 #include "CACFString.h"
52 #include "CAAudioChannelLayout.h"
53 #include "CAAUParameter.h"
54 #include "CAAUMIDIMap.h"
56 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
58 #pragma mark __CAStreamBasicDescription
60 static const CFStringRef kSampleRate = CFSTR("sample rate");
61 static const CFStringRef kFormat = CFSTR("format");
62 static const CFStringRef kFormatFlags = CFSTR("format flags");
63 static const CFStringRef kPacketBytes = CFSTR("packet bytes");
64 static const CFStringRef kFramePackets = CFSTR("frame packets");
65 static const CFStringRef kFrameBytes = CFSTR("frame bytes");
66 static const CFStringRef kFrameChannels = CFSTR("frame channels");
67 static const CFStringRef kChannelBits = CFSTR("channel bits");
69 // This will return a value that should be used as the key for this struct
70 // and a CFData object that contains the current state of this object
71 OSStatus CAStreamBasicDescription::Save (CFPropertyListRef *outData) const
73 CACFDictionary dict(false);
75 if (!dict.AddFloat64 (kSampleRate, mSampleRate)) goto error;
76 if (!dict.AddUInt32 (kFormat, mFormatID)) goto error;
77 if (!dict.AddUInt32 (kFormatFlags, mFormatFlags)) goto error;
78 if (!dict.AddUInt32 (kPacketBytes, mBytesPerPacket)) goto error;
79 if (!dict.AddUInt32 (kFramePackets, mFramesPerPacket)) goto error;
80 if (!dict.AddUInt32 (kFrameBytes, mBytesPerFrame)) goto error;
81 if (!dict.AddUInt32 (kFrameChannels, mChannelsPerFrame)) goto error;
82 if (!dict.AddUInt32 (kChannelBits, mBitsPerChannel)) goto error;
84 *outData = dict.GetDict();
89 dict.ShouldRelease (true);
94 // Given a CFData object generated by the save command, this will re-establish
95 // the CAStreamBasicDescription
96 OSStatus CAStreamBasicDescription::Restore (CFPropertyListRef& inData)
98 if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
99 CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
101 if (!dict.GetFloat64 (kSampleRate, mSampleRate)) return paramErr;
102 if (!dict.GetUInt32 (kFormat, mFormatID)) return paramErr;
103 if (!dict.GetUInt32 (kFormatFlags, mFormatFlags)) return paramErr;
104 if (!dict.GetUInt32 (kPacketBytes, mBytesPerPacket)) return paramErr;
105 if (!dict.GetUInt32 (kFramePackets, mFramesPerPacket)) return paramErr;
106 if (!dict.GetUInt32 (kFrameBytes, mBytesPerFrame)) return paramErr;
107 if (!dict.GetUInt32 (kFrameChannels, mChannelsPerFrame)) return paramErr;
108 if (!dict.GetUInt32 (kChannelBits, mBitsPerChannel)) return paramErr;
113 #pragma mark __CAComponentDescription
115 static const CFStringRef kType = CFSTR("type");
116 static const CFStringRef kSubType = CFSTR("subtype");
117 static const CFStringRef kManu = CFSTR("manufacturer");
119 OSStatus CAComponentDescription::Save (CFPropertyListRef *outData) const
121 CACFDictionary dict(false);
122 if (!dict.AddUInt32 (kType, componentType)) goto error;
123 if (!dict.AddUInt32 (kSubType, componentSubType)) goto error;
124 if (!dict.AddUInt32 (kManu, componentManufacturer)) goto error;
126 *outData = dict.GetDict();
130 dict.ShouldRelease (true);
134 OSStatus CAComponentDescription::Restore (CFPropertyListRef &inData)
136 if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
137 CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
139 if (!dict.GetUInt32 (kType, componentType)) return paramErr;
140 if (!dict.GetUInt32 (kSubType, componentSubType)) return paramErr;
141 if (!dict.GetUInt32 (kManu, componentManufacturer)) return paramErr;
144 componentFlagsMask = 0;
149 #pragma mark __CAComponent
151 OSStatus CAComponent::Save (CFPropertyListRef *outData) const
153 OSStatus result = mDesc.Save (outData);
154 if (result) return result;
156 //add the name string of the component for a human readable name...
157 // this name string is *not* restored when restoring the component
158 CFStringRef name = GetCompName ();
159 if (name && *outData)
160 CFDictionarySetValue ((CFMutableDictionaryRef)(*outData), CFSTR("name"), name);
165 OSStatus CAComponent::Restore (CFPropertyListRef &inData)
167 if (mDesc.Restore (inData)) return paramErr;
171 mComp = AudioComponentFindNext (NULL, &mDesc);
172 // this will restore the current flags...
174 AudioComponentGetDescription (Comp(), &mDesc);
180 #pragma mark __CAAudioChannelLayout
182 static const CFStringRef kACLTagKey = CFSTR("acl tag");
183 static const CFStringRef kACLBitmapKey = CFSTR("chan bitmap");
184 static const CFStringRef kACLLabelKey = CFSTR("label");
185 static const CFStringRef kACLFlagsKey = CFSTR("flags");
186 static const CFStringRef kACLCoords0Key = CFSTR("coords 0");
187 static const CFStringRef kACLCoords1Key = CFSTR("coords 1");
188 static const CFStringRef kACLCoords2Key = CFSTR("coords 2");
189 static const CFStringRef kACLDescsKey = CFSTR("descriptions");
191 OSStatus CAAudioChannelLayout::Save (CFPropertyListRef *outData) const
193 const AudioChannelLayout& layout = Layout();
195 CACFDictionary dict (false);
196 if (!dict.AddUInt32 (kACLTagKey, layout.mChannelLayoutTag))
198 if (layout.mChannelBitmap && !dict.AddUInt32 (kACLBitmapKey, layout.mChannelBitmap))
201 if (layout.mNumberChannelDescriptions)
203 CFMutableArrayRef descs = CFArrayCreateMutable (NULL, layout.mNumberChannelDescriptions, &kCFTypeArrayCallBacks);
205 const AudioChannelDescription *desc = layout.mChannelDescriptions;
206 for (unsigned int i = 0; i < layout.mNumberChannelDescriptions; ++i, ++desc)
208 CACFDictionary descDict (true);
209 if (!descDict.AddUInt32 (kACLLabelKey, desc->mChannelLabel))
210 { CFRelease (descs); goto badadd; }
211 if (!descDict.AddUInt32 (kACLFlagsKey, desc->mChannelFlags))
212 { CFRelease (descs); goto badadd; }
213 if (!descDict.AddFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
214 { CFRelease (descs); goto badadd; }
215 if (!descDict.AddFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
216 { CFRelease (descs); goto badadd; }
217 if (!descDict.AddFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
218 { CFRelease (descs); goto badadd; }
220 CFArrayAppendValue (descs, descDict.AsPropertyList());
222 dict.AddArray (kACLDescsKey, descs);
227 *outData = dict.GetDict();
232 dict.ShouldRelease(true);
236 OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData)
238 if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
239 CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
241 RefCountedLayout *temp = NULL;
242 AudioChannelLayout* layout;
244 CFArrayRef descs = NULL;
247 if (dict.GetArray (kACLDescsKey, descs)) {
248 numDescs = static_cast<OSStatus>(CFArrayGetCount (descs));
251 temp = RefCountedLayout::CreateWithNumberChannelDescriptions(numDescs);
252 layout = temp->GetLayout();
254 if (!dict.GetUInt32 (kACLTagKey, layout->mChannelLayoutTag))
256 if (dict.HasKey (kACLBitmapKey)) {
257 if (!dict.GetUInt32 (kACLBitmapKey, layout->mChannelBitmap))
260 layout->mChannelBitmap = 0;
262 layout->mNumberChannelDescriptions = numDescs;
266 AudioChannelDescription *desc = layout->mChannelDescriptions;
267 for (unsigned int i = 0; i < numDescs; ++i, ++desc)
269 CFDictionaryRef descDict = (CFDictionaryRef)CFArrayGetValueAtIndex (descs, i);
270 CACFDictionary theDesc (descDict, false);
272 if (!theDesc.GetUInt32 (kACLLabelKey, desc->mChannelLabel))
274 if (!theDesc.GetUInt32 (kACLFlagsKey, desc->mChannelFlags))
276 if (!theDesc.GetFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
278 if (!theDesc.GetFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
280 if (!theDesc.GetFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
296 #pragma mark __AudioUnitParameter
298 static const CFStringRef kAUScopeStr = CFSTR("scope");
299 static const CFStringRef kAUElementIDStr = CFSTR("element ID");
300 static const CFStringRef kAUParameterIDStr = CFSTR("paramID");
302 void CAAUParameter::Save (CFPropertyListRef &outData) const
304 return CAAUParameter::Save (*this, outData);
307 // static functions to save/restore AudioUnitParameter
308 void CAAUParameter::Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData)
310 CACFDictionary dict(false);
311 dict.AddUInt32 (kAUScopeStr, inParam.mScope);
312 dict.AddUInt32 (kAUElementIDStr, inParam.mElement);
313 dict.AddUInt32 (kAUParameterIDStr, inParam.mParameterID);
315 outData = dict.AsPropertyList();
318 OSStatus CAAUParameter::Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam)
320 if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
321 CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
323 if (!dict.GetUInt32 (kAUScopeStr, outParam.mScope)) return paramErr;
324 if (!dict.GetUInt32 (kAUElementIDStr, outParam.mElement)) return paramErr;
325 if (!dict.GetUInt32 (kAUParameterIDStr, outParam.mParameterID)) return paramErr;
330 #pragma mark __MIDIMap
332 const CFStringRef kParamMIDIStr = CFSTR("param maps");
334 const CFStringRef kMIDIFlagsStr = CFSTR("flags");
335 const CFStringRef kMIDISubMinStr = CFSTR("sub min");
336 const CFStringRef kMIDISubMaxStr = CFSTR("sub max");
337 const CFStringRef kMIDIStatusStr = CFSTR("midi status byte");
338 const CFStringRef kMIDIDataByteStr = CFSTR("midi data1 byte");
339 const CFStringRef kAUStr = CFSTR("unit");
341 static const CFStringRef kLocalElementIDStr = CFSTR("element ID");
342 static const CFStringRef kLocalScopeStr = CFSTR("scope");
343 static const CFStringRef kLocalParameterIDStr = CFSTR("paramID");
345 void CAAUMIDIMap::Save(CFPropertyListRef &outData) const
347 CACFDictionary paramDict(false);
349 paramDict.AddUInt32 (kLocalScopeStr, mScope);
350 paramDict.AddUInt32 (kLocalElementIDStr, mElement);
351 paramDict.AddUInt32 (kLocalParameterIDStr, mParameterID);
352 paramDict.AddUInt32 (kMIDIFlagsStr, mFlags);
353 paramDict.AddFloat32 (kMIDISubMinStr, mSubRangeMin);
354 paramDict.AddFloat32 (kMIDISubMaxStr, mSubRangeMax);
356 UInt32 data = mStatus;
357 paramDict.AddUInt32 (kMIDIStatusStr, data);
360 paramDict.AddUInt32 (kMIDIDataByteStr, data);
362 outData = paramDict.GetCFDictionary();
365 void CAAUMIDIMap::Restore(CFDictionaryRef inData)
367 CACFDictionary paramDict (inData, false);
369 if (!paramDict.GetUInt32 (kLocalScopeStr, mScope)) return;
370 if (!paramDict.GetUInt32 (kLocalElementIDStr, mElement)) return;
371 if (!paramDict.GetUInt32 (kLocalParameterIDStr, mParameterID)) return;
372 if (!paramDict.GetUInt32 (kMIDIFlagsStr, mFlags)) return;
373 if (!paramDict.GetFloat32 (kMIDISubMinStr, mSubRangeMin)) return;
374 if (!paramDict.GetFloat32 (kMIDISubMaxStr, mSubRangeMax)) return;
376 if (!paramDict.GetUInt32 (kMIDIStatusStr, data)) return;
378 if (!paramDict.GetUInt32 (kMIDIDataByteStr, data)) return;
382 void CAAUMIDIMap::SaveAsMapPList (AudioUnit inUnit, const AUParameterMIDIMapping* inMappings, UInt32 inNumMappings, CFPropertyListRef &outData, CFStringRef inName)
385 CACFDictionary mappingDict (false);
386 CACFArray maps (true);
388 for (UInt32 i = 0; i< inNumMappings; ++i)
390 CFPropertyListRef data;
391 CAAUMIDIMap paramMap(inMappings[i]);
392 paramMap.Save (data);
395 maps.AppendCFType (data);
400 if (maps.GetNumberItems()) {
401 mappingDict.AddCFType (kParamMIDIStr, maps.GetCFArray());
403 // Add the AU info here - where this map came from
404 CAAudioUnit au (inUnit);
405 CFPropertyListRef data;
406 au.Comp().Save (&data);
408 mappingDict.AddCFType (kAUStr, data);
411 if (!inName) inName = CFSTR("Untitled");
412 mappingDict.AddString (CFSTR("name"), inName);
414 mappingDict.AddUInt32 (CFSTR("version"), 1);
416 outData = mappingDict.AsPropertyList();
418 mappingDict.ShouldRelease(true);
423 UInt32 CAAUMIDIMap::NumberOfMaps (const CFDictionaryRef inData)
425 CACFDictionary dict (inData, false);
427 if (dict.HasKey (kParamMIDIStr))
430 dict.GetArray (kParamMIDIStr, cfArray);
432 CACFArray array (cfArray, false);
434 return array.GetNumberItems();
439 void CAAUMIDIMap::RestoreFromMapPList (const CFDictionaryRef inData, AUParameterMIDIMapping* outMappings, UInt32 inNumMappings)
442 CACFDictionary dict (inData, false);
444 if (dict.HasKey (kParamMIDIStr))
447 dict.GetArray (kParamMIDIStr, cfArray);
449 CACFArray array (cfArray, false);
451 UInt32 count = array.GetNumberItems();
452 if (count > inNumMappings)
453 count = inNumMappings;
455 for (unsigned int i = 0; i < count; ++i)
457 CFDictionaryRef paramsDictRef;
458 if (!array.GetDictionary(i, paramsDictRef))
461 CAAUMIDIMap parameterMap;
462 parameterMap.Restore(paramsDictRef);
463 outMappings[i] = parameterMap;