diff options
Diffstat (limited to 'distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp')
-rwxr-xr-x | distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp | 462 |
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; + } + } +} + + |