Jamoma API  0.6.0.a19
CAPersistence.cpp
1 /* Copyright 2007 Apple Inc. All Rights Reserved.
2 
3  Disclaimer: IMPORTANT: This Apple software is supplied to you by
4  Apple Inc. ("Apple") in consideration of your agreement to the
5  following terms, and your use, installation, modification or
6  redistribution of this Apple software constitutes acceptance of these
7  terms. If you do not agree with these terms, please do not use,
8  install, modify or redistribute this Apple software.
9 
10  In consideration of your agreement to abide by the following terms, and
11  subject to these terms, Apple grants you a personal, non-exclusive
12  license, under Apple's copyrights in this original Apple software (the
13  "Apple Software"), to use, reproduce, modify and redistribute the Apple
14  Software, with or without modifications, in source and/or binary forms;
15  provided that if you redistribute the Apple Software in its entirety and
16  without modifications, you must retain this notice and the following
17  text and disclaimers in all such redistributions of the Apple Software.
18  Neither the name, trademarks, service marks or logos of Apple Inc.
19  may be used to endorse or promote products derived from the Apple
20  Software without specific prior written permission from Apple. Except
21  as expressly stated in this notice, no other rights or licenses, express
22  or implied, are granted by Apple herein, including but not limited to
23  any patent rights that may be infringed by your derivative works or by
24  other works in which the Apple Software may be incorporated.
25 
26  The Apple Software is provided by Apple on an "AS IS" basis. APPLE
27  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
28  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
29  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
30  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
31 
32  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
33  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
36  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
37  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
38  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
39  POSSIBILITY OF SUCH DAMAGE.
40 */
41 #include "CACFArray.h"
42 #include "CACFDictionary.h"
43 
44 #include "CAAudioUnit.h"
45 #include "CACFString.h"
46 #include "CAAudioChannelLayout.h"
47 #include "CAAUParameter.h"
48 #include "CAAUMIDIMap.h"
49 
50 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
51 
52 #pragma mark __CAStreamBasicDescription
53 
54 static const CFStringRef kSampleRate = CFSTR("sample rate");
55 static const CFStringRef kFormat = CFSTR("format");
56 static const CFStringRef kFormatFlags = CFSTR("format flags");
57 static const CFStringRef kPacketBytes = CFSTR("packet bytes");
58 static const CFStringRef kFramePackets = CFSTR("frame packets");
59 static const CFStringRef kFrameBytes = CFSTR("frame bytes");
60 static const CFStringRef kFrameChannels = CFSTR("frame channels");
61 static const CFStringRef kChannelBits = CFSTR("channel bits");
62 
63  // This will return a value that should be used as the key for this struct
64  // and a CFData object that contains the current state of this object
65 OSStatus CAStreamBasicDescription::Save (CFPropertyListRef *outData) const
66 {
67  CACFDictionary dict(false);
68 
69  if (!dict.AddFloat64 (kSampleRate, mSampleRate)) goto error;
70  if (!dict.AddUInt32 (kFormat, mFormatID)) goto error;
71  if (!dict.AddUInt32 (kFormatFlags, mFormatFlags)) goto error;
72  if (!dict.AddUInt32 (kPacketBytes, mBytesPerPacket)) goto error;
73  if (!dict.AddUInt32 (kFramePackets, mFramesPerPacket)) goto error;
74  if (!dict.AddUInt32 (kFrameBytes, mBytesPerFrame)) goto error;
75  if (!dict.AddUInt32 (kFrameChannels, mChannelsPerFrame)) goto error;
76  if (!dict.AddUInt32 (kChannelBits, mBitsPerChannel)) goto error;
77 
78  *outData = dict.GetDict();
79 
80  return noErr;
81 
82 error:
83  dict.ShouldRelease (true);
84  return paramErr;
85 }
86 
87 
88  // Given a CFData object generated by the save command, this will re-establish
89  // the CAStreamBasicDescription
90 OSStatus CAStreamBasicDescription::Restore (CFPropertyListRef& inData)
91 {
92  if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
93  CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
94 
95  if (!dict.GetFloat64 (kSampleRate, mSampleRate)) return paramErr;
96  if (!dict.GetUInt32 (kFormat, mFormatID)) return paramErr;
97  if (!dict.GetUInt32 (kFormatFlags, mFormatFlags)) return paramErr;
98  if (!dict.GetUInt32 (kPacketBytes, mBytesPerPacket)) return paramErr;
99  if (!dict.GetUInt32 (kFramePackets, mFramesPerPacket)) return paramErr;
100  if (!dict.GetUInt32 (kFrameBytes, mBytesPerFrame)) return paramErr;
101  if (!dict.GetUInt32 (kFrameChannels, mChannelsPerFrame)) return paramErr;
102  if (!dict.GetUInt32 (kChannelBits, mBitsPerChannel)) return paramErr;
103 
104  return noErr;
105 }
106 
107 #pragma mark __CAComponentDescription
108 
109 static const CFStringRef kType = CFSTR("type");
110 static const CFStringRef kSubType = CFSTR("subtype");
111 static const CFStringRef kManu = CFSTR("manufacturer");
112 
113 OSStatus CAComponentDescription::Save (CFPropertyListRef *outData) const
114 {
115  CACFDictionary dict(false);
116  if (!dict.AddUInt32 (kType, componentType)) goto error;
117  if (!dict.AddUInt32 (kSubType, componentSubType)) goto error;
118  if (!dict.AddUInt32 (kManu, componentManufacturer)) goto error;
119 
120  *outData = dict.GetDict();
121 
122  return 0;
123 error:
124  dict.ShouldRelease (true);
125  return paramErr;
126 }
127 
128 OSStatus CAComponentDescription::Restore (CFPropertyListRef &inData)
129 {
130  if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
131  CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
132 
133  if (!dict.GetUInt32 (kType, componentType)) return paramErr;
134  if (!dict.GetUInt32 (kSubType, componentSubType)) return paramErr;
135  if (!dict.GetUInt32 (kManu, componentManufacturer)) return paramErr;
136 
137  componentFlags = 0;
138  componentFlagsMask = 0;
139 
140  return 0;
141 }
142 
143 #pragma mark __CAComponent
144 
145 OSStatus CAComponent::Save (CFPropertyListRef *outData) const
146 {
147  OSStatus result = mDesc.Save (outData);
148  if (result) return result;
149 
150  //add the name string of the component for a human readable name...
151  // this name string is *not* restored when restoring the component
152  CFStringRef name = GetCompName ();
153  if (name && *outData)
154  CFDictionarySetValue ((CFMutableDictionaryRef)(*outData), CFSTR("name"), name);
155 
156  return noErr;
157 }
158 
159 OSStatus CAComponent::Restore (CFPropertyListRef &inData)
160 {
161  if (mDesc.Restore (inData)) return paramErr;
162 
163  Clear();
164 
165  mComp = AudioComponentFindNext (NULL, &mDesc);
166  // this will restore the current flags...
167  if (mComp)
168  AudioComponentGetDescription (Comp(), &mDesc);
169 
170  return noErr;
171 }
172 
173 
174 #pragma mark __CAAudioChannelLayout
175 
176 static const CFStringRef kACLTagKey = CFSTR("acl tag");
177 static const CFStringRef kACLBitmapKey = CFSTR("chan bitmap");
178 static const CFStringRef kACLLabelKey = CFSTR("label");
179 static const CFStringRef kACLFlagsKey = CFSTR("flags");
180 static const CFStringRef kACLCoords0Key = CFSTR("coords 0");
181 static const CFStringRef kACLCoords1Key = CFSTR("coords 1");
182 static const CFStringRef kACLCoords2Key = CFSTR("coords 2");
183 static const CFStringRef kACLDescsKey = CFSTR("descriptions");
184 
185 OSStatus CAAudioChannelLayout::Save (CFPropertyListRef *outData) const
186 {
187  const AudioChannelLayout& layout = Layout();
188 
189  CACFDictionary dict (false);
190  if (!dict.AddUInt32 (kACLTagKey, layout.mChannelLayoutTag))
191  goto badadd;
192  if (layout.mChannelBitmap && !dict.AddUInt32 (kACLBitmapKey, layout.mChannelBitmap))
193  goto badadd;
194 
195  if (layout.mNumberChannelDescriptions)
196  {
197  CFMutableArrayRef descs = CFArrayCreateMutable (NULL, layout.mNumberChannelDescriptions, &kCFTypeArrayCallBacks);
198 
199  const AudioChannelDescription *desc = layout.mChannelDescriptions;
200  for (unsigned int i = 0; i < layout.mNumberChannelDescriptions; ++i, ++desc)
201  {
202  CACFDictionary descDict (true);
203  if (!descDict.AddUInt32 (kACLLabelKey, desc->mChannelLabel))
204  { CFRelease (descs); goto badadd; }
205  if (!descDict.AddUInt32 (kACLFlagsKey, desc->mChannelFlags))
206  { CFRelease (descs); goto badadd; }
207  if (!descDict.AddFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
208  { CFRelease (descs); goto badadd; }
209  if (!descDict.AddFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
210  { CFRelease (descs); goto badadd; }
211  if (!descDict.AddFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
212  { CFRelease (descs); goto badadd; }
213 
214  CFArrayAppendValue (descs, descDict.AsPropertyList());
215  }
216  dict.AddArray (kACLDescsKey, descs);
217 
218  CFRelease (descs);
219  }
220 
221  *outData = dict.GetDict();
222 
223  return noErr;
224 
225 badadd:
226  dict.ShouldRelease(true);
227  return paramErr;
228 }
229 
230 OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData)
231 {
232  if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
233  CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
234 
235  RefCountedLayout *temp = NULL;
236  AudioChannelLayout* layout;
237 
238  CFArrayRef descs = NULL;
239  UInt32 numDescs = 0;
240 
241  if (dict.GetArray (kACLDescsKey, descs)) {
242  numDescs = CFArrayGetCount (descs);
243  }
244 
245  temp = RefCountedLayout::CreateWithNumberChannelDescriptions(numDescs);
246  layout = temp->GetLayout();
247 
248  if (!dict.GetUInt32 (kACLTagKey, layout->mChannelLayoutTag))
249  goto badget;
250  if (dict.HasKey (kACLBitmapKey)) {
251  if (!dict.GetUInt32 (kACLBitmapKey, layout->mChannelBitmap))
252  goto badget;
253  } else
254  layout->mChannelBitmap = 0;
255 
256  layout->mNumberChannelDescriptions = numDescs;
257 
258  if (numDescs)
259  {
260  AudioChannelDescription *desc = layout->mChannelDescriptions;
261  for (unsigned int i = 0; i < numDescs; ++i, ++desc)
262  {
263  CFDictionaryRef descDict = (CFDictionaryRef)CFArrayGetValueAtIndex (descs, i);
264  CACFDictionary theDesc (descDict, false);
265 
266  if (!theDesc.GetUInt32 (kACLLabelKey, desc->mChannelLabel))
267  goto badget;
268  if (!theDesc.GetUInt32 (kACLFlagsKey, desc->mChannelFlags))
269  goto badget;
270  if (!theDesc.GetFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
271  goto badget;
272  if (!theDesc.GetFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
273  goto badget;
274  if (!theDesc.GetFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
275  goto badget;
276  }
277  }
278  if (mLayout)
279  mLayout->release();
280 
281  mLayout = temp;
282 
283  return noErr;
284 
285 badget:
286  delete temp;
287  return paramErr;
288 }
289 
290 #pragma mark __AudioUnitParameter
291 
292 static const CFStringRef kAUScopeStr = CFSTR("scope");
293 static const CFStringRef kAUElementIDStr = CFSTR("element ID");
294 static const CFStringRef kAUParameterIDStr = CFSTR("paramID");
295 
296 void CAAUParameter::Save (CFPropertyListRef &outData) const
297 {
298  return CAAUParameter::Save (*this, outData);
299 }
300 
301 // static functions to save/restore AudioUnitParameter
302 void CAAUParameter::Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData)
303 {
304  CACFDictionary dict(false);
305  dict.AddUInt32 (kAUScopeStr, inParam.mScope);
306  dict.AddUInt32 (kAUElementIDStr, inParam.mElement);
307  dict.AddUInt32 (kAUParameterIDStr, inParam.mParameterID);
308 
309  outData = dict.AsPropertyList();
310 }
311 
312 OSStatus CAAUParameter::Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam)
313 {
314  if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
315  CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
316 
317  if (!dict.GetUInt32 (kAUScopeStr, outParam.mScope)) return paramErr;
318  if (!dict.GetUInt32 (kAUElementIDStr, outParam.mElement)) return paramErr;
319  if (!dict.GetUInt32 (kAUParameterIDStr, outParam.mParameterID)) return paramErr;
320  return noErr;
321 }
322 
323 
324 #pragma mark __MIDIMap
325 
326 const CFStringRef kParamMIDIStr = CFSTR("param maps");
327 
328 const CFStringRef kMIDIFlagsStr = CFSTR("flags");
329 const CFStringRef kMIDISubMinStr = CFSTR("sub min");
330 const CFStringRef kMIDISubMaxStr = CFSTR("sub max");
331 const CFStringRef kMIDIStatusStr = CFSTR("midi status byte");
332 const CFStringRef kMIDIDataByteStr = CFSTR("midi data1 byte");
333 const CFStringRef kAUStr = CFSTR("unit");
334 
335 static const CFStringRef kLocalElementIDStr = CFSTR("element ID");
336 static const CFStringRef kLocalScopeStr = CFSTR("scope");
337 static const CFStringRef kLocalParameterIDStr = CFSTR("paramID");
338 
339 void CAAUMIDIMap::Save(CFPropertyListRef &outData) const
340 {
341  CACFDictionary paramDict(false);
342 
343  paramDict.AddUInt32 (kLocalScopeStr, mScope);
344  paramDict.AddUInt32 (kLocalElementIDStr, mElement);
345  paramDict.AddUInt32 (kLocalParameterIDStr, mParameterID);
346  paramDict.AddUInt32 (kMIDIFlagsStr, mFlags);
347  paramDict.AddFloat32 (kMIDISubMinStr, mSubRangeMin);
348  paramDict.AddFloat32 (kMIDISubMaxStr, mSubRangeMax);
349 
350  UInt32 data = mStatus;
351  paramDict.AddUInt32 (kMIDIStatusStr, data);
352 
353  data = mData1;
354  paramDict.AddUInt32 (kMIDIDataByteStr, data);
355 
356  outData = paramDict.GetCFDictionary();
357 }
358 
359 void CAAUMIDIMap::Restore(CFDictionaryRef inData)
360 {
361  CACFDictionary paramDict (inData, false);
362 
363  if (!paramDict.GetUInt32 (kLocalScopeStr, mScope)) return;
364  if (!paramDict.GetUInt32 (kLocalElementIDStr, mElement)) return;
365  if (!paramDict.GetUInt32 (kLocalParameterIDStr, mParameterID)) return;
366  if (!paramDict.GetUInt32 (kMIDIFlagsStr, mFlags)) return;
367  if (!paramDict.GetFloat32 (kMIDISubMinStr, mSubRangeMin)) return;
368  if (!paramDict.GetFloat32 (kMIDISubMaxStr, mSubRangeMax)) return;
369  UInt32 data;
370  if (!paramDict.GetUInt32 (kMIDIStatusStr, data)) return;
371  mStatus = data;
372  if (!paramDict.GetUInt32 (kMIDIDataByteStr, data)) return;
373  mData1 = data;
374 }
375 
376 void CAAUMIDIMap::SaveAsMapPList (AudioUnit inUnit, const AUParameterMIDIMapping* inMappings, UInt32 inNumMappings, CFPropertyListRef &outData, CFStringRef inName)
377 {
378 
379  CACFDictionary mappingDict (false);
380  CACFArray maps (true);
381 
382  for (UInt32 i = 0; i< inNumMappings; ++i)
383  {
384  CFPropertyListRef data;
385  CAAUMIDIMap paramMap(inMappings[i]);
386  paramMap.Save (data);
387  if (data)
388  {
389  maps.AppendCFType (data);
390  CFRelease(data);
391  }
392  }
393 
394  if (maps.GetNumberItems()) {
395  mappingDict.AddCFType (kParamMIDIStr, maps.GetCFArray());
396 
397  // Add the AU info here - where this map came from
398  CAAudioUnit au (inUnit);
399  CFPropertyListRef data;
400  au.Comp().Save (&data);
401 
402  mappingDict.AddCFType (kAUStr, data);
403  CFRelease(data);
404 
405  if (!inName) inName = CFSTR("Untitled");
406  mappingDict.AddString (CFSTR("name"), inName);
407 
408  mappingDict.AddUInt32 (CFSTR("version"), 1);
409 
410  outData = mappingDict.AsPropertyList();
411  } else {
412  mappingDict.ShouldRelease(true);
413  outData = NULL;
414  }
415 }
416 
417 UInt32 CAAUMIDIMap::NumberOfMaps (const CFDictionaryRef inData)
418 {
419  CACFDictionary dict (inData, false);
420 
421  if (dict.HasKey (kParamMIDIStr))
422  {
423  CFArrayRef cfArray;
424  dict.GetArray (kParamMIDIStr, cfArray);
425 
426  CACFArray array (cfArray, false);
427 
428  return array.GetNumberItems();
429  }
430  return 0;
431 }
432 
433 void CAAUMIDIMap::RestoreFromMapPList (const CFDictionaryRef inData, AUParameterMIDIMapping* outMappings, UInt32 inNumMappings)
434 {
435 
436  CACFDictionary dict (inData, false);
437 
438  if (dict.HasKey (kParamMIDIStr))
439  {
440  CFArrayRef cfArray;
441  dict.GetArray (kParamMIDIStr, cfArray);
442 
443  CACFArray array (cfArray, false);
444 
445  UInt32 count = array.GetNumberItems();
446  if (count > inNumMappings)
447  count = inNumMappings;
448 
449  for (unsigned int i = 0; i < count; ++i)
450  {
451  CFDictionaryRef paramsDictRef;
452  if (!array.GetDictionary(i, paramsDictRef))
453  return;
454 
455  CAAUMIDIMap parameterMap;
456  parameterMap.Restore(paramsDictRef);
457  outMappings[i] = parameterMap;
458  }
459  }
460 }
461 
462