summaryrefslogtreecommitdiff
path: root/distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp')
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp462
1 files changed, 462 insertions, 0 deletions
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp b/distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp
new file mode 100755
index 00000000..dab99cb9
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp
@@ -0,0 +1,462 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ 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.
+*/
+#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 = 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;
+ }
+ }
+}
+
+