diff options
Diffstat (limited to 'libs/appleutility/CoreAudio/PublicUtility')
117 files changed, 27296 insertions, 0 deletions
diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp new file mode 100644 index 0000000000..c2c8468bd9 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp @@ -0,0 +1,169 @@ +/* + File: AUOutputBL.cpp + Abstract: AUOutputBL.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 "AUOutputBL.h" +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <AudioUnit/AUComponent.h> +#else + #include <AUComponent.h> +#endif +/* +struct AudioBufferList +{ + UInt32 mNumberBuffers; + AudioBuffer mBuffers[1]; +}; +struct AudioBuffer +{ + UInt32 mNumberChannels; // number of interleaved channels in the buffer + UInt32 mDataByteSize; // the size of the buffer pointed to by mData + void* mData; // the pointer to the buffer +}; +*/ + +AUOutputBL::AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames) + : mFormat (inDesc), + mBufferMemory(NULL), + mBufferList (NULL), + mNumberBuffers (0), // keep this here, so can ensure integrity of ABL + mBufferSize (0), + mFrames(inDefaultNumFrames) +{ + mNumberBuffers = mFormat.IsInterleaved() ? 1 : mFormat.NumberChannels(); + mBufferList = reinterpret_cast<AudioBufferList*>(new Byte[offsetof(AudioBufferList, mBuffers) + (mNumberBuffers * sizeof(AudioBuffer))]); +} + +AUOutputBL::~AUOutputBL() +{ + if (mBufferMemory) + delete[] mBufferMemory; + + if (mBufferList) + delete [] (Byte *)mBufferList; +} + +void AUOutputBL::Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated) +{ + UInt32 channelsPerBuffer = mFormat.IsInterleaved() ? mFormat.NumberChannels() : 1; + + if (mBufferMemory == NULL || inWantNullBufferIfAllocated) + { + mBufferList->mNumberBuffers = mNumberBuffers; + AudioBuffer *buf = &mBufferList->mBuffers[0]; + for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) { + buf->mNumberChannels = channelsPerBuffer; + buf->mDataByteSize = mFormat.FramesToBytes (inNumFrames); + buf->mData = NULL; + } + } + else + { + UInt32 nBytes = mFormat.FramesToBytes (inNumFrames); + if ((nBytes * mNumberBuffers) > AllocatedBytes()) + throw OSStatus(kAudioUnitErr_TooManyFramesToProcess); + + mBufferList->mNumberBuffers = mNumberBuffers; + AudioBuffer *buf = &mBufferList->mBuffers[0]; + Byte* p = mBufferMemory; + for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) { + buf->mNumberChannels = channelsPerBuffer; + buf->mDataByteSize = nBytes; + buf->mData = p; + p += mBufferSize; + } + } +} + + +void AUOutputBL::Allocate (UInt32 inNumFrames) +{ + if (inNumFrames) + { + UInt32 nBytes = mFormat.FramesToBytes (inNumFrames); + + if (nBytes <= AllocatedBytes()) + return; + + // align successive buffers for Altivec and to take alternating + // cache line hits by spacing them by odd multiples of 16 + if (mNumberBuffers > 1) + nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10; + + mBufferSize = nBytes; + + UInt32 memorySize = mBufferSize * mNumberBuffers; + Byte *newMemory = new Byte[memorySize]; + memset(newMemory, 0, memorySize); // make buffer "hot" + + Byte *oldMemory = mBufferMemory; + mBufferMemory = newMemory; + delete[] oldMemory; + + mFrames = inNumFrames; + } + else + { + if (mBufferMemory) { + delete [] mBufferMemory; + mBufferMemory = NULL; + } + mBufferSize = 0; + mFrames = 0; + } +} + +#if DEBUG +void AUOutputBL::Print() +{ + printf ("AUOutputBL::Print\n"); + mFormat.Print(); + printf ("Num Buffers:%d, mFrames:%d, allocatedMemory:%c\n", (int)mBufferList->mNumberBuffers, (int)mFrames, (mBufferMemory != NULL ? 'T' : 'F')); + AudioBuffer *buf = &mBufferList->mBuffers[0]; + for (UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i, ++buf) + printf ("\tBuffer:%d, Size:%d, Chans:%d, Buffer:%p\n", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData); +} +#endif + diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h new file mode 100644 index 0000000000..0baad3a579 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h @@ -0,0 +1,118 @@ +/* + File: AUOutputBL.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __AUOutputBL_h__ +#define __AUOutputBL_h__ + +#include "CAStreamBasicDescription.h" +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) +#else +#endif + +// ____________________________________________________________________________ +// +// AUOutputBL - Simple Buffer List wrapper targetted to use with retrieving AU output +// Works in one of two ways (both adjustable)... Can use it with NULL pointers, or allocate +// memory to receive the data in. + +// Before using this with any call to AudioUnitRender, it needs to be Prepared +// as some calls to AudioUnitRender can reset the ABL + +class AUOutputBL { +public: + + // you CANNOT use one of these - it will crash! +// AUOutputBL (); + + // this is the constructor that you use + // it can't be reset once you've constructed it + AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames = 512); + ~AUOutputBL(); + + void Prepare () + { + Prepare (mFrames); + } + + // this version can throw if this is an allocted ABL and inNumFrames is > AllocatedFrames() + // you can set the bool to true if you want a NULL buffer list even if allocated + // inNumFrames must be a valid number (will throw if inNumFrames is 0) + void Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated = false); + + AudioBufferList* ABL() { return mBufferList; } + + // You only need to call this if you want to allocate a buffer list + // if you want an empty buffer list, just call Prepare() + // if you want to dispose previously allocted memory, pass in 0 + // then you either have an empty buffer list, or you can re-allocate + // Memory is kept around if an Allocation request is less than what is currently allocated + void Allocate (UInt32 inNumberFrames); + + UInt32 AllocatedFrames() const { return mFrames; } + + const CAStreamBasicDescription& GetFormat() const { return mFormat; } + +#if DEBUG + void Print(); +#endif + +private: + UInt32 AllocatedBytes () const { return (mBufferSize * mNumberBuffers); } + + CAStreamBasicDescription mFormat; + Byte* mBufferMemory; + AudioBufferList* mBufferList; + UInt32 mNumberBuffers; + UInt32 mBufferSize; + UInt32 mFrames; + +// don't want to copy these.. can if you want, but more code to write! + AUOutputBL () {} + AUOutputBL (const AUOutputBL &c); + AUOutputBL& operator= (const AUOutputBL& c); +}; + +#endif // __AUOutputBL_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp new file mode 100644 index 0000000000..87d7848790 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp @@ -0,0 +1,139 @@ +/* + File: AUParamInfo.cpp + Abstract: AUParamInfo.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 "AUParamInfo.h" +#include "CAXException.h" + +AUParamInfo::AUParamInfo (AudioUnit inAU, + bool inIncludeExpert, + bool inIncludeReadOnly, + AudioUnitScope inScope, + AudioUnitElement inElement) + : mAU (inAU), + mNumParams (0), + mParamListID(NULL), + mScope (inScope), + mElement (inElement) +{ + UInt32 size; + OSStatus result = AudioUnitGetPropertyInfo(mAU, kAudioUnitProperty_ParameterList, inScope, mElement, &size, NULL); + if (size == 0 || result) return; + + int nparams = size / sizeof(AudioUnitPropertyID); + mParamListID = new AudioUnitParameterID[nparams]; + + memset (mParamListID, 0xFF, size); + + AudioUnitParameterID *paramList = new AudioUnitParameterID[nparams]; + + result = AudioUnitGetProperty(mAU, kAudioUnitProperty_ParameterList, mScope, mElement, paramList, &size); + if (result) { + delete [] mParamListID; + delete [] paramList; + mParamListID = NULL; + return; + } + + ParameterMap params; + for (int i = 0; i < nparams; ++i) + { + CAAUParameter auvp (mAU, paramList[i], mScope, mElement); // took out only using global scope in CAAUParameter creation + const AudioUnitParameterInfo ¶mInfo = auvp.ParamInfo(); + + // don't include if parameter can't be read or written + if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable) + && !(paramInfo.flags & kAudioUnitParameterFlag_IsReadable)) + continue; + + // only include if expert params wanted + if (!inIncludeExpert && auvp.IsExpert()) + continue; + + // only include if read only params are wanted + if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable) + && (paramInfo.flags & kAudioUnitParameterFlag_IsReadable)) + { + if (!inIncludeReadOnly) + continue; + } + + mParamListID[mNumParams] = paramList[i]; + mNumParams++; + + // ok - if we're here, then we have a parameter we are going to display. + UInt32 clump = 0; + auvp.GetClumpID (clump); + mParams[clump].push_back (auvp); + } + + delete [] paramList; +} + +AUParamInfo::~AUParamInfo() +{ + delete [] mParamListID; +} + +UInt32 AUParamInfo::NumParamsForClump (UInt32 inClump) const +{ + ParameterMap::const_iterator it = mParams.find(inClump); + if (it != mParams.end()) + return static_cast<UInt32>((*it).second.size()); + return 0; +} + +const CAAUParameter* AUParamInfo::GetParamInfo (AudioUnitParameterID inParamID) const +{ + for (ParameterMap::const_iterator it = mParams.begin(); it != mParams.end(); ++it) { + const ParameterList &list = (*it).second; + for (ParameterList::const_iterator iter = list.begin(); iter != list.end(); ++iter) { + if (inParamID == (*iter).mParameterID) { + return &(*iter); + } + } + } + return NULL; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h new file mode 100644 index 0000000000..d15fbfeb2d --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h @@ -0,0 +1,112 @@ +/* + File: AUParamInfo.h + Abstract: Part of CoreAudio Utility Classes + 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 <map> +#include <vector> +#include <AudioUnit/AudioUnit.h> +#include "CAAUParameter.h" + +/* + The ParameterMap returned by the Map() method is a map where + - the key is the clumpID + - the value is a ParameterList (vector<CAAUParameter>) + + If you have parameters on multiple scopes (or elements within a scope), then you should create one of these + for each scope-element pair +*/ + +class AUParamInfo { + +public: + typedef std::vector <CAAUParameter> ParameterList; + typedef std::map <UInt32, ParameterList, std::less<UInt32> > ParameterMap; + + + + AUParamInfo (AudioUnit inAU, + bool inIncludeExpert, + bool inIncludeReadOnly, + AudioUnitScope inScope = kAudioUnitScope_Global, + AudioUnitElement inElement = 0); + + ~AUParamInfo(); + + const ParameterMap& Map () const { return mParams; } + + // some convenience methods + UInt32 NumParams () const { return mNumParams; } + + AudioUnitParameterID ParamID (UInt32 inIndex) const + { + if (inIndex < mNumParams) return mParamListID[inIndex]; + return 0xFFFFFFFF; + } + + UInt32 NumClumps () const { return static_cast<UInt32>(mParams.size()); } + + UInt32 NumParamsForClump (UInt32 inClump) const; + + // returns NULL if there's no info for the parameter + const CAAUParameter* GetParamInfo (AudioUnitParameterID inParamID) const; + + AudioUnitScope GetScope () const { return mScope; } + AudioUnitElement GetElement () const { return mElement; } + +private: + + AudioUnit mAU; + UInt32 mNumParams; + AudioUnitParameterID * mParamListID; + + ParameterMap mParams; + AudioUnitScope mScope; + AudioUnitElement mElement; + + // disallow + AUParamInfo () {} + AUParamInfo (const AUParamInfo &c) {} + AUParamInfo& operator= (const AUParamInfo& c) { return *this; } +}; diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp new file mode 100644 index 0000000000..4e72b22858 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp @@ -0,0 +1,227 @@ +/* + File: CAAUMIDIMap.cpp + Abstract: CAAUMIDIMap.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 "CAAUMIDIMap.h" +#include <pthread.h> + +struct AllMidiTransformers +{ + MIDILinearTransformer linearTrans; + MIDILogTransformer logTrans; + MIDIExpTransformer expTrans; + MIDISqrtTransformer sqrtTrans; + MIDISquareTransformer squareTrans; + MIDICubeRtTransformer cubeRtTrans; + MIDICubeTransformer cubeTrans; +}; + +AllMidiTransformers* gAllMidiTransformers = NULL; + +#if TARGET_OS_MAC +static pthread_once_t sOnce = PTHREAD_ONCE_INIT; + +static void InitAllMidiTransformers() +{ + gAllMidiTransformers = new AllMidiTransformers(); +} + +static void CheckInitAllMidiTransformers() +{ + pthread_once(&sOnce, InitAllMidiTransformers); +} +#endif + +MIDIValueTransformer * CAAUMIDIMap::GetTransformer (UInt32 inFlags) +{ +#if TARGET_OS_MAC + if (gAllMidiTransformers == NULL) + CheckInitAllMidiTransformers(); +#else + if (gAllMidiTransformers == NULL) + gAllMidiTransformers = new AllMidiTransformers(); +#endif + + if (AudioUnitDisplayTypeIsLogarithmic(inFlags)) + return &gAllMidiTransformers->logTrans; + else if (AudioUnitDisplayTypeIsExponential(inFlags)) + return &gAllMidiTransformers->expTrans; + else if (AudioUnitDisplayTypeIsSquareRoot(inFlags)) + return &gAllMidiTransformers->sqrtTrans; + else if (AudioUnitDisplayTypeIsSquared(inFlags)) + return &gAllMidiTransformers->squareTrans; + else if (AudioUnitDisplayTypeIsCubed(inFlags)) + return &gAllMidiTransformers->cubeTrans; + else if (AudioUnitDisplayTypeIsCubeRoot(inFlags)) + return &gAllMidiTransformers->cubeRtTrans; + else + return &gAllMidiTransformers->linearTrans; +} + +// The CALLER of this method must ensure that the status byte's MIDI Command matches!!! +bool CAAUMIDIMap::MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const +{ + // see if the channels match first + SInt8 chan = Channel(); + // channel matches (if chan is less than zero, "Any Channel" flag is set) + if (chan >= 0 && chan != inChannel) + return false; + + // match the special cases first + if (IsKeyEvent()) { + // we're using this key event as an on/off type switch + if (IsBipolar()) { + if (IsKeyPressure()){ + if (IsBipolar_OnValue()) { + if (inData2 > 63) { + outLinear = 1; + return true; + } + } else { + if (inData2 < 64) { + outLinear = 0; + return true; + } + } + return false; + } + else { + if (IsBipolar_OnValue()) { + if (inData1 > 63) { + outLinear = 1; + return true; + } + } else { + if (inData1 < 64) { + outLinear = 0; + return true; + } + } + return false; + } + } + if (IsAnyNote()) { +// not quite sure how to interpret this... + if (IsKeyPressure()) + outLinear = inData2 / 127.0; + else + outLinear = inData1 / 127.0; + return true; + } + if (mData1 == inData1) { + if (IsKeyPressure()) + outLinear = inData2 / 127.0; + else + outLinear = 1; + return true; + } + return false; + } + else if (IsControlChange()) { + // controller ID matches + if (mData1 == inData1) { + if (IsBipolar()) { + if (IsBipolar_OnValue()) { + if (inData2 > 63) { + outLinear = 1; + return true; + } + } else { + if (inData2 < 64) { + outLinear = 0; + return true; + } + } + return false; + } + //printf("this in midi matches %X with ", this); + outLinear = inData2 / 127.; + return true; + } + return false; + } + + // this just matches on the patch change value itself... + if (IsPatchChange()) { + if (mData1 == inData1) { + outLinear = 1; + return true; + } + return false; + } + + // finally, for the other two, just check the bi-polar matching conditions + // pitch bend and after touch + if (IsBipolar()) { + if (IsBipolar_OnValue()) { + if (inData1 > 63) { + outLinear = 1; + return true; + } + } else { + if (inData1 < 64) { + outLinear = 0; + return true; + } + } + return false; + } + + if (IsPitchBend()) { + UInt16 value = (inData2 << 7) | inData1; + outLinear = value / 16383.; + } + else if (IsChannelPressure()) { + outLinear = inData1 / 127.0; + } + + return true; +} + + +void CAAUMIDIMap::Print () const +{ + printf ("CAAUMIDIMap:%p, (%u/%u), mParamID %d, IsValid:%c, Status:0x%X, mData1 %d, Flags:0x%X\n", this, (unsigned int)mScope, (unsigned int)mElement, (int)mParameterID, (IsValid() ? 'T' : 'F'), mStatus, mData1, (int)mFlags); +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h new file mode 100644 index 0000000000..a53fdf70dc --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h @@ -0,0 +1,541 @@ +/* + File: CAAUMIDIMap.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAAUMIDIMap_h_ +#define __CAAUMIDIMap_h_ + +#include <AudioUnit/AudioUnitProperties.h> +#include <algorithm> + +/* +enum { + kAUParameterMIDIMapping_AnyChannelFlag = (1L << 0), + // If this flag is set and mStatus is a MIDI channel message, then the MIDI channel number + // in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel. + + kAUParameterMIDIMapping_AnyNoteFlag = (1L << 1), + // If this flag is set and mStatus is a Note On, Note Off, or Polyphonic Pressure message, + // the message's note number is ignored; the mapping is from ANY note number. + + kAUParameterMIDIMapping_SubRange = (1L << 2), + // set this flag if the midi control should map only to a sub-range of the parameter's value + // then specify that range in the mSubRangeMin and mSubRangeMax members + + kAUParameterMIDIMapping_Toggle = (1L << 3), + // this is only useful for boolean typed parameters. When set, it means that the parameter's + // value should be toggled (if true, become false and vice versa) when the represented MIDI message + // is received + + kAUParameterMIDIMapping_Bipolar = (1L << 4), + // this can be set to when mapping a MIDI Controller to indicate that the parameter (typically a boolean + // style parameter) will only have its value changed to either the on or off state of a MIDI controller message + // (0 < 64 is off, 64 < 127 is on) such as the sustain pedal. The seeting of the next flag + // (kAUParameterMIDIMapping_Bipolar_On) determine whether the parameter is mapped to the on or off + // state of the controller + kAUParameterMIDIMapping_Bipolar_On = (1L << 5) + // only a valid flag if kAUParameterMIDIMapping_Bipolar is set +}; + +// The reserved fields here are being used to reserve space (as well as align to 64 bit size) for future use +// When/If these fields are used, the names of the fields will be changed to reflect their functionality +// so, apps should NOT refer to these reserved fields directly by name +typedef struct AUParameterMIDIMapping +{ + AudioUnitScope mScope; + AudioUnitElement mElement; + AudioUnitParameterID mParameterID; + UInt32 mFlags; + Float32 mSubRangeMin; + Float32 mSubRangeMax; + UInt8 mStatus; + UInt8 mData1; + UInt8 reserved1; // MUST be set to zero + UInt8 reserved2; // MUST be set to zero + UInt32 reserved3; // MUST be set to zero +} AUParameterMIDIMapping; +*/ + +/* +Parameter To MIDI Mapping Properties +These properties are used to: +Describe a current set of mappings between MIDI messages and Parameter value setting +Create a mapping between a parameter and a MIDI message through either: +- explicitly adding (or removing) the mapping +- telling the AU to hot-map the next MIDI message to a specified Parameter + The same MIDI Message can map to one or more parameters + One Parameter can be mapped from multiple MIDI messages + + In general usage, these properties only apply to AU's that implement the MIDI API + AU Instruments (type=='aumu') and Music Effects (type == 'aumf') + + These properties are used in the Global scope. The scope and element members of the structure describe + the scope and element of the parameter. In all usages, mScope, mElement and mParameterID must be + correctly specified. + + + * The AUParameterMIDIMapping Structure + + Command mStatus mData1 + Note Off 0x8n Note Num + Note On 0x9n Note Num + Key Pressure 0xAn Note Num + Control Change 0xBn ControllerID + Patch Change 0xCn Patch Num + Channel Pressure DxDn 0 (Unused) + Pitch Bend 0xEn 0 (Unused) + + (where n is 0-0xF to correspond to MIDI channels 1-16) + + Details: + + In general MIDI Commands can be mapped to either a specific channel as specified in the mStatus bit. + If the kAUParameterMIDIMapping_AnyChannelFlag bit is set mStatus is a MIDI channel message, then the + MIDI channel number in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel. + + For note commands (note on, note off, key pressure), the MIDI message can trigger either with just a specific + note number, or any note number if the kAUParameterMIDIMapping_AnyNoteFlag bit is set. In these instances, the + note number is used as the trigger value (for instance, a note message could be used to set the + cut off frequency of a filter). + + The Properties: + + kAudioUnitProperty_AllParameterMIDIMappings array of AUParameterMIDIMapping (read/write) + This property is used to both retreive and set the current mapping state between (some/many/all of) its parameters + and MIDI messages. When set, it should replace any previous mapped settings the AU had. + + If this property is implemented by a non-MIDI capable AU (such as an 'aufx' type), then the property is + read only, and recommends a suggested set of mappings for the host to perform. In this case, it is the + host's responsibility to map MIDI message to the AU parameters. As described previously, there are a set + of default mappings (see AudioToolbox/AUMIDIController.h) that the host can recommend to the user + in this circumstance. + + This property's size will be very dynamic, depending on the number of mappings currently in affect, so the + caller should always get the size of the property first before retrieving it. The AU should return an error + if the caller doesn't provide enough space to return all of the current mappings. + + kAudioUnitProperty_AddParameterMIDIMapping array of AUParameterMIDIMapping (write only) + This property is used to Add mappings to the existing set of mappings the AU possesses. It does NOT replace + any existing mappings. + + kAudioUnitProperty_RemoveParameterMIDIMapping array of AUParameterMIDIMapping (write only) + This property is used to remove the specified mappings from the AU. If a mapping is specified that does not + currently exist in the AU, then it should just be ignored. + + kAudioUnitProperty_HotMapParameterMIDIMapping AUParameterMIDIMapping (read/write) + This property is used in two ways, determined by the value supplied by the caller. + (1) If a mapping struct is provided, then that struct provides *all* of the information that the AU should + use to map the parameter, *except* for the MIDI message. The AU should then listen for the next MIDI message + and associate that MIDI message with the supplied AUParameter mapping. When this MIDI message is received and + the mapping made, the AU should also issue a notification on this property + (kAudioUnitProperty_HotMapParameterMIDIMapping) to indicate to the host that the mapping has been made. The host + can then retrieve the mapping that was made by getting the value of this property. + + To avoid possible confusion, it is recommended that once the host has retrieved this mapping (if it is + presenting a UI to describe the mappings for example), that it then clears the mapping state as described next. + + Thus, the only time this property will return a valid value is when the AU has made a mapping. If the AU's mapping + state has been cleared (or it has not been asked to make a mapping), then the AU should return + kAudioUnitErr_InvalidPropertyValue if the host tries to read this value. + + (2) If the value passed in is NULL, then if the AU had a parameter that it was in the process of mapping, it + should disregard that (stop listening to the MIDI messages to create a mapping) and discard the partially + mapped struct. If the value is NULL and the AU is not in the process of mapping, the AU can ignore the request. + + At all times, the _AllMappings property will completely describe the current known state of the AU's mappings + of MIDI messages to parameters. +*/ + + +/* + When mapping, it is recommended that LSB controllers are in general not mapped (ie. the controller range of 32 < 64) + as many host parsers will map 14 bit control values. If you know (or can present an option) that the host deals with + 7 bit controllers only, then these controller ID's can be mapped of course. +*/ + + +struct MIDIValueTransformer { + virtual double tolinear(double) = 0; + virtual double fromlinear(double) = 0; +#if DEBUG + // suppress warning + virtual ~MIDIValueTransformer() { } +#endif +}; + +struct MIDILinearTransformer : public MIDIValueTransformer { + virtual double tolinear(double x) { return x; } + virtual double fromlinear(double x) { return x; } +}; + +struct MIDILogTransformer : public MIDIValueTransformer { + virtual double tolinear(double x) { return log(std::max(x, .00001)); } + virtual double fromlinear(double x) { return exp(x); } +}; + +struct MIDIExpTransformer : public MIDIValueTransformer { + virtual double tolinear(double x) { return exp(x); } + virtual double fromlinear(double x) { return log(std::max(x, .00001)); } +}; + +struct MIDISqrtTransformer : public MIDIValueTransformer { + virtual double tolinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); } + virtual double fromlinear(double x) { return x < 0. ? -(x * x) : x * x; } +}; + +struct MIDISquareTransformer : public MIDIValueTransformer { + virtual double tolinear(double x) { return x < 0. ? -(x * x) : x * x; } + virtual double fromlinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); } +}; + +struct MIDICubeRtTransformer : public MIDIValueTransformer { + virtual double tolinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); } + virtual double fromlinear(double x) { return x * x * x; } +}; + +struct MIDICubeTransformer : public MIDIValueTransformer { + virtual double tolinear(double x) { return x * x * x; } + virtual double fromlinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); } +}; + + +class CAAUMIDIMap : public AUParameterMIDIMapping { + +public: +// variables for more efficient parsing of MIDI to Param value + Float32 mMinValue; + Float32 mMaxValue; + MIDIValueTransformer *mTransType; + +// methods + static MIDIValueTransformer *GetTransformer (UInt32 inFlags); + + CAAUMIDIMap() { memset(this, 0, sizeof(CAAUMIDIMap)); } + CAAUMIDIMap (const AUParameterMIDIMapping& inMap) + { + memset(this, 0, sizeof(CAAUMIDIMap)); + memcpy (this, &inMap, sizeof(inMap)); + } + CAAUMIDIMap (AudioUnitScope inScope, AudioUnitElement inElement, AudioUnitParameterID inParam) + { + memset(this, 0, sizeof(CAAUMIDIMap)); + mScope = inScope; + mElement = inElement; + mParameterID = inParam; + } + + + bool IsValid () const { return mStatus != 0; } + + // returns -1 if any channel bit is set + SInt32 Channel () const { return IsAnyChannel() ? -1 : (mStatus & 0xF); } + bool IsAnyChannel () const { + return mFlags & kAUParameterMIDIMapping_AnyChannelFlag; + } + // preserves the existing channel info in the status byte + // preserves any previously set mFlags value + void SetAnyChannel (bool inFlag) + { + if (inFlag) + mFlags |= kAUParameterMIDIMapping_AnyChannelFlag; + else + mFlags &= ~kAUParameterMIDIMapping_AnyChannelFlag; + } + + bool IsAnyNote () const { + return (mFlags & kAUParameterMIDIMapping_AnyNoteFlag) != 0; + } + // preserves the existing key num in the mData1 byte + // preserves any previously set mFlags value + void SetAnyNote (bool inFlag) + { + if (inFlag) + mFlags |= kAUParameterMIDIMapping_AnyNoteFlag; + else + mFlags &= ~kAUParameterMIDIMapping_AnyNoteFlag; + } + + bool IsToggle() const { return (mFlags & kAUParameterMIDIMapping_Toggle) != 0; } + void SetToggle (bool inFlag) + { + if (inFlag) + mFlags |= kAUParameterMIDIMapping_Toggle; + else + mFlags &= ~kAUParameterMIDIMapping_Toggle; + } + + bool IsBipolar() const { return (mFlags & kAUParameterMIDIMapping_Bipolar) != 0; } + // inUseOnValue is valid ONLY if inFlag is true + void SetBipolar (bool inFlag, bool inUseOnValue = false) + { + if (inFlag) { + mFlags |= kAUParameterMIDIMapping_Bipolar; + if (inUseOnValue) + mFlags |= kAUParameterMIDIMapping_Bipolar_On; + else + mFlags &= ~kAUParameterMIDIMapping_Bipolar_On; + } else { + mFlags &= ~kAUParameterMIDIMapping_Bipolar; + mFlags &= ~kAUParameterMIDIMapping_Bipolar_On; + } + } + bool IsBipolar_OnValue () const { return (mFlags & kAUParameterMIDIMapping_Bipolar_On) != 0; } + + bool IsSubRange () const { return (mFlags & kAUParameterMIDIMapping_SubRange) != 0; } + void SetSubRange (Float32 inStartValue, Float32 inStopValue) + { + mFlags |= kAUParameterMIDIMapping_SubRange; + + mSubRangeMin = inStartValue; + mSubRangeMax = inStopValue; + } + + void SetParamRange(Float32 minValue, Float32 maxValue) + { + mMinValue = minValue; + mMaxValue = maxValue; + } + + // this will retain the subrange values previously set. + void SetSubRange (bool inFlag) + { + if (inFlag) + mFlags |= kAUParameterMIDIMapping_SubRange; + else + mFlags &= ~kAUParameterMIDIMapping_SubRange; + } + + bool IsAnyValue() const{return !IsBipolar();} + bool IsOnValue() const{return IsBipolar_OnValue();} + bool IsOffValue() const{return IsBipolar();} + + bool IsNoteOff () const { return ((mStatus & 0xF0) == 0x80); } + bool IsNoteOn () const { return ((mStatus & 0xF0) == 0x90); } + + bool IsKeyPressure () const { return ((mStatus & 0xF0) == 0xA0); } + + bool IsKeyEvent () const { return (mStatus > 0x7F) && (mStatus < 0xB0); } + + bool IsPatchChange () const { return ((mStatus & 0xF0) == 0xC0); } + bool IsChannelPressure () const { return ((mStatus & 0xF0) == 0xD0); } + bool IsPitchBend () const { return ((mStatus & 0xF0) == 0xE0); } + bool IsControlChange () const { return ((mStatus & 0xF0) == 0xB0); } + + + void SetControllerOnValue(){SetBipolar(true,true);} + void SetControllerOffValue(){SetBipolar(true,false);} + void SetControllerAnyValue(){SetBipolar(false,false);} + + // All of these Set calls will reset the mFlags field based on the + // anyChannel param value + void SetNoteOff (UInt8 key, SInt8 channel, bool anyChannel = false) + { + mStatus = 0x80 | (channel & 0xF); + mData1 = key; + mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0); + + } + + void SetNoteOn (UInt8 key, SInt8 channel, bool anyChannel = false) + { + mStatus = 0x90 | (channel & 0xF); + mData1 = key; + mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0); + } + + void SetPolyKey (UInt8 key, SInt8 channel, bool anyChannel = false) + { + mStatus = 0xA0 | (channel & 0xF); + mData1 = key; + mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0); + } + + void SetControlChange (UInt8 controllerID, SInt8 channel, bool anyChannel = false) + { + mStatus = 0xB0 | (channel & 0xF); + mData1 = controllerID; + mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0); + } + + void SetPatchChange (UInt8 patchChange, SInt8 channel, bool anyChannel = false) + { + mStatus = 0xC0 | (channel & 0xF); + mData1 = patchChange; + mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0); + } + + void SetChannelPressure (SInt8 channel, bool anyChannel = false) + { + mStatus = 0xD0 | (channel & 0xF); + mData1 = 0; + mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0); + } + + void SetPitchBend (SInt8 channel, bool anyChannel = false) + { + mStatus = 0xE0 | (channel & 0xF); + mData1 = 0; + mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0); + } + + + Float32 ParamValueFromMIDILinear (Float32 inLinearValue) const + { + Float32 low, high; + if (IsSubRange()){ + low = mSubRangeMin; + high = mSubRangeMax; + } + else { + low = mMinValue; + high = mMaxValue; + } + + + // WE ARE ASSUMING YOU HAVE SET THIS UP PROPERLY!!!!! (or this will crash cause it will be NULL) + return (Float32)mTransType->fromlinear((inLinearValue * (high - low)) + low); + } + + + // The CALLER of this method must ensure that the status byte's MIDI Command (ignoring the channel) matches!!! + bool MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const; + + void Print () const; + + void Save (CFPropertyListRef &outData) const; + void Restore (CFDictionaryRef inData); + + static void SaveAsMapPList (AudioUnit inUnit, + const AUParameterMIDIMapping * inMappings, + UInt32 inNumMappings, + CFPropertyListRef &outData, + CFStringRef inName = NULL); + + // inNumMappings describes how much memory is allocated in outMappings + static void RestoreFromMapPList (const CFDictionaryRef inData, + AUParameterMIDIMapping * outMappings, + UInt32 inNumMappings); + + static UInt32 NumberOfMaps (const CFDictionaryRef inData); +}; + + + // these sorting operations sort for run-time efficiency based on the MIDI messages +inline bool operator== (const CAAUMIDIMap &a, const CAAUMIDIMap &b) +{ + // ignore channel first + return (((a.mStatus & 0xF0) == (b.mStatus & 0xF0)) + && (a.mData1 == b.mData1) + && ((a.mStatus & 0xF) == (b.mStatus & 0xf)) // now compare the channel + && (a.mParameterID == b.mParameterID) + && (a.mElement == b.mElement) + && (a.mScope == b.mScope)); + + // reserved field comparisons - ignored until/if they are used +} + +inline bool operator< (const CAAUMIDIMap &a, const CAAUMIDIMap &b) +{ + if ((a.mStatus & 0xF0) != (b.mStatus & 0xF0)) + return ((a.mStatus & 0xF0) < (b.mStatus & 0xF0)); + + if (a.mData1 != b.mData1) + return (a.mData1 < b.mData1); + + if ((a.mStatus & 0xF) != (b.mStatus & 0xf)) // now compare the channel + return ((a.mStatus & 0xF) < (b.mStatus & 0xf)); + +// reserved field comparisons - ignored until/if they are used + +// we're sorting this by MIDI, so we don't really care how the rest is sorted + return ((a.mParameterID < b.mParameterID) + && (a.mElement < b.mElement) + && (a.mScope < b.mScope)); +} + + + +class CompareMIDIMap { + int compare (const CAAUMIDIMap &a, const CAAUMIDIMap &b) + { + if ((a.mStatus & 0xF0) < (b.mStatus & 0xF0)) + return -1; + if ((a.mStatus & 0xF0) > (b.mStatus & 0xF0)) + return 1; + + // note event + if (a.mStatus < 0xB0 || a.mStatus >= 0xD0) + return 0; + if (a.mData1 > b.mData1) return 1; + if (a.mData1 < b.mData1) return -1; + return 0; + } + +public: + bool operator() (const CAAUMIDIMap &a, const CAAUMIDIMap &b) { + return compare (a, b) < 0; + } + bool Finish (const CAAUMIDIMap &a, const CAAUMIDIMap &b) { + return compare (a, b) != 0; + } +}; + + +/* + usage: To find potential mapped events for a given status byte, where mMMapEvents is a sorted vec + CompareMIDIMap comparObj; + sortVecIter lower_iter = std::lower_bound(mMMapEvents.begin(), mMMapEvents.end(), inStatusByte, compareObj); + for (;lower_iter < mMMapEvents.end(); ++lower_iter) { + // then, see if we go out of the status byte range, using the Finish method + if (compareObj.Finish(map, tempMap)) // tempMap is a CAAUMIDIMap object with the status/dataByte 1 set + break; + // ... + } + + in the for loop you call the MIDI_Matches call, to see if the MIDI event matches a given AUMIDIParam mapping + special note: you HAVE to transform note on (with vel zero) events to the note off status byte +*/ + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp new file mode 100644 index 0000000000..b24ff9945c --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp @@ -0,0 +1,233 @@ +/* + File: CAAUMIDIMapManager.cpp + Abstract: CAAUMIDIMapManager.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 "CAAUMIDIMapManager.h" +#include <AudioToolbox/AudioUnitUtilities.h> + +CAAUMIDIMapManager::CAAUMIDIMapManager() +{ + hotMapping = false; +} + +static void FillInMap (CAAUMIDIMap &map, AUBase &That) +{ + AudioUnitParameterInfo info; + That.GetParameterInfo (map.mScope, map.mParameterID, info); + + if (map.IsSubRange()) { + map.mMinValue = map.mSubRangeMin; + map.mMaxValue = map.mSubRangeMax; + } else { + map.mMinValue = info.minValue; + map.mMaxValue = info.maxValue; + } + + map.mTransType = CAAUMIDIMap::GetTransformer(info.flags); +} + +OSStatus CAAUMIDIMapManager::SortedInsertToParamaterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That) +{ + for (unsigned int i = 0; i < inNumMaps; ++i) + { + CAAUMIDIMap map(maps[i]); + + FillInMap (map, That); + + int idx = FindParameterIndex (maps[i]); + if (idx > -1) + mParameterMaps.erase(mParameterMaps.begin() + idx); + + // least disruptive place to put this is at the end + mParameterMaps.push_back(map); + } + + std::sort(mParameterMaps.begin(), mParameterMaps.end(), CompareMIDIMap()); + + return noErr; +} + +void CAAUMIDIMapManager::GetHotParameterMap(AUParameterMIDIMapping &outMap ) +{ + outMap = mHotMap; +} + +void CAAUMIDIMapManager::SortedRemoveFromParameterMaps(AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange) +{ + if (hotMapping) { + hotMapping = false; + } + + outMapDidChange = false; + for (unsigned int i = 0; i < inNumMaps; ++i) { + int idx = FindParameterIndex (maps[i]); + if (idx > -1) { + //mParameterMaps[idx].Print(); + mParameterMaps.erase(mParameterMaps.begin() + idx); + outMapDidChange = true; + } + } +} + +void CAAUMIDIMapManager::ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That) +{ + mParameterMaps.clear(); + + for (unsigned int i = 0; i < inNumMaps; ++i) { + CAAUMIDIMap mapping(inMappings[i]); + + FillInMap (mapping, That); + mParameterMaps.push_back (mapping); + } + + std::sort(mParameterMaps.begin(),mParameterMaps.end(), CompareMIDIMap()); +} + +bool CAAUMIDIMapManager::HandleHotMapping(UInt8 inStatus, + UInt8 inChannel, + UInt8 inData1, + AUBase &That) +{ //used to set the hot map info + + if (inStatus == 0xf0) return false; + + if (!hotMapping) return false; + hotMapping = false; + + mHotMap.mStatus = inStatus | inChannel; + mHotMap.mData1 = inData1; + + SortedInsertToParamaterMaps (&mHotMap, 1, That); + return true; +} + +#if DEBUG + +void CAAUMIDIMapManager::Print() +{ + for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) { + CAAUMIDIMap* listmap = &(*i); + listmap->Print(); + } +} + +#endif // DEBUG + +void CAAUMIDIMapManager::GetMaps(AUParameterMIDIMapping* maps) +{ + int i = 0; + for ( ParameterMaps::iterator iter = mParameterMaps.begin(); iter < mParameterMaps.end(); ++iter, ++i) { + AUParameterMIDIMapping &listmap = (*iter); + maps[i] = listmap; + } +} + +int CAAUMIDIMapManager::FindParameterIndex (AUParameterMIDIMapping &inMap) +{ + //used to get back hot mapping and one at a time maps, for ui + + int idx = 0; + for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) { + CAAUMIDIMap & listmap = (*i); + if ( (listmap.mParameterID == inMap.mParameterID) && + (listmap.mScope == inMap.mScope) && + (listmap.mElement == inMap.mElement) ) + { + return idx; + } + idx++; + } + return -1; +} + +bool CAAUMIDIMapManager::FindParameterMapEventMatch( UInt8 inStatus, + UInt8 inChannel, + UInt8 inData1, + UInt8 inData2, + UInt32 inBufferOffset, + AUBase& inAUBase) +{ + bool ret_value = false; + + if (inStatus == 0x90 && !inData2) + inStatus = 0x80 | inChannel; + + //used to test for midi matches once map is made + CAAUMIDIMap tempMap; + tempMap.mStatus = inStatus | inChannel; + tempMap.mData1 = inData1; + + CompareMIDIMap compareObj; + + AudioUnitEvent event; + event.mEventType = kAudioUnitEvent_ParameterValueChange; + event.mArgument.mParameter.mAudioUnit = inAUBase.GetComponentInstance(); + + ParameterMaps::iterator lower_iter = + std::lower_bound(mParameterMaps.begin(), mParameterMaps.end(), tempMap, compareObj); + + while (lower_iter < mParameterMaps.end()) + { + CAAUMIDIMap & map = (*lower_iter); + if (compareObj.Finish(map, tempMap)) + break; + + Float32 value; + if (map.MIDI_Matches(inChannel, inData1, inData2, value)) + { + inAUBase.SetParameter ( map.mParameterID, map.mScope, map.mElement, + map.ParamValueFromMIDILinear(value), inBufferOffset); + + event.mArgument.mParameter.mParameterID = map.mParameterID; + event.mArgument.mParameter.mScope = map.mScope; + event.mArgument.mParameter.mElement = map.mElement; + + AUEventListenerNotify(NULL, NULL, &event); + ret_value = true; + } + ++lower_iter; + } + return ret_value; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h new file mode 100644 index 0000000000..8926d8f6e1 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h @@ -0,0 +1,102 @@ +/* + File: CAAUMIDIMapManager.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAAUMIDIMapManager_h_ +#define __CAAUMIDIMapManager_h_ + +#include "AUBase.h" +#include "CAAUMIDIMap.h" +#include <vector> +#include <AudioToolbox/AudioUnitUtilities.h> + +class CAAUMIDIMapManager { + +protected: + + typedef std::vector<CAAUMIDIMap> ParameterMaps; + ParameterMaps mParameterMaps; + + bool hotMapping; + AUParameterMIDIMapping mHotMap; + +public: + + CAAUMIDIMapManager(); + + UInt32 NumMaps(){return static_cast<UInt32>(mParameterMaps.size());} + void GetMaps(AUParameterMIDIMapping* maps); + + int FindParameterIndex(AUParameterMIDIMapping &map); + + void GetHotParameterMap(AUParameterMIDIMapping &outMap); + + void SortedRemoveFromParameterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange); + OSStatus SortedInsertToParamaterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That); + + void ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That); + + bool IsHotMapping(){return hotMapping;} + void SetHotMapping (AUParameterMIDIMapping &inMap){hotMapping = true; mHotMap = inMap; } + + bool HandleHotMapping( UInt8 inStatus, + UInt8 inChannel, + UInt8 inData1, + AUBase &That); + + + bool FindParameterMapEventMatch(UInt8 inStatus, + UInt8 inChannel, + UInt8 inData1, + UInt8 inData2, + UInt32 inBufferOffset, + AUBase& inAUBase); +#if DEBUG + void Print(); +#endif +}; + + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp new file mode 100644 index 0000000000..2d8fe18341 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp @@ -0,0 +1,400 @@ +/* + File: CAAUParameter.cpp + Abstract: CAAUParameter.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 "CAAUParameter.h" + +CAAUParameter::CAAUParameter() +{ + memset(this, 0, sizeof(CAAUParameter)); +} + +CAAUParameter::CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element) +{ + memset(this, 0, sizeof(CAAUParameter)); + Init (au, param, scope, element); +} + +CAAUParameter::CAAUParameter (AudioUnitParameter &inParam) +{ + memset(this, 0, sizeof(CAAUParameter)); + Init (inParam.mAudioUnit, inParam.mParameterID, inParam.mScope, inParam.mElement); +} + +CAAUParameter::CAAUParameter(const CAAUParameter &a) +{ + memset(this, 0, sizeof(CAAUParameter)); + *this = a; +} + +CAAUParameter & CAAUParameter::operator = (const CAAUParameter &a) +{ + if (mParamName) CFRelease(mParamName); + if (mParamTag) CFRelease(mParamTag); + if (mNamedParams) CFRelease(mNamedParams); + + memcpy(this, &a, sizeof(CAAUParameter)); + + if (mParamName) CFRetain(mParamName); + if (mParamTag) CFRetain(mParamTag); + if (mNamedParams) CFRetain(mNamedParams); + + return *this; +} + +CAAUParameter::~CAAUParameter() +{ + if (mParamName) CFRelease(mParamName); + if (mParamTag) CFRelease(mParamTag); + if (mNamedParams) CFRelease (mNamedParams); +} + +void CAAUParameter::Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element) +{ + mAudioUnit = au; + mParameterID = param; + mScope = scope; + mElement = element; + + UInt32 propertySize = sizeof(mParamInfo); + OSStatus err = AudioUnitGetProperty(au, kAudioUnitProperty_ParameterInfo, + scope, param, &mParamInfo, &propertySize); + if (err) + memset(&mParamInfo, 0, sizeof(mParamInfo)); + if (mParamInfo.flags & kAudioUnitParameterFlag_HasCFNameString) { + mParamName = mParamInfo.cfNameString; + if (!(mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease)) + CFRetain (mParamName); + } else + mParamName = CFStringCreateWithCString(NULL, mParamInfo.name, kCFStringEncodingUTF8); + + const char* str = 0; + switch (mParamInfo.unit) + { + case kAudioUnitParameterUnit_Boolean: + str = "T/F"; + break; + case kAudioUnitParameterUnit_Percent: + case kAudioUnitParameterUnit_EqualPowerCrossfade: + str = "%"; + break; + case kAudioUnitParameterUnit_Seconds: + str = "Secs"; + break; + case kAudioUnitParameterUnit_SampleFrames: + str = "Samps"; + break; + case kAudioUnitParameterUnit_Phase: + case kAudioUnitParameterUnit_Degrees: + str = "Degr."; + break; + case kAudioUnitParameterUnit_Hertz: + str = "Hz"; + break; + case kAudioUnitParameterUnit_Cents: + case kAudioUnitParameterUnit_AbsoluteCents: + str = "Cents"; + break; + case kAudioUnitParameterUnit_RelativeSemiTones: + str = "S-T"; + break; + case kAudioUnitParameterUnit_MIDINoteNumber: + case kAudioUnitParameterUnit_MIDIController: + str = "MIDI"; + //these are inclusive, so add one value here + mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue); + break; + case kAudioUnitParameterUnit_Decibels: + str = "dB"; + break; + case kAudioUnitParameterUnit_MixerFaderCurve1: + case kAudioUnitParameterUnit_LinearGain: + str = "Gain"; + break; + case kAudioUnitParameterUnit_Pan: + str = "L/R"; + break; + case kAudioUnitParameterUnit_Meters: + str = "Mtrs"; + break; + case kAudioUnitParameterUnit_Octaves: + str = "8ve"; + break; + case kAudioUnitParameterUnit_BPM: + str = "BPM"; + break; + case kAudioUnitParameterUnit_Beats: + str = "Beats"; + break; + case kAudioUnitParameterUnit_Milliseconds: + str = "msecs"; + break; + case kAudioUnitParameterUnit_Ratio: + str = "Ratio"; + break; + case kAudioUnitParameterUnit_Indexed: + { + propertySize = sizeof(mNamedParams); + err = AudioUnitGetProperty (au, + kAudioUnitProperty_ParameterValueStrings, + scope, + param, + &mNamedParams, + &propertySize); + if (!err && mNamedParams) { + mNumIndexedParams = CFArrayGetCount(mNamedParams); + } else { + //these are inclusive, so add one value here + mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue); + } + str = NULL; + } + break; + case kAudioUnitParameterUnit_CustomUnit: + { + CFStringRef unitName = mParamInfo.unitName; + static char paramStr[256]; + CFStringGetCString (unitName, paramStr, 256, kCFStringEncodingUTF8); + if (mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease) + CFRelease (unitName); + str = paramStr; + break; + } + case kAudioUnitParameterUnit_Generic: + case kAudioUnitParameterUnit_Rate: + default: + str = NULL; + break; + } + + if (str) + mParamTag = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8); + else + mParamTag = NULL; +} + + +Float32 CAAUParameter::GetValue() const +{ + Float32 value = 0.; + //OSStatus err = + AudioUnitGetParameter(mAudioUnit, mParameterID, mScope, mElement, &value); + return value; +} + +CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue, + const CAAUParameter * inParameter, + UInt32 inDigits, + UInt32 minDigits) { + if (!inParameter) return nil; + + AudioUnitParameterInfo info = inParameter->ParamInfo(); + int pow10; + + switch (info.unit) { + case kAudioUnitParameterUnit_Hertz: + // number of significant digits based on value + pow10 = int(log10(fmax(inParameterValue, .000001))); + break; + default: + // number of significant digits based on parameter range + pow10 = int(log10(fmax(double(info.maxValue - info.minValue), .000001))); + break; + } + + // pow10 range nDigitsAfterDecimal + // -2 .0100-.0999 4 + // -1 .100-.999 3 + // 0 1.00-9.99 2 + // 1 10.0-99.9 1 + // 2 100-999 0 + // 3 1000-9990 -1 + // 4 10000-99900 -2 + + int nDigitsAfterDecimal = inDigits - (pow10 + 1); + if (nDigitsAfterDecimal < 0) + nDigitsAfterDecimal = 0; // the least number of digits possible is zero + + if (info.flags & kAudioUnitParameterFlag_IsHighResolution) + nDigitsAfterDecimal = 4; + + CFLocaleRef currentLocale = CFLocaleCopyCurrent(); + CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle); + + CFNumberRef maxFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal); + + if (nDigitsAfterDecimal > 0) + nDigitsAfterDecimal = minDigits; + + CFNumberRef minFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal); + + CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMinFractionDigits, minFractionDigits); + CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMaxFractionDigits, maxFractionDigits); + CFStringRef formattedNumberString = CFNumberFormatterCreateStringWithValue (NULL, numberFormatter, kCFNumberDoubleType, &inParameterValue); + + CFRelease(currentLocale); + CFRelease(numberFormatter); + CFRelease(maxFractionDigits); + CFRelease(minFractionDigits); + + return formattedNumberString; +} + +CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue, + const CAAUParameter * inParameter, + UInt32 inDigits) { + return CreateLocalizedStringForParameterValue (inParameterValue, inParameter, inDigits, 1); +} + +double ValueForLocalizedParameterString (CFStringRef string, const CAAUParameter * inParameter) { + CFLocaleRef currentLocale = CFLocaleCopyCurrent(); + CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle); + + double value = 0; + Boolean worked = CFNumberFormatterGetValueFromString (numberFormatter, string, NULL, kCFNumberDoubleType, &value); + + CFRelease(currentLocale); + CFRelease(numberFormatter); + + if (worked) + return value; + else { + AudioUnitParameterInfo info = inParameter->ParamInfo(); + return info.defaultValue; + } +} + +CFStringRef CAAUParameter::GetStringFromValueCopy(const Float32 *value) const +{ + if (HasNamedParams()) + { + Float32 val = (value == NULL ? GetValue() : *value); + int index = int(mParamInfo.minValue) + int(val); + CFStringRef str = GetParamName (index); + if (str) { + CFRetain (str); + return str; + } + } + else if (ValuesHaveStrings()) + { + AudioUnitParameterStringFromValue stringValue; + stringValue.inParamID = mParameterID; + stringValue.inValue = value; + stringValue.outString = NULL; + UInt32 propertySize = sizeof(stringValue); + + OSStatus err = AudioUnitGetProperty (mAudioUnit, + kAudioUnitProperty_ParameterStringFromValue, + mScope, + 0, + &stringValue, + &propertySize); + + if (!err && stringValue.outString != NULL) + return stringValue.outString; + } + + Float32 val = (value == NULL ? GetValue() : *value); + AudioUnitParameterUnit unit = this->ParamInfo().unit; + if (unit == kAudioUnitParameterUnit_Cents || unit == kAudioUnitParameterUnit_AbsoluteCents) + return CreateLocalizedStringForParameterValue(val, this, 4, 0); + else + return CreateLocalizedStringForParameterValue(val, this, 4); +} + +Float32 CAAUParameter::GetValueFromString(CFStringRef str) const +{ + if (ValuesHaveStrings()) + { + AudioUnitParameterValueFromString valueString; + valueString.inParamID = mParameterID; + valueString.inString = str; + UInt32 propertySize = sizeof(valueString); + + OSStatus err = AudioUnitGetProperty (mAudioUnit, + kAudioUnitProperty_ParameterValueFromString, + mScope, + 0, + &valueString, + &propertySize); + + if (!err) { + return valueString.outValue; + } + } + + return (Float32) ValueForLocalizedParameterString(str, this); +} + +void CAAUParameter::SetValue( AUParameterListenerRef inListener, + void * inObject, + Float32 inValue) const +{ + // clip inValue as: maxValue >= inValue >= minValue before setting + Float32 valueToSet = inValue; + if (valueToSet > mParamInfo.maxValue) + valueToSet = mParamInfo.maxValue; + if (valueToSet < mParamInfo.minValue) + valueToSet = mParamInfo.minValue; + + AUParameterSet(inListener, inObject, this, valueToSet, 0); +} + +#if DEBUG +void CAAUParameter::Print() const +{ + UInt32 clump = 0; + GetClumpID (clump); + + UInt32 len = static_cast<UInt32>(CFStringGetLength(mParamName)); + char* chars = (char*)malloc (len * 2); // give us plenty of room for unichar chars + if (!CFStringGetCString (mParamName, chars, len * 2, kCFStringEncodingUTF8)) + chars[0] = 0; + + printf ("ID: %ld, Clump: %u, Name: %s\n", (long unsigned int) mParameterID, (unsigned int) clump, chars); + free (chars); +} +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h new file mode 100644 index 0000000000..f8b5733d8c --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h @@ -0,0 +1,191 @@ +/* + File: CAAUParameter.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAAUParameter_h__ +#define __CAAUParameter_h__ + +#include <AudioToolbox/AudioUnitUtilities.h> + +// ____________________________________________________________________________ +// CAAUParameter +// complete parameter specification + /*! @class CAAUParameter */ +class CAAUParameter : public AudioUnitParameter { +public: + /*! @ctor CAAUParameter.0 */ + CAAUParameter(); + /*! @ctor CAAUParameter.1 */ + CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element); + /*! @ctor CAAUParameter.2 */ + CAAUParameter(AudioUnitParameter &inParam); + /*! @ctor CAAUParameter.3 */ + CAAUParameter(const CAAUParameter &a); + /*! @dtor ~CAAUParameter */ + ~CAAUParameter(); + + /*! @method operator <@ */ + bool operator < (const CAAUParameter &a) const + { + return memcmp(this, &a, sizeof(AudioUnitParameter)) < 0; + } + + /*! @method operator ==@ */ + bool operator == (const CAAUParameter &a) const + { + return !memcmp(this, &a, sizeof(AudioUnitParameter)); + } + + /*! @method operator =@ */ + CAAUParameter & operator = (const CAAUParameter &a); + + /*! @method GetValue */ + Float32 GetValue() const; + /*! @method SetValue */ + void SetValue( AUParameterListenerRef inListener, + void * inObject, + Float32 inValue) const; + + /*! @method GetName */ + CFStringRef GetName() const { return mParamName; } + // borrowed reference! + + /*! @method GetStringFromValueCopy */ + CFStringRef GetStringFromValueCopy(const Float32 *value = NULL) const; + // returns a copy of the name of the current parameter value + // or null if there is no name associated + // caller must release + /*! @method ValuesHaveStrings */ + bool ValuesHaveStrings () const + { + return (mParamInfo.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0; + } + + /*! @method GetValueFromString */ + Float32 GetValueFromString (CFStringRef str) const; + // caller must release + + /*! @method ParamInfo */ + const AudioUnitParameterInfo & + ParamInfo() const { return mParamInfo; } + + /*! @method GetParamTag */ + CFStringRef GetParamTag() const { return mParamTag; } + // this may return null! - + // in which case there is no descriptive tag for the parameter + + /*! @method GetParamName */ + CFStringRef GetParamName (int inIndex) const + // this can return null if there is no name for the parameter + { + return (mNamedParams && inIndex < mNumIndexedParams) + ? (CFStringRef) CFArrayGetValueAtIndex(mNamedParams, inIndex) + : 0; + } + + /*! @method GetNumIndexedParams */ + int GetNumIndexedParams () const { return mNumIndexedParams; } + + /*! @method IsIndexedParam */ + bool IsIndexedParam () const { return mNumIndexedParams != 0; } + + /*! @method HasNamedParams */ + bool HasNamedParams () const { return IsIndexedParam() && mNamedParams; } + + /*! @method GetClumpID */ + bool GetClumpID (UInt32 &outClumpID) const + { + if (mParamInfo.flags & kAudioUnitParameterFlag_HasClump) { + outClumpID = mParamInfo.clumpID; + return true; + } + return false; + } + + /*! @method HasDisplayTransformation */ + bool HasDisplayTransformation () const + { + return GetAudioUnitParameterDisplayType (mParamInfo.flags); + } + + /*! @method IsExpert */ + bool IsExpert () const + { + return mParamInfo.flags & kAudioUnitParameterFlag_ExpertMode; + } +#if DEBUG + void Print () const; +#endif + + // these methods are defined in CAPersistence.cpp + // they will persist and restore only the scope, element and param ID's of the AudioUnitParameter + // however, this is sufficient to be able to save/restore a CAAUParameter object + void Save (CFPropertyListRef &outData) const; + + static void Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData); + + static OSStatus Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam); + +protected: + // cached parameter info + /*! @var mParamInfo */ + AudioUnitParameterInfo mParamInfo; + /*! @var mParamName */ + CFStringRef mParamName; + /*! @var mParamTag */ + CFStringRef mParamTag; + /*! @var mNumIndexedParams */ + short mNumIndexedParams; + /*! @var mNamedParams */ + CFArrayRef mNamedParams; + +private: + void Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element); + +}; + + + +#endif // __CAAUParameter_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp new file mode 100644 index 0000000000..1cda39c99d --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp @@ -0,0 +1,707 @@ +/* + File: CAAUProcessor.cpp + Abstract: CAAUProcessor.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 "CAAUProcessor.h" +#include "CAXException.h" + +static OSStatus SilenceInputCallback (void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) +{ + AudioBuffer *buf = ioData->mBuffers; + for (UInt32 i = ioData->mNumberBuffers; i--; ++buf) + memset((Byte *)buf->mData, 0, buf->mDataByteSize); + + //provide a hint that our input data is silent. + *ioActionFlags &= kAudioUnitRenderAction_OutputIsSilence; + return noErr; +} + +static AURenderCallbackStruct sSilentCallback = { SilenceInputCallback, NULL }; + + +CAAUProcessor::CAAUProcessor (const CAComponent& inComp) + : mPreflightABL(NULL) +{ + OSStatus result = CAAudioUnit::Open (inComp, mUnit); + if (result) + throw result; + memset (&mUserCallback, 0, sizeof (AURenderCallbackStruct)); + mMaxTailTime = 10.; +} + +CAAUProcessor::~CAAUProcessor () +{ + if (mPreflightABL) + delete mPreflightABL; +} + +inline OSStatus SetInputCallback (CAAudioUnit &inUnit, AURenderCallbackStruct &inInputCallback) +{ + return inUnit.SetProperty (kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &inInputCallback, + sizeof(inInputCallback)); +} + +static AURenderCallbackStruct sRenderCallback; +static OSStatus PrerollRenderProc ( void * /*inRefCon*/, + AudioUnitRenderActionFlags * /*inActionFlags*/, + const AudioTimeStamp * /*inTimeStamp*/, + UInt32 /*inBusNumber*/, + UInt32 /*inNumFrames*/, + AudioBufferList *ioData) +{ + AudioBuffer *buf = ioData->mBuffers; + for (UInt32 i = ioData->mNumberBuffers; i--; ++buf) + memset((Byte *)buf->mData, 0, buf->mDataByteSize); + + return noErr; +} + +OSStatus Preroll (CAAudioUnit & inAU, UInt32 inFrameSize) +{ + CAStreamBasicDescription desc; + OSStatus result = inAU.GetFormat (kAudioUnitScope_Input, 0, desc); + bool hasInput = false; + //we have input + if (result == noErr) + { + sRenderCallback.inputProc = PrerollRenderProc; + sRenderCallback.inputProcRefCon = 0; + + result = inAU.SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, + 0, &sRenderCallback, sizeof(sRenderCallback)); + if (result) return result; + hasInput = true; + } + + AudioUnitRenderActionFlags flags = 0; + AudioTimeStamp time; + memset (&time, 0, sizeof(time)); + time.mFlags = kAudioTimeStampSampleTimeValid; + + CAStreamBasicDescription outputFormat; + ca_require_noerr (result = inAU.GetFormat (kAudioUnitScope_Output, 0, outputFormat), home); + { + AUOutputBL list (outputFormat, inFrameSize); + list.Prepare (); + + result = inAU.Render (&flags, &time, 0, inFrameSize, list.ABL()); + if (result) { printf("A result %d\n", (int)result); goto home; } + } + +home: + if (hasInput) { + // remove our installed callback + sRenderCallback.inputProc = 0; + sRenderCallback.inputProcRefCon = 0; + + inAU.SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, + 0, &sRenderCallback, sizeof(sRenderCallback)); + } + return result; +} + + +OSStatus CAAUProcessor::EstablishInputCallback (AURenderCallbackStruct &inInputCallback) +{ + OSStatus result = SetInputCallback (mUnit, inInputCallback); + if (!result) + memcpy (&mUserCallback, &inInputCallback, sizeof(AURenderCallbackStruct)); + else + memset (&mUserCallback, 0, sizeof (AURenderCallbackStruct)); + return result; +} + +OSStatus CAAUProcessor::SetAUPreset (CFPropertyListRef inPreset) +{ + return mUnit.SetProperty (kAudioUnitProperty_ClassInfo, + kAudioUnitScope_Global, + 0, + &inPreset, + sizeof(inPreset)); +} + +OSStatus CAAUProcessor::SetAUPresetIndex (SInt32 inPresetIndex) +{ + AUPreset aup; + aup.presetName = NULL; + aup.presetNumber = inPresetIndex; + return mUnit.SetPresentPreset(aup); +} + + +OSStatus CAAUProcessor::SetParameter (AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 value, UInt32 bufferOffsetFrames) +{ + return mUnit.SetParameter(inID, scope, element, value, bufferOffsetFrames); +} + + +UInt32 CAAUProcessor::MaxFramesPerRender () const +{ + UInt32 maxFrames; + UInt32 propSize = sizeof (maxFrames); + if (mUnit.GetProperty (kAudioUnitProperty_MaximumFramesPerSlice, + kAudioUnitScope_Global, 0, &maxFrames, &propSize)) + { + return 0; + } + return maxFrames; +} + +OSStatus CAAUProcessor::SetMaxFramesPerRender (UInt32 inMaxFrames) +{ + return mUnit.SetProperty (kAudioUnitProperty_MaximumFramesPerSlice, + kAudioUnitScope_Global, 0, &inMaxFrames, sizeof(inMaxFrames)); +} + +OSStatus CAAUProcessor::Initialize (const CAStreamBasicDescription &inInputDesc, + const CAStreamBasicDescription &inOutputDesc, + UInt64 inNumInputSamples) +{ + return DoInitialisation (inInputDesc, inOutputDesc, inNumInputSamples, MaxFramesPerRender()); +} + +OSStatus CAAUProcessor::Reinitialize (UInt32 inNewMaxFrames) +{ + OSStatus result; + CAStreamBasicDescription inputDesc, outputDesc; + + ca_require_noerr (result = mUnit.GetFormat (kAudioUnitScope_Input, 0, inputDesc), home); + ca_require_noerr (result = mUnit.GetFormat (kAudioUnitScope_Output, 0, outputDesc), home); + + ca_require_noerr (result = DoInitialisation (inputDesc, outputDesc, mNumInputSamples, inNewMaxFrames), home); + +home: + return result; +} + + +OSStatus CAAUProcessor::DoInitialisation (const CAStreamBasicDescription &inInputFormat, + const CAStreamBasicDescription &inOutputFormat, + UInt64 inNumInputSamples, + UInt32 inMaxFrames) +{ + OSStatus result; + + if (inNumInputSamples == 0 && IsOfflineAU()) + return kAudioUnitErr_InvalidOfflineRender; + + mNumInputSamples = inNumInputSamples; + + // first check that we can do this number of channels + if (mUnit.CanDo (inInputFormat.NumberChannels(), inOutputFormat.NumberChannels()) == false) + ca_require_noerr (result = kAudioUnitErr_FailedInitialization, home); + + // just uninitialise the AU as a matter of course + ca_require_noerr (result = mUnit.Uninitialize(), home); + + ca_require_noerr (result = mUnit.SetFormat (kAudioUnitScope_Input, 0, inInputFormat), home); + ca_require_noerr (result = mUnit.SetFormat (kAudioUnitScope_Output, 0, inOutputFormat), home); + ca_require_noerr (result = SetMaxFramesPerRender (inMaxFrames), home); + +#if !TARGET_OS_IPHONE + // if we're any AU but an offline AU, we should tell it that we've processing offline + if (!IsOfflineAU()) { + UInt32 isOffline = (IsOfflineContext() ? 1 : 0); + // don't care whether this succeeds of fails as many AU's don't care about this + // but the ones that do its important that they are told their render context + mUnit.SetProperty (kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &isOffline, sizeof(isOffline)); + } else { + // tell the offline unit how many input samples we wish to process... + mUnit.SetProperty (kAudioUnitOfflineProperty_InputSize, + kAudioUnitScope_Global, 0, + &mNumInputSamples, sizeof(mNumInputSamples)); + } +#endif + + ca_require_noerr (result = mUnit.Initialize(), home); + + ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home); + + // finally reset our time stamp + // the time stamp we use with the AU Render - only sample count is valid + memset (&mRenderTimeStamp, 0, sizeof(mRenderTimeStamp)); + mRenderTimeStamp.mFlags = kAudioTimeStampSampleTimeValid; + + // now, if we're NOT an offline AU, preflighting is not required + // if we are an offline AU, we should preflight.. an offline AU will tell us when its preflighting is done + mPreflightDone = false; + + if (mPreflightABL) { + delete mPreflightABL; + mPreflightABL = NULL; + } + + mPreflightABL = new AUOutputBL (inOutputFormat); + + mLastPercentReported = 0; + +home: + return result; +} + +void CAAUProcessor::CalculateRemainderSamples (Float64 inSampleRate) +{ + mLatencySamples = 0; + mTailSamplesToProcess = 0; + mTailSamples = 0; + mTailSamplesRemaining = 0; + return; + + // nothing to do because we're not processing offline + if (IsOfflineContext() == false) return; + + // because an offline unit has some indeterminancy about what it does with the input samples + // it is *required* to deal internally with both latency and tail + if (!IsOfflineAU()) + { + // when offline we need to deal with both latency and tail + + // if the AU has latency - how many samples at the start will be zero? + // we'll end up chucking these away. + Float64 renderTimeProps; + UInt32 propSize = sizeof (renderTimeProps); + OSStatus result = mUnit.GetProperty (kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, + &renderTimeProps, &propSize); + + Float64 latencySamples = 0; + if (result == noErr) // we have latency to deal with - its reported in seconds + latencySamples = renderTimeProps * inSampleRate; + + // AU tail + // if the AU has a tail - we'll pull that many zeroes through at the end to flush + // out this tail - think of a decaying digital delay or reverb... + result = mUnit.GetProperty (kAudioUnitProperty_TailTime, kAudioUnitScope_Global, 0, + &renderTimeProps, &propSize); + if (renderTimeProps > mMaxTailTime) + renderTimeProps = mMaxTailTime; + Float64 tailSamples = 0; + if (result == noErr) + tailSamples = renderTimeProps * inSampleRate; + + // this dictates how many samples at the end we need to pull through... + // we add latency to tail because we throw the latency samples away from the start of the rendering + // and we have to pull that many samples after the end of course to get the last of the original data + // then to that is added the tail of the effect... + mTailSamplesToProcess = UInt32(tailSamples + latencySamples); + mTailSamples = UInt32(tailSamples); + mLatencySamples = UInt32(latencySamples); + } +} + +#if !TARGET_OS_IPHONE +CFStringRef CAAUProcessor::GetOLPreflightName () const +{ + if (OfflineAUNeedsPreflight()) + { + CFStringRef str; + UInt32 size = sizeof(str); + OSStatus result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightName, + kAudioUnitScope_Global, 0, + &str, &size); + return result ? NULL : str; + } + return NULL; // says NO to preflighting +} + +bool CAAUProcessor::OfflineAUNeedsPreflight () const +{ + if (IsOfflineAU()) { + UInt32 preflightRequirements; + UInt32 size = sizeof(preflightRequirements); + OSStatus result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightRequirements, + kAudioUnitScope_Global, 0, + &preflightRequirements, &size); + if (result) + return false; + return preflightRequirements; + } + return false; +} +#endif + +OSStatus CAAUProcessor::Preflight (bool inProcessPreceedingTail) +{ + printf(">>>>CAAUProcessor::Preflight\n"); + //we're preflighting again, so reset ourselves + if (mPreflightDone) { + mPreflightDone = false; + // the time stamp we use with the AU Render - only sample count is valid + memset (&mRenderTimeStamp, 0, sizeof(mRenderTimeStamp)); + mRenderTimeStamp.mFlags = kAudioTimeStampSampleTimeValid; + mUnit.GlobalReset(); + } + + Float64 sampleRate; + OSStatus result = mUnit.GetSampleRate (kAudioUnitScope_Output, 0, sampleRate); + CalculateRemainderSamples (sampleRate); + + UInt32 numFrames = MaxFramesPerRender(); + if (numFrames == 0) + return kAudioUnitErr_InvalidProperty; + + if (!IsOfflineAU()) + { + if ((IsOfflineContext() == false && inProcessPreceedingTail) || IsOfflineContext()) + { + // re-establish the user's input callback + ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home); + + // Consume the number of input samples indicated by the AU's latency or tail + // based on whether the AU is being used in an offline context or not. + + UInt32 latSamps = IsOfflineContext() ? mLatencySamples : mTailSamples; + printf("latSamps %d\n", (int)latSamps); + latSamps = 0; + while (latSamps > 0) + { + if (latSamps < numFrames) + numFrames = latSamps; + + // process the samples (the unit's input callback will read the samples + // from the file and convert them to float for processing + AudioUnitRenderActionFlags renderFlags = 0; + mPreflightABL->Prepare(); + result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, numFrames, mPreflightABL->ABL()); + if (result) { printf("B result %d\n", (int)result); goto home; } + + mRenderTimeStamp.mSampleTime += numFrames; + latSamps -= numFrames; + } + if (IsOfflineContext()) + mRenderTimeStamp.mSampleTime = mLatencySamples; + } + else + { + // processing real-time but not processing preceeding tail, so we should preroll the AU + ca_require_noerr (result = Preroll(mUnit, numFrames), home); + + // re-establish the user's input callback + ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home); + + mRenderTimeStamp.mSampleTime = 0; + } + } +#if !TARGET_OS_IPHONE + else + { + // re-establish the user's input callback + ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home); + + UInt32 preflightRequirements; + UInt32 size; size = sizeof(preflightRequirements); + ca_require_noerr (result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightRequirements, + kAudioUnitScope_Global, 0, + &preflightRequirements, &size), home); + + // 0 indicates none, otherwise optional or required -> we do it for either + if (preflightRequirements) + { + for (;;) { + // here we need to do the preflight loop - we don't expect any data back, but have to + // give the offline unit all of its input data to allow it to prepare its processing + AudioUnitRenderActionFlags renderFlags = kAudioOfflineUnitRenderAction_Preflight; + mPreflightABL->Prepare(); + result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, numFrames, mPreflightABL->ABL()); + if (result) { printf("C result %d\n", (int)result); goto home; } + mRenderTimeStamp.mSampleTime += numFrames; + + if (renderFlags & kAudioOfflineUnitRenderAction_Complete) + break; + } + } + // the time stamp we use with the AU Render - only sample count is valid + mRenderTimeStamp.mSampleTime = 0; + } +#endif + + if (result == noErr) { + mPreflightDone = true; + } + +home: + printf("<<<<CAAUProcessor::Preflight\n"); + return result; +} + +#if !TARGET_OS_IPHONE +OSStatus CAAUProcessor::OfflineAUPreflight (UInt32 inNumFrames, bool &outIsDone) +{ + if (!IsOfflineAU()) + return -50/*paramErr*/; + if (mNumInputSamples == 0) + return -50/*paramErr*/; + + UInt32 preflightRequirements; + UInt32 size = sizeof(preflightRequirements); + OSStatus result; + ca_require_noerr (result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightRequirements, + kAudioUnitScope_Global, 0, + &preflightRequirements, &size), home); + + // 0 indicates none, otherwise optional or required -> we do it for either + if (preflightRequirements) + { + AudioUnitRenderActionFlags renderFlags = kAudioOfflineUnitRenderAction_Preflight; + mPreflightABL->Prepare(); + result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, inNumFrames, mPreflightABL->ABL()); + if (result) { printf("D result %d\n", (int)result); goto home; } + mRenderTimeStamp.mSampleTime += inNumFrames; + + if (renderFlags & kAudioOfflineUnitRenderAction_Complete) { + outIsDone = true; + mRenderTimeStamp.mSampleTime = 0; + mPreflightDone = true; + mLastPercentReported = 0; + } + } + else + { + outIsDone = true; + mRenderTimeStamp.mSampleTime = 0; + mPreflightDone = true; + mLastPercentReported = 0; + } + +home: + return result; +} +#endif + +void SetBufferListToNumFrames (AudioBufferList &list, UInt32 inNumFrames) +{ + for (unsigned int i = 0; i < list.mNumberBuffers; ++i) { + AudioBuffer &buf = list.mBuffers[i]; + if (buf.mDataByteSize > 0) + buf.mDataByteSize = inNumFrames * sizeof (Float32); + } +} + +OSStatus CAAUProcessor::Render (AudioBufferList *ioData, + UInt32 &ioNumFrames, + bool &outIsSilence, + bool *outOLCompleted, + bool *outOLRequiresPostProcess) +{ + if (IsOfflineContext()) + { + if (!mPreflightDone) + return kAudioUnitErr_InvalidOfflineRender; + + // YES - this is correct!!! you have to provide both if rendering in an offline Context + *outOLCompleted = false; + *outOLRequiresPostProcess = false; + + if (!IsOfflineAU() && !mUnit.Comp().Desc().IsFConv()) + { + // have we processed the input we expect too? + // in an offline case, we want to create output that matches the input + // for an OfflineAU type, it manages this internally, so we don't have to do anything + // for a FormatConverter AU, we don't know and can't tell, so we can't do anything here + // for any other AU type (effect, instrument) the Prime assumption is that it will + // ask for the same number of frames of input as it is asked to output + // so we can ask what it is doing, and get a sample accurate output (which is input + tail time) + if (mRenderTimeStamp.mSampleTime + ioNumFrames >= InputSampleCount()) + { + // if we fall into here, we have just a partial number of input samples left + // (less input less than what we've been asked to produce output for. + *outOLCompleted = true; + // we require post processing if we've got some tail (or latency) samples to flush through + *outOLRequiresPostProcess = mTailSamplesToProcess > 0; + if (InputSampleCount() > mRenderTimeStamp.mSampleTime) { + ioNumFrames = (UInt32)(InputSampleCount() - mRenderTimeStamp.mSampleTime); + } else { + ioNumFrames = 0; + } + mTailSamplesRemaining = mTailSamplesToProcess; + // we've got no input samples to process this time. + SetBufferListToNumFrames (*ioData, ioNumFrames); + if (ioNumFrames == 0) { + if (*outOLRequiresPostProcess) + SetInputCallback (mUnit, sSilentCallback); + else + mUnit.GlobalReset (); //flush this out, as we're done with this phase + return noErr; + } + } + } + AudioUnitRenderActionFlags renderFlags = IsOfflineAU() ? kAudioOfflineUnitRenderAction_Render : 0; + OSStatus result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, ioNumFrames, ioData); + if (result) { printf("E result %d\n", (int)result); } + if (result) { + if (mUnit.Comp().Desc().IsFConv()) { + // this is the only way we can tell we're done with a FormatConverter AU + // - ie. client returns an error from input + result = noErr; + *outOLCompleted = true; + *outOLRequiresPostProcess = mTailSamplesToProcess > 0; + ioNumFrames = 0; + SetBufferListToNumFrames (*ioData, ioNumFrames); + } else + return result; + } +// for (UInt32 i = 0; i < ioNumFrames; ++i) { +// union { +// float f; +// unsigned char c[4]; +// } u; +// u.f = ((float*)(ioData->mBuffers[0].mData))[i]; +// printf("aup out %4d %14.10f %02X %02X %02X %02X\n", (int)i, u.f, u.c[0], u.c[1], u.c[2], u.c[3]); +// } + mRenderTimeStamp.mSampleTime += ioNumFrames; + outIsSilence = (renderFlags & kAudioUnitRenderAction_OutputIsSilence); + + // if we're an Offline AU type, it will set this flag on completion of its processing + if (renderFlags & kAudioOfflineUnitRenderAction_Complete) { + // we now need to calculate how many frames we rendered. + // as we're dealing with PCM non-interleaved buffers, we can calculate the numFrames simply + ioNumFrames = ioData->mBuffers[0].mDataByteSize / sizeof(Float32); + *outOLCompleted = true; + *outOLRequiresPostProcess = false; + mUnit.GlobalReset (); //flush this out, as we're done with this phase + } else { + if (*outOLCompleted) { + if (*outOLRequiresPostProcess) + result = SetInputCallback (mUnit, sSilentCallback); + else + mUnit.GlobalReset (); //flush this out, as we're done with this phase + } + } + + return result; + } + +// rendering in a RT context: + AudioUnitRenderActionFlags renderFlags = 0; + OSStatus result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, ioNumFrames, ioData); + if (result) { printf("F result %d\n", (int)result); } + if (!result) { + mRenderTimeStamp.mSampleTime += ioNumFrames; + outIsSilence = (renderFlags & kAudioUnitRenderAction_OutputIsSilence); + } +// for (UInt32 i = 0; i < ioNumFrames; ++i) { +// union { +// float f; +// unsigned char c[4]; +// } u; +// u.f = ((float*)(ioData->mBuffers[0].mData))[i]; +// printf("aup out %4d %14.10f %02X %02X %02X %02X\n", (int)i, u.f, u.c[0], u.c[1], u.c[2], u.c[3]); +// } + + return result; +} + +OSStatus CAAUProcessor::PostProcess (AudioBufferList *ioData, + UInt32 &ioNumFrames, + bool &outIsSilence, + bool &outDone) +{ + if (IsOfflineAU() || !IsOfflineContext()) + return kAudioUnitErr_CannotDoInCurrentContext; + + outDone = false; + + // we've got less samples to process than we've been asked to process + if (mTailSamplesRemaining <= SInt32(ioNumFrames)) { + outDone = true; + ioNumFrames = mTailSamplesRemaining > 0 ? mTailSamplesRemaining : 0; + SetBufferListToNumFrames (*ioData, ioNumFrames); + if (ioNumFrames == 0) + return noErr; + } + + AudioUnitRenderActionFlags renderFlags = 0; + OSStatus result; + result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, ioNumFrames, ioData); + if (result) { printf("G result %d\n", (int)result); goto home; } + mRenderTimeStamp.mSampleTime += ioNumFrames; + mTailSamplesRemaining -= ioNumFrames; + outIsSilence = (renderFlags & kAudioUnitRenderAction_OutputIsSilence); + + if (outDone) { + ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home); + mUnit.GlobalReset (); //flush this out, as we're done with this phase + } +home: + return result; +} + +#if !TARGET_OS_IPHONE +Float32 CAAUProcessor::GetOLPercentComplete () +{ + if (!IsOfflineContext()) + return 0; + + Float32 percentDone = mLastPercentReported; + + if (IsOfflineAU()) + { + // we get the output size every time, as this can change as parameters are changed + UInt64 numOutputSamples = mNumInputSamples; + UInt32 propSize = sizeof(numOutputSamples); + mUnit.GetProperty (kAudioUnitOfflineProperty_OutputSize, + kAudioUnitScope_Global, 0, &numOutputSamples, &propSize); + + percentDone = (mRenderTimeStamp.mSampleTime / Float64(numOutputSamples)) * 100.; + } + else + { + percentDone = (mRenderTimeStamp.mSampleTime / Float64(mNumInputSamples + mTailSamples)) * 100.; + } + + if (percentDone > mLastPercentReported) + mLastPercentReported = percentDone; + + return mLastPercentReported; +} +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h new file mode 100644 index 0000000000..f0fb34574d --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h @@ -0,0 +1,293 @@ +/* + File: CAAUProcessor.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAAUProcessor_h__ +#define __CAAUProcessor_h__ + +#include <AudioToolbox/AudioToolbox.h> +#include "CAStreamBasicDescription.h" +#include "CAAudioUnit.h" +#include "AUOutputBL.h" + +#if TARGET_OS_IPHONE + #include <AssertMacros.h> +#endif +/* + This class wraps an AU (using the CAAudioUnit helper class) to use that AU for processing data + It can be used in a RealTime context (rendering data with RT constraints) or in an OffLine context + such as using an AU to process data that is stored in a file, and on which there are no + RT constraints to be imposed. + + Order of operations: + Create an instance + Establish an Input Callback + Initialize the AU to the audio formats and whether it is going to process in an offline or RT context + Preflight + + while (...) + Render // based on your calling context + + PostProcess if needed (only in OL case) + + After any initialization, preflighting is required. + + Parameter Values on the AU should be set just before each call to Render. The sampleFrameOffsets + supplied when setting those values are an offset into that next render buffer's numFrames. + + RT vs OT is determined by whether the inputSampleCount is set during Initialization, thus + this class can move the AU between RT and OL contexts. If you are using an AU of type 'auol' + (Offline), then it cannot be used in a RT context. + + The CAAUProcessor will only call your Input Callback for input when it needs valid input. + This input callback will contain a sample time that indicates where within your input + you should read data from, where after preflighting, the first output data produces is for + the output sample count of zero. + + MaxFrames should be set before initialisation (or is also passed in to the Reinitialize API) + + If RT, then PostProcessing will *never* be required, nor will Render ever return an isDone value + If OL, then Render will at some point return isDone==true, and then also indicate if PostProcessing is required + + If using a Format Converter AU in offline context, then the only way for it to determine that you've finished + is for the Input callback to return an error. This means ultimately, that you'll have potentially longer output + than you should have. The only way to manage this is for the caller to know the relationship between + input to output samples that will be required, and to call Render for just that amount of output samples + then return an error, so the tail and latency can be processed. + + Tail and Latency are *only* calculated at initialisation.. Some AU's may change these properties based on + either different presets or parameter settings... Ideally, this class should listen to those properties + and recalculate its values based on those changes. +*/ + +class CAAUProcessor { +public: + // by default this is set to process offline + CAAUProcessor (const CAComponent& inComp); + ~CAAUProcessor (); + + CAAudioUnit& AU() { return mUnit; } + const CAAudioUnit& AU() const { return mUnit; } + +#pragma mark __Setup APIs + bool IsOfflineContext () const { return mNumInputSamples != 0; } + + // this contains the callback and client data that the AU + // uses to call when it needs input + OSStatus EstablishInputCallback (AURenderCallbackStruct &inInputCallback); + + OSStatus SetAUPreset (CFPropertyListRef inPreset); + OSStatus SetAUPresetIndex (SInt32 inPresetIndex); + + OSStatus SetParameter (AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 value, UInt32 bufferOffsetFrames = 0); + + // a result of zero here signifies an error + UInt32 MaxFramesPerRender () const; + + // this call can return an error if the AU is initialized - see Reinitialize + OSStatus SetMaxFramesPerRender (UInt32 inMaxFrames); + + // Prepares the AU for processing at the specified format + // only doing n-n channel processing here.. could extend this for n-m channel processing easily enough + // if you are processing using an Offline AU, you HAVE to specify the numInputSamples to process + // if you are processing real-time, then inNumInputSamples should be zero + OSStatus Initialize (const CAStreamBasicDescription &inIODesc, UInt64 inNumInputSamples = 0) + { + return Initialize (inIODesc, inIODesc, inNumInputSamples); + } + OSStatus Initialize (const CAStreamBasicDescription &inInputDesc, + const CAStreamBasicDescription &inOutputDesc, + UInt64 inNumInputSamples = 0); + + // takes the existing format state of the AU, but resets the AUProcessor so that: + // applies an optional new number of max frames + // the AUProcessor will have to be Preflighted again after this call + // Use this when you want to keep the same formats, same input sample count, + // but want to re-initialize the AU to use a new num max frames and prepare it + // appropriately... + OSStatus Reinitialize (UInt32 inNewMaxFrames); + + + +#pragma mark __Render APIs + // Preflighting - you HAVE to preflight + // returns noErr when preflighting is done + + // Offline Context: + // Offline AU's require preflighting, even if they will end up doing no work. + // In the case where the AU is offline the latency samples are trimmed and not returned + // from the consequent Render calls + + // If you are NOT an offline AU then the first time Render is called, + // there will need to be some consumption of the input before you will get any valid output data. + // This is determined by the value of the AU's reported latency. So, in this case preflight + // will consume those initial samples and then return. + // Your InputCallback MUST provide the initial data that is to be processed. + + // RealTime Context: + // (1 No priming. In this case inProcessPreceedingTail is false (the default) and no + // processing is done on the AU. However, because preflight is the first time that Rendering + // is called on an AU we can presume that this is outside the context of the processing that + // is occuring in the host application. To avoid taking page faults, priming cold memory, etc. + // when the AU *is* consequently used to render real data, the AU is prerolled and reset if this is the case. + + // (2) Prime the AU's buffers with input data that preceeds the portion of audio you + // want to process. This amount of input data is equivalent to the tail time of the AU + // which expresses how long it takes for an sample on input to disappear from the output + // (Think of a delay or a reverb) + // So, by setting inProcessPreceedingTail to true, the preflight call will consume + // the tail time samples of input (which should be valid input BEFORE the data to be processed) + // So, your input proc here will HAVE to read samples from the preceeding input. The time + // stamps to your input proc in this case can be interpreted as 0 is the start of the preceeding data + // and you'll need to read up to the numSamples of tail time of the preceeding data. + // It discards the output results of the preflighting. If you don't have any previous data + // with which to prepare the AU, then you do NOT need to take this path and can do the step below. + + // In both of these cases the inital latency frames are *not* trimmed from + // the output that will be generated by a consequent call to render. + OSStatus Preflight (bool inProcessPreceedingTail = false); + + // this can be used with an OfflineAU to do a gradual preflight (so you could for instance, + // present a progress indicator. The Preflight call will do it all at once. + // If you break out of the preflight before you are done, then you HAVE to reinitialise the AU + // before you can either do another preflight or do a render, otherwise the Render call will produce + // invalid results. + OSStatus OfflineAUPreflight (UInt32 inNumFrames, bool &outIsDone); + + // Here's the major stage that produces output. + // You pass in two bool flags and an ioNumFrames.... + + // So ioNumFrames will be *untouched* if outOLCompleted == false + // if outOLCompleted is true, ioNumFrames contains the number of valid frames within the ioData data that are valid data + // (ioData's pointers and sizes will also have been resized to match these number of frames) + // outOLRequiresPostProcess should also be checked when outOLCompleted is true, + // to see if any post-processing is required + // if rendering in a RT context, then neither outOLCompleted or outOLRequiresPostProcess is required + // if rendering in an OL context, both must be specified. + // Caller MUST provide an ABL that is set up in the previously specified output format + + // If you receive kAudioUnitErr_InvalidOfflineRender when dealing with an OfflineAU Type, then you have either not + // preflighted it (and the AU requires it) or you have changed some state (its num input samples, its start offest) + // and it needs to be re-preflighted. In that case, preflight the AU again first. + OSStatus Render (AudioBufferList *ioData, + UInt32 &ioNumFrames, + bool &outIsSilence, + bool *outOLCompleted = NULL, + bool *outOLRequiresPostProcess = NULL); + + // call this method if outOLRequiresPostProcess returned true upon rendering completion + OSStatus PostProcess (AudioBufferList *ioData, UInt32 &ioNumFrames, bool &outIsSilence, bool &outDone); + + // This method returns how many input samples will need to be provided before + // valid output data is produced. + UInt32 LatencySampleCount () const { return mLatencySamples; } + + UInt32 TailSampleCount () const { return mTailSamples; } + + UInt64 InputSampleCount () const { return mNumInputSamples; } + + // the class maintains the TimeStamp from render call to render call + // this value is the sample count that will be used in the *next* render call + Float64 SampleTime () const { return mRenderTimeStamp.mSampleTime; } + + // in some settings (for instance a delay with 100% feedback) tail time is essentially infinite + // so you should safeguard the final OL render stage (post process) which is aimed at pulling the tail through + // default is 10 seconds + Float64 GetMaxTailTime () const { return mMaxTailTime; } + + // this ONLY takes affect when you initialise the processor, it doesn't change that AU's tail time, + // but just the max amount of time that this object will allow the AU to post-process data + // set this to 0, to use the AU's tail time with no adjustment + void SetMaxTailTime (Float64 inTailTimeSecs) { mMaxTailTime = inTailTimeSecs; } + +#if !TARGET_OS_IPHONE + // if this is NULL, then there is no explicit (optional or required) preflight requirement of the AU + // if this is valid, then the AU either requires or optionally requires preflighting. The default + // behaviour in this case is that the processor will preflight. This name can be used to preset + // to the user. If the AU doesn't present a name, but preflighting is optional/required, then the + // processor return "Preflight" as its string. + // the String should be released by the caller. + CFStringRef GetOLPreflightName () const; + + // Returns true if this is processor is an offline AU, and that AU (whether optional or required) + // needs preflighting + bool OfflineAUNeedsPreflight () const; + + // this provides a rough approximation of the progress of an Offline Processing operation (both for the + // preflight and the render phases) + Float32 GetOLPercentComplete (); +#endif + +private: + CAAudioUnit mUnit; + UInt32 mLatencySamples; + UInt32 mTailSamples; + UInt32 mTailSamplesToProcess; + UInt64 mNumInputSamples; + AudioTimeStamp mRenderTimeStamp; + bool mPreflightDone; + AUOutputBL * mPreflightABL; + SInt32 mTailSamplesRemaining; + AURenderCallbackStruct mUserCallback; + Float64 mMaxTailTime; + Float32 mLastPercentReported; + + bool IsOfflineAU () const { return mUnit.Comp().Desc().IsOffline(); } + + void CalculateRemainderSamples (Float64 inSampleRate); + + OSStatus DoInitialisation (const CAStreamBasicDescription &inInputFormat, + const CAStreamBasicDescription &inOutputFormat, + UInt64 inNumInputSamples, + UInt32 inMaxFrames); + + // stop automatic copying of this object + CAAUProcessor () {} + CAAUProcessor (const CAAUProcessor &c) {} + CAAUProcessor& operator= (const CAAUProcessor& c) { return *this; } +}; + +#endif //__CAAUProcessor_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h b/libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h new file mode 100644 index 0000000000..c9a611bf7a --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h @@ -0,0 +1,305 @@ +/* + File: CAAtomic.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +/* + This file implements all Atomic operations using Interlocked functions specified in + Winbase.h +NOTE: According to Microsoft documentation, all Interlocked functions generates a +full barrier. + On Windows: + As the Interlocked functions returns the Old value, Extra checks and operations + are made after the atomic operation to return value consistent with OSX counterparts. +*/ +#ifndef __CAAtomic_h__ +#define __CAAtomic_h__ + +#if TARGET_OS_WIN32 + #include <windows.h> + #include <intrin.h> + #pragma intrinsic(_InterlockedOr)
+ #pragma intrinsic(_InterlockedAnd) +#else + #include <CoreFoundation/CFBase.h> + #include <libkern/OSAtomic.h> +#endif + +inline void CAMemoryBarrier() +{ +#if TARGET_OS_WIN32 + MemoryBarrier(); +#else + OSMemoryBarrier(); +#endif +} + +inline SInt32 CAAtomicAdd32Barrier(SInt32 theAmt, volatile SInt32* theValue) +{ +#if TARGET_OS_WIN32 + long lRetVal = InterlockedExchangeAdd((volatile long*)theValue, theAmt); + // InterlockedExchangeAdd returns the original value which differs from OSX version. + // At this point the addition would have occured and hence returning the new value + // to keep it sync with OSX. + return lRetVal + theAmt; +#else + return OSAtomicAdd32Barrier(theAmt, (volatile int32_t *)theValue); +#endif +} + +inline SInt32 CAAtomicOr32Barrier(UInt32 theMask, volatile UInt32* theValue) +{ +#if TARGET_OS_WIN32 + // InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic + // function instead. + long j = _InterlockedOr((volatile long*)theValue, theMask); + // _InterlockedOr returns the original value which differs from OSX version. + // Returning the new value similar to OSX + return (SInt32)(j | theMask); +#else + return OSAtomicOr32Barrier(theMask, (volatile uint32_t *)theValue); +#endif +} + +inline SInt32 CAAtomicAnd32Barrier(UInt32 theMask, volatile UInt32* theValue) +{ +#if TARGET_OS_WIN32 +// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic +// function instead. + long j = _InterlockedAnd((volatile long*)theValue, theMask); + // _InterlockedAnd returns the original value which differs from OSX version. + // Returning the new value similar to OSX + return (SInt32)(j & theMask); +#else + return OSAtomicAnd32Barrier(theMask, (volatile uint32_t *)theValue); +#endif +} + +inline bool CAAtomicCompareAndSwap32Barrier(SInt32 oldValue, SInt32 newValue, volatile SInt32 *theValue) +{ +#if TARGET_OS_WIN32 + // InterlockedCompareExchange returns the old value. But we need to return bool value. + long lRetVal = InterlockedCompareExchange((volatile long*)theValue, newValue, oldValue); +// Hence we check if the new value is set and if it is we return true else false. +// If theValue is equal to oldValue then the swap happens. Otherwise swap doesn't happen. + return (oldValue == lRetVal); +#else + return OSAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile int32_t *)theValue); +#endif +} + + +inline SInt32 CAAtomicIncrement32(volatile SInt32* theValue) +{ +#if TARGET_OS_WIN32 + return (SInt32)InterlockedIncrement((volatile long*)theValue); +#else + return OSAtomicIncrement32((volatile int32_t *)theValue); +#endif +} + +inline SInt32 CAAtomicDecrement32(volatile SInt32* theValue) +{ +#if TARGET_OS_WIN32 + return (SInt32)InterlockedDecrement((volatile long*)theValue); +#else + return OSAtomicDecrement32((volatile int32_t *)theValue); +#endif +} + +inline SInt32 CAAtomicIncrement32Barrier(volatile SInt32* theValue) +{ +#if TARGET_OS_WIN32 + return CAAtomicIncrement32(theValue); +#else + return OSAtomicIncrement32Barrier((volatile int32_t *)theValue); +#endif +} + +inline SInt32 CAAtomicDecrement32Barrier(volatile SInt32* theValue) +{ +#if TARGET_OS_WIN32 + return CAAtomicDecrement32(theValue); +#else + return OSAtomicDecrement32Barrier((volatile int32_t *)theValue); +#endif +} + +inline bool CAAtomicTestAndClearBarrier(int bitToClear, void* theAddress) +{ +#if TARGET_OS_WIN32 + BOOL bOldVal = InterlockedBitTestAndReset((long*)theAddress, bitToClear); + return (bOldVal ? true : false); +#else + return OSAtomicTestAndClearBarrier(bitToClear, (volatile void *)theAddress); +#endif +} + +inline bool CAAtomicTestAndClear(int bitToClear, void* theAddress) +{ +#if TARGET_OS_WIN32 + BOOL bOldVal = CAAtomicTestAndClearBarrier(bitToClear, (long*)theAddress); + return (bOldVal ? true : false); +#else + return OSAtomicTestAndClear(bitToClear, (volatile void *)theAddress); +#endif +} + +inline bool CAAtomicTestAndSetBarrier(int bitToSet, void* theAddress) +{ +#if TARGET_OS_WIN32 + BOOL bOldVal = InterlockedBitTestAndSet((long*)theAddress, bitToSet); + return (bOldVal ? true : false); +#else + return OSAtomicTestAndSetBarrier(bitToSet, (volatile void *)theAddress); +#endif +} + +// int32_t flavors -- for C++ only since we can't overload in C +// CFBase.h defines SInt32 as signed int which is similar to int32_t. If CFBase.h is included, then +// this will generate redefinition error. But on Mac, CFBase.h, still includes MacTypes.h where +// SInt32 is defined as signed long so this would work there. +// So in order to fix the redefinition errors, we define these functions only if MacTypes.h is included. +#if defined(__cplusplus) && defined(__MACTYPES__) && !__LP64__ +inline int32_t CAAtomicAdd32Barrier(int32_t theAmt, volatile int32_t* theValue) +{ + return CAAtomicAdd32Barrier(theAmt, (volatile SInt32 *)theValue); +} + +inline int32_t CAAtomicOr32Barrier(uint32_t theMask, volatile uint32_t* theValue) +{ + return CAAtomicOr32Barrier(theMask, (volatile UInt32 *)theValue); +} + +inline int32_t CAAtomicAnd32Barrier(uint32_t theMask, volatile uint32_t* theValue) +{ + return CAAtomicAnd32Barrier(theMask, (volatile UInt32 *)theValue); +} + +inline bool CAAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue, volatile int32_t *theValue) +{ + return CAAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile SInt32 *)theValue); +} + +inline int32_t CAAtomicIncrement32(volatile int32_t* theValue) +{ + return CAAtomicIncrement32((volatile SInt32 *)theValue); +} + +inline int32_t CAAtomicDecrement32(volatile int32_t* theValue) +{ + return CAAtomicDecrement32((volatile SInt32 *)theValue); +} + +inline int32_t CAAtomicIncrement32Barrier(volatile int32_t* theValue) +{ + return CAAtomicIncrement32Barrier((volatile SInt32 *)theValue); +} + +inline int32_t CAAtomicDecrement32Barrier(volatile int32_t* theValue) +{ + return CAAtomicDecrement32Barrier((volatile SInt32 *)theValue); +} +#endif // __cplusplus && !__LP64__ + +#if __LP64__ +inline bool CAAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue ) +{ + return OSAtomicCompareAndSwap64Barrier(__oldValue, __newValue, __theValue); +} +#endif + +inline bool CAAtomicCompareAndSwapPtrBarrier(void *__oldValue, void *__newValue, volatile void ** __theValue) +{ +#if __LP64__ + return CAAtomicCompareAndSwap64Barrier((int64_t)__oldValue, (int64_t)__newValue, (int64_t *)__theValue); +#else + return CAAtomicCompareAndSwap32Barrier((int32_t)__oldValue, (int32_t)__newValue, (int32_t *)__theValue); +#endif +} + +/* Spinlocks. These use memory barriers as required to synchronize access to shared + * memory protected by the lock. The lock operation spins, but employs various strategies + * to back off if the lock is held, making it immune to most priority-inversion livelocks. + * The try operation immediately returns false if the lock was held, true if it took the + * lock. The convention is that unlocked is zero, locked is nonzero. + */ +#define CA_SPINLOCK_INIT 0 + +typedef int32_t CASpinLock; + +bool CASpinLockTry( volatile CASpinLock *__lock ); +void CASpinLockLock( volatile CASpinLock *__lock ); +void CASpinLockUnlock( volatile CASpinLock *__lock ); + +inline void CASpinLockLock( volatile CASpinLock *__lock ) +{ +#if TARGET_OS_MAC + OSSpinLockLock(__lock); +#else + while (CAAtomicTestAndSetBarrier(0, (void*)__lock)) + usleep(1000); // ??? +#endif +} + +inline void CASpinLockUnlock( volatile CASpinLock *__lock ) +{ +#if TARGET_OS_MAC + OSSpinLockUnlock(__lock); +#else + CAAtomicTestAndClearBarrier(0, (void*)__lock); +#endif +} + +inline bool CASpinLockTry( volatile CASpinLock *__lock ) +{ +#if TARGET_OS_MAC + return OSSpinLockTry(__lock); +#else + return (CAAtomicTestAndSetBarrier(0, (void*)__lock) == 0); +#endif +} + + +#endif // __CAAtomic_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h b/libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h new file mode 100644 index 0000000000..8d40fc5d27 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h @@ -0,0 +1,239 @@ +/* + File: CAAtomicStack.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAAtomicStack_h__ +#define __CAAtomicStack_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <libkern/OSAtomic.h> +#else + #include <CAAtomic.h> +#endif + +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4 + #include <CoreServices/CoreServices.h> +#endif + +// linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically +// class T must implement T *& next(). +template <class T> +class TAtomicStack { +public: + TAtomicStack() : mHead(NULL) { } + + // non-atomic routines, for use when initializing/deinitializing, operate NON-atomically + void push_NA(T *item) + { + item->next() = mHead; + mHead = item; + } + + T * pop_NA() + { + T *result = mHead; + if (result) + mHead = result->next(); + return result; + } + + bool empty() const { return mHead == NULL; } + + T * head() { return mHead; } + + // atomic routines + void push_atomic(T *item) + { + T *head_; + do { + head_ = mHead; + item->next() = head_; + } while (!compare_and_swap(head_, item, &mHead)); + } + + void push_multiple_atomic(T *item) + // pushes entire linked list headed by item + { + T *head_, *p = item, *tail; + // find the last one -- when done, it will be linked to head + do { + tail = p; + p = p->next(); + } while (p); + do { + head_ = mHead; + tail->next() = head_; + } while (!compare_and_swap(head_, item, &mHead)); + } + + T * pop_atomic_single_reader() + // this may only be used when only one thread may potentially pop from the stack. + // if multiple threads may pop, this suffers from the ABA problem. + // <rdar://problem/4606346> TAtomicStack suffers from the ABA problem + { + T *result; + do { + if ((result = mHead) == NULL) + break; + } while (!compare_and_swap(result, result->next(), &mHead)); + return result; + } + + T * pop_atomic() + // This is inefficient for large linked lists. + // prefer pop_all() to a series of calls to pop_atomic. + // push_multiple_atomic has to traverse the entire list. + { + T *result = pop_all(); + if (result) { + T *next = result->next(); + if (next) + // push all the remaining items back onto the stack + push_multiple_atomic(next); + } + return result; + } + + T * pop_all() + { + T *result; + do { + if ((result = mHead) == NULL) + break; + } while (!compare_and_swap(result, NULL, &mHead)); + return result; + } + + T* pop_all_reversed() + { + TAtomicStack<T> reversed; + T *p = pop_all(), *next; + while (p != NULL) { + next = p->next(); + reversed.push_NA(p); + p = next; + } + return reversed.mHead; + } + + static bool compare_and_swap(T *oldvalue, T *newvalue, T **pvalue) + { +#if TARGET_OS_MAC + #if __LP64__ + return ::OSAtomicCompareAndSwap64Barrier(int64_t(oldvalue), int64_t(newvalue), (int64_t *)pvalue); + #elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + return ::OSAtomicCompareAndSwap32Barrier(int32_t(oldvalue), int32_t(newvalue), (int32_t *)pvalue); + #else + return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue); + #endif +#else + //return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue); + return CAAtomicCompareAndSwap32Barrier(SInt32(oldvalue), SInt32(newvalue), (SInt32*)pvalue); +#endif + } + +protected: + T * mHead; +}; + +#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) && !TARGET_OS_WIN32) +#include <libkern/OSAtomic.h> + +class CAAtomicStack { +public: + CAAtomicStack(size_t nextPtrOffset) : mNextPtrOffset(nextPtrOffset) { + /*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/ + mHead.opaque1 = 0; mHead.opaque2 = 0; + } + // a subset of the above + void push_atomic(void *p) { OSAtomicEnqueue(&mHead, p, mNextPtrOffset); } + void push_NA(void *p) { push_atomic(p); } + + void * pop_atomic() { return OSAtomicDequeue(&mHead, mNextPtrOffset); } + void * pop_atomic_single_reader() { return pop_atomic(); } + void * pop_NA() { return pop_atomic(); } + +private: + OSQueueHead mHead; + size_t mNextPtrOffset; +}; + +// a more efficient subset of TAtomicStack using OSQueue. +template <class T> +class TAtomicStack2 { +public: + TAtomicStack2() { + /*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/ + mHead.opaque1 = 0; mHead.opaque2 = 0; + mNextPtrOffset = -1; + } + void push_atomic(T *item) { + if (mNextPtrOffset < 0) { + T **pnext = &item->next(); // hack around offsetof not working with C++ + mNextPtrOffset = (Byte *)pnext - (Byte *)item; + } + OSAtomicEnqueue(&mHead, item, mNextPtrOffset); + } + void push_NA(T *item) { push_atomic(item); } + + T * pop_atomic() { return (T *)OSAtomicDequeue(&mHead, mNextPtrOffset); } + T * pop_atomic_single_reader() { return pop_atomic(); } + T * pop_NA() { return pop_atomic(); } + + // caution: do not try to implement pop_all_reversed here. the writer could add new elements + // while the reader is trying to pop old ones! + +private: + OSQueueHead mHead; + ssize_t mNextPtrOffset; +}; + +#else + +#define TAtomicStack2 TAtomicStack + +#endif // MAC_OS_X_VERSION_MAX_ALLOWED && !TARGET_OS_WIN32 + +#endif // __CAAtomicStack_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp new file mode 100644 index 0000000000..d3644ed2e4 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp @@ -0,0 +1,239 @@ +/* + File: CAAudioBufferList.cpp + Abstract: CAAudioBufferList.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CAAudioBufferList.h" +#include "CADebugMacros.h" +#include "CALogMacros.h" +#include <stdlib.h> +#include <string.h> + +//============================================================================= +// CAAudioBufferList +//============================================================================= + +AudioBufferList* CAAudioBufferList::Create(UInt32 inNumberBuffers) +{ + UInt32 theSize = CalculateByteSize(inNumberBuffers); + AudioBufferList* theAnswer = static_cast<AudioBufferList*>(calloc(1, theSize)); + if(theAnswer != NULL) + { + theAnswer->mNumberBuffers = inNumberBuffers; + } + return theAnswer; +} + +void CAAudioBufferList::Destroy(AudioBufferList* inBufferList) +{ + free(inBufferList); +} + +UInt32 CAAudioBufferList::CalculateByteSize(UInt32 inNumberBuffers) +{ + UInt32 theSize = SizeOf32(AudioBufferList) - SizeOf32(AudioBuffer); + theSize += inNumberBuffers * SizeOf32(AudioBuffer); + return theSize; +} + +UInt32 CAAudioBufferList::GetTotalNumberChannels(const AudioBufferList& inBufferList) +{ + UInt32 theAnswer = 0; + + for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex) + { + theAnswer += inBufferList.mBuffers[theIndex].mNumberChannels; + } + + return theAnswer; +} + +bool CAAudioBufferList::GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel) +{ + bool theAnswer = false; + UInt32 theIndex = 0; + + while((theIndex < inBufferList.mNumberBuffers) && (inChannel >= inBufferList.mBuffers[theIndex].mNumberChannels)) + { + inChannel -= inBufferList.mBuffers[theIndex].mNumberChannels; + ++theIndex; + } + + if(theIndex < inBufferList.mNumberBuffers) + { + outBufferNumber = theIndex; + outBufferChannel = inChannel; + theAnswer = true; + } + + return theAnswer; +} + +void CAAudioBufferList::Clear(AudioBufferList& outBufferList) +{ + // assumes that "0" is actually the 0 value for this stream format + for(UInt32 theBufferIndex = 0; theBufferIndex < outBufferList.mNumberBuffers; ++theBufferIndex) + { + if(outBufferList.mBuffers[theBufferIndex].mData != NULL) + { + memset(outBufferList.mBuffers[theBufferIndex].mData, 0, outBufferList.mBuffers[theBufferIndex].mDataByteSize); + } + } +} + +void CAAudioBufferList::Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel) +{ + // This is a brute force copy method that can handle ABL's that have different buffer layouts + // This means that this method is probably not the fastest way to do this for all cases. + // This method also assumes that both the source and destination sample formats are Float32 + + UInt32 theInputChannel = inStartingSourceChannel; + UInt32 theNumberInputChannels = GetTotalNumberChannels(inSource); + UInt32 theOutputChannel = inStartingDestinationChannel; + UInt32 theNumberOutputChannels = GetTotalNumberChannels(outDestination); + + UInt32 theInputBufferIndex = 0; + UInt32 theInputBufferChannel = 0; + UInt32 theOutputBufferIndex = 0; + UInt32 theOutputBufferChannel = 0; + while((theInputChannel < theNumberInputChannels) && (theOutputChannel < theNumberOutputChannels)) + { + GetBufferForChannel(inSource, theInputChannel, theInputBufferIndex, theInputBufferChannel); + + GetBufferForChannel(inSource, theOutputChannel, theOutputBufferIndex, theOutputBufferChannel); + + CopyChannel(inSource.mBuffers[theInputBufferIndex], theInputBufferChannel, outDestination.mBuffers[theOutputBufferIndex], theOutputBufferChannel); + + ++theInputChannel; + ++theOutputChannel; + } +} + +void CAAudioBufferList::CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel) +{ + // set up the stuff for the loop + UInt32 theNumberFramesToCopy = outDestination.mDataByteSize / (outDestination.mNumberChannels * SizeOf32(Float32)); + const Float32* theSource = static_cast<const Float32*>(inSource.mData); + Float32* theDestination = static_cast<Float32*>(outDestination.mData); + + // loop through the data and copy the samples + while(theNumberFramesToCopy > 0) + { + // copy the data + theDestination[inDestinationChannel] = theSource[inSourceChannel]; + + // adjust the pointers + --theNumberFramesToCopy; + theSource += inSource.mNumberChannels; + theDestination += outDestination.mNumberChannels; + } +} + +void CAAudioBufferList::Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList) +{ + // assumes that the buffers are Float32 samples and the listst have the same layout + // this is a lame algorithm, by the way. it could at least be unrolled a couple of times + for(UInt32 theBufferIndex = 0; theBufferIndex < ioSummedBufferList.mNumberBuffers; ++theBufferIndex) + { + Float32* theSourceBuffer = static_cast<Float32*>(inSourceBufferList.mBuffers[theBufferIndex].mData); + Float32* theSummedBuffer = static_cast<Float32*>(ioSummedBufferList.mBuffers[theBufferIndex].mData); + UInt32 theNumberSamplesToMix = ioSummedBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(Float32); + if((theSourceBuffer != NULL) && (theSummedBuffer != NULL) && (theNumberSamplesToMix > 0)) + { + while(theNumberSamplesToMix > 0) + { + *theSummedBuffer += *theSourceBuffer; + ++theSummedBuffer; + ++theSourceBuffer; + --theNumberSamplesToMix; + } + } + } +} + +bool CAAudioBufferList::HasData(AudioBufferList& inBufferList) +{ + bool hasData = false; + for(UInt32 theBufferIndex = 0; !hasData && (theBufferIndex < inBufferList.mNumberBuffers); ++theBufferIndex) + { + if(inBufferList.mBuffers[theBufferIndex].mData != NULL) + { + UInt32* theBuffer = (UInt32*)inBufferList.mBuffers[theBufferIndex].mData; + UInt32 theNumberSamples = inBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(UInt32); + for(UInt32 theSampleIndex = 0; !hasData && (theSampleIndex < theNumberSamples); ++theSampleIndex) + { + hasData = theBuffer[theSampleIndex] != 0; + } + } + } + return hasData; +} + +#if CoreAudio_Debug +void CAAudioBufferList::PrintToLog(const AudioBufferList& inBufferList) +{ + PrintInt(" Number streams: ", inBufferList.mNumberBuffers); + + for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex) + { + PrintIndexedInt(" Channels in stream", theIndex + 1, inBufferList.mBuffers[theIndex].mNumberChannels); + PrintIndexedInt(" Buffer size of stream", theIndex + 1, inBufferList.mBuffers[theIndex].mDataByteSize); + } +} +#endif + +const AudioBufferList* CAAudioBufferList::GetEmptyBufferList() +{ + static bool sInitializer = false; + static AudioBufferList sEmptyABL; + if(!sInitializer) + { + memset(&sEmptyABL, 0, sizeof(AudioBufferList)); + } + return &sEmptyABL; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h new file mode 100644 index 0000000000..70614f3eb6 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h @@ -0,0 +1,108 @@ +/* + File: CAAudioBufferList.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAAudioBufferList_h__) +#define __CAAudioBufferList_h__ + +//============================================================================= +// Includes +//============================================================================= + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif + +#include "CAException.h" +#include "CADebugMacros.h" + +//============================================================================= +// Types +//============================================================================= + +typedef AudioBufferList* AudioBufferListPtr; + +//============================================================================= +// CAAudioBufferList +//============================================================================= + +struct CAAudioBufferList +{ + +// Construction/Destruction +public: + static AudioBufferList* Create(UInt32 inNumberBuffers); + static void Destroy(AudioBufferList* inBufferList); + static UInt32 CalculateByteSize(UInt32 inNumberBuffers); + +// Operations +public: + static UInt32 GetTotalNumberChannels(const AudioBufferList& inBufferList); + static bool GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel); + static void Clear(AudioBufferList& outBufferList); + static void Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel); + static void CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel); + static void Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList); + static bool HasData(AudioBufferList& inBufferList); +#if CoreAudio_Debug + static void PrintToLog(const AudioBufferList& inBufferList); +#endif + + static const AudioBufferList* GetEmptyBufferList(); + +}; + +// Declare a variably-sized AudioBufferList on the stack +#define STACK_ABL(name, nbufs) \ + ThrowIf(nbufs < 1 || nbufs > 64, CAException(kAudio_ParamError), "STACK_ABL: invalid number of buffers") \ + const size_t name##_ByteSize = sizeof(AudioBufferList) + (nbufs - 1) * sizeof(AudioBuffer); \ + AudioBufferList &name = *(AudioBufferList *)alloca(name##_ByteSize); \ + name.mNumberBuffers = nbufs; + + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp new file mode 100644 index 0000000000..74753598db --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp @@ -0,0 +1,153 @@ +/* + File: CAAudioChannelLayout.cpp + Abstract: CAAudioChannelLayout.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +// Self Include +#include "CAAudioChannelLayout.h" +#include "CAAutoDisposer.h" +#include <stdlib.h> +#include <string.h> + +//============================================================================= +// CAAudioChannelLayout +//============================================================================= + +AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions) +{ + UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions); + AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(CA_calloc(1, theSize)); + if(theAnswer != NULL) + { + SetAllToUnknown(*theAnswer, inNumberChannelDescriptions); + } + return theAnswer; +} + +void CAAudioChannelLayout::Destroy(AudioChannelLayout* inChannelLayout) +{ + free(inChannelLayout); +} + +void CAAudioChannelLayout::SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions) +{ + outChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; + outChannelLayout.mChannelBitmap = 0; + outChannelLayout.mNumberChannelDescriptions = inNumberChannelDescriptions; + for(UInt32 theChannelIndex = 0; theChannelIndex < inNumberChannelDescriptions; ++theChannelIndex) + { + outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelLabel = kAudioChannelLabel_Unknown; + outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelFlags = 0; + outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[0] = 0; + outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[1] = 0; + outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[2] = 0; + } +} + +bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y) +{ + // compare based on the number of channel descriptions present + // (this may be too strict a comparison if all you care about are matching layout tags) + UInt32 theSize1 = CAAudioChannelLayout::CalculateByteSize(x.mNumberChannelDescriptions); + UInt32 theSize2 = CAAudioChannelLayout::CalculateByteSize(y.mNumberChannelDescriptions); + + if (theSize1 != theSize2) + return false; + + return !memcmp (&x, &y, theSize1); +} + +bool operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y) +{ + return !(x == y); +} + +// counting the one bits in a word +inline UInt32 CountOnes(UInt32 x) +{ + // secret magic algorithm for counting bits in a word. + UInt32 t; + x = x - ((x >> 1) & 0x55555555); + t = ((x >> 2) & 0x33333333); + x = (x & 0x33333333) + t; + x = (x + (x >> 4)) & 0x0F0F0F0F; + x = x + (x << 8); + x = x + (x << 16); + return x >> 24; +} + +UInt32 CAAudioChannelLayout::NumberChannels (const AudioChannelLayout& inLayout) +{ + if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) + return inLayout.mNumberChannelDescriptions; + + if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) + return CountOnes (inLayout.mChannelBitmap); + + return AudioChannelLayoutTag_GetNumberOfChannels(inLayout.mChannelLayoutTag); +} + +void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout) +{ + if (layout == NULL) + { + fprintf (file, "\tNULL layout\n"); + return; + } + fprintf (file, "\tTag=0x%X, ", (int)layout->mChannelLayoutTag); + if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) + fprintf (file, "Using Bitmap:0x%X\n", (int)layout->mChannelBitmap); + else { + fprintf (file, "Num Chan Descs=%d\n", (int)layout->mNumberChannelDescriptions); + const AudioChannelDescription *desc = layout->mChannelDescriptions; + for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; ++i, ++desc) { + fprintf (file, "\t\tLabel=%d, Flags=0x%X, ", (int)desc->mChannelLabel, (int)desc->mChannelFlags); + fprintf (file, "[az=%f,el=%f,dist=%f]\n", desc->mCoordinates[0], desc->mCoordinates[1], desc->mCoordinates[2]); + } + } +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h new file mode 100644 index 0000000000..4307054aee --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h @@ -0,0 +1,199 @@ +/* + File: CAAudioChannelLayout.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAAudioChannelLayout_h__) +#define __CAAudioChannelLayout_h__ + +//============================================================================= +// Includes +//============================================================================= + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> + #include <CoreFoundation/CoreFoundation.h> +#else + #include <CoreAudioTypes.h> + #include <CoreFoundation.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "CADebugMacros.h" +#include "CAAutoDisposer.h" + +#if !HAL_Build + #include "CAReferenceCounted.h" +#endif + +//============================================================================= +// CAAudioChannelLayout +//============================================================================= + +bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y); +bool operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y); + +extern "C" void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout); + +class CAAudioChannelLayout +{ +// static Construction/Destruction +public: + static AudioChannelLayout* Create(UInt32 inNumberChannelDescriptions); + static void Destroy(AudioChannelLayout* inChannelLayout); + static UInt32 CalculateByteSize(UInt32 inNumberChannelDescriptions) { + return SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription) + (inNumberChannelDescriptions * SizeOf32(AudioChannelDescription)); + } + static void SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions); + static UInt32 NumberChannels(const AudioChannelLayout& inLayout); + +#if !HAL_Build +// object methods +public: + CAAudioChannelLayout (); + + CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround); + // if inChooseSurround is false, then symmetrical speaker arrangements + // are chosen in place of surround layouts if there is a choice + // This call chooses layouts based on the expected defaults in + // AudioUnit usage + CAAudioChannelLayout (AudioChannelLayoutTag inTag); + CAAudioChannelLayout (const CAAudioChannelLayout &c); + CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout); + ~CAAudioChannelLayout(); + + CAAudioChannelLayout& operator= (const AudioChannelLayout* inChannelLayout); + CAAudioChannelLayout& operator= (const CAAudioChannelLayout& c); + bool operator== (const CAAudioChannelLayout &c) const; + bool operator!= (const CAAudioChannelLayout &c) const; + + void SetWithTag(AudioChannelLayoutTag inTag); + + bool IsValid() const { return NumberChannels() > 0; } + UInt32 Size() const { return mLayout ? mLayout->Size() : 0; } + + UInt32 NumberChannels() const { return mLayout ? mLayout->NumberChannels() : 0; } + + AudioChannelLayoutTag Tag() const { return Layout().mChannelLayoutTag; } + const AudioChannelLayout& Layout() const { return mLayout->Layout(); } + operator const AudioChannelLayout *() const { return &Layout(); } + + void Print () const { Print (stdout); } + void Print (FILE* file) const; + + OSStatus Save (CFPropertyListRef *outData) const; + OSStatus Restore (CFPropertyListRef &inData); + +private: + class RefCountedLayout : public CAReferenceCounted { + void * operator new(size_t /* size */, size_t aclSize) + { + return CA_malloc(sizeof(RefCountedLayout) - sizeof(AudioChannelLayout) + aclSize); + } + + void operator delete(void *mem) + { + free(mem); + } + + + RefCountedLayout(UInt32 inDataSize) : + mByteSize(inDataSize) + { + memset(&mACL, 0, inDataSize); + } + + public: + static RefCountedLayout *CreateWithNumberChannelDescriptions(unsigned nChannels) { + size_t size = CAAudioChannelLayout::CalculateByteSize(nChannels); + return new(size) RefCountedLayout((UInt32)size); + } + + static RefCountedLayout *CreateWithLayout(const AudioChannelLayout *layout) { + size_t size = CAAudioChannelLayout::CalculateByteSize(layout->mNumberChannelDescriptions); + RefCountedLayout *acl = new(size) RefCountedLayout((UInt32)size); + memcpy(&acl->mACL, layout, size); + return acl; + } + static RefCountedLayout *CreateWithLayoutTag(AudioChannelLayoutTag layoutTag) { + RefCountedLayout *acl = CreateWithNumberChannelDescriptions(0); + acl->mACL.mChannelLayoutTag = layoutTag; + return acl; + } + + const AudioChannelLayout & Layout() const { return mACL; } + + UInt32 Size () const { return mByteSize; } + + UInt32 NumberChannels() { return CAAudioChannelLayout::NumberChannels(Layout()); } + + private: + const UInt32 mByteSize; + AudioChannelLayout mACL; + // * * * mACL is variable length and thus must be last * * * + + // only the constructors can change the actual state of the layout + friend CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround); + friend OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData); + friend CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout); + friend void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag); + + AudioChannelLayout * GetLayout() { return &mACL; } + + private: + // prohibited methods: private and unimplemented. + RefCountedLayout(); + RefCountedLayout(const RefCountedLayout& c); + RefCountedLayout& operator=(const RefCountedLayout& c); + }; + + RefCountedLayout *mLayout; +#endif // HAL_Build + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp new file mode 100644 index 0000000000..009d4b3b5e --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp @@ -0,0 +1,210 @@ +/* + File: CAAudioChannelLayoutObject.cpp + Abstract: CAAudioChannelLayoutObject.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 "CAAudioChannelLayout.h" +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <AudioToolbox/AudioFormat.h> +#else + #include <AudioFormat.h> +#endif + +CAAudioChannelLayout::CAAudioChannelLayout () +{ + mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0); +} + +//============================================================================= +// CAAudioChannelLayout::CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround) +{ + // this chooses default layouts based on the number of channels... + AudioChannelLayoutTag tag; + + switch (inNumberChannels) + { + default: + // here we have a "broken" layout, in the sense that we haven't any idea how to lay this out + mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(inNumberChannels); + SetAllToUnknown(*mLayout->GetLayout(), inNumberChannels); + return; // don't fall into the tag case + case 1: + tag = kAudioChannelLayoutTag_Mono; + break; + case 2: + tag = inChooseSurround ? kAudioChannelLayoutTag_Binaural : kAudioChannelLayoutTag_Stereo; + break; + case 4: + tag = inChooseSurround ? kAudioChannelLayoutTag_Ambisonic_B_Format : kAudioChannelLayoutTag_AudioUnit_4; + break; + case 5: + tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_5_0 : kAudioChannelLayoutTag_AudioUnit_5; + break; + case 6: + tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_6_0 : kAudioChannelLayoutTag_AudioUnit_6; + break; + case 7: + tag = kAudioChannelLayoutTag_AudioUnit_7_0; + break; + case 8: + tag = kAudioChannelLayoutTag_AudioUnit_8; + break; + } + + mLayout = RefCountedLayout::CreateWithLayoutTag(tag); +} + +//============================================================================= +// CAAudioChannelLayout::CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout::CAAudioChannelLayout (AudioChannelLayoutTag inLayoutTag) + : mLayout(NULL) +{ + SetWithTag(inLayoutTag); +} + +//============================================================================= +// CAAudioChannelLayout::CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout::CAAudioChannelLayout (const CAAudioChannelLayout &c) + : mLayout(NULL) +{ + *this = c; +} + + +//============================================================================= +// CAAudioChannelLayout::AudioChannelLayout +//============================================================================= +CAAudioChannelLayout::CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout) + : mLayout(NULL) +{ + *this = inChannelLayout; +} + +//============================================================================= +// CAAudioChannelLayout::~CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout::~CAAudioChannelLayout () +{ + if (mLayout) { + mLayout->release(); + mLayout = NULL; + } +} + +//============================================================================= +// CAAudioChannelLayout::CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout& CAAudioChannelLayout::operator= (const CAAudioChannelLayout &c) +{ + if (mLayout != c.mLayout) { + if (mLayout) + mLayout->release(); + + if ((mLayout = c.mLayout) != NULL) + mLayout->retain(); + } + + return *this; +} + +CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout) +{ + if (mLayout && &mLayout->Layout() == inChannelLayout) + return *this; + + if (mLayout) + mLayout->release(); + + if (inChannelLayout == NULL) + { + mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0); + } + else + { + mLayout = RefCountedLayout::CreateWithLayout(inChannelLayout); + } + return *this; +} + +void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag) +{ + if (mLayout) + mLayout->release(); + + mLayout = RefCountedLayout::CreateWithLayoutTag(inTag); +} + +//============================================================================= +// CAAudioChannelLayout::operator== +//============================================================================= +bool CAAudioChannelLayout::operator== (const CAAudioChannelLayout &c) const +{ + if (mLayout == c.mLayout) + return true; + return Layout() == c.Layout(); +} + +//============================================================================= +// CAAudioChannelLayout::operator!= +//============================================================================= +bool CAAudioChannelLayout::operator!= (const CAAudioChannelLayout &c) const +{ + if (mLayout == c.mLayout) + return false; + + return !(Layout() == c.Layout()); +} + +//============================================================================= +// CAAudioChannelLayout::Print +//============================================================================= +void CAAudioChannelLayout::Print (FILE* file) const +{ + CAShowAudioChannelLayout (file, &Layout()); +} + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp new file mode 100644 index 0000000000..ce2efeae60 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp @@ -0,0 +1,424 @@ +/* + File: CAAudioFileFormats.cpp + Abstract: CAAudioFileFormats.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 "CAAudioFileFormats.h" +#include <algorithm> +#include <ctype.h> + +CAAudioFileFormats *CAAudioFileFormats::sInstance = NULL; + +CAAudioFileFormats *CAAudioFileFormats::Instance(bool loadDataFormats) +{ + if (sInstance == NULL) + sInstance = new CAAudioFileFormats(loadDataFormats); + return sInstance; +} + +/* +class CompareFileFormatNames { +public: + bool operator() (const CAAudioFileFormats::FileFormatInfo &a, const CAAudioFileFormats::FileFormatInfo &b) + { + return CFStringCompare(a.mFileTypeName, b.mFileTypeName, + kCFCompareCaseInsensitive | kCFCompareLocalized) == kCFCompareLessThan; + } +};*/ + +static int CompareFileFormatNames(const void *va, const void *vb) +{ + CAAudioFileFormats::FileFormatInfo *a = (CAAudioFileFormats::FileFormatInfo *)va, + *b = (CAAudioFileFormats::FileFormatInfo *)vb; + return CFStringCompare(a->mFileTypeName, b->mFileTypeName, + kCFCompareCaseInsensitive | kCFCompareLocalized); +} + +CAAudioFileFormats::CAAudioFileFormats(bool loadDataFormats) : + mNumFileFormats(0), mFileFormats(NULL) +{ + OSStatus err; + UInt32 size; + UInt32 *fileTypes = NULL; + + // get all file types + err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size); + if (err != noErr) goto bail; + mNumFileFormats = size / sizeof(UInt32); + mFileFormats = new FileFormatInfo[mNumFileFormats]; + fileTypes = new UInt32[mNumFileFormats]; + err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size, fileTypes); + if (err != noErr) goto bail; + + // get info for each file type + for (int i = 0; i < mNumFileFormats; ++i) { + FileFormatInfo *ffi = &mFileFormats[i]; + OSType filetype = fileTypes[i]; + + ffi->mFileTypeID = filetype; + + // file type name + ffi->mFileTypeName = NULL; + size = sizeof(CFStringRef); + err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_FileTypeName, sizeof(UInt32), &filetype, &size, &ffi->mFileTypeName); + if (err == noErr && ffi->mFileTypeName) + CFRetain(ffi->mFileTypeName); + + // file extensions + size = sizeof(CFArrayRef); + err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_ExtensionsForType, + sizeof(OSType), &filetype, &size, &ffi->mExtensions); + if (err) + ffi->mExtensions = NULL; + + // file data formats + ffi->mNumDataFormats = 0; + ffi->mDataFormats = NULL; + + if (loadDataFormats) + ffi->LoadDataFormats(); + } + + // sort file formats by name + qsort(mFileFormats, mNumFileFormats, sizeof(FileFormatInfo), CompareFileFormatNames); +bail: + delete[] fileTypes; +} + +void CAAudioFileFormats::FileFormatInfo::LoadDataFormats() +{ + if (mDataFormats != NULL) return; + + UInt32 *writableFormats = NULL, *readableFormats = NULL; + int nWritableFormats, nReadableFormats; + // get all writable formats + UInt32 size; + OSStatus err = AudioFormatGetPropertyInfo(kAudioFormatProperty_EncodeFormatIDs, 0, NULL, &size); + if (err != noErr) goto bail; + nWritableFormats = size / sizeof(UInt32); + writableFormats = new UInt32[nWritableFormats]; + err = AudioFormatGetProperty(kAudioFormatProperty_EncodeFormatIDs, 0, NULL, &size, writableFormats); + if (err != noErr) goto bail; + + // get all readable formats + err = AudioFormatGetPropertyInfo(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &size); + if (err != noErr) goto bail; + nReadableFormats = size / sizeof(UInt32); + readableFormats = new UInt32[nReadableFormats]; + err = AudioFormatGetProperty(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &size, readableFormats); + if (err != noErr) goto bail; + + err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_AvailableFormatIDs, sizeof(UInt32), &mFileTypeID, &size); + if (err == noErr) { + mNumDataFormats = size / sizeof(OSType); + OSType *formatIDs = new OSType[mNumDataFormats]; + err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AvailableFormatIDs, + sizeof(UInt32), &mFileTypeID, &size, formatIDs); + if (err == noErr) { + mDataFormats = new DataFormatInfo[mNumDataFormats]; + for (int j = 0; j < mNumDataFormats; ++j) { + int k; + bool anyBigEndian = false, anyLittleEndian = false; + DataFormatInfo *dfi = &mDataFormats[j]; + dfi->mFormatID = formatIDs[j]; + dfi->mReadable = (dfi->mFormatID == kAudioFormatLinearPCM); + dfi->mWritable = (dfi->mFormatID == kAudioFormatLinearPCM); + for (k = 0; k < nReadableFormats; ++k) + if (readableFormats[k] == dfi->mFormatID) { + dfi->mReadable = true; + break; + } + for (k = 0; k < nWritableFormats; ++k) + if (writableFormats[k] == dfi->mFormatID) { + dfi->mWritable = true; + break; + } + + dfi->mNumVariants = 0; + AudioFileTypeAndFormatID tf = { mFileTypeID, dfi->mFormatID }; + err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_AvailableStreamDescriptionsForFormat, + sizeof(AudioFileTypeAndFormatID), &tf, &size); + if (err == noErr) { + dfi->mNumVariants = size / sizeof(AudioStreamBasicDescription); + dfi->mVariants = new AudioStreamBasicDescription[dfi->mNumVariants]; + err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AvailableStreamDescriptionsForFormat, + sizeof(AudioFileTypeAndFormatID), &tf, &size, dfi->mVariants); + if (err) { + dfi->mNumVariants = 0; + delete[] dfi->mVariants; + dfi->mVariants = NULL; + } else { + for (k = 0; k < dfi->mNumVariants; ++k) { + AudioStreamBasicDescription *desc = &dfi->mVariants[k]; + if (desc->mBitsPerChannel > 8) { + if (desc->mFormatFlags & kAudioFormatFlagIsBigEndian) + anyBigEndian = true; + else + anyLittleEndian = true; + } + } + } + } + + dfi->mEitherEndianPCM = (anyBigEndian && anyLittleEndian); + } + } + delete[] formatIDs; + } +bail: + delete[] readableFormats; + delete[] writableFormats; +} + +// note that the outgoing format will have zero for the sample rate, channels per frame, bytesPerPacket, bytesPerFrame +bool CAAudioFileFormats::InferDataFormatFromFileFormat(AudioFileTypeID filetype, CAStreamBasicDescription &fmt) +{ + // if the file format only supports one data format + for (int i = 0; i < mNumFileFormats; ++i) { + FileFormatInfo *ffi = &mFileFormats[i]; + ffi->LoadDataFormats(); + if (ffi->mFileTypeID == filetype && ffi->mNumDataFormats > 0) { + DataFormatInfo *dfi = &ffi->mDataFormats[0]; + if (ffi->mNumDataFormats > 1) { + // file can contain multiple data formats. Take PCM if it's there. + for (int j = 0; j < ffi->mNumDataFormats; ++j) { + if (ffi->mDataFormats[j].mFormatID == kAudioFormatLinearPCM) { + dfi = &ffi->mDataFormats[j]; + break; + } + } + } + memset(&fmt, 0, sizeof(fmt)); + fmt.mFormatID = dfi->mFormatID; + if (dfi->mNumVariants > 0) { + // take the first variant as a default + fmt = dfi->mVariants[0]; + if (dfi->mNumVariants > 1 && dfi->mFormatID == kAudioFormatLinearPCM) { + // look for a 16-bit variant as a better default + for (int j = 0; j < dfi->mNumVariants; ++j) { + AudioStreamBasicDescription *desc = &dfi->mVariants[j]; + if (desc->mBitsPerChannel == 16) { + fmt = *desc; + break; + } + } + } + } + return true; + } + } + return false; +} + +bool CAAudioFileFormats::InferFileFormatFromFilename(CFStringRef filename, AudioFileTypeID &filetype) +{ + bool result = false; + CFRange range = CFStringFind(filename, CFSTR("."), kCFCompareBackwards); + if (range.location == kCFNotFound) return false; + range.location += 1; + range.length = CFStringGetLength(filename) - range.location; + CFStringRef ext = CFStringCreateWithSubstring(NULL, filename, range); + for (int i = 0; i < mNumFileFormats; ++i) { + FileFormatInfo *ffi = &mFileFormats[i]; + if (ffi->MatchExtension(ext)) { + filetype = ffi->mFileTypeID; + result = true; + break; + } + } + CFRelease(ext); + return result; +} + +bool CAAudioFileFormats::InferFileFormatFromFilename(const char *filename, AudioFileTypeID &filetype) +{ + if (filename == NULL) return false; + CFStringRef cfname = CFStringCreateWithCString(NULL, filename, kCFStringEncodingUTF8); + bool result = InferFileFormatFromFilename(cfname, filetype); + CFRelease(cfname); + return result; +} + +bool CAAudioFileFormats::InferFileFormatFromDataFormat(const CAStreamBasicDescription &fmt, + AudioFileTypeID &filetype) +{ + // if there's exactly one file format that supports this data format + FileFormatInfo *theFileFormat = NULL; + for (int i = 0; i < mNumFileFormats; ++i) { + FileFormatInfo *ffi = &mFileFormats[i]; + ffi->LoadDataFormats(); + DataFormatInfo *dfi = ffi->mDataFormats, *dfiend = dfi + ffi->mNumDataFormats; + for ( ; dfi < dfiend; ++dfi) + if (dfi->mFormatID == fmt.mFormatID) { + if (theFileFormat != NULL) + return false; // ambiguous + theFileFormat = ffi; // got a candidate + } + } + if (theFileFormat == NULL) + return false; + filetype = theFileFormat->mFileTypeID; + return true; +} + +bool CAAudioFileFormats::IsKnownDataFormat(OSType dataFormat) +{ + for (int i = 0; i < mNumFileFormats; ++i) { + FileFormatInfo *ffi = &mFileFormats[i]; + ffi->LoadDataFormats(); + DataFormatInfo *dfi = ffi->mDataFormats, *dfiend = dfi + ffi->mNumDataFormats; + for ( ; dfi < dfiend; ++dfi) + if (dfi->mFormatID == dataFormat) + return true; + } + return false; +} + +CAAudioFileFormats::FileFormatInfo * CAAudioFileFormats::FindFileFormat(UInt32 formatID) +{ + for (int i = 0; i < mNumFileFormats; ++i) { + FileFormatInfo *ffi = &mFileFormats[i]; + if (ffi->mFileTypeID == formatID) + return ffi; + } + return NULL; +} + +bool CAAudioFileFormats::FileFormatInfo::AnyWritableFormats() +{ + LoadDataFormats(); + DataFormatInfo *dfi = mDataFormats, *dfiend = dfi + mNumDataFormats; + for ( ; dfi < dfiend; ++dfi) + if (dfi->mWritable) + return true; + return false; +} + +char *OSTypeToStr(char *buf, size_t bufsize, OSType t) +{ + if (bufsize > 0) { + char *p = buf, *pend = buf + bufsize; + char str[4] = {0}, *q = str; + *(UInt32 *)str = CFSwapInt32HostToBig(t); + for (int i = 0; i < 4 && p < pend; ++i) { + if (isprint(*q) && *q != '\\') + *p++ = *q++; + else { + snprintf(p, pend - p, "\\x%02x", *q++); + p += 4; + } + } + if (p >= pend) p = pend - 1; + *p = '\0'; + } + return buf; +} + +int StrToOSType(const char *str, OSType &t) +{ + char buf[4]; + const char *p = str; + int x; + for (int i = 0; i < 4; ++i) { + if (*p != '\\') { + if ((buf[i] = *p++) == '\0') { + // special-case for 'aac ': if we only got three characters, assume the last was a space + if (i == 3) { + --p; + buf[i] = ' '; + break; + } + goto fail; + } + } else { + if (*++p != 'x') goto fail; + if (sscanf(++p, "%02X", &x) != 1) goto fail; + buf[i] = x; + p += 2; + } + } + t = CFSwapInt32BigToHost(*(UInt32 *)buf); + return static_cast<int>(p - str); +fail: + return 0; +} + +#if DEBUG + +void CAAudioFileFormats::DebugPrint() +{ + for (int i = 0; i < mNumFileFormats; ++i) + mFileFormats[i].DebugPrint(); +} + +void CAAudioFileFormats::FileFormatInfo::DebugPrint() +{ + char ftype[20]; + char ftypename[64]; + CFStringGetCString(mFileTypeName, ftypename, sizeof(ftypename), kCFStringEncodingUTF8); + printf("File type: '%s' = %s\n Extensions:", OSTypeToStr(ftype, sizeof(ftype), mFileTypeID), ftypename); + int i, n = NumberOfExtensions(); + for (i = 0; i < n; ++i) { + GetExtension(i, ftype, sizeof(ftype)); + printf(" .%s", ftype); + } + LoadDataFormats(); + printf("\n Formats:\n"); + for (i = 0; i < mNumDataFormats; ++i) + mDataFormats[i].DebugPrint(); +} + +void CAAudioFileFormats::DataFormatInfo::DebugPrint() +{ + char buf[20]; + static const char *ny[] = { "not ", "" }; + printf(" '%s': %sreadable %swritable\n", OSTypeToStr(buf, sizeof(buf), mFormatID), ny[mReadable], ny[mWritable]); + for (int i = 0; i < mNumVariants; ++i) { + CAStreamBasicDescription desc(mVariants[i]); + desc.PrintFormat(stdout, " ", ""); + //printf(" %d bytes/frame\n", desc.mBytesPerFrame); + } +} +#endif + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h new file mode 100644 index 0000000000..3d2f90f6de --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h @@ -0,0 +1,149 @@ +/* + File: CAAudioFileFormats.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAAudioFileFormats_h__ +#define __CAAudioFileFormats_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <AudioToolbox/AudioToolbox.h> +#else + #include <AudioToolbox.h> +#endif +#include "CAStreamBasicDescription.h" + +class CAAudioFileFormats { +public: + enum { noErr = 0 }; + + struct DataFormatInfo { + DataFormatInfo() : mVariants(NULL) { } + ~DataFormatInfo() { delete[] mVariants; } + + UInt32 mFormatID; + int mNumVariants; + AudioStreamBasicDescription * mVariants; + bool mReadable; + bool mWritable; + bool mEitherEndianPCM; + +#if DEBUG + void DebugPrint(); +#endif + }; + + struct FileFormatInfo { + FileFormatInfo() : mFileTypeName(NULL), mExtensions(NULL), mDataFormats(NULL) { } + ~FileFormatInfo() { + delete[] mDataFormats; + if (mFileTypeName) + CFRelease(mFileTypeName); + if (mExtensions) + CFRelease(mExtensions); + } + + AudioFileTypeID mFileTypeID; + CFStringRef mFileTypeName; + CFArrayRef mExtensions; + int mNumDataFormats; + DataFormatInfo * mDataFormats; // NULL until loaded! + + int NumberOfExtensions() { return static_cast<int>(mExtensions ? CFArrayGetCount(mExtensions) : 0); } + char * GetExtension(int index, char *buf, int buflen) { + CFStringRef cfext = (CFStringRef)CFArrayGetValueAtIndex(mExtensions, index); + CFStringGetCString(cfext, buf, buflen, kCFStringEncodingUTF8); + return buf; + } + bool MatchExtension(CFStringRef testExt) { // testExt should not include "." + CFIndex n = NumberOfExtensions(); + for (CFIndex i = 0; i < n; ++i) { + CFStringRef ext = (CFStringRef)CFArrayGetValueAtIndex(mExtensions, i); + if (CFStringCompare(ext, testExt, kCFCompareCaseInsensitive) == kCFCompareEqualTo) + return true; + } + return false; + } + bool AnyWritableFormats(); + void LoadDataFormats(); + +#if DEBUG + void DebugPrint(); +#endif + }; + +private: // use Instance() + CAAudioFileFormats(bool loadDataFormats); + ~CAAudioFileFormats(); +public: + + bool InferDataFormatFromFileFormat(AudioFileTypeID filetype, CAStreamBasicDescription &fmt); + + bool InferFileFormatFromFilename(const char *filename, AudioFileTypeID &filetype); + + bool InferFileFormatFromFilename(CFStringRef filename, AudioFileTypeID &filetype); + + bool InferFileFormatFromDataFormat(const CAStreamBasicDescription &fmt, AudioFileTypeID &filetype); + + bool IsKnownDataFormat(UInt32 dataFormat); + +#if DEBUG + void DebugPrint(); +#endif + + int mNumFileFormats; + FileFormatInfo * mFileFormats; + + FileFormatInfo * FindFileFormat(UInt32 formatID); + + static CAAudioFileFormats * Instance(bool loadDataFormats=true); + +private: + static CAAudioFileFormats * sInstance; +}; + +char * OSTypeToStr(char *buf, size_t bufsize, UInt32 t); +int StrToOSType(const char *str, UInt32 &t); + +#endif // __CAAudioFileFormats_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp new file mode 100644 index 0000000000..0200ec9b79 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp @@ -0,0 +1,135 @@ +/* + File: CAAudioTimeStamp.cpp + Abstract: CAAudioTimeStamp.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CAAudioTimeStamp.h" + +//============================================================================= +// CAAudioTimeStamp +//============================================================================= + +const AudioTimeStamp CAAudioTimeStamp::kZero = { 0.0, 0, 0.0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0 }; + +bool operator<(const AudioTimeStamp& x, const AudioTimeStamp& y) +{ + bool isLessThan = false; + bool isDone = false; + + // check the sample time + if(!isDone) + { + if((x.mFlags & kAudioTimeStampSampleTimeValid) && (y.mFlags & kAudioTimeStampSampleTimeValid)) + { + isLessThan = x.mSampleTime < y.mSampleTime; + isDone = true; + } + } + + // check the host time + if(!isDone) + { + if((x.mFlags & kAudioTimeStampHostTimeValid) && (y.mFlags & kAudioTimeStampHostTimeValid)) + { + isLessThan = x.mHostTime < y.mHostTime; + isDone = true; + } + } + + // check the word clock time + if(!isDone) + { + if((x.mFlags & kAudioTimeStampWordClockTimeValid) && (y.mFlags & kAudioTimeStampWordClockTimeValid)) + { + isLessThan = x.mWordClockTime < y.mWordClockTime; + // commented out to prevent this from being flagged as a dead store by the static analyzer + //isDone = true; + } + } + + return isLessThan; +} + +bool operator==(const AudioTimeStamp& x, const AudioTimeStamp& y) +{ + bool isEqual = false; + bool isDone = false; + + // check the sample time + if(!isDone) + { + if((x.mFlags & kAudioTimeStampSampleTimeValid) && (y.mFlags & kAudioTimeStampSampleTimeValid)) + { + isEqual = x.mSampleTime == y.mSampleTime; + isDone = true; + } + } + + // check the host time + if(!isDone) + { + if((x.mFlags & kAudioTimeStampHostTimeValid) && (y.mFlags & kAudioTimeStampHostTimeValid)) + { + isEqual = x.mHostTime == y.mHostTime; + isDone = true; + } + } + + // check the word clock time + if(!isDone) + { + if((x.mFlags & kAudioTimeStampWordClockTimeValid) && (y.mFlags & kAudioTimeStampWordClockTimeValid)) + { + isEqual = x.mWordClockTime == y.mWordClockTime; + // commented out to prevent this from being flagged as a dead store by the static analyzer + //isDone = true; + } + } + + return isEqual; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h new file mode 100644 index 0000000000..9b8d6abe41 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h @@ -0,0 +1,97 @@ +/* + File: CAAudioTimeStamp.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAAudioTimeStamp_h__) +#define __CAAudioTimeStamp_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif + +#include <string.h> + +//============================================================================= +// CAAudioTimeStamp +//============================================================================= + +struct CAAudioTimeStamp +: + public AudioTimeStamp +{ + +// Construction/Destruction +public: + CAAudioTimeStamp() { memset(this, 0, sizeof(AudioTimeStamp)); } + CAAudioTimeStamp(const AudioTimeStamp& v) { memcpy(this, &v, sizeof(AudioTimeStamp)); } + CAAudioTimeStamp(Float64 inSampleTime) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mFlags = kAudioTimeStampSampleTimeValid; } + CAAudioTimeStamp(UInt64 inHostTime) { memset(this, 0, sizeof(AudioTimeStamp)); mHostTime = inHostTime; mFlags = kAudioTimeStampHostTimeValid; } + CAAudioTimeStamp(Float64 inSampleTime, UInt64 inHostTime) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mHostTime = inHostTime; mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid; } + CAAudioTimeStamp(Float64 inSampleTime, UInt64 inHostTime, Float64 inRateScalar) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mHostTime = inHostTime; mRateScalar = inRateScalar; mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid | kAudioTimeStampRateScalarValid; } + +// Assignment +public: + CAAudioTimeStamp& operator=(const AudioTimeStamp& v) { memcpy(this, &v, sizeof(AudioTimeStamp)); return *this; } + +// Constants +public: + static const AudioTimeStamp kZero; + +}; + +bool operator<(const AudioTimeStamp& x, const AudioTimeStamp& y); +bool operator==(const AudioTimeStamp& x, const AudioTimeStamp& y); +inline bool operator!=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !(x == y); } +inline bool operator<=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return (x < y) || (x == y); } +inline bool operator>=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !(x < y); } +inline bool operator>(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !((x < y) || (x == y)); } + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp new file mode 100644 index 0000000000..53da5a1cc6 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp @@ -0,0 +1,1421 @@ +/* + File: CAAudioUnit.cpp + Abstract: CAAudioUnit.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 "CAAudioUnit.h" + +#if !TARGET_OS_IPHONE +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h> + #include <dlfcn.h> +#else + #include <Components.h> +#endif +#endif + +#include "CAXException.h" +#include "CAReferenceCounted.h" +#include "AUOutputBL.h" //this is for the Preroll only + +struct StackAUChannelInfo { + StackAUChannelInfo (UInt32 inSize) : mChanInfo ((AUChannelInfo*)malloc (inSize)) {} + ~StackAUChannelInfo() { free (mChanInfo); } + + AUChannelInfo* mChanInfo; +}; + +// is this symbol is not defined then we use the default setting which is that fast dispatch +// is supported on a desktop environment +#ifndef CA_AU_USE_FAST_DISPATCH + #define CA_AU_USE_FAST_DISPATCH !TARGET_OS_IPHONE +#endif + +#if CA_AU_USE_FAST_DISPATCH +static void *LoadGetComponentInstanceStorage (void *inst); +#endif + + +class CAAudioUnit::AUState : public CAReferenceCounted { +public: + AUState (AudioComponent inComp) + : mUnit(0), mNode (0) + { + OSStatus result = ::AudioComponentInstanceNew (inComp, &mUnit); + if (result) + throw result; + Init(); + } + + AUState (const AUNode &inNode, const AudioUnit& inUnit) + : mUnit (inUnit), mNode (inNode) + { + Init(); + } + + ~AUState(); + + AudioUnit mUnit; + AUNode mNode; + + OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 &outValue) const + { +#if CA_AU_USE_FAST_DISPATCH + if (mGetParamProc != NULL) { + return (mGetParamProc) (mConnInstanceStorage, inID, scope, element, &outValue); + } +#endif + return AudioUnitGetParameter(mUnit, inID, scope, element, &outValue); + } + + OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 value, UInt32 bufferOffsetFrames) + { +#if CA_AU_USE_FAST_DISPATCH + if (mSetParamProc != NULL) { + return (mSetParamProc) (mConnInstanceStorage, inID, scope, element, value, bufferOffsetFrames); + } +#endif + return AudioUnitSetParameter(mUnit, inID, scope, element, value, bufferOffsetFrames); + } + + OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags, + const AudioTimeStamp * inTimeStamp, + UInt32 inOutputBusNumber, + UInt32 inNumberFrames, + AudioBufferList * ioData) + { +#if CA_AU_USE_FAST_DISPATCH + if (mRenderProc != NULL) { + return (mRenderProc) (mConnInstanceStorage, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData); + } +#endif + return AudioUnitRender(mUnit, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData); + } + + OSStatus MIDIEvent (UInt32 inStatus, + UInt32 inData1, + UInt32 inData2, + UInt32 inOffsetSampleFrame) + { +#if !TARGET_OS_WIN32 +#if CA_AU_USE_FAST_DISPATCH + if (mMIDIEventProc != NULL) { + return (mMIDIEventProc) (mConnInstanceStorage, inStatus, inData1, inData2, inOffsetSampleFrame); + } +#endif + return MusicDeviceMIDIEvent (mUnit, inStatus, inData1, inData2, inOffsetSampleFrame); +#else // ON WINDOWS _ NO MIDI EVENT dispatch + return paramErr; +#endif + } + + OSStatus StartNote (MusicDeviceInstrumentID inInstrument, + MusicDeviceGroupID inGroupID, + NoteInstanceID * outNoteInstanceID, + UInt32 inOffsetSampleFrame, + const MusicDeviceNoteParams * inParams) + { +#if !TARGET_OS_WIN32 +#if CA_AU_USE_FAST_DISPATCH + if (mStartNoteProc != NULL) { + return (mStartNoteProc) (mConnInstanceStorage, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams); + } +#endif + return MusicDeviceStartNote (mUnit, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams); +#else + return paramErr; +#endif + } + OSStatus StopNote (MusicDeviceGroupID inGroupID, + NoteInstanceID inNoteInstanceID, + UInt32 inOffsetSampleFrame) + { +#if !TARGET_OS_WIN32 +#if CA_AU_USE_FAST_DISPATCH + if (mStopNoteProc != NULL) { + return (mStopNoteProc) (mConnInstanceStorage, inGroupID, inNoteInstanceID, inOffsetSampleFrame); + } +#endif + return MusicDeviceStopNote (mUnit, inGroupID, inNoteInstanceID, inOffsetSampleFrame); +#else + return paramErr; +#endif + } + +private: + // get the fast dispatch pointers + void Init() + { +#if CA_AU_USE_FAST_DISPATCH + UInt32 size = sizeof(AudioUnitRenderProc); + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kAudioUnitRenderSelect, + &mRenderProc, &size) != noErr) + mRenderProc = NULL; + + size = sizeof(AudioUnitGetParameterProc); + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kAudioUnitGetParameterSelect, + &mGetParamProc, &size) != noErr) + mGetParamProc = NULL; + + size = sizeof(AudioUnitSetParameterProc); + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kAudioUnitSetParameterSelect, + &mSetParamProc, &size) != noErr) + mSetParamProc = NULL; + + size = sizeof(MusicDeviceMIDIEventProc); + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kMusicDeviceMIDIEventSelect, + &mMIDIEventProc, &size) != noErr) + mMIDIEventProc = NULL; + + size = sizeof(MusicDeviceStartNoteProc); + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kMusicDeviceStartNoteSelect, + &mStartNoteProc, &size) != noErr) + mStartNoteProc = NULL; + + size = sizeof(MusicDeviceStopNoteProc); + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kMusicDeviceStopNoteSelect, + &mStopNoteProc, &size) != noErr) + mStopNoteProc = NULL; + + if (mRenderProc || mGetParamProc || mSetParamProc || mMIDIEventProc || mStartNoteProc || mStopNoteProc) { + mConnInstanceStorage = LoadGetComponentInstanceStorage ( mUnit ); + } else + mConnInstanceStorage = NULL; +#else + mConnInstanceStorage = NULL; +#endif + } + +#if CA_AU_USE_FAST_DISPATCH + AudioUnitRenderProc mRenderProc; + AudioUnitGetParameterProc mGetParamProc; + AudioUnitSetParameterProc mSetParamProc; + MusicDeviceMIDIEventProc mMIDIEventProc; + MusicDeviceStartNoteProc mStartNoteProc; + MusicDeviceStopNoteProc mStopNoteProc; +#endif + + void * mConnInstanceStorage; + +private: + // get the compiler to tell us when we do a bad thing!!! + AUState () {} + AUState (const AUState&); + AUState& operator= (const AUState&); +}; + + +CAAudioUnit::AUState::~AUState () +{ + if (mUnit && (mNode == 0)) { + ::AudioComponentInstanceDispose (mUnit); + } + mNode = 0; + mUnit = 0; +} + +OSStatus CAAudioUnit::Open (const CAComponent& inComp, CAAudioUnit &outUnit) +{ + try { + outUnit = inComp; + return noErr; + } catch (OSStatus res) { + return res; + } catch (...) { + return -1; + } +} + +CAAudioUnit::CAAudioUnit (const AudioUnit& inUnit) + : mComp (inUnit), mDataPtr (new AUState (kCAAU_DoNotKnowIfAUNode, inUnit)) +{ +} + +CAAudioUnit::CAAudioUnit (const CAComponent& inComp) + : mComp (inComp), mDataPtr (new AUState (mComp.Comp())) +{ +} + +CAAudioUnit::CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit) + : mComp (inUnit), mDataPtr(new AUState (inNode, inUnit)) +{ +} + +CAAudioUnit::~CAAudioUnit () +{ + Close(); +} + +void CAAudioUnit::Close() +{ + if (mDataPtr) { + mDataPtr->release(); + mDataPtr = NULL; + } +} + +CAAudioUnit& CAAudioUnit::operator= (const CAAudioUnit &a) +{ + if (mDataPtr != a.mDataPtr) { + if (mDataPtr) + mDataPtr->release(); + + if ((mDataPtr = a.mDataPtr) != NULL) + mDataPtr->retain(); + + mComp = a.mComp; + } + + return *this; +} + +bool CAAudioUnit::operator== (const CAAudioUnit& y) const +{ + if (mDataPtr == y.mDataPtr) return true; + AudioUnit au1 = mDataPtr ? mDataPtr->mUnit : 0; + AudioUnit au2 = y.mDataPtr ? y.mDataPtr->mUnit : 0; + return au1 == au2; +} + +bool CAAudioUnit::operator== (const AudioUnit& y) const +{ + if (!mDataPtr) return false; + return mDataPtr->mUnit == y; +} + +OSStatus CAAudioUnit::RemovePropertyListener (AudioUnitPropertyID inID, + AudioUnitPropertyListenerProc inProc, + void * inProcUserData) +{ + // we call this first. If it fails we call the old API as the failure can + // mean that the AU doesn't implement that selector. + OSStatus result = AudioUnitRemovePropertyListenerWithUserData(AU(), inID, + inProc, inProcUserData); + #if !__LP64__ && !TARGET_OS_IPHONE + if (result) result = AudioUnitRemovePropertyListener (AU(), inID, inProc); + #endif + return result; +} + +#pragma mark __State Management + +bool CAAudioUnit::IsValid () const +{ + return mDataPtr ? mDataPtr->mUnit != 0 : false; +} + +AudioUnit CAAudioUnit::AU() const +{ + return mDataPtr ? mDataPtr->mUnit : 0; +} + +AUNode CAAudioUnit::GetAUNode () const +{ + return mDataPtr ? mDataPtr->mNode : 0; +} + +#pragma mark __Format Handling + +bool CAAudioUnit::CanDo ( int inChannelsIn, + int inChannelsOut) const +{ + // this is the default assumption of an audio effect unit + Boolean* isWritable = 0; + UInt32 dataSize = 0; + // lets see if the unit has any channel restrictions + OSStatus result = AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + &dataSize, isWritable); //don't care if this is writable + + // if this property is NOT implemented an FX unit + // is expected to deal with same channel valance in and out + if (result) + { + if ((Comp().Desc().IsEffect() && inChannelsIn == inChannelsOut) + || (Comp().Desc().IsOffline() && inChannelsIn == inChannelsOut)) + { + return true; + } + else + { + // the au should either really tell us about this + // or we will assume the worst + return false; + } + } + + StackAUChannelInfo info (dataSize); + + result = GetProperty (kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + info.mChanInfo, &dataSize); + if (result) { return false; } + + return ValidateChannelPair (inChannelsIn, inChannelsOut, info.mChanInfo, (dataSize / sizeof (AUChannelInfo))); +} + +int CAAudioUnit::GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt) +{ + // this is the default assumption of an audio effect unit + Boolean* isWritable = 0; + UInt32 dataSize = 0; + // lets see if the unit has any channel restrictions + OSStatus result = AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + &dataSize, isWritable); //don't care if this is writable + + // if this property is NOT implemented an FX unit + // is expected to deal with same channel valance in and out + + if (result) + { + if (Comp().Desc().IsEffect()) + { + return 1; + } + else if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) { + // directly query Bus Formats + // Note that that these may refer to different subBusses + // (eg. Kick, Snare,.. on a Drummachine) + // eventually the Bus-Name for each configuration should be exposed + // for the User to select.. + + UInt32 elCountIn, elCountOut; + + if (GetElementCount (kAudioUnitScope_Input, elCountIn)) return -1; + if (GetElementCount (kAudioUnitScope_Output, elCountOut)) return -1; + + cnt = std::max(elCountIn, elCountOut); + + *chaninfo = (AUChannelInfo*) malloc (sizeof (AUChannelInfo) * cnt); + + for (unsigned int i = 0; i < elCountIn; ++i) { + UInt32 numChans; + if (NumberChannels (kAudioUnitScope_Input, i, numChans)) return -1; + (*chaninfo)[i].inChannels = numChans; + } + for (unsigned int i = elCountIn; i < cnt; ++i) { + (*chaninfo)[i].inChannels = 0; + } + + for (unsigned int i = 0; i < elCountOut; ++i) { + UInt32 numChans; + if (NumberChannels (kAudioUnitScope_Output, i, numChans)) return -1; + (*chaninfo)[i].outChannels = numChans; + } + for (unsigned int i = elCountOut; i < cnt; ++i) { + (*chaninfo)[i].outChannels = 0; + } + return 0; + } + else + { + // the au should either really tell us about this + // or we will assume the worst + return -1; + } + } + + *chaninfo = (AUChannelInfo*) malloc (dataSize); + cnt = dataSize / sizeof (AUChannelInfo); + + result = GetProperty (kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + *chaninfo, &dataSize); + + if (result) { return -1; } + return 0; +} + +bool CAAudioUnit::ValidateChannelPair (int inChannelsIn, + int inChannelsOut, + const AUChannelInfo * info, + UInt32 numChanInfo) const +{ +// we've the following cases (some combinations) to test here: +/* +>0 An explicit number of channels on either side +0 that side (generally input!) has no elements +-1 wild card: +-1,-1 any num channels as long as same channels on in and out +-1,-2 any num channels channels on in and out - special meaning +-2+ indicates total num channs AU can handle + - elements configurable to any num channels, + - element count in scope must be writable +*/ + + //now chan layout can contain -1 for either scope (ie. doesn't care) + for (unsigned int i = 0; i < numChanInfo; ++i) + { + //less than zero on both sides - check for special attributes + if ((info[i].inChannels < 0) && (info[i].outChannels < 0)) + { + // these are our wild card matches + if (info[i].inChannels == -1 && info[i].outChannels == -1) { + if (inChannelsIn && inChannelsOut) { + if (inChannelsOut == inChannelsIn) + return true; + } else + return true; // if one of these is zero, then a -1 means any + } + else if ((info[i].inChannels == -1 && info[i].outChannels == -2) + || (info[i].inChannels == -2 && info[i].outChannels == -1)) + { + return true; + } + // these are our total num channels matches + // element count MUST be writable + else { + bool outWrite = false; bool inWrite = false; + IsElementCountWritable (kAudioUnitScope_Output, outWrite); + IsElementCountWritable (kAudioUnitScope_Input, inWrite); + if (inWrite && outWrite) { + if ((inChannelsOut <= abs(info[i].outChannels)) + && (inChannelsIn <= abs(info[i].inChannels))) + { + return true; + } + } + } + } + + // special meaning on input, specific num on output + else if (info[i].inChannels < 0) { + if (info[i].outChannels == inChannelsOut) + { + // can do any in channels + if (info[i].inChannels == -1) { + return true; + } + // total chans on input + else { + bool inWrite = false; + IsElementCountWritable (kAudioUnitScope_Input, inWrite); + if (inWrite && (inChannelsIn <= abs(info[i].inChannels))) { + return true; + } + } + } + } + + // special meaning on output, specific num on input + else if (info[i].outChannels < 0) { + if (info[i].inChannels == inChannelsIn) + { + // can do any out channels + if (info[i].outChannels == -1) { + return true; + } + // total chans on output + else { + bool outWrite = false; + IsElementCountWritable (kAudioUnitScope_Output, outWrite); + if (outWrite && (inChannelsOut <= abs(info[i].outChannels))) { + return true; + } + } + } + } + + // both chans in struct >= 0 - thus has to explicitly match + else if ((info[i].inChannels == inChannelsIn) && (info[i].outChannels == inChannelsOut)) { + return true; + } + + // now check to see if a wild card on the args (inChannelsIn or inChannelsOut chans is zero) is found + // tells us to match just one side of the scopes + else if (inChannelsIn == 0) { + if (info[i].outChannels == inChannelsOut) { + return true; + } + } + else if (inChannelsOut == 0) { + if (info[i].inChannels == inChannelsIn) { + return true; + } + } + } + + return false; +} + +static +bool CheckDynCount (SInt32 inTotalChans, const CAAUChanHelper &inHelper) +{ + int totalChans = 0; + for (unsigned int i = 0; i < inHelper.mNumEls; ++i) + totalChans += inHelper.mChans[i]; + return (totalChans <= inTotalChans); +} + +bool CAAudioUnit::CheckOneSide (const CAAUChanHelper &inHelper, + bool checkOutput, + const AUChannelInfo *info, + UInt32 numInfo) const +{ + // now we can use the wildcard option (see above impl) to see if this matches + for (unsigned int el = 0; el < inHelper.mNumEls; ++el) { + bool testAlready = false; + for (unsigned int i = 0; i < el; ++i) { + if (inHelper.mChans[i] == inHelper.mChans[el]) { + testAlready = true; + break; + } + } + if (!testAlready) { + if (checkOutput) { + if (!ValidateChannelPair (0, inHelper.mChans[el], info, numInfo)) return false; + } else { + if (!ValidateChannelPair (inHelper.mChans[el], 0, info, numInfo)) return false; + } + } + } + return true; +} + +bool CAAudioUnit::CanDo (const CAAUChanHelper &inputs, + const CAAUChanHelper &outputs) const + +{ +// first check our state + // huh! + if (inputs.mNumEls == 0 && outputs.mNumEls == 0) return false; + + UInt32 elCount; + if (GetElementCount (kAudioUnitScope_Input, elCount)) { return false; } + if (elCount != inputs.mNumEls) return false; + + if (GetElementCount (kAudioUnitScope_Output, elCount)) { return false; } + if (elCount != outputs.mNumEls) return false; + +// (1) special cases (effects and sources (generators and instruments) only) + UInt32 dataSize = 0; + if (GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, &dataSize, NULL) != noErr) + { + if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline()) { + UInt32 numChan = outputs.mNumEls > 0 ? outputs.mChans[0] : inputs.mChans[0]; + for (unsigned int in = 0; in < inputs.mNumEls; ++in) + if (numChan != inputs.mChans[in]) return false; + for (unsigned int out = 0; out < outputs.mNumEls; ++out) + if (numChan != outputs.mChans[out]) return false; + return true; + } + + // in this case, all the channels have to match the current config + if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) { + for (unsigned int in = 0; in < inputs.mNumEls; ++in) { + UInt32 chan; + if (NumberChannels (kAudioUnitScope_Input, in, chan)) return false; + if (chan != UInt32(inputs.mChans[in])) return false; + } + for (unsigned int out = 0; out < outputs.mNumEls; ++out) { + UInt32 chan; + if (NumberChannels (kAudioUnitScope_Output, out, chan)) return false; + if (chan != UInt32(outputs.mChans[out])) return false; + } + return true; + } + + // if we get here we can't determine anything about channel capabilities + return false; + } + + StackAUChannelInfo info (dataSize); + + if (GetProperty (kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + info.mChanInfo, &dataSize) != noErr) + { + return false; + } + + int numInfo = dataSize / sizeof(AUChannelInfo); + +// (2) Test for dynamic capability (or no elements on that scope) + SInt32 dynInChans = 0; + if (ValidateDynamicScope (kAudioUnitScope_Input, dynInChans, info.mChanInfo, numInfo)) { + if (CheckDynCount (dynInChans, inputs) == false) return false; + } + + SInt32 dynOutChans = 0; + if (ValidateDynamicScope (kAudioUnitScope_Output, dynOutChans, info.mChanInfo, numInfo)) { + if (CheckDynCount (dynOutChans, outputs) == false) return false; + } + + if (dynOutChans && dynInChans) { return true; } + +// (3) Just need to test one side + if (dynInChans || (inputs.mNumEls == 0)) { + return CheckOneSide (outputs, true, info.mChanInfo, numInfo); + } + + if (dynOutChans || (outputs.mNumEls == 0)) { + return CheckOneSide (inputs, false, info.mChanInfo, numInfo); + } + +// (4) - not a dynamic AU, has ins and outs, and has channel constraints so we test every possible pairing + for (unsigned int in = 0; in < inputs.mNumEls; ++in) + { + bool testInAlready = false; + for (unsigned int i = 0; i < in; ++i) { + if (inputs.mChans[i] == inputs.mChans[in]) { + testInAlready = true; + break; + } + } + if (!testInAlready) { + for (unsigned int out = 0; out < outputs.mNumEls; ++out) { + // try to save a little bit and not test the same pairing multiple times... + bool testOutAlready = false; + for (unsigned int i = 0; i < out; ++i) { + if (outputs.mChans[i] == outputs.mChans[out]) { + testOutAlready = true; + break; + } + } + if (!testOutAlready) { + if (!ValidateChannelPair (inputs.mChans[in], outputs.mChans[out],info.mChanInfo, numInfo)) { + return false; + } + } + } + } + } + + return true; +} + +bool CAAudioUnit::SupportsNumChannels () const +{ + // this is the default assumption of an audio effect unit + Boolean* isWritable = 0; + UInt32 dataSize = 0; + // lets see if the unit has any channel restrictions + OSStatus result = AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + &dataSize, isWritable); //don't care if this is writable + + // if this property is NOT implemented an FX unit + // is expected to deal with same channel valance in and out + if (result) { + if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline()) + return true; + } + return result == noErr; +} + +OSStatus CAAudioUnit::GetChannelLayoutTags (AudioUnitScope inScope, + AudioUnitElement inEl, + ChannelTagVector &outChannelVector) const +{ + if (HasChannelLayouts (inScope, inEl) == false) return kAudioUnitErr_InvalidProperty; + + UInt32 dataSize; + OSStatus result = AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_SupportedChannelLayoutTags, + inScope, inEl, + &dataSize, NULL); + + if (result) return result; + + // OK lets get our channel layouts and see if the one we want is present + AudioChannelLayoutTag* info = (AudioChannelLayoutTag*)malloc (dataSize); + result = AudioUnitGetProperty (AU(), + kAudioUnitProperty_SupportedChannelLayoutTags, + inScope, inEl, + info, &dataSize); + if (result) goto home; + + outChannelVector.erase (outChannelVector.begin(), outChannelVector.end()); + for (unsigned int i = 0; i < (dataSize / sizeof (AudioChannelLayoutTag)); ++i) + outChannelVector.push_back (info[i]); + +home: + free (info); + return result; +} + +bool CAAudioUnit::HasChannelLayouts (AudioUnitScope inScope, + AudioUnitElement inEl) const +{ + OSStatus result = AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_SupportedChannelLayoutTags, + inScope, inEl, + NULL, NULL); + return !result; +} + +bool CAAudioUnit::HasChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl) const +{ + Boolean writable; + UInt32 size; + + return AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_AudioChannelLayout, + inScope, inEl, + &size, &writable) == noErr; +} + +OSStatus CAAudioUnit::GetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + CAAudioChannelLayout &outLayout) const +{ + UInt32 size; + OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_AudioChannelLayout, + inScope, inEl, &size, NULL); + if (result) return result; + + AudioChannelLayout *layout = (AudioChannelLayout*)malloc (size); + + ca_require_noerr (result = AudioUnitGetProperty (AU(), kAudioUnitProperty_AudioChannelLayout, + inScope, inEl, layout, &size), home); + + outLayout = CAAudioChannelLayout (layout); + +home: + free (layout); + return result; +} + +OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + const CAAudioChannelLayout &inLayout) +{ + OSStatus result = AudioUnitSetProperty (AU(), + kAudioUnitProperty_AudioChannelLayout, + inScope, inEl, + inLayout, inLayout.Size()); + return result; +} + +OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + const AudioChannelLayout &inLayout, + UInt32 inSize) +{ + OSStatus result = AudioUnitSetProperty (AU(), + kAudioUnitProperty_AudioChannelLayout, + inScope, inEl, + &inLayout, inSize); + return result; +} + +OSStatus CAAudioUnit::ClearChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl) +{ + return AudioUnitSetProperty (AU(), + kAudioUnitProperty_AudioChannelLayout, + inScope, inEl, NULL, 0); +} + +OSStatus CAAudioUnit::GetFormat (AudioUnitScope inScope, + AudioUnitElement inEl, + AudioStreamBasicDescription &outFormat) const +{ + UInt32 dataSize = sizeof (AudioStreamBasicDescription); + return AudioUnitGetProperty (AU(), kAudioUnitProperty_StreamFormat, + inScope, inEl, + &outFormat, &dataSize); +} + +OSStatus CAAudioUnit::SetFormat (AudioUnitScope inScope, + AudioUnitElement inEl, + const AudioStreamBasicDescription &inFormat) +{ + return AudioUnitSetProperty (AU(), kAudioUnitProperty_StreamFormat, + inScope, inEl, + const_cast<AudioStreamBasicDescription*>(&inFormat), + sizeof (AudioStreamBasicDescription)); +} + +OSStatus CAAudioUnit::GetSampleRate (AudioUnitScope inScope, + AudioUnitElement inEl, + Float64 &outRate) const +{ + UInt32 dataSize = sizeof (Float64); + return AudioUnitGetProperty (AU(), kAudioUnitProperty_SampleRate, + inScope, inEl, + &outRate, &dataSize); +} + +OSStatus CAAudioUnit::SetSampleRate (AudioUnitScope inScope, + AudioUnitElement inEl, + Float64 inRate) +{ + AudioStreamBasicDescription desc; + OSStatus result = GetFormat (inScope, inEl, desc); + if (result) return result; + desc.mSampleRate = inRate; + return SetFormat (inScope, inEl, desc); +} + +OSStatus CAAudioUnit::SetSampleRate (Float64 inSampleRate) +{ + OSStatus result; + + UInt32 elCount; + ca_require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home); + if (elCount) { + for (unsigned int i = 0; i < elCount; ++i) { + ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Input, i, inSampleRate), home); + } + } + + ca_require_noerr (result = GetElementCount(kAudioUnitScope_Output, elCount), home); + if (elCount) { + for (unsigned int i = 0; i < elCount; ++i) { + ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Output, i, inSampleRate), home); + } + } + +home: + return result; +} + +OSStatus CAAudioUnit::NumberChannels (AudioUnitScope inScope, + AudioUnitElement inEl, + UInt32 &outChans) const +{ + AudioStreamBasicDescription desc; + OSStatus result = GetFormat (inScope, inEl, desc); + if (!result) + outChans = desc.mChannelsPerFrame; + return result; +} + +OSStatus CAAudioUnit::SetNumberChannels (AudioUnitScope inScope, + AudioUnitElement inEl, + UInt32 inChans) +{ + // set this as the output of the AU + CAStreamBasicDescription desc; + OSStatus result = GetFormat (inScope, inEl, desc); + if (result) return result; + desc.ChangeNumberChannels (inChans, desc.IsInterleaved()); + result = SetFormat (inScope, inEl, desc); + return result; +} + +OSStatus CAAudioUnit::IsElementCountWritable (AudioUnitScope inScope, bool &outWritable) const +{ + Boolean isWritable; + UInt32 outDataSize; + OSStatus result = GetPropertyInfo (kAudioUnitProperty_ElementCount, inScope, 0, &outDataSize, &isWritable); + if (result) + return result; + outWritable = isWritable ? true : false; + return noErr; +} + +OSStatus CAAudioUnit::GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const +{ + UInt32 propSize = sizeof(outCount); + return GetProperty (kAudioUnitProperty_ElementCount, inScope, 0, &outCount, &propSize); +} + +OSStatus CAAudioUnit::SetElementCount (AudioUnitScope inScope, UInt32 inCount) +{ + return SetProperty (kAudioUnitProperty_ElementCount, inScope, 0, &inCount, sizeof(inCount)); +} + +bool CAAudioUnit::HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const +{ + // ok - now we need to check the AU's capability here. + // this is the default assumption of an audio effect unit + Boolean* isWritable = 0; + UInt32 dataSize = 0; + OSStatus result = GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + &dataSize, isWritable); //don't care if this is writable + + // AU has to explicitly tell us about this. + if (result) return false; + + StackAUChannelInfo info (dataSize); + + result = GetProperty (kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + info.mChanInfo, &dataSize); + if (result) return false; + + return ValidateDynamicScope (inScope, outTotalNumChannels, info.mChanInfo, (dataSize / sizeof(AUChannelInfo))); +} + +// as we've already checked that the element count is writable +// the following conditions will match this.. +/* +-1, -2 -> signifies no restrictions +-2, -1 -> signifies no restrictions -> in this case outTotalNumChannels == -1 (any num channels) + +-N (where N is less than -2), signifies the total channel count on the scope side (in or out) +*/ +bool CAAudioUnit::ValidateDynamicScope (AudioUnitScope inScope, + SInt32 &outTotalNumChannels, + const AUChannelInfo *info, + UInt32 numInfo) const +{ + bool writable = false; + OSStatus result = IsElementCountWritable (inScope, writable); + if (result || (writable == false)) + return false; + + //now chan layout can contain -1 for either scope (ie. doesn't care) + for (unsigned int i = 0; i < numInfo; ++i) + { + // lets test the special wild card case first... + // this says the AU can do any num channels on input or output - for eg. Matrix Mixer + if (((info[i].inChannels == -1) && (info[i].outChannels == -2)) + || ((info[i].inChannels == -2) && (info[i].outChannels == -1))) + { + outTotalNumChannels = -1; + return true; + } + + // ok lets now test our special case.... + if (inScope == kAudioUnitScope_Input) { + // isn't dynamic on this side at least + if (info[i].inChannels >= 0) + continue; + + if (info[i].inChannels < -2) { + outTotalNumChannels = abs (info[i].inChannels); + return true; + } + } + + else if (inScope == kAudioUnitScope_Output) { + // isn't dynamic on this side at least + if (info[i].outChannels >= 0) + continue; + + if (info[i].outChannels < -2) { + outTotalNumChannels = abs (info[i].outChannels); + return true; + } + } + + else { + break; // wrong scope was specified + } + } + + return false; +} + +OSStatus CAAudioUnit::ConfigureDynamicScope (AudioUnitScope inScope, + UInt32 inNumElements, + UInt32 *inChannelsPerElement, + Float64 inSampleRate) +{ + SInt32 numChannels = 0; + bool isDyamic = HasDynamicScope (inScope, numChannels); + if (isDyamic == false) + return kAudioUnitErr_InvalidProperty; + + //lets to a sanity check... + // if numChannels == -1, then it can do "any"... + if (numChannels > 0) { + SInt32 count = 0; + for (unsigned int i = 0; i < inNumElements; ++i) + count += inChannelsPerElement[i]; + if (count > numChannels) + return kAudioUnitErr_InvalidPropertyValue; + } + + OSStatus result = SetElementCount (inScope, inNumElements); + if (result) + return result; + + for (unsigned int i = 0; i < inNumElements; ++i) { + CAStreamBasicDescription desc; + result = GetFormat (inScope, i, desc); + if (result) return result; + desc.ChangeNumberChannels (inChannelsPerElement[i], desc.IsInterleaved()); + desc.mSampleRate = inSampleRate; + result = SetFormat (inScope, i, desc); + if (result) + return result; + } + return noErr; +} + +#pragma mark __Properties + +bool CAAudioUnit::CanBypass () const +{ + Boolean outWritable; + OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_BypassEffect, + kAudioUnitScope_Global, 0, + NULL, &outWritable); + return (!result && outWritable); +} + +bool CAAudioUnit::GetBypass () const +{ + UInt32 dataSize = sizeof (UInt32); + UInt32 outBypass; + OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_BypassEffect, + kAudioUnitScope_Global, 0, + &outBypass, &dataSize); + return (result ? false : outBypass); +} + +OSStatus CAAudioUnit::SetBypass (bool inBypass) const +{ + UInt32 bypass = inBypass ? 1 : 0; + return AudioUnitSetProperty (AU(), kAudioUnitProperty_BypassEffect, + kAudioUnitScope_Global, 0, + &bypass, sizeof (UInt32)); +} + +OSStatus CAAudioUnit::GetMaxFramesPerSlice (UInt32& outMaxFrames) const +{ + UInt32 dataSize = sizeof(outMaxFrames); + return AudioUnitGetProperty (AU(), kAudioUnitProperty_MaximumFramesPerSlice, + kAudioUnitScope_Global, 0, + &outMaxFrames, &dataSize); +} + +OSStatus CAAudioUnit::SetMaxFramesPerSlice (UInt32 inMaxFrames) +{ + return AudioUnitSetProperty (AU(), kAudioUnitProperty_MaximumFramesPerSlice, + kAudioUnitScope_Global, 0, + &inMaxFrames, sizeof (UInt32)); +} + +Float64 CAAudioUnit::Latency () const +{ + Float64 secs; + UInt32 size = sizeof(secs); + if (GetProperty (kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, &secs, &size)) + return 0; + return secs; +} + +OSStatus CAAudioUnit::GetAUPreset (CFPropertyListRef &outData) const +{ + UInt32 dataSize = sizeof(outData); + return AudioUnitGetProperty (AU(), kAudioUnitProperty_ClassInfo, + kAudioUnitScope_Global, 0, + &outData, &dataSize); +} + +OSStatus CAAudioUnit::SetAUPreset (CFPropertyListRef &inData) +{ + return AudioUnitSetProperty (AU(), kAudioUnitProperty_ClassInfo, + kAudioUnitScope_Global, 0, + &inData, sizeof (CFPropertyListRef)); +} + +#if !TARGET_OS_IPHONE +OSStatus CAAudioUnit::SetAUPresetFromDocument (CFPropertyListRef &inData) +{ + return AudioUnitSetProperty (AU(), kAudioUnitProperty_ClassInfoFromDocument, + kAudioUnitScope_Global, 0, + &inData, sizeof (CFPropertyListRef)); +} +#endif + +OSStatus CAAudioUnit::GetPresentPreset (AUPreset &outData) const +{ + UInt32 dataSize = sizeof(outData); + OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_PresentPreset, + kAudioUnitScope_Global, 0, + &outData, &dataSize); +#if !TARGET_OS_IPHONE +#ifndef __LP64__ + if (result == kAudioUnitErr_InvalidProperty) { + dataSize = sizeof(outData); + result = AudioUnitGetProperty (AU(), kAudioUnitProperty_CurrentPreset, + kAudioUnitScope_Global, 0, + &outData, &dataSize); + if (result == noErr) { + // we now retain the CFString in the preset so for the client of this API + // it is consistent (ie. the string should be released when done) + if (outData.presetName) + CFRetain (outData.presetName); + } + } +#endif +#endif + return result; +} + +OSStatus CAAudioUnit::SetPresentPreset (AUPreset &inData) +{ + OSStatus result = AudioUnitSetProperty (AU(), kAudioUnitProperty_PresentPreset, + kAudioUnitScope_Global, 0, + &inData, sizeof (AUPreset)); +#if !TARGET_OS_IPHONE +#ifndef __LP64__ + if (result == kAudioUnitErr_InvalidProperty) { + result = AudioUnitSetProperty (AU(), kAudioUnitProperty_CurrentPreset, + kAudioUnitScope_Global, 0, + &inData, sizeof (AUPreset)); + } +#endif +#endif + return result; +} + +bool CAAudioUnit::HasCustomView () const +{ +#if !TARGET_OS_IPHONE + UInt32 dataSize = 0; + OSStatus result = -4/*unimpErr*/; +#ifndef __LP64__ + result = GetPropertyInfo(kAudioUnitProperty_GetUIComponentList, + kAudioUnitScope_Global, 0, + &dataSize, NULL); +#endif + if (result || !dataSize) { + dataSize = 0; + result = GetPropertyInfo(kAudioUnitProperty_CocoaUI, + kAudioUnitScope_Global, 0, + &dataSize, NULL); + if (result || !dataSize) + return false; + } + return true; +#else + return false; +#endif + +} + +OSStatus CAAudioUnit::GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 &outValue) const +{ + return mDataPtr ? mDataPtr->GetParameter (inID, scope, element, outValue) : static_cast<OSStatus>(paramErr); +} + +OSStatus CAAudioUnit::SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 value, UInt32 bufferOffsetFrames) +{ + return mDataPtr ? mDataPtr->SetParameter (inID, scope, element, value, bufferOffsetFrames) : static_cast<OSStatus>(paramErr); +} + +OSStatus CAAudioUnit::MIDIEvent (UInt32 inStatus, + UInt32 inData1, + UInt32 inData2, + UInt32 inOffsetSampleFrame) +{ + return mDataPtr ? mDataPtr->MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame) : paramErr; +} + +OSStatus CAAudioUnit::StartNote (MusicDeviceInstrumentID inInstrument, + MusicDeviceGroupID inGroupID, + NoteInstanceID * outNoteInstanceID, + UInt32 inOffsetSampleFrame, + const MusicDeviceNoteParams * inParams) +{ + return mDataPtr ? mDataPtr->StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams) + : paramErr; +} + +OSStatus CAAudioUnit::StopNote (MusicDeviceGroupID inGroupID, + NoteInstanceID inNoteInstanceID, + UInt32 inOffsetSampleFrame) +{ + return mDataPtr ? mDataPtr->StopNote (inGroupID, inNoteInstanceID, inOffsetSampleFrame) : paramErr; +} + + +#pragma mark __Render + +OSStatus CAAudioUnit::Render (AudioUnitRenderActionFlags * ioActionFlags, + const AudioTimeStamp * inTimeStamp, + UInt32 inOutputBusNumber, + UInt32 inNumberFrames, + AudioBufferList * ioData) +{ + return mDataPtr ? mDataPtr->Render (ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData) : static_cast<OSStatus>(paramErr); +} + +extern "C" OSStatus +AudioUnitProcess ( AudioUnit inUnit, + AudioUnitRenderActionFlags * ioActionFlags, + const AudioTimeStamp * inTimeStamp, + UInt32 inNumberFrames, + AudioBufferList * ioData); + +OSStatus CAAudioUnit::Process (AudioUnitRenderActionFlags & ioActionFlags, + const AudioTimeStamp & inTimeStamp, + UInt32 inNumberFrames, + AudioBufferList & ioData) +{ +#if defined(__MAC_10_7) || defined(__IPHONE_4_0) + return AudioUnitProcess (AU(), &ioActionFlags, &inTimeStamp, inNumberFrames, &ioData); +#else + return -4/*unimpErr*/; +#endif +} + +extern "C" OSStatus +AudioUnitProcessMultiple ( AudioUnit inUnit, + AudioUnitRenderActionFlags * ioActionFlags, + const AudioTimeStamp * inTimeStamp, + UInt32 inNumberFrames, + UInt32 inNumberInputBufferLists, + const AudioBufferList ** inInputBufferLists, + UInt32 inNumberOutputBufferLists, + AudioBufferList ** ioOutputBufferLists); + +OSStatus CAAudioUnit::ProcessMultiple (AudioUnitRenderActionFlags & ioActionFlags, + const AudioTimeStamp & inTimeStamp, + UInt32 inNumberFrames, + UInt32 inNumberInputBufferLists, + const AudioBufferList ** inInputBufferLists, + UInt32 inNumberOutputBufferLists, + AudioBufferList ** ioOutputBufferLists) +{ +#if defined(__MAC_10_7) || defined(__IPHONE_4_0) + return AudioUnitProcessMultiple (AU(), &ioActionFlags, &inTimeStamp, inNumberFrames, + inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists); +#else + return -4/*unimpErr*/; +#endif +} + +#pragma mark __CAAUChanHelper + +CAAUChanHelper::CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope) + :mChans(NULL), mNumEls(0), mDidAllocate(false) +{ + UInt32 elCount; + if (inAU.GetElementCount (inScope, elCount)) return; + if (elCount > kStaticElCount) { + mChans = new UInt32[elCount]; + mDidAllocate = true; + memset (mChans, 0, sizeof(int) * elCount); + } else { + mChans = mStaticChans; + memset (mChans, 0, sizeof(int) * kStaticElCount); + } + for (unsigned int i = 0; i < elCount; ++i) { + UInt32 numChans; + if (inAU.NumberChannels (inScope, i, numChans)) return; + mChans[i] = numChans; + } + mNumEls = elCount; +} + +CAAUChanHelper::CAAUChanHelper(UInt32 inMaxElems) + : mNumEls(inMaxElems), mDidAllocate(false) +{ + if (inMaxElems > kStaticElCount) { + mChans = new UInt32[inMaxElems]; + mDidAllocate = true; + memset (mChans, 0, sizeof(int) * inMaxElems); + } else { + mChans = mStaticChans; + memset (mChans, 0, sizeof(int) * kStaticElCount); + } +} + +CAAUChanHelper::~CAAUChanHelper() +{ + if (mDidAllocate) delete [] mChans; +} + +CAAUChanHelper& CAAUChanHelper::operator= (const CAAUChanHelper &c) +{ + if (mDidAllocate) delete [] mChans; + if (c.mDidAllocate) { + mChans = new UInt32[c.mNumEls]; + mDidAllocate = true; + } else { + mDidAllocate = false; + mChans = mStaticChans; + } + memcpy (mChans, c.mChans, c.mNumEls * sizeof(int)); + + return *this; +} + + +#pragma mark __Print Utilities + +void CAAudioUnit::Print (FILE* file) const +{ + fprintf (file, "AudioUnit:%p\n", AU()); + if (IsValid()) { + fprintf (file, "\tnode=%ld\t", (long)GetAUNode()); Comp().Print (file); + } +} + +#if CA_AU_USE_FAST_DISPATCH +// Handle GetComponentInstanceStorage(ComponentInstance aComponentInstance) +static void *LoadGetComponentInstanceStorage (void *inst) +{ + typedef void* (*GetComponentInstanceStorageProc)(void* aComponentInstance); + static GetComponentInstanceStorageProc sGetComponentInstanceStorageProc = NULL; + + static int sDoCSLoad = 1; + if (sDoCSLoad) { + sDoCSLoad = 0; + void *theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY); + if (!theImage) return NULL; + + sGetComponentInstanceStorageProc = (GetComponentInstanceStorageProc) dlsym(theImage, "GetComponentInstanceStorage"); + } + if (sGetComponentInstanceStorageProc) + return (*sGetComponentInstanceStorageProc)(inst); + return NULL; +} +#endif + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h new file mode 100644 index 0000000000..07a522e912 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h @@ -0,0 +1,439 @@ +/* + File: CAAudioUnit.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAAudioUnit_h__ +#define __CAAudioUnit_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> + #include <AudioUnit/AudioUnit.h> + #include <AudioToolbox/AUGraph.h> + #include <AudioUnit/MusicDevice.h> +#else + #include <ConditionalMacros.h> + #include <CoreAudioTypes.h> + #include <AudioUnit.h> + #include <MusicDevice.h> + #include <AUGraph.h> + #include <MusicDevice.h> +#endif + +#include <vector> +#include "CAStreamBasicDescription.h" +#include "CAComponent.h" +#include "CAAudioChannelLayout.h" + +// defined below +class CAAUChanHelper; + +// These constructors will NOT throw exceptions - so "check" after creation if AU IsValid() +// The destructor will NOT automatically close the AU down +// This state should be managed by the Caller +// once closed, the unit represented by this object is no longer valid +// it is up to the user of this object to ensure its validity is in sync +// if it is removed from a graph + +// methods that can significantly change the state of the AU (like its format) are +// NOT const whereas those that don't change the externally related state of the AU are not const + +class CAAudioUnit { + enum { + paramErr = -50, + badComponentSelector = (long)0x80008002 + }; +public: + typedef std::vector<AudioChannelLayoutTag> ChannelTagVector; + typedef ChannelTagVector::iterator ChannelTagVectorIter; + +public: + CAAudioUnit () + : mDataPtr(0) {} + + CAAudioUnit (const AudioUnit& inUnit); + + CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit); + + CAAudioUnit (const CAAudioUnit& y) + : mDataPtr(0) { *this = y; } + + static OSStatus Open (const CAComponent& inComp, CAAudioUnit &outUnit); + + ~CAAudioUnit (); + + void Close (); + + + CAAudioUnit& operator= (const CAAudioUnit& y); + + bool operator== (const CAAudioUnit& y) const; + + bool operator== (const AudioUnit& y) const; + +#pragma mark __State Management + bool IsValid () const; + + AudioUnit AU() const; + operator AudioUnit () const { return AU(); } + + const CAComponent& Comp() const { return mComp; } + + const CAComponentDescription& Desc() const { return mComp.Desc(); } + + bool FromAUGraph () const { return GetAUNode() != 0 && GetAUNode() != kCAAU_DoNotKnowIfAUNode; } + + AUNode GetAUNode () const; + operator AUNode () const { return GetAUNode(); } + +#pragma mark __API Wrapper + OSStatus Initialize() const { + return AudioUnitInitialize(AU()); + } + OSStatus Uninitialize() const { + return AudioUnitUninitialize(AU()); + } + OSStatus GetPropertyInfo(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, + UInt32 *outDataSize, Boolean *outWritable) const + { + return AudioUnitGetPropertyInfo(AU(), propID, scope, element, outDataSize, outWritable); + } + OSStatus GetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, + void *outData, UInt32 *ioDataSize) const + { + return AudioUnitGetProperty(AU(), propID, scope, element, outData, ioDataSize); + } + OSStatus SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, + const void *inData, UInt32 inDataSize) + { + return AudioUnitSetProperty(AU(), propID, scope, element, inData, inDataSize); + } + OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 value, UInt32 bufferOffsetFrames=0); + + OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 &outValue) const; + + OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags, + const AudioTimeStamp * inTimeStamp, + UInt32 inOutputBusNumber, + UInt32 inNumberFrames, + AudioBufferList * ioData); + + OSStatus Process (AudioUnitRenderActionFlags & ioActionFlags, + const AudioTimeStamp & inTimeStamp, + UInt32 inNumberFrames, + AudioBufferList & ioData); + + OSStatus ProcessMultiple (AudioUnitRenderActionFlags & ioActionFlags, + const AudioTimeStamp & inTimeStamp, + UInt32 inNumberFrames, + UInt32 inNumberInputBufferLists, + const AudioBufferList ** inInputBufferLists, + UInt32 inNumberOutputBufferLists, + AudioBufferList ** ioOutputBufferLists); + + + OSStatus Reset (AudioUnitScope scope, AudioUnitElement element) + { + return AudioUnitReset (AU(), scope, element); + } + OSStatus GlobalReset () + { + return AudioUnitReset (AU(), kAudioUnitScope_Global, 0); + } + + OSStatus AddRenderNotify (AURenderCallback inProc, void *inProcRefCon) + { + return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon); + } + + OSStatus RemoveRenderNotify (AURenderCallback inProc, void *inProcRefCon) + { + return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon); + } + + OSStatus AddPropertyListener (AudioUnitPropertyID inID, + AudioUnitPropertyListenerProc inProc, + void * inProcRefCon) + { + return AudioUnitAddPropertyListener (AU(), inID, inProc, inProcRefCon); + } + + OSStatus RemovePropertyListener (AudioUnitPropertyID inID, + AudioUnitPropertyListenerProc inProc, + void * inProcUserData); + + OSStatus MIDIEvent (UInt32 inStatus, + UInt32 inData1, + UInt32 inData2, + UInt32 inOffsetSampleFrame); + + // uses the default VoiceForGroup value - this is the normal case + OSStatus StartNote (MusicDeviceGroupID inGroupID, + NoteInstanceID * outNoteInstanceID, + UInt32 inOffsetSampleFrame, + const MusicDeviceNoteParams * inParams) + { + return StartNote (kMusicNoteEvent_UseGroupInstrument, + inGroupID, outNoteInstanceID, + inOffsetSampleFrame, inParams); + } + + OSStatus StartNote (MusicDeviceInstrumentID inInstrument, + MusicDeviceGroupID inGroupID, + NoteInstanceID * outNoteInstanceID, + UInt32 inOffsetSampleFrame, + const MusicDeviceNoteParams * inParams); + + OSStatus StopNote (MusicDeviceGroupID inGroupID, + NoteInstanceID inNoteInstanceID, + UInt32 inOffsetSampleFrame); + +#pragma mark __Format Utilities + // typically you ask this about an AU + // These Questions are asking about Input and Output... + + // These ones just say whether an AU can do a single combination of channels + // and is fine if the AU has a single output (and if an input, a single input) + bool CanDo (int inChannelsInOut) const + { + return CanDo (inChannelsInOut, inChannelsInOut); + } + + bool CanDo ( int inChannelsIn, + int inChannelsOut) const; + + // This version does a more thorough test for ANY AU with ANY ins/outs + // you pass in the channel helper (for the current element count on that scope) + + bool CanDo ( const CAAUChanHelper &input, + const CAAUChanHelper &output) const; + + bool SupportsNumChannels () const; + + bool HasChannelLayouts (AudioUnitScope inScope, + AudioUnitElement inEl) const; + + int GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt); + OSStatus GetChannelLayoutTags (AudioUnitScope inScope, + AudioUnitElement inEl, + ChannelTagVector &outChannelVector) const; + + bool HasChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl) const; + + OSStatus GetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + CAAudioChannelLayout &outLayout) const; + + OSStatus SetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + const CAAudioChannelLayout &inLayout); + + OSStatus SetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + const AudioChannelLayout &inLayout, + UInt32 inSize); + + OSStatus ClearChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl); + + OSStatus GetFormat (AudioUnitScope inScope, + AudioUnitElement inEl, + AudioStreamBasicDescription &outFormat) const; + // if an AudioChannelLayout is either required or set, this call can fail + // and the SetChannelLayout call should be used to set the format + OSStatus SetFormat (AudioUnitScope inScope, + AudioUnitElement inEl, + const AudioStreamBasicDescription &inFormat); + + OSStatus GetSampleRate (AudioUnitScope inScope, + AudioUnitElement inEl, + Float64 &outRate) const; + OSStatus SetSampleRate (AudioUnitScope inScope, + AudioUnitElement inEl, + Float64 inRate); + + // this sets the sample rate on all in/out buses of the AU + OSStatus SetSampleRate (Float64 inSampleRate); + + OSStatus NumberChannels (AudioUnitScope inScope, + AudioUnitElement inEl, + UInt32 &outChans) const; + + OSStatus GetNumberChannels (AudioUnitScope inScope, + AudioUnitElement inEl, + UInt32 &outChans) const + { + return NumberChannels (inScope, inEl, outChans); + } + + OSStatus SetNumberChannels (AudioUnitScope inScope, + AudioUnitElement inEl, + UInt32 inChans); + + OSStatus IsElementCountWritable (AudioUnitScope inScope, bool &outWritable) const; + + OSStatus GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const; + + OSStatus SetElementCount (AudioUnitScope inScope, UInt32 inCount); + + // value of -1 for outTotalNumChannels indicates no restriction on num channels + // for ex. the Matrix Mixer satisfies this (its in/out element count is writable, and can be set to + // any number of channels. + // outTotalNumChannels is only valid if method returns true... + bool HasDynamicInputs (SInt32 &outTotalNumChannels) const + { + return HasDynamicScope (kAudioUnitScope_Input, outTotalNumChannels); + } + + bool HasDynamicOutputs (SInt32 &outTotalNumChannels) const + { + return HasDynamicScope (kAudioUnitScope_Output, outTotalNumChannels); + } + + // here, if the in (or out) elements are dynamic, then you supply the number of elements + // you want on in (or out) scope, and the number of channels on each consecutive element + OSStatus ConfigureDynamicInput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate) + { + return ConfigureDynamicScope (kAudioUnitScope_Input, inNumElements, inChannelsPerElement, inSampleRate); + } + + OSStatus ConfigureDynamicOutput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate) + { + return ConfigureDynamicScope (kAudioUnitScope_Output, inNumElements, inChannelsPerElement, inSampleRate); + } + + bool CanBypass () const; + + bool GetBypass () const; + + OSStatus SetBypass (bool inBypass) const; + + OSStatus GetMaxFramesPerSlice (UInt32& outMaxFrames) const; + + OSStatus SetMaxFramesPerSlice (UInt32 inMaxFrames); + + Float64 Latency () const; + + // these calls just deal with the global preset state + // you could rescope them to deal with presets on the part scope + OSStatus GetAUPreset (CFPropertyListRef &outData) const; + + OSStatus SetAUPreset (CFPropertyListRef &inData); + + OSStatus SetAUPresetFromDocument (CFPropertyListRef &inData); + + OSStatus GetPresentPreset (AUPreset &outData) const; + + OSStatus SetPresentPreset (AUPreset &inData); + + bool HasCustomView () const; + +#pragma mark __Print + void Print () const { Print (stdout); } + void Print (FILE* file) const; + +private: + CAComponent mComp; + + class AUState; + AUState* mDataPtr; + + // this can throw - so wrap this up in a static that returns a result code... + CAAudioUnit (const CAComponent& inComp); + + bool HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const; + OSStatus ConfigureDynamicScope (AudioUnitScope inScope, + UInt32 inNumElements, + UInt32 *inChannelsPerElement, + Float64 inSampleRate); + bool ValidateChannelPair (int inChannelsIn, + int inChannelsOut, + const AUChannelInfo * info, + UInt32 numChanInfo) const; + + bool ValidateDynamicScope (AudioUnitScope inScope, + SInt32 &outTotalNumChannels, + const AUChannelInfo * info, + UInt32 numInfo) const; + bool CheckOneSide (const CAAUChanHelper &inHelper, + bool checkOutput, + const AUChannelInfo *info, + UInt32 numInfo) const; + enum { + kCAAU_DoNotKnowIfAUNode = -1 + }; +}; + +class CAAUChanHelper { +public: + CAAUChanHelper() + : mChans(mStaticChans), mNumEls(0), mDidAllocate(false) + { + memset (mChans, 0, sizeof(UInt32) * kStaticElCount); + } + CAAUChanHelper(UInt32 inMaxElems); + CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope); + CAAUChanHelper (const CAAUChanHelper &c) + : mChans(mStaticChans), mNumEls(0), mDidAllocate(false) + { *this = c; } + + ~CAAUChanHelper(); + + CAAUChanHelper& operator= (const CAAUChanHelper &c); + + UInt32 * mChans; + UInt32 mNumEls; + +private: + enum { + kStaticElCount = 8 + }; + UInt32 mStaticChans[kStaticElCount]; + bool mDidAllocate; +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h new file mode 100644 index 0000000000..42bebfacc3 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h @@ -0,0 +1,143 @@ +/* + File: CAAudioUnitOutputCapturer.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAAudioUnitOutputCapturer_h__ +#define __CAAudioUnitOutputCapturer_h__ + +#include <AudioToolbox/ExtendedAudioFile.h> + +/* + Class to capture output from an AudioUnit for analysis. + + example: + + CFURL fileurl = CFURLCreateWithFileSystemPath(NULL, CFSTR("/tmp/recording.caf"), kCFURLPOSIXPathStyle, false); + + CAAudioUnitOutputCapturer captor(someAU, fileurl, 'caff', anASBD); + + { + captor.Start(); + ... + captor.Stop(); + } // can repeat + + captor.Close(); // can be omitted; happens automatically from destructor +*/ + +class CAAudioUnitOutputCapturer { +public: + enum { noErr = 0 }; + + CAAudioUnitOutputCapturer(AudioUnit au, CFURLRef outputFileURL, AudioFileTypeID fileType, const AudioStreamBasicDescription &format, UInt32 busNumber = 0) : + mFileOpen(false), + mClientFormatSet(false), + mAudioUnit(au), + mExtAudioFile(NULL), + mBusNumber (busNumber) + { + CFShow(outputFileURL); + OSStatus err = ExtAudioFileCreateWithURL(outputFileURL, fileType, &format, NULL, kAudioFileFlags_EraseFile, &mExtAudioFile); + if (!err) + mFileOpen = true; + } + + void Start() { + if (mFileOpen) { + if (!mClientFormatSet) { + AudioStreamBasicDescription clientFormat; + UInt32 size = sizeof(clientFormat); + AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, mBusNumber, &clientFormat, &size); + ExtAudioFileSetProperty(mExtAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat); + mClientFormatSet = true; + } + ExtAudioFileWriteAsync(mExtAudioFile, 0, NULL); // initialize async writes + AudioUnitAddRenderNotify(mAudioUnit, RenderCallback, this); + } + } + + void Stop() { + if (mFileOpen) + AudioUnitRemoveRenderNotify(mAudioUnit, RenderCallback, this); + } + + void Close() { + if (mExtAudioFile) { + ExtAudioFileDispose(mExtAudioFile); + mExtAudioFile = NULL; + } + } + + ~CAAudioUnitOutputCapturer() { + Close(); + } + +private: + static OSStatus RenderCallback( void * inRefCon, + AudioUnitRenderActionFlags * ioActionFlags, + const AudioTimeStamp * inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList * ioData) + { + if (*ioActionFlags & kAudioUnitRenderAction_PostRender) { + CAAudioUnitOutputCapturer *This = (CAAudioUnitOutputCapturer *)inRefCon; + static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8); + if (This->mBusNumber == inBusNumber && !(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError)) { + OSStatus result = ExtAudioFileWriteAsync(This->mExtAudioFile, inNumberFrames, ioData); + if (result) DebugMessageN1("ERROR WRITING FRAMES: %d\n", (int)result); + } + } + return noErr; + } + + bool mFileOpen; + bool mClientFormatSet; + AudioUnit mAudioUnit; + ExtAudioFileRef mExtAudioFile; + UInt32 mBusNumber; +}; + +#endif // __CAAudioUnitOutputCapturer_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp new file mode 100644 index 0000000000..203e437af6 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp @@ -0,0 +1,262 @@ +/* + File: CAAudioValueRange.cpp + Abstract: CAAudioValueRange.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CAAudioValueRange.h" + +// Standard Library +#include <algorithm> + +//================================================================================================== +// CAAudioValueRange +//================================================================================================== + +Float64 CAAudioValueRange::BoundValue(const AudioValueRange& inRange, Float64 inValue) +{ + if (inValue <= inRange.mMinimum) + { + return inRange.mMinimum; + } + else if (inValue >= inRange.mMaximum) + { + return inRange.mMaximum; + } + else + { + return inValue; + } +} + +Float64 CAAudioValueRange::PickCommonSampleRate(const AudioValueRange& inRange) +{ + // This routine will pick a "common" sample rate from the give range of rates or the maximum + // if no common rates can be found. It assumes that inRange contains a continuous range of + // sample rates. + Float64 theAnswer = inRange.mMaximum; + + if(ContainsValue(inRange, 44100.0)) + { + theAnswer = 44100.0; + } + else if(ContainsValue(inRange, 48000.0)) + { + theAnswer = 48000.0; + } + else if(ContainsValue(inRange, 96000.0)) + { + theAnswer = 96000.0; + } + else if(ContainsValue(inRange, 88200.0)) + { + theAnswer = 88200.0; + } + else if(ContainsValue(inRange, 64000.0)) + { + theAnswer = 64000.0; + } + else if(ContainsValue(inRange, 32000.0)) + { + theAnswer = 32000.0; + } + else if(ContainsValue(inRange, 24000.0)) + { + theAnswer = 24000.0; + } + else if(ContainsValue(inRange, 22050.0)) + { + theAnswer = 22050.0; + } + else if(ContainsValue(inRange, 16000.0)) + { + theAnswer = 16000.0; + } + else if(ContainsValue(inRange, 12000.0)) + { + theAnswer = 12000.0; + } + else if(ContainsValue(inRange, 11025.0)) + { + theAnswer = 11025.0; + } + else if(ContainsValue(inRange, 8000.0)) + { + theAnswer = 8000.0; + } + + return theAnswer; +} + +bool CAAudioValueRange::Intersection(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange) +{ + bool isNonEmpty; + if(!IsStrictlyLessThan(x, y) && !IsStrictlyGreaterThan(x, y)) + { + outRange.mMinimum = std::max(x.mMinimum, y.mMinimum); + outRange.mMaximum = std::min(x.mMaximum, y.mMaximum); + isNonEmpty = true; + } + else + { + outRange.mMinimum = 0; + outRange.mMaximum = 0; + isNonEmpty = false; + } + return isNonEmpty; +} + +bool CAAudioValueRange::Union(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange) +{ + bool isDisjoint; + if(!IsStrictlyLessThan(x, y) && !IsStrictlyGreaterThan(x, y)) + { + outRange.mMinimum = std::min(x.mMinimum, y.mMinimum); + outRange.mMaximum = std::max(x.mMaximum, y.mMaximum); + isDisjoint = false; + } + else + { + outRange.mMinimum = 0; + outRange.mMaximum = 0; + isDisjoint = true; + } + return isDisjoint; +} + +void CAAudioValueRange_ComputeUnion(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outUnion) +{ + // this method assumes that the ranges in inRangeList are disjoint and that they are sorted from low to high and + outUnion.clear(); + + // start at the beginning of inRangeList + CAAudioValueRangeList::const_iterator theIterator = inRangeList.begin(); + + // iterate through inRangeList and add all the ranges that are strictly less than inRange + while((theIterator != inRangeList.end()) && CAAudioValueRange::IsStrictlyLessThan(*theIterator, inRange)) + { + // put this range in the union + outUnion.push_back(*theIterator); + + // go to the next one + std::advance(theIterator, 1); + } + + if(theIterator != inRangeList.end()) + { + if(!CAAudioValueRange::IsStrictlyGreaterThan(*theIterator, inRange)) + { + // inRange intersects the range that theIterator points at, but might actually intersect several contiguous ranges + + // initialize the starting point, noting that we can skip the current one since we already know it's in the intersection + CAAudioValueRangeList::const_iterator theGreaterIterator = theIterator; + std::advance(theGreaterIterator, 1); + + // iterate until we find a range that is strictly greater than inRange + while((theGreaterIterator != inRangeList.end()) && !CAAudioValueRange::IsStrictlyGreaterThan(*theGreaterIterator, inRange)) + { + // go to the next one + std::advance(theGreaterIterator, 1); + } + + // theGreaterIterator now points at either one past the highest range in the intersection or the end of the vector + // Either way, we have to adjust it to point at the true highest range in the intersection + std::advance(theGreaterIterator, -1); + + // now theIterator points at the lowest range in the intersection and theGreaterIterator points at the highest + // so we can compute the coagulated range + AudioValueRange theCoagulation; + theCoagulation.mMinimum = std::min(theIterator->mMinimum, inRange.mMinimum); + theCoagulation.mMaximum = std::max(theGreaterIterator->mMaximum, inRange.mMaximum); + + // add the coagulation to the union + outUnion.push_back(theCoagulation); + + // adjust theIterator to point at the next range for processing + theIterator = theGreaterIterator; + std::advance(theIterator, 1); + } + else + { + // the range theIterator points at is strictly greater than inRange, so insert inRange in front of it and we're done + outUnion.push_back(inRange); + } + + // we need to now copy the remaining higher ranges in inRangeList into the union + while(theIterator != inRangeList.end()) + { + // put this range in the union + outUnion.push_back(*theIterator); + + // go to the next one + std::advance(theIterator, 1); + } + } + else + { + // inRange is larger than all of the ranges in inRangeList, so just add it onto the end of the union and we're done + // This is also the case if inRangeList is empty + outUnion.push_back(inRange); + } +} + +void CAAudioValueRange_ComputeIntersection(UInt32 inNumberRangeList1Items, AudioValueRange inRangeList1[], const CAAudioValueRangeList& inRangeList2, CAAudioValueRangeList& outIntersections) +{ + outIntersections.clear(); + for(UInt32 theRangeList1Index = 0; theRangeList1Index < inNumberRangeList1Items; ++theRangeList1Index) + { + for(CAAudioValueRangeList::const_iterator theRangeList2Iterator = inRangeList2.begin(); theRangeList2Iterator != inRangeList2.end(); std::advance(theRangeList2Iterator, 1)) + { + AudioValueRange theIntersection; + if(CAAudioValueRange::Intersection(inRangeList1[theRangeList1Index], *theRangeList2Iterator, theIntersection)) + { + outIntersections.push_back(theIntersection); + } + } + } +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h new file mode 100644 index 0000000000..e17c4574bc --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h @@ -0,0 +1,121 @@ +/* + File: CAAudioValueRange.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAAudioValueRange_h__) +#define __CAAudioValueRange_h__ + +//============================================================================= +// Includes +//============================================================================= + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif +// Standard Library Includes +#include <functional> +#include <vector> + +//============================================================================= +// CAAudioValueRange +//============================================================================= + +struct CAAudioValueRange +: + public AudioValueRange +{ + +// Construction/Destruction +public: + CAAudioValueRange() { mMinimum = 0.0; mMaximum = 0.0; } + CAAudioValueRange(const AudioValueRange& v) { mMinimum = v.mMinimum; mMaximum = v.mMaximum; } + CAAudioValueRange(Float64 inMinimum, Float64 inMaximum) { mMinimum = inMinimum; mMaximum = inMaximum; } + +// Assignment +public: + CAAudioValueRange& operator=(const AudioValueRange& v) { mMinimum = v.mMinimum; mMaximum = v.mMaximum; return *this; } + +// Operations +public: + static bool ContainsValue(const AudioValueRange& inRange, Float64 inValue) { return (inValue >= inRange.mMinimum) && (inValue <= inRange.mMaximum); } + static Float64 BoundValue(const AudioValueRange& inRange, Float64 inValue); + static Float64 PickCommonSampleRate(const AudioValueRange& inRange); + static bool IsStrictlyLessThan(const AudioValueRange& x, const AudioValueRange& y) { return x.mMaximum < y.mMinimum; } + static bool IsStrictlyGreaterThan(const AudioValueRange& x, const AudioValueRange& y) { return x.mMinimum > y.mMaximum; } + static bool IsStrictlyContainedBy(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); } + static bool OverlapsLow(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum < y.mMinimum) && (x.mMaximum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); } + static bool OverlapsHigh(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum >= y.mMinimum) && (x.mMinimum <= y.mMaximum) && (x.mMaximum > y.mMaximum); } + static bool Intersection(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange); + static bool Union(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange); + +// STL Helpers +public: + struct LessThan + : + public std::binary_function<AudioValueRange, AudioValueRange, bool> + { + bool operator()(const AudioValueRange& x, const AudioValueRange& y) const + { + return x.mMinimum < y.mMinimum; + } + }; + +}; + +inline bool operator<(const AudioValueRange& x, const AudioValueRange& y) { return x.mMinimum < y.mMinimum; } +inline bool operator==(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); } +inline bool operator!=(const AudioValueRange& x, const AudioValueRange& y) { return !(x == y); } +inline bool operator<=(const AudioValueRange& x, const AudioValueRange& y) { return (x < y) || (x == y); } +inline bool operator>=(const AudioValueRange& x, const AudioValueRange& y) { return !(x < y); } +inline bool operator>(const AudioValueRange& x, const AudioValueRange& y) { return !((x < y) || (x == y)); } + +typedef std::vector<CAAudioValueRange> CAAudioValueRangeList; +void CAAudioValueRange_ComputeUnion(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outUnion); +void CAAudioValueRange_ComputeIntersection(UInt32 inNumberRangeList1Items, AudioValueRange inRangeList1[], const CAAudioValueRangeList& inRangeList2, CAAudioValueRangeList& outIntersections); + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h b/libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h new file mode 100644 index 0000000000..2da241506c --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h @@ -0,0 +1,508 @@ +/* + File: CAAutoDisposer.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAPtr_h__) +#define __CAPtr_h__ + +#include <stdlib.h> // for malloc +#include <new> // for bad_alloc +#include <string.h> // for memset + +inline void* CA_malloc(size_t size) +{ + void* p = malloc(size); + if (!p && size) throw std::bad_alloc(); + return p; +} + +inline void* CA_realloc(void* old, size_t size) +{ +#if TARGET_OS_WIN32 + void* p = realloc(old, size); +#else + void* p = reallocf(old, size); // reallocf ensures the old pointer is freed if memory is full (p is NULL). +#endif + if (!p && size) throw std::bad_alloc(); + return p; +} + +#ifndef UINTPTR_MAX +#if __LP64__ +#define UINTPTR_MAX 18446744073709551615ULL +#else +#define UINTPTR_MAX 4294967295U +#endif +#endif + +inline void* CA_calloc(size_t n, size_t size) +{ + // ensure that multiplication will not overflow + if (n && UINTPTR_MAX / n < size) throw std::bad_alloc(); + + size_t nsize = n*size; + void* p = malloc(nsize); + if (!p && nsize) throw std::bad_alloc(); + + memset(p, 0, nsize); + return p; +} + + +// helper class for automatic conversions +template <typename T> +struct CAPtrRef +{ + T* ptr_; + + explicit CAPtrRef(T* ptr) : ptr_(ptr) {} +}; + +template <typename T> +class CAAutoFree +{ +private: + T* ptr_; + +public: + + CAAutoFree() : ptr_(0) {} + + explicit CAAutoFree(T* ptr) : ptr_(ptr) {} + + template<typename U> + CAAutoFree(CAAutoFree<U>& that) : ptr_(that.release()) {} // take ownership + + // C++ std says: a template constructor is never a copy constructor + CAAutoFree(CAAutoFree<T>& that) : ptr_(that.release()) {} // take ownership + + CAAutoFree(size_t n, bool clear = false) + // this becomes an ambiguous call if n == 0 + : ptr_(0) + { + size_t maxItems = ~size_t(0) / sizeof(T); + if (n > maxItems) + throw std::bad_alloc(); + + ptr_ = static_cast<T*>(clear ? CA_calloc(n, sizeof(T)) : CA_malloc(n * sizeof(T))); + } + + ~CAAutoFree() { free(); } + + void alloc(size_t numItems, bool clear = false) + { + size_t maxItems = ~size_t(0) / sizeof(T); + if (numItems > maxItems) throw std::bad_alloc(); + + free(); + ptr_ = static_cast<T*>(clear ? CA_calloc(numItems, sizeof(T)) : CA_malloc(numItems * sizeof(T))); + } + + void allocBytes(size_t numBytes, bool clear = false) + { + free(); + ptr_ = static_cast<T*>(clear ? CA_calloc(1, numBytes) : CA_malloc(numBytes)); + } + + void reallocBytes(size_t numBytes) + { + ptr_ = static_cast<T*>(CA_realloc(ptr_, numBytes)); + } + + void reallocItems(size_t numItems) + { + size_t maxItems = ~size_t(0) / sizeof(T); + if (numItems > maxItems) throw std::bad_alloc(); + + ptr_ = static_cast<T*>(CA_realloc(ptr_, numItems * sizeof(T))); + } + + template <typename U> + CAAutoFree& operator=(CAAutoFree<U>& that) + { + set(that.release()); // take ownership + return *this; + } + + CAAutoFree& operator=(CAAutoFree& that) + { + set(that.release()); // take ownership + return *this; + } + + CAAutoFree& operator=(T* ptr) + { + set(ptr); + return *this; + } + + template <typename U> + CAAutoFree& operator=(U* ptr) + { + set(ptr); + return *this; + } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + + T* operator()() const { return ptr_; } + T* get() const { return ptr_; } + operator T*() const { return ptr_; } + + bool operator==(CAAutoFree const& that) const { return ptr_ == that.ptr_; } + bool operator!=(CAAutoFree const& that) const { return ptr_ != that.ptr_; } + bool operator==(T* ptr) const { return ptr_ == ptr; } + bool operator!=(T* ptr) const { return ptr_ != ptr; } + + T* release() + { + // release ownership + T* result = ptr_; + ptr_ = 0; + return result; + } + + void set(T* ptr) + { + if (ptr != ptr_) + { + ::free(ptr_); + ptr_ = ptr; + } + } + + void free() + { + set(0); + } + + + // automatic conversions to allow assignment from results of functions. + // hard to explain. see auto_ptr implementation and/or Josuttis' STL book. + CAAutoFree(CAPtrRef<T> ref) : ptr_(ref.ptr_) { } + + CAAutoFree& operator=(CAPtrRef<T> ref) + { + set(ref.ptr_); + return *this; + } + + template<typename U> + operator CAPtrRef<U>() + { return CAPtrRef<U>(release()); } + + template<typename U> + operator CAAutoFree<U>() + { return CAAutoFree<U>(release()); } + +}; + + +template <typename T> +class CAAutoDelete +{ +private: + T* ptr_; + +public: + CAAutoDelete() : ptr_(0) {} + + explicit CAAutoDelete(T* ptr) : ptr_(ptr) {} + + template<typename U> + CAAutoDelete(CAAutoDelete<U>& that) : ptr_(that.release()) {} // take ownership + + // C++ std says: a template constructor is never a copy constructor + CAAutoDelete(CAAutoDelete<T>& that) : ptr_(that.release()) {} // take ownership + + ~CAAutoDelete() { free(); } + + template <typename U> + CAAutoDelete& operator=(CAAutoDelete<U>& that) + { + set(that.release()); // take ownership + return *this; + } + + CAAutoDelete& operator=(CAAutoDelete& that) + { + set(that.release()); // take ownership + return *this; + } + + CAAutoDelete& operator=(T* ptr) + { + set(ptr); + return *this; + } + + template <typename U> + CAAutoDelete& operator=(U* ptr) + { + set(ptr); + return *this; + } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + + T* operator()() const { return ptr_; } + T* get() const { return ptr_; } + operator T*() const { return ptr_; } + + bool operator==(CAAutoDelete const& that) const { return ptr_ == that.ptr_; } + bool operator!=(CAAutoDelete const& that) const { return ptr_ != that.ptr_; } + bool operator==(T* ptr) const { return ptr_ == ptr; } + bool operator!=(T* ptr) const { return ptr_ != ptr; } + + T* release() + { + // release ownership + T* result = ptr_; + ptr_ = 0; + return result; + } + + void set(T* ptr) + { + if (ptr != ptr_) + { + delete ptr_; + ptr_ = ptr; + } + } + + void free() + { + set(0); + } + + + // automatic conversions to allow assignment from results of functions. + // hard to explain. see auto_ptr implementation and/or Josuttis' STL book. + CAAutoDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { } + + CAAutoDelete& operator=(CAPtrRef<T> ref) + { + set(ref.ptr_); + return *this; + } + + template<typename U> + operator CAPtrRef<U>() + { return CAPtrRef<U>(release()); } + + template<typename U> + operator CAAutoFree<U>() + { return CAAutoFree<U>(release()); } + +}; + + +template <typename T> +class CAAutoArrayDelete +{ +private: + T* ptr_; + +public: + CAAutoArrayDelete() : ptr_(0) {} + + explicit CAAutoArrayDelete(T* ptr) : ptr_(ptr) {} + + template<typename U> + CAAutoArrayDelete(CAAutoArrayDelete<U>& that) : ptr_(that.release()) {} // take ownership + + // C++ std says: a template constructor is never a copy constructor + CAAutoArrayDelete(CAAutoArrayDelete<T>& that) : ptr_(that.release()) {} // take ownership + + // this becomes an ambiguous call if n == 0 + CAAutoArrayDelete(size_t n) : ptr_(new T[n]) {} + + ~CAAutoArrayDelete() { free(); } + + void alloc(size_t numItems) + { + free(); + ptr_ = new T [numItems]; + } + + template <typename U> + CAAutoArrayDelete& operator=(CAAutoArrayDelete<U>& that) + { + set(that.release()); // take ownership + return *this; + } + + CAAutoArrayDelete& operator=(CAAutoArrayDelete& that) + { + set(that.release()); // take ownership + return *this; + } + + CAAutoArrayDelete& operator=(T* ptr) + { + set(ptr); + return *this; + } + + template <typename U> + CAAutoArrayDelete& operator=(U* ptr) + { + set(ptr); + return *this; + } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + + T* operator()() const { return ptr_; } + T* get() const { return ptr_; } + operator T*() const { return ptr_; } + + bool operator==(CAAutoArrayDelete const& that) const { return ptr_ == that.ptr_; } + bool operator!=(CAAutoArrayDelete const& that) const { return ptr_ != that.ptr_; } + bool operator==(T* ptr) const { return ptr_ == ptr; } + bool operator!=(T* ptr) const { return ptr_ != ptr; } + + T* release() + { + // release ownership + T* result = ptr_; + ptr_ = 0; + return result; + } + + void set(T* ptr) + { + if (ptr != ptr_) + { + delete [] ptr_; + ptr_ = ptr; + } + } + + void free() + { + set(0); + } + + + // automatic conversions to allow assignment from results of functions. + // hard to explain. see auto_ptr implementation and/or Josuttis' STL book. + CAAutoArrayDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { } + + CAAutoArrayDelete& operator=(CAPtrRef<T> ref) + { + set(ref.ptr_); + return *this; + } + + template<typename U> + operator CAPtrRef<U>() + { return CAPtrRef<U>(release()); } + + template<typename U> + operator CAAutoArrayDelete<U>() + { return CAAutoFree<U>(release()); } + +}; + + + + + +// convenience function +template <typename T> +void free(CAAutoFree<T>& p) +{ + p.free(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#if 0 +// example program showing ownership transfer + +CAAutoFree<char> source() +{ + // source allocates and returns ownership to the caller. + const char* str = "this is a test"; + size_t size = strlen(str) + 1; + CAAutoFree<char> captr(size, false); + strlcpy(captr(), str, size); + printf("source %08X %08X '%s'\n", &captr, captr(), captr()); + return captr; +} + +void user(CAAutoFree<char> const& captr) +{ + // passed by const reference. user can access the pointer but does not take ownership. + printf("user: %08X %08X '%s'\n", &captr, captr(), captr()); +} + +void sink(CAAutoFree<char> captr) +{ + // passed by value. sink takes ownership and frees the pointer on return. + printf("sink: %08X %08X '%s'\n", &captr, captr(), captr()); +} + + +int main (int argc, char * const argv[]) +{ + + CAAutoFree<char> captr(source()); + printf("main captr A %08X %08X\n", &captr, captr()); + user(captr); + sink(captr); + printf("main captr B %08X %08X\n", &captr, captr()); + return 0; +} +#endif + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h b/libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h new file mode 100644 index 0000000000..21cb516a60 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h @@ -0,0 +1,206 @@ +/* + File: CABitOperations.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef _CABitOperations_h_ +#define _CABitOperations_h_ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + //#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h> + #include <CoreFoundation/CFBase.h> +#else +// #include <MacTypes.h> + #include "CFBase.h" +#endif +#include <TargetConditionals.h> + +// return whether a number is a power of two +inline UInt32 IsPowerOfTwo(UInt32 x) +{ + return (x & (x-1)) == 0; +} + +// count the leading zeros in a word +// Metrowerks Codewarrior. powerpc native count leading zeros instruction: +// I think it's safe to remove this ... +//#define CountLeadingZeroes(x) ((int)__cntlzw((unsigned int)x)) + +inline UInt32 CountLeadingZeroes(UInt32 arg) +{ +// GNUC / LLVM have a builtin +#if defined(__GNUC__) || defined(__llvm___) +#if (TARGET_CPU_X86 || TARGET_CPU_X86_64) + if (arg == 0) return 32; +#endif // TARGET_CPU_X86 || TARGET_CPU_X86_64 + return __builtin_clz(arg); +#elif TARGET_OS_WIN32 + UInt32 tmp; + __asm{ + bsr eax, arg + mov ecx, 63 + cmovz eax, ecx + xor eax, 31 + mov tmp, eax // this moves the result in tmp to return. + } + return tmp; +#else +#error "Unsupported architecture" +#endif // defined(__GNUC__) +} +// Alias (with different spelling) +#define CountLeadingZeros CountLeadingZeroes + +inline UInt32 CountLeadingZeroesLong(UInt64 arg) +{ +// GNUC / LLVM have a builtin +#if defined(__GNUC__) || defined(__llvm___) +#if (TARGET_CPU_X86 || TARGET_CPU_X86_64) + if (arg == 0) return 64; +#endif // TARGET_CPU_X86 || TARGET_CPU_X86_64 + return __builtin_clzll(arg); +#elif TARGET_OS_WIN32 + UInt32 x = CountLeadingZeroes((UInt32)(arg >> 32)); + if(x < 32) + return x; + else + return 32+CountLeadingZeroes((UInt32)arg); +#else +#error "Unsupported architecture" +#endif // defined(__GNUC__) +} +#define CountLeadingZerosLong CountLeadingZeroesLong + +// count trailing zeroes +inline UInt32 CountTrailingZeroes(UInt32 x) +{ + return 32 - CountLeadingZeroes(~x & (x-1)); +} + +// count leading ones +inline UInt32 CountLeadingOnes(UInt32 x) +{ + return CountLeadingZeroes(~x); +} + +// count trailing ones +inline UInt32 CountTrailingOnes(UInt32 x) +{ + return 32 - CountLeadingZeroes(x & (~x-1)); +} + +// number of bits required to represent x. +inline UInt32 NumBits(UInt32 x) +{ + return 32 - CountLeadingZeroes(x); +} + +// base 2 log of next power of two greater or equal to x +inline UInt32 Log2Ceil(UInt32 x) +{ + return 32 - CountLeadingZeroes(x - 1); +} + +// base 2 log of next power of two less or equal to x +inline UInt32 Log2Floor(UInt32 x) +{ + return 32 - CountLeadingZeroes(x) - 1; +} + +// next power of two greater or equal to x +inline UInt32 NextPowerOfTwo(UInt32 x) +{ + return 1 << Log2Ceil(x); +} + +// counting the one bits in a word +inline UInt32 CountOnes(UInt32 x) +{ + // secret magic algorithm for counting bits in a word. + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; +} + +// counting the zero bits in a word +inline UInt32 CountZeroes(UInt32 x) +{ + return CountOnes(~x); +} + +// return the bit position (0..31) of the least significant bit +inline UInt32 LSBitPos(UInt32 x) +{ + return CountTrailingZeroes(x & -(SInt32)x); +} + +// isolate the least significant bit +inline UInt32 LSBit(UInt32 x) +{ + return x & -(SInt32)x; +} + +// return the bit position (0..31) of the most significant bit +inline UInt32 MSBitPos(UInt32 x) +{ + return 31 - CountLeadingZeroes(x); +} + +// isolate the most significant bit +inline UInt32 MSBit(UInt32 x) +{ + return 1 << MSBitPos(x); +} + +// Division optimized for power of 2 denominators +inline UInt32 DivInt(UInt32 numerator, UInt32 denominator) +{ + if(IsPowerOfTwo(denominator)) + return numerator >> (31 - CountLeadingZeroes(denominator)); + else + return numerator/denominator; +} + +#endif + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABool.h b/libs/appleutility/CoreAudio/PublicUtility/CABool.h new file mode 100644 index 0000000000..719fd74bb2 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CABool.h @@ -0,0 +1,89 @@ +/* + File: CABool.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CABool_h__) +#define __CABool_h__ + +//============================================================================= +// Includes +//============================================================================= + +// System Includes +#include "CADebugMacros.h" +#include "CAException.h" + +//============================================================================= +// CABool +// +// This class implements a boolean value that has a third state that marks +// it as uninitialized. Accessing the value of an instance of this class that +// is uninitialized will throw an exception. +//============================================================================= + +class CABool +{ + +// Construction/Destruction +public: + CABool() : mValue(-1) {} + CABool(bool inValue) : mValue(inValue ? 1 : 0) {} + CABool(const CABool& inValue) : mValue(inValue.mValue) {} + ~CABool() {} + + CABool& operator=(bool inValue) { mValue = inValue; return *this; } + CABool& operator=(const CABool& inValue) { mValue = inValue.mValue; return *this; } + + operator bool() const { ThrowIf(mValue == -1, CAException('nope'), "CABool: uninitialized"); return mValue != 0; } + bool IsInitialized() const { return mValue != -1; } + void Uninitialize() { mValue = -1; } + +private: + SInt32 mValue; + + CABool(const void*); // prevent accidental instantiation with a pointer via bool constructor +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp new file mode 100644 index 0000000000..3249013b59 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp @@ -0,0 +1,259 @@ +/* + File: CABufferList.cpp + Abstract: CABufferList.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 "CABufferList.h" +#include "CAByteOrder.h" + +void CABufferList::AllocateBuffers(UInt32 nBytes) +{ + if (nBytes <= GetNumBytes()) return; + + if (mABL.mNumberBuffers > 1) + // align successive buffers for Altivec and to take alternating + // cache line hits by spacing them by odd multiples of 16 + nBytes = ((nBytes + 15) & ~15) | 16; + UInt32 memorySize = nBytes * mABL.mNumberBuffers; + Byte *newMemory = new Byte[memorySize], *p = newMemory; + memset(newMemory, 0, memorySize); // get page faults now, not later + + AudioBuffer *buf = mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { + if (buf->mData != NULL && buf->mDataByteSize > 0) + // preserve existing buffer contents + memcpy(p, buf->mData, buf->mDataByteSize); + buf->mDataByteSize = nBytes; + buf->mData = p; + p += nBytes; + } + Byte *oldMemory = mBufferMemory; + mBufferMemory = newMemory; + mBufferCapacity = nBytes; + delete[] oldMemory; +} + +void CABufferList::AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inSrcList, CABufferList *inSetPtrList) +{ + if (mABL.mNumberBuffers != inSrcList->mABL.mNumberBuffers) return; + if (mABL.mNumberBuffers != inSetPtrList->mABL.mNumberBuffers) return; + if (nBytes <= GetNumBytes()) { + CopyAllFrom(inSrcList, inSetPtrList); + return; + } + inSetPtrList->VerifyNotTrashingOwnedBuffer(); + UInt32 fromByteSize = inSrcList->GetNumBytes(); + + if (mABL.mNumberBuffers > 1) + // align successive buffers for Altivec and to take alternating + // cache line hits by spacing them by odd multiples of 16 + nBytes = ((nBytes + 15) & ~15) | 16; + UInt32 memorySize = nBytes * mABL.mNumberBuffers; + Byte *newMemory = new Byte[memorySize], *p = newMemory; + memset(newMemory, 0, memorySize); // make buffer "hot" + + AudioBuffer *buf = mABL.mBuffers; + AudioBuffer *ptrBuf = inSetPtrList->mABL.mBuffers; + AudioBuffer *srcBuf = inSrcList->mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++buf, ++ptrBuf, ++srcBuf) { + if (srcBuf->mData != NULL && srcBuf->mDataByteSize > 0) + // preserve existing buffer contents + memmove(p, srcBuf->mData, srcBuf->mDataByteSize); + buf->mDataByteSize = nBytes; + buf->mData = p; + ptrBuf->mDataByteSize = srcBuf->mDataByteSize; + ptrBuf->mData = p; + p += nBytes; + } + Byte *oldMemory = mBufferMemory; + mBufferMemory = newMemory; + mBufferCapacity = nBytes; + if (inSrcList != inSetPtrList) + inSrcList->BytesConsumed(fromByteSize); + delete[] oldMemory; +} + +void CABufferList::DeallocateBuffers() +{ + AudioBuffer *buf = mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { + buf->mData = NULL; + buf->mDataByteSize = 0; + } + if (mBufferMemory != NULL) { + delete[] mBufferMemory; + mBufferMemory = NULL; + mBufferCapacity = 0; + } + +} + +static void show(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label, const char *fmtstr=NULL) +{ + printf("%s %p (%d fr%s):\n", label ? label : "AudioBufferList", &abl, framesToPrint, fmtstr ? fmtstr : ""); + const AudioBuffer *buf = abl.mBuffers; + for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++buf) { + printf(" [%2d] %5dbytes %dch @ %p", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData); + if (framesToPrint && buf->mData != NULL) { + printf(":"); + Byte *p = (Byte *)buf->mData; + for (int j = framesToPrint * buf->mNumberChannels; --j >= 0; ) + switch (wordSize) { + case 0: // native float + printf(" %6.3f", *(Float32 *)p); + p += sizeof(Float32); + break; + // positive: big endian + case 1: + case -1: + printf(" %02X", *p); + p += 1; + break; + case 2: + printf(" %04X", CFSwapInt16BigToHost(*(UInt16 *)p)); + p += 2; + break; + case 3: + printf(" %06X", (p[0] << 16) | (p[1] << 8) | p[2]); + p += 3; + break; + case 4: + printf(" %08X", (unsigned int)CFSwapInt32BigToHost(*(UInt32 *)p)); + p += 4; + break; + case 10: + printf(" %6.3f", CASwapFloat32BigToHost(*(Float32 *)p)); + p += sizeof(Float32); + break; + case -2: + printf(" %04X", CFSwapInt16LittleToHost(*(UInt16 *)p)); + p += 2; + break; + case -3: + printf(" %06X", (p[2] << 16) | (p[1] << 8) | p[0]); + p += 3; + break; + case -4: + printf(" %08X", (unsigned int)CFSwapInt32LittleToHost(*(UInt32 *)p)); + p += 4; + break; + case -10: + printf(" %6.3f", CASwapFloat32LittleToHost(*(Float32 *)p)); + p += sizeof(Float32); + break; + } + } + printf("\n"); + } +} + +void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &asbd, const char *label) +{ + CAStreamBasicDescription fmt(asbd); + int wordSize = 1; + char fmtstr[80] = { 0 }; + + if (fmt.mFormatID == kAudioFormatLinearPCM) { + if (fmt.mFormatFlags & kLinearPCMFormatFlagIsFloat) { + if (fmt.mBitsPerChannel == 32) { + if (fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) { + wordSize = 10; + strlcpy(fmtstr, ", BEF", sizeof(fmtstr)); + } else { + wordSize = -10; + strlcpy(fmtstr, ", LEF", sizeof(fmtstr)); + } + } + } else { + wordSize = fmt.SampleWordSize(); + if (wordSize > 0) { + int fracbits = (asbd.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift; + if (fracbits > 0) + snprintf(fmtstr, sizeof(fmtstr), ", %d.%d-bit", (int)asbd.mBitsPerChannel - fracbits, fracbits); + else + snprintf(fmtstr, sizeof(fmtstr), ", %d-bit", (int)asbd.mBitsPerChannel); + + if (!(fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian)) { + wordSize = -wordSize; + strlcat(fmtstr, " LEI", sizeof(fmtstr)); + } else { + strlcat(fmtstr, " BEI", sizeof(fmtstr)); + } + } + } + } + show(abl, framesToPrint, wordSize, label, fmtstr); +} + +void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label) +{ + show(abl, framesToPrint, wordSize, label); +} + +extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize) +{ + show(*abl, framesToPrint, wordSize, NULL); +} + +// if the return result is odd, there was a null buffer. +extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullok) +{ + const AudioBuffer *buf = abl->mBuffers, *bufend = buf + abl->mNumberBuffers; + int sum = 0; // defeat attempts by the compiler to optimize away the code that touches the buffers + int anyNull = 0; + for ( ; buf < bufend; ++buf) { + const int *p = (const int *)buf->mData; + if (p == NULL) { + anyNull = 1; + if (nullok) continue; + } + unsigned datasize = buf->mDataByteSize; + if (datasize >= sizeof(int) && p != NULL) { + sum += p[0]; + sum += p[datasize / sizeof(int) - 1]; + } + } + return anyNull | (sum & ~1); +} + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABufferList.h b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.h new file mode 100644 index 0000000000..72c93f8626 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.h @@ -0,0 +1,324 @@ +/* + File: CABufferList.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CABufferList_h__ +#define __CABufferList_h__ + +#include <stddef.h> +#include "CAStreamBasicDescription.h" +#include "CAXException.h" + +void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &fmt, const char *label=NULL); +void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label=NULL); +extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize); +extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullOK=false); + +/* ____________________________________________________________________________ +// CABufferList - variable length buffer list + + This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList + is preferred. + + CABufferList can be used in one of two ways: + - as mutable pointers into non-owned memory + - as an immutable array of buffers (owns its own memory). + + All buffers are assumed to have the same format (number of channels, word size), so that + we can assume their mDataByteSizes are all the same. +____________________________________________________________________________ */ +class CABufferList { +public: + void * operator new(size_t /*size*/, int nBuffers) { + return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer)); + } + static CABufferList * New(const char *name, const CAStreamBasicDescription &format) + { + UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels(); + return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer); + } + static CABufferList * New(const CAStreamBasicDescription &format) { return New("", format); } + + static CABufferList * New(UInt32 numBuffers, UInt32 channelsPerBuffer, const char *name="") { + return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer); + } + +protected: + CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) : + mName(name), + mBufferMemory(NULL), + mBufferCapacity(0) + { + //XAssert(numBuffers > 0 /*&& channelsPerBuffer > 0*/); + mABL.mNumberBuffers = numBuffers; + AudioBuffer *buf = mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { + buf->mNumberChannels = channelsPerBuffer; + buf->mDataByteSize = 0; + buf->mData = NULL; + } + } + +public: + ~CABufferList() + { + if (mBufferMemory) + delete[] mBufferMemory; + } + + const char * Name() { return mName; } + + const AudioBufferList & GetBufferList() const { return mABL; } + + AudioBufferList & GetModifiableBufferList() { return _GetBufferList(); } + + UInt32 GetNumberBuffers() const { return mABL.mNumberBuffers; } + + UInt32 GetNumBytes() const + { + return mABL.mBuffers[0].mDataByteSize; + } + + void SetBytes(UInt32 nBytes, void *data) + { + VerifyNotTrashingOwnedBuffer(); + XAssert(mABL.mNumberBuffers == 1); + mABL.mBuffers[0].mDataByteSize = nBytes; + mABL.mBuffers[0].mData = data; + } + + void CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl) + // copies bytes from srcbl + // make ptrbl reflect the length copied + // note that srcbl may be same as ptrbl! + { + // Note that this buffer *can* own memory and its pointers/lengths are not + // altered; only its buffer contents, which are copied from srcbl. + // The pointers/lengths in ptrbl are updated to reflect the addresses/lengths + // of the copied data, and srcbl's contents are consumed. + ptrbl->VerifyNotTrashingOwnedBuffer(); + UInt32 nBytes = srcbl->GetNumBytes(); + AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = srcbl->mABL.mBuffers, + *ptrbuf = ptrbl->mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf, ++ptrbuf) { + memmove(mybuf->mData, srcbuf->mData, srcbuf->mDataByteSize); + ptrbuf->mData = mybuf->mData; + ptrbuf->mDataByteSize = srcbuf->mDataByteSize; + } + if (srcbl != ptrbl) + srcbl->BytesConsumed(nBytes); + } + + // copies data from another buffer list. + void CopyDataFrom(const AudioBufferList &other) + { + for (unsigned i = 0; i < other.mNumberBuffers; ++i) { + XAssert(mBufferCapacity == 0 || other.mBuffers[i].mDataByteSize <= mBufferCapacity); + memcpy(mABL.mBuffers[i].mData, other.mBuffers[i].mData, + mABL.mBuffers[i].mDataByteSize = other.mBuffers[i].mDataByteSize); + } + } + + void AppendFrom(CABufferList *blp, UInt32 nBytes) + { + // this may mutate a buffer that owns memory. + AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = blp->mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) { + XAssert(nBytes <= srcbuf->mDataByteSize); + XAssert(mBufferCapacity == 0 || mybuf->mDataByteSize + nBytes <= mBufferCapacity); + memcpy((Byte *)mybuf->mData + mybuf->mDataByteSize, srcbuf->mData, nBytes); + mybuf->mDataByteSize += nBytes; + } + blp->BytesConsumed(nBytes); + } + + void PadWithZeroes(UInt32 desiredBufferSize) + // for cases where an algorithm (e.g. SRC) requires some + // padding to create silence following end-of-file + { + XAssert(mBufferCapacity == 0 || desiredBufferSize <= mBufferCapacity); + if (GetNumBytes() > desiredBufferSize) return; + AudioBuffer *buf = mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { + memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize); + buf->mDataByteSize = desiredBufferSize; + } + } + + void SetToZeroes(UInt32 nBytes) + { + XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity); + AudioBuffer *buf = mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { + memset((Byte *)buf->mData, 0, nBytes); + buf->mDataByteSize = nBytes; + } + } + + void Reset() + { + DeallocateBuffers(); + } + + Boolean SameDataAs(const CABufferList* anotherBufferList) + { + // check to see if two buffer lists point to the same memory. + if (mABL.mNumberBuffers != anotherBufferList->mABL.mNumberBuffers) return false; + + for (UInt32 i = 0; i < mABL.mNumberBuffers; ++i) { + if (mABL.mBuffers[i].mData != anotherBufferList->mABL.mBuffers[i].mData) return false; + } + return true; + } + + void BytesConsumed(UInt32 nBytes) + // advance buffer pointers, decrease buffer sizes + { + VerifyNotTrashingOwnedBuffer(); + AudioBuffer *buf = mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { + XAssert(nBytes <= buf->mDataByteSize); + buf->mData = (Byte *)buf->mData + nBytes; + buf->mDataByteSize -= nBytes; + } + } + + void SetFrom(const AudioBufferList *abl) + { + VerifyNotTrashingOwnedBuffer(); + memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl); + } + + void SetFrom(const CABufferList *blp) + { + SetFrom(&blp->GetBufferList()); + } + + void SetFrom(const AudioBufferList *abl, UInt32 nBytes) + { + VerifyNotTrashingOwnedBuffer(); + AudioBuffer *mybuf = mABL.mBuffers; + const AudioBuffer *srcbuf = abl->mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) { + mybuf->mNumberChannels = srcbuf->mNumberChannels; + mybuf->mDataByteSize = nBytes; + mybuf->mData = srcbuf->mData; + } + } + + void SetFrom(const CABufferList *blp, UInt32 nBytes) + { + SetFrom(&blp->GetBufferList(), nBytes); + } + + AudioBufferList * ToAudioBufferList(AudioBufferList *abl) const + { + memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mABL.mNumberBuffers] - (char *)abl); + return abl; + } + + void AllocateBuffers(UInt32 nBytes); + void AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList); + + void DeallocateBuffers(); + + void UseExternalBuffer(Byte *ptr, UInt32 nBytes); + + void AdvanceBufferPointers(UInt32 nBytes) // $$$ ReducingSize + // this is for bufferlists that function simply as + // an array of pointers into another bufferlist, being advanced, + // as in RenderOutput implementations + { + VerifyNotTrashingOwnedBuffer(); + AudioBuffer *buf = mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { + buf->mData = (Byte *)buf->mData + nBytes; + buf->mDataByteSize -= nBytes; + } + } + + void SetNumBytes(UInt32 nBytes) + { + XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity); + AudioBuffer *buf = mABL.mBuffers; + for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) + buf->mDataByteSize = nBytes; + } + + void Print(const char *label=NULL, int nframes=0, int wordSize=0) const + { + if (label == NULL) + label = mName; + printf("%s - ", label); + CAShowAudioBufferList(&GetBufferList(), nframes, wordSize); + if (mBufferMemory) + printf(" owned memory @ 0x%p:\n", mBufferMemory); + } + + UInt32 GetCapacityBytes() const { return mBufferCapacity; } + + template <typename T> + T* GetData(UInt32 inBuffer) { + return static_cast<T*>(mABL.mBuffers[inBuffer].mData); + } + +protected: + AudioBufferList & _GetBufferList() { return mABL; } // use with care + // if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer + void VerifyNotTrashingOwnedBuffer() + { + // This needs to be called from places where we are modifying the buffer pointers. + // It's an error to modify the buffer pointers or lengths if we own the buffer memory. + XAssert(mBufferMemory == NULL); + } + + const char * mName; // for debugging + Byte * mBufferMemory; + UInt32 mBufferCapacity; // max mDataByteSize of each buffer + AudioBufferList mABL; + // don't add anything here +}; + +#endif // __CABufferList_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp new file mode 100644 index 0000000000..2161be7447 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp @@ -0,0 +1,84 @@ +/* + File: CABundleLocker.cpp + Abstract: CABundleLocker.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 "CABundleLocker.h" +#include <pthread.h> + +/* +some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle +*/ + +static pthread_mutex_t sCABundleLocker = PTHREAD_MUTEX_INITIALIZER; + +#define RECURSIVE_LOCK 0 + +#if RECURSIVE_LOCK +static pthread_once_t sOnce = PTHREAD_ONCE_INIT; + +static void InitCABundleLocker() +{ + // have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&sCABundleLocker, &attr); + pthread_mutexattr_destroy(&attr); +} +#endif + +CABundleLocker::CABundleLocker() +{ +#if RECURSIVE_LOCK + pthread_once(&sOnce, InitCABundleLocker); +#endif + pthread_mutex_lock(&sCABundleLocker); +} + +CABundleLocker::~CABundleLocker() +{ + pthread_mutex_unlock(&sCABundleLocker); +} + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h new file mode 100644 index 0000000000..821ca34af0 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h @@ -0,0 +1,69 @@ +/* + File: CABundleLocker.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef _CABundleLocker_h_ +#define _CABundleLocker_h_ + +#include <TargetConditionals.h> + +/* +some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle +*/ + +class CABundleLocker +{ +public: + +#if TARGET_OS_MAC + CABundleLocker(); + ~CABundleLocker(); +#else + CABundleLocker() {} + ~CABundleLocker() {} +#endif +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h b/libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h new file mode 100644 index 0000000000..9a56c6d858 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h @@ -0,0 +1,161 @@ +/* + File: CAByteOrder.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAByteOrder_h__) +#define __CAByteOrder_h__ + +//============================================================================= +// Includes +//============================================================================= + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreFoundation/CoreFoundation.h> +#else + #include "CoreFoundation.h" +#endif + + +#if defined(__cplusplus) +extern "C" { +#endif + +CF_INLINE Float32 CASwapFloat32 (Float32 arg) { + union { + Float32 f; + UInt32 i; + } flip; + + flip.f = arg; + flip.i = CFSwapInt32 (flip.i); + + return flip.f; +} + +CF_INLINE Float64 CASwapFloat64 (Float64 arg) { + union { + Float64 f; + UInt64 i; + } flip; + + flip.f = arg; + flip.i = CFSwapInt64 (flip.i); + + return flip.f; +} + +#pragma mark -Flippers + +CF_INLINE Float32 CASwapFloat32BigToHost(Float32 arg) { +#if defined(__BIG_ENDIAN__) + return arg; +#else + return CASwapFloat32(arg); +#endif +} + +CF_INLINE Float64 CASwapFloat64BigToHost(Float64 arg) { +#if defined(__BIG_ENDIAN__) + return arg; +#else + return CASwapFloat64(arg); +#endif +} + +CF_INLINE Float32 CASwapFloat32HostToBig(Float32 arg) { +#if defined(__BIG_ENDIAN__) + return arg; +#else + return CASwapFloat32(arg); +#endif +} + +CF_INLINE Float64 CASwapFloat64HostToBig(Float64 arg) { +#if defined(__BIG_ENDIAN__) + return arg; +#else + return CASwapFloat64(arg); +#endif +} + +CF_INLINE Float32 CASwapFloat32LittleToHost(Float32 arg) { +#if defined(__LITTLE_ENDIAN__) + return arg; +#else + return CASwapFloat32(arg); +#endif +} + +CF_INLINE Float64 CASwapFloat64LittleToHost(Float64 arg) { +#if defined(__LITTLE_ENDIAN__) + return arg; +#else + return CASwapFloat64(arg); +#endif +} + +CF_INLINE Float32 CASwapFloat32HostToLittle(Float32 arg) { +#if defined(__LITTLE_ENDIAN__) + return arg; +#else + return CASwapFloat32(arg); +#endif +} + +CF_INLINE Float64 CASwapFloat64HostToLittle(Float64 arg) { +#if defined(__LITTLE_ENDIAN__) + return arg; +#else + return CASwapFloat64(arg); +#endif +} + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp new file mode 100644 index 0000000000..e7c057d8da --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp @@ -0,0 +1,821 @@ +/* + File: CACFArray.cpp + Abstract: CACFArray.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +// Self Include +#include "CACFArray.h" + +// PublicUtility Includes +#include "CACFDictionary.h" +#include "CACFNumber.h" +#include "CACFString.h" + +//============================================================================= +// CACFArray +//============================================================================= + +bool CACFArray::HasItem(const void* inItem) const +{ + bool theAnswer = false; + if(mCFArray != NULL) + { + CFRange theRange = { 0, CFArrayGetCount(mCFArray)}; + theAnswer = CFArrayContainsValue(mCFArray, theRange, inItem); + } + return theAnswer; +} + +bool CACFArray::GetIndexOfItem(const void* inItem, UInt32& outIndex) const +{ + bool theAnswer = false; + outIndex = 0; + if(mCFArray != NULL) + { + CFRange theRange = { 0, CFArrayGetCount(mCFArray)}; + CFIndex theIndex = CFArrayGetFirstIndexOfValue(mCFArray, theRange, inItem); + if(theIndex != -1) + { + theAnswer = true; + outIndex = ToUInt32(theIndex); + } + } + return theAnswer; +} + +bool CACFArray::GetBool(UInt32 inIndex, bool& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inIndex, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID())) + { + outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue)); + theAnswer = true; + } + else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + SInt32 theNumericValue = 0; + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue); + outValue = theNumericValue != 0; + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetSInt32(UInt32 inIndex, SInt32& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetUInt32(UInt32 inIndex, UInt32& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetSInt64(UInt32 inIndex, SInt64& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetUInt64(UInt32 inIndex, UInt64& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetFloat32(UInt32 inIndex, Float32& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat32Type, &outItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetFloat64(UInt32 inIndex, Float64& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat64Type, &outItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::Get4CC(UInt32 inIndex, UInt32& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inIndex, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue); + theAnswer = true; + } + else if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID())) + { + CFStringRef theString = static_cast<CFStringRef>(theValue); + if(CFStringGetLength(theString) == 4) + { + char theCString[5]; + CFStringGetCString(theString, theCString, 5, kCFStringEncodingASCII); + outValue = CFSwapInt32BigToHost(*reinterpret_cast<UInt32*>(theCString)); + } + } + } + + return theAnswer; +} + +bool CACFArray::GetString(UInt32 inIndex, CFStringRef& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID())) + { + outItem = static_cast<CFStringRef>(theItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetArray(UInt32 inIndex, CFArrayRef& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID())) + { + outItem = static_cast<CFArrayRef>(theItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID())) + { + outItem = static_cast<CFDictionaryRef>(theItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetData(UInt32 inIndex, CFDataRef& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFDataGetTypeID())) + { + outItem = static_cast<CFDataRef>(theItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetUUID(UInt32 inIndex, CFUUIDRef& outItem) const +{ + bool theAnswer = false; + + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFUUIDGetTypeID())) + { + outItem = static_cast<CFUUIDRef>(theItem); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFArray::GetCFType(UInt32 inIndex, CFTypeRef& outItem) const +{ + bool theAnswer = false; + + if((mCFArray != NULL) && (inIndex < GetNumberItems())) + { + outItem = CFArrayGetValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex)); + theAnswer = outItem != NULL; + } + + return theAnswer; +} + +void CACFArray::GetCACFString(UInt32 inIndex, CACFString& outItem) const +{ + outItem = static_cast<CFStringRef>(NULL); + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID())) + { + outItem = static_cast<CFStringRef>(theItem); + } + } +} + +void CACFArray::GetCACFArray(UInt32 inIndex, CACFArray& outItem) const +{ + outItem = static_cast<CFArrayRef>(NULL); + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID())) + { + outItem = static_cast<CFArrayRef>(theItem); + } + } +} + +void CACFArray::GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const +{ + outItem = static_cast<CFDictionaryRef>(NULL); + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID())) + { + outItem = static_cast<CFDictionaryRef>(theItem); + } + } +} + +bool CACFArray::AppendBool(bool inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFBoolean theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = AppendCFType(theItem.GetCFBoolean()); + } + } + + return theAnswer; +} + +bool CACFArray::AppendSInt32(SInt32 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = AppendCFType(theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::AppendUInt32(UInt32 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = AppendCFType(theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::AppendSInt64(SInt64 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = AppendCFType(theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::AppendUInt64(UInt64 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = AppendCFType(theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::AppendFloat32(Float32 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = AppendCFType(theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::AppendFloat64(Float64 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = AppendCFType(theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::AppendString(const CFStringRef inItem) +{ + return AppendCFType(inItem); +} + +bool CACFArray::AppendArray(const CFArrayRef inItem) +{ + return AppendCFType(inItem); +} + +bool CACFArray::AppendDictionary(const CFDictionaryRef inItem) +{ + return AppendCFType(inItem); +} + +bool CACFArray::AppendData(const CFDataRef inItem) +{ + return AppendCFType(inItem); +} + +bool CACFArray::AppendCFType(const CFTypeRef inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CFArrayAppendValue(mCFArray, inItem); + theAnswer = true; + } + + return theAnswer; +} + +bool CACFArray::InsertBool(UInt32 inIndex, bool inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFBoolean theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = InsertCFType(inIndex, theItem.GetCFBoolean()); + } + } + + return theAnswer; +} + +bool CACFArray::InsertSInt32(UInt32 inIndex, SInt32 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = InsertCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::InsertUInt32(UInt32 inIndex, UInt32 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = InsertCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::InsertSInt64(UInt32 inIndex, SInt64 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = InsertCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::InsertUInt64(UInt32 inIndex, UInt64 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = InsertCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::InsertFloat32(UInt32 inIndex, Float32 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = InsertCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::InsertFloat64(UInt32 inIndex, Float64 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = InsertCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::InsertString(UInt32 inIndex, const CFStringRef inItem) +{ + return InsertCFType(inIndex, inItem); +} + +bool CACFArray::InsertArray(UInt32 inIndex, const CFArrayRef inItem) +{ + return InsertCFType(inIndex, inItem); +} + +bool CACFArray::InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem) +{ + return InsertCFType(inIndex, inItem); +} + +bool CACFArray::InsertData(UInt32 inIndex, const CFDataRef inItem) +{ + return InsertCFType(inIndex, inItem); +} + +bool CACFArray::InsertCFType(UInt32 inIndex, const CFTypeRef inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable) + { + if(inIndex < GetNumberItems()) + { + CFArrayInsertValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex), inItem); + } + else + { + CFArrayAppendValue(mCFArray, inItem); + } + theAnswer = true; + } + + return theAnswer; +} + +bool CACFArray::SetBool(UInt32 inIndex, bool inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems())) + { + CACFBoolean theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = SetCFType(inIndex, theItem.GetCFBoolean()); + } + } + + return theAnswer; +} + +bool CACFArray::SetSInt32(UInt32 inIndex, SInt32 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems())) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = SetCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::SetUInt32(UInt32 inIndex, UInt32 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems())) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = SetCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::SetSInt64(UInt32 inIndex, SInt64 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems())) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = SetCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::SetUInt64(UInt32 inIndex, UInt64 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems())) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = SetCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::SetFloat32(UInt32 inIndex, Float32 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems())) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = SetCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::SetFloat64(UInt32 inIndex, Float64 inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems())) + { + CACFNumber theItem(inItem); + if(theItem.IsValid()) + { + theAnswer = SetCFType(inIndex, theItem.GetCFNumber()); + } + } + + return theAnswer; +} + +bool CACFArray::SetString(UInt32 inIndex, const CFStringRef inItem) +{ + return SetCFType(inIndex, inItem); +} + +bool CACFArray::SetArray(UInt32 inIndex, const CFArrayRef inItem) +{ + return SetCFType(inIndex, inItem); +} + +bool CACFArray::SetDictionary(UInt32 inIndex, const CFDictionaryRef inItem) +{ + return SetCFType(inIndex, inItem); +} + +bool CACFArray::SetData(UInt32 inIndex, const CFDataRef inItem) +{ + return SetCFType(inIndex, inItem); +} + +bool CACFArray::SetCFType(UInt32 inIndex, const CFTypeRef inItem) +{ + bool theAnswer = false; + + if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems())) + { + CFArraySetValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex), inItem); + theAnswer = true; + } + + return theAnswer; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFArray.h b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.h new file mode 100644 index 0000000000..89c8c559e4 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.h @@ -0,0 +1,195 @@ +/* + File: CACFArray.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFArray_h__) +#define __CACFArray_h__ + +//============================================================================= +// Includes +//============================================================================= + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> + #include <CoreFoundation/CoreFoundation.h> +#else + #include <CoreAudioTypes.h> + #include <CoreFoundation.h> +#endif + +#include "CADebugMacros.h" + +//============================================================================= +// Types +//============================================================================= + +class CACFDictionary; +class CACFString; + +//============================================================================= +// CACFArray +//============================================================================= + +class CACFArray +{ + +// Construction/Destruction +public: + CACFArray() : mCFArray(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)), mRelease(true), mMutable(true) {} + explicit CACFArray(bool inRelease) : mCFArray(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {} + CACFArray(UInt32 inMaxNumberItems, bool inRelease) : mCFArray(CFArrayCreateMutable(NULL, static_cast<CFIndex>(inMaxNumberItems), &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {} + CACFArray(CFArrayRef inCFArray, bool inRelease) : mCFArray(const_cast<CFMutableArrayRef>(inCFArray)), mRelease(inRelease), mMutable(false) {} + CACFArray(CFMutableArrayRef inCFArray, bool inRelease) : mCFArray(inCFArray), mRelease(inRelease), mMutable(true) {} + CACFArray(const CACFArray& inArray) : mCFArray(inArray.mCFArray), mRelease(inArray.mRelease), mMutable(inArray.mMutable) { Retain(); } + CACFArray& operator=(const CACFArray& inArray) { Release(); mCFArray = inArray.mCFArray; mRelease = inArray.mRelease; mMutable = inArray.mMutable; Retain(); return *this; } + CACFArray& operator=(CFArrayRef inCFArray) { Release(); mCFArray = const_cast<CFMutableArrayRef>(inCFArray); mMutable = false; Retain(); return *this; } + CACFArray& operator=(CFMutableArrayRef inCFArray) { Release(); mCFArray = inCFArray; mMutable = true; Retain(); return *this; } + ~CACFArray() { Release(); } + +private: + void Retain() { if(mRelease && (mCFArray != NULL)) { CFRetain(mCFArray); } } + void Release() { if(mRelease && (mCFArray != NULL)) { CFRelease(mCFArray); } } + +// Attributes +public: + bool IsValid() const { return mCFArray != NULL; } + bool IsMutable() const { return mMutable; } + bool CanModify() const { return mMutable && (mCFArray != NULL); } + + bool WillRelease() const { return mRelease; } + void ShouldRelease(bool inRelease) { mRelease = inRelease; } + + CFTypeID GetTypeID() const { return CFGetTypeID(mCFArray); } + + CFArrayRef GetCFArray() const { return mCFArray; } + CFArrayRef CopyCFArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; } + + CFMutableArrayRef GetCFMutableArray() const { return mCFArray; } + CFMutableArrayRef CopyCFMutableArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; } + CFPropertyListRef AsPropertyList() const { return mCFArray; } + + void SetCFMutableArrayFromCopy(CFArrayRef inArray, bool inRelease = true) { Release(); mCFArray = CFArrayCreateMutableCopy(NULL, 0, inArray); mMutable = true; mRelease = inRelease; } + +// Item Operations +public: + UInt32 GetNumberItems() const { UInt32 theAnswer = 0; if(mCFArray != NULL) { theAnswer = ToUInt32(CFArrayGetCount(mCFArray)); } return theAnswer; } + bool HasItem(const void* inItem) const; + void RemoveItem(const void* inItem) { UInt32 theIndex; if(CanModify() && GetIndexOfItem(inItem, theIndex)) { RemoveItemAtIndex(theIndex); } } + bool GetIndexOfItem(const void* inItem, UInt32& outIndex) const; + void RemoveItemAtIndex(UInt32 inIndex) { if(CanModify()) { CFArrayRemoveValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex)); } } + void Clear() { if(CanModify()) { CFArrayRemoveAllValues(mCFArray); } } + void Sort(CFComparatorFunction inCompareFunction) { if(CanModify()) { CFRange theRange = { 0, CFArrayGetCount(mCFArray) }; CFArraySortValues(mCFArray, theRange, inCompareFunction, NULL); } } + void SortNumbers() { Sort((CFComparatorFunction)CFNumberCompare); } + void SortStrings() { Sort((CFComparatorFunction)CFStringCompare); } + + bool GetBool(UInt32 inIndex, bool& outValue) const; + bool GetSInt32(UInt32 inIndex, SInt32& outItem) const; + bool GetUInt32(UInt32 inIndex, UInt32& outItem) const; + bool GetSInt64(UInt32 inIndex, SInt64& outItem) const; + bool GetUInt64(UInt32 inIndex, UInt64& outItem) const; + bool GetFloat32(UInt32 inIndex, Float32& outItem) const; + bool GetFloat64(UInt32 inIndex, Float64& outItem) const; + bool Get4CC(UInt32 inIndex, UInt32& outValue) const; + bool GetString(UInt32 inIndex, CFStringRef& outItem) const; + bool GetArray(UInt32 inIndex, CFArrayRef& outItem) const; + bool GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const; + bool GetData(UInt32 inIndex, CFDataRef& outItem) const; + bool GetUUID(UInt32 inIndex, CFUUIDRef& outItem) const; + bool GetCFType(UInt32 inIndex, CFTypeRef& outItem) const; + + void GetCACFString(UInt32 inIndex, CACFString& outItem) const; + void GetCACFArray(UInt32 inIndex, CACFArray& outItem) const; + void GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const; + + bool AppendBool(bool inItem); + bool AppendSInt32(SInt32 inItem); + bool AppendUInt32(UInt32 inItem); + bool AppendSInt64(SInt64 inItem); + bool AppendUInt64(UInt64 inItem); + bool AppendFloat32(Float32 inItem); + bool AppendFloat64(Float64 inItem); + bool AppendString(const CFStringRef inItem); + bool AppendArray(const CFArrayRef inItem); + bool AppendDictionary(const CFDictionaryRef inItem); + bool AppendData(const CFDataRef inItem); + bool AppendCFType(const CFTypeRef inItem); + + bool InsertBool(UInt32 inIndex, bool inItem); + bool InsertSInt32(UInt32 inIndex, SInt32 inItem); + bool InsertUInt32(UInt32 inIndex, UInt32 inItem); + bool InsertSInt64(UInt32 inIndex, SInt64 inItem); + bool InsertUInt64(UInt32 inIndex, UInt64 inItem); + bool InsertFloat32(UInt32 inIndex, Float32 inItem); + bool InsertFloat64(UInt32 inIndex, Float64 inItem); + bool InsertString(UInt32 inIndex, const CFStringRef inItem); + bool InsertArray(UInt32 inIndex, const CFArrayRef inItem); + bool InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem); + bool InsertData(UInt32 inIndex, const CFDataRef inItem); + bool InsertCFType(UInt32 inIndex, const CFTypeRef inItem); + + bool SetBool(UInt32 inIndex, bool inItem); + bool SetSInt32(UInt32 inIndex, SInt32 inItem); + bool SetUInt32(UInt32 inIndex, UInt32 inItem); + bool SetSInt64(UInt32 inIndex, SInt64 inItem); + bool SetUInt64(UInt32 inIndex, UInt64 inItem); + bool SetFloat32(UInt32 inIndex, Float32 inItem); + bool SetFloat64(UInt32 inIndex, Float64 inItem); + bool SetString(UInt32 inIndex, const CFStringRef inItem); + bool SetArray(UInt32 inIndex, const CFArrayRef inItem); + bool SetDictionary(UInt32 inIndex, const CFDictionaryRef inItem); + bool SetData(UInt32 inIndex, const CFDataRef inItem); + bool SetCFType(UInt32 inIndex, const CFTypeRef inItem); + +// Implementation +private: + CFMutableArrayRef mCFArray; + bool mRelease; + bool mMutable; + + CACFArray(const void*); // prevent accidental instantiation with a pointer via bool constructor +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFData.h b/libs/appleutility/CoreAudio/PublicUtility/CACFData.h new file mode 100644 index 0000000000..7ce08dcf13 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFData.h @@ -0,0 +1,108 @@ +/* + File: CACFData.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFData_h__) +#define __CACFData_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> + #include <CoreFoundation/CFData.h> +#else + #include <CoreAudioTypes.h> + #include <CFData.h> +#endif + +#include "CADebugMacros.h" + +//============================================================================= +// CACFData +//============================================================================= + +class CACFData +{ + +// Construction/Destruction +public: + explicit CACFData(CFDataRef inCFData) : mCFData(inCFData), mWillRelease(true) {} + CACFData(CFDataRef inCFData, bool inWillRelease) : mCFData(inCFData), mWillRelease(inWillRelease) {} + CACFData(const void* inData, UInt32 inDataSize) : mCFData(NULL), mWillRelease(true) { mCFData = CFDataCreate(NULL, static_cast<const UInt8*>(inData), static_cast<CFIndex>(inDataSize)); } + ~CACFData() { Release(); } + CACFData(const CACFData& inNumber) : mCFData(inNumber.mCFData), mWillRelease(inNumber.mWillRelease) { Retain(); } + CACFData& operator=(const CACFData& inNumber) { Release(); mCFData = inNumber.mCFData; mWillRelease = inNumber.mWillRelease; Retain(); return *this; } + CACFData& operator=(CFDataRef inCFData) { Release(); mCFData = inCFData; mWillRelease = true; return *this; } + +private: + void Retain() { if(mWillRelease && (mCFData != NULL)) { CFRetain(mCFData); } } + void Release() { if(mWillRelease && (mCFData != NULL)) { CFRelease(mCFData); } } + + CFDataRef mCFData; + bool mWillRelease; + +// Operations +public: + void AllowRelease() { mWillRelease = true; } + void DontAllowRelease() { mWillRelease = false; } + bool IsValid() { return mCFData != NULL; } + +// Value Access +public: + CFDataRef GetCFData() const { return mCFData; } + CFDataRef CopyCFData() const { if(mCFData != NULL) { CFRetain(mCFData); } return mCFData; } + + UInt32 GetSize() const { return ToUInt32(CFDataGetLength(mCFData)); } + const void* GetDataPtr() const { return CFDataGetBytePtr(mCFData); } + void CopyData(UInt32 inStartOffset, void* outData, UInt32 inDataSize) const { CFRange theRange = { static_cast<CFIndex>(inStartOffset), static_cast<CFIndex>(inDataSize) }; CFDataGetBytes(mCFData, theRange, static_cast<UInt8*>(outData)); } + + SInt32 GetSInt32() const { SInt32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(SInt32)); return theAnswer; } + Float32 GetFloat32() const { Float32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(Float32)); return theAnswer; } + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp new file mode 100644 index 0000000000..fbac774ab5 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp @@ -0,0 +1,581 @@ +/* + File: CACFDictionary.cpp + Abstract: CACFDictionary.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +// Self Include +#include "CACFDictionary.h" + +// PublicUtility Includes +#include "CACFArray.h" +#include "CACFNumber.h" +#include "CACFString.h" + +//============================================================================= +// CACFDictionary +//============================================================================= + +bool CACFDictionary::HasKey(const CFStringRef inKey) const +{ + return CFDictionaryContainsKey(mCFDictionary, inKey) != 0; +} + +UInt32 CACFDictionary::Size () const +{ + return mCFDictionary ? ToUInt32(CFDictionaryGetCount(mCFDictionary)) : 0; +} + +void CACFDictionary::GetKeys (const void **keys) const +{ + CFDictionaryGetKeysAndValues(mCFDictionary, keys, NULL); +} + +void CACFDictionary::GetKeysAndValues (const void **keys, const void **values) const +{ + CFDictionaryGetKeysAndValues(mCFDictionary, keys, values); +} + +bool CACFDictionary::GetBool(const CFStringRef inKey, bool& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID())) + { + outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue)); + theAnswer = true; + } + else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + SInt32 theNumericValue = 0; + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue); + outValue = theNumericValue != 0; + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetSInt32(const CFStringRef inKey, SInt32& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetUInt32(const CFStringRef inKey, UInt32& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetSInt64(const CFStringRef inKey, SInt64& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetUInt64(const CFStringRef inKey, UInt64& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetFloat32FromString(const CFStringRef inKey, Float32& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID())) + { + outValue = static_cast<Float32>(CFStringGetDoubleValue(static_cast<CFStringRef>(theValue))); + } + } + + return theAnswer; +} + +bool CACFDictionary::GetUInt32FromString(const CFStringRef inKey, UInt32& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID())) + { + outValue = CFStringGetIntValue(static_cast<CFStringRef>(theValue)); + } + } + + return theAnswer; +} + +bool CACFDictionary::GetFloat32(const CFStringRef inKey, Float32& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetFloat64(const CFStringRef inKey, Float64& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetFixed32(const CFStringRef inKey, Float32& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + SInt32 theFixed32 = 0; + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theFixed32); + + // this is a 16.16 value so convert it to a float + Float32 theSign = theFixed32 < 0 ? -1.0f : 1.0f; + theFixed32 *= (SInt32)theSign; + Float32 theWholePart = (theFixed32 & 0x7FFF0000) >> 16; + Float32 theFractPart = theFixed32 & 0x0000FFFF; + theFractPart /= 65536.0f; + outValue = theSign * (theWholePart + theFractPart); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetFixed64(const CFStringRef inKey, Float64& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + SInt64 theFixed64 = 0; + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &theFixed64); + outValue = static_cast<Float64>(theFixed64 >> 32); + outValue += static_cast<Float64>(theFixed64 & 0x00000000FFFFFFFFLL) / static_cast<Float64>(0x0000000100000000LL); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::Get4CC(const CFStringRef inKey, UInt32& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue); + theAnswer = true; + } + else if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID())) + { + CFStringRef theString = static_cast<CFStringRef>(theValue); + if(CFStringGetLength(theString) == 4) + { + char theCString[5]; + CFStringGetCString(theString, theCString, 5, kCFStringEncodingASCII); + outValue = CFSwapInt32BigToHost(*reinterpret_cast<UInt32*>(theCString)); + } + } + } + + return theAnswer; +} + +bool CACFDictionary::GetString(const CFStringRef inKey, CFStringRef& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID())) + { + outValue = static_cast<CFStringRef>(theValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetArray(const CFStringRef inKey, CFArrayRef& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID())) + { + outValue = static_cast<CFArrayRef>(theValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID())) + { + outValue = static_cast<CFDictionaryRef>(theValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetData(const CFStringRef inKey, CFDataRef& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFDataGetTypeID())) + { + outValue = static_cast<CFDataRef>(theValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const +{ + bool theAnswer = false; + + if(mCFDictionary != NULL) + { + outValue = CFDictionaryGetValue(mCFDictionary, inKey); + theAnswer = (outValue != NULL); + } + + return theAnswer; +} + +bool CACFDictionary::GetURL(const CFStringRef inKey, CFURLRef& outValue) const +{ + bool theAnswer = false; + + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFURLGetTypeID())) + { + outValue = static_cast<CFURLRef>(theValue); + theAnswer = true; + } + } + + return theAnswer; +} + +bool CACFDictionary::GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const +{ + bool theAnswer = false; + + if(mCFDictionary != NULL) + { + CACFString theKey(inKey); + if(theKey.IsValid()) + { + theAnswer = GetCFType(theKey.GetCFString(), outValue); + } + } + + return theAnswer; +} + +void CACFDictionary::GetCACFString(const CFStringRef inKey, CACFString& outValue) const +{ + outValue = static_cast<CFStringRef>(NULL); + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID())) + { + outValue = static_cast<CFStringRef>(theValue); + } + } +} + +void CACFDictionary::GetCACFArray(const CFStringRef inKey, CACFArray& outValue) const +{ + outValue = static_cast<CFArrayRef>(NULL); + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID())) + { + outValue = static_cast<CFArrayRef>(theValue); + } + } +} + +void CACFDictionary::GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outValue) const +{ + outValue = static_cast<CFDictionaryRef>(NULL); + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID())) + { + outValue = static_cast<CFDictionaryRef>(theValue); + } + } +} + +bool CACFDictionary::AddBool(const CFStringRef inKey, bool inValue) +{ + CACFBoolean theValue(inValue); + return AddCFType(inKey, theValue.GetCFBoolean()); +} + +bool CACFDictionary::AddSInt32(const CFStringRef inKey, SInt32 inValue) +{ + CACFNumber theValue(inValue); + return AddCFType(inKey, theValue.GetCFNumber()); +} + +bool CACFDictionary::AddUInt32(const CFStringRef inKey, UInt32 inValue) +{ + CACFNumber theValue(inValue); + return AddCFType(inKey, theValue.GetCFNumber()); +} + +bool CACFDictionary::AddSInt64(const CFStringRef inKey, SInt64 inValue) +{ + CACFNumber theValue(inValue); + return AddCFType(inKey, theValue.GetCFNumber()); +} + +bool CACFDictionary::AddUInt64(const CFStringRef inKey, UInt64 inValue) +{ + CACFNumber theValue(inValue); + return AddCFType(inKey, theValue.GetCFNumber()); +} + +bool CACFDictionary::AddFloat32(const CFStringRef inKey, Float32 inValue) +{ + CACFNumber theValue(inValue); + return AddCFType(inKey, theValue.GetCFNumber()); +} + +bool CACFDictionary::AddFloat64(const CFStringRef inKey, Float64 inValue) +{ + CACFNumber theValue(inValue); + return AddCFType(inKey, theValue.GetCFNumber()); +} + +bool CACFDictionary::AddNumber(const CFStringRef inKey, const CFNumberRef inValue) +{ + return AddCFType(inKey, inValue); +} + +bool CACFDictionary::AddString(const CFStringRef inKey, const CFStringRef inValue) +{ + return AddCFType(inKey, inValue); +} + +bool CACFDictionary::AddArray(const CFStringRef inKey, const CFArrayRef inValue) +{ + return AddCFType(inKey, inValue); +} + +bool CACFDictionary::AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue) +{ + return AddCFType(inKey, inValue); +} + +bool CACFDictionary::AddData(const CFStringRef inKey, const CFDataRef inValue) +{ + return AddCFType(inKey, inValue); +} + +bool CACFDictionary::AddURL(const CFStringRef inKey, const CFURLRef inValue) +{ + return AddCFType (inKey, inValue); +} + +bool CACFDictionary::AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue) +{ + bool theAnswer = false; + + if (inKey) + { + CACFString theKey(inKey); + if(theKey.IsValid()) + { + theAnswer = AddCFType(theKey.GetCFString(), inValue); + } + } + + return theAnswer; +} + +bool CACFDictionary::AddCString(const CFStringRef inKey, const char* inValue) +{ + bool theAnswer = false; + + if (inValue) + { + CACFString theValue(inValue); + if(theValue.IsValid()) + { + theAnswer = AddCFType(inKey, theValue.GetCFString()); + } + } + return theAnswer; +} + +bool CACFDictionary::AddCFType(const CFStringRef inKey, const CFTypeRef inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL) && inValue) + { + CFDictionarySetValue(mCFDictionary, inKey, inValue); + theAnswer = true; + } + + return theAnswer; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h new file mode 100644 index 0000000000..c389e50042 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h @@ -0,0 +1,176 @@ +/* + File: CACFDictionary.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFDictionary_h__) +#define __CACFDictionary_h__ + +//============================================================================= +// Includes +//============================================================================= + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreFoundation/CoreFoundation.h> +#else + #include <CoreFoundation.h> +#endif + +//============================================================================= +// Types +//============================================================================= + +class CACFArray; +class CACFString; + +//============================================================================= +// CACFDictionary +//============================================================================= + +class CACFDictionary +{ + +// Construction/Destruction +public: + CACFDictionary() : mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(true), mMutable(true) {} + explicit CACFDictionary(bool inRelease) : mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(inRelease), mMutable(true) {} + CACFDictionary(CFDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(const_cast<CFMutableDictionaryRef>(inCFDictionary)), mRelease(inRelease), mMutable(false) {} + CACFDictionary(CFMutableDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(inCFDictionary), mRelease(inRelease), mMutable(true) {} + CACFDictionary(const CACFDictionary& inDictionary) : mCFDictionary(inDictionary.mCFDictionary), mRelease(inDictionary.mRelease), mMutable(inDictionary.mMutable) { Retain(); } + CACFDictionary& operator=(const CACFDictionary& inDictionary) { Release(); mCFDictionary = inDictionary.mCFDictionary; mRelease = inDictionary.mRelease; mMutable = inDictionary.mMutable; Retain(); return *this; } + CACFDictionary& operator=(CFDictionaryRef inDictionary) { Release(); mCFDictionary = const_cast<CFMutableDictionaryRef>(inDictionary); mMutable = false; Retain(); return *this; } + CACFDictionary& operator=(CFMutableDictionaryRef inDictionary) { Release(); mCFDictionary = inDictionary; mMutable = true; Retain(); return *this; } + ~CACFDictionary() { Release(); } + +private: + void Retain() { if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } } + void Release() { if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } } + +// Attributes +public: + bool IsValid() const { return mCFDictionary != NULL; } + bool IsMutable() const { return mMutable;} + bool CanModify() const { return mMutable && (mCFDictionary != NULL); } + + bool WillRelease() const { return mRelease; } + void ShouldRelease(bool inRelease) { mRelease = inRelease; } + + CFDictionaryRef GetDict() const { return mCFDictionary; } + CFDictionaryRef GetCFDictionary() const { return mCFDictionary; } + CFDictionaryRef CopyCFDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; } + + CFMutableDictionaryRef GetMutableDict() { return mCFDictionary; } + CFMutableDictionaryRef GetCFMutableDictionary() const { return mCFDictionary; } + CFMutableDictionaryRef CopyCFMutableDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; } + void SetCFMutableDictionaryFromCopy(CFDictionaryRef inDictionary, bool inRelease = true) { Release(); mCFDictionary = CFDictionaryCreateMutableCopy(NULL, 0, inDictionary); mMutable = true; mRelease = inRelease; } + void SetCFMutableDictionaryToEmpty(bool inRelease = true) { Release(); mCFDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); mMutable = true; mRelease = inRelease; } + + CFPropertyListRef AsPropertyList() const { return mCFDictionary; } + OSStatus GetDictIfMutable(CFMutableDictionaryRef& outDict) const { OSStatus theAnswer = -1; if(mMutable) { outDict = mCFDictionary; theAnswer = 0; } return theAnswer; } + +// Item Operations +public: + bool HasKey(const CFStringRef inKey) const; + UInt32 Size() const; + void GetKeys(const void** keys) const; + void GetKeysAndValues (const void **keys, const void **values) const; + + bool GetBool(const CFStringRef inKey, bool& outValue) const; + bool GetSInt32(const CFStringRef inKey, SInt32& outValue) const; + bool GetUInt32(const CFStringRef inKey, UInt32& outValue) const; + bool GetUInt32FromString(const CFStringRef inKey, UInt32& outValue) const; + bool GetSInt64(const CFStringRef inKey, SInt64& outValue) const; + bool GetUInt64(const CFStringRef inKey, UInt64& outValue) const; + bool GetFloat32(const CFStringRef inKey, Float32& outValue) const; + bool GetFloat32FromString(const CFStringRef inKey, Float32& outValue) const; + bool GetFloat64(const CFStringRef inKey, Float64& outValue) const; + bool GetFixed32(const CFStringRef inKey, Float32& outValue) const; + bool GetFixed64(const CFStringRef inKey, Float64& outValue) const; + bool Get4CC(const CFStringRef inKey, UInt32& outValue) const; + bool GetString(const CFStringRef inKey, CFStringRef& outValue) const; + bool GetArray(const CFStringRef inKey, CFArrayRef& outValue) const; + bool GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const; + bool GetData(const CFStringRef inKey, CFDataRef& outValue) const; + bool GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const; + bool GetURL(const CFStringRef inKey, CFURLRef& outValue) const; + bool GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const; + + void GetCACFString(const CFStringRef inKey, CACFString& outItem) const; + void GetCACFArray(const CFStringRef inKey, CACFArray& outItem) const; + void GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outItem) const; + + bool AddBool(const CFStringRef inKey, bool inValue); + bool AddSInt32(const CFStringRef inKey, SInt32 inValue); + bool AddUInt32(const CFStringRef inKey, UInt32 inValue); + bool AddSInt64(const CFStringRef inKey, SInt64 inValue); + bool AddUInt64(const CFStringRef inKey, UInt64 inValue); + bool AddFloat32(const CFStringRef inKey, Float32 inValue); + bool AddFloat64(const CFStringRef inKey, Float64 inValue); + bool AddNumber(const CFStringRef inKey, const CFNumberRef inValue); + bool AddString(const CFStringRef inKey, const CFStringRef inValue); + bool AddArray(const CFStringRef inKey, const CFArrayRef inValue); + bool AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue); + bool AddData(const CFStringRef inKey, const CFDataRef inValue); + bool AddCFType(const CFStringRef inKey, const CFTypeRef inValue); + bool AddURL(const CFStringRef inKey, const CFURLRef inValue); + + bool AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue); + bool AddCString(const CFStringRef inKey, const char* inValue); + + void RemoveKey(const CFStringRef inKey) { if(CanModify()) { CFDictionaryRemoveValue(mCFDictionary, inKey); } } + void Clear() { if(CanModify()) { CFDictionaryRemoveAllValues(mCFDictionary); } } + + void Show() { CFShow(mCFDictionary); } + +// Implementation +private: + CFMutableDictionaryRef mCFDictionary; + bool mRelease; + bool mMutable; + + CACFDictionary(const void*); // prevent accidental instantiation with a pointer via bool constructor +}; + +#endif //__CACFDictionary_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp new file mode 100644 index 0000000000..36c6923e2d --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp @@ -0,0 +1,107 @@ +/* + File: CACFDistributedNotification.cpp + Abstract: CACFDistributedNotification.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CACFDistributedNotification.h" + +// PublicUtility Includes +#include "CADebugMacros.h" + +//================================================================================================== +// CACFDistributedNotification +//================================================================================================== + +void CACFDistributedNotification::AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior) +{ +#if !TARGET_OS_IPHONE + CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter(); + CFNotificationSuspensionBehavior theSuspensionBehavior = inSuspensionBehavior; +#else + #pragma unused(inSuspensionBehavior) + CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter(); + CFNotificationSuspensionBehavior theSuspensionBehavior = static_cast<CFNotificationSuspensionBehavior>(0); +#endif + + CFNotificationCenterAddObserver(theCenter, inObserver, inCallback, inName, NULL, theSuspensionBehavior); +} + +void CACFDistributedNotification::RemoveObserver(const void* inObserver, CFStringRef inName) +{ +#if !TARGET_OS_IPHONE + CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter(); +#else + CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter(); +#endif + + CFNotificationCenterRemoveObserver(theCenter, inObserver, inName, NULL); +} + +void CACFDistributedNotification::PostNotification(CFStringRef inName, CFDictionaryRef inUserInfo, bool inPostToAllSessions) +{ +#if !TARGET_OS_IPHONE + CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter(); + CFDictionaryRef theUserInfo = inUserInfo; + CFOptionFlags theFlags = kCFNotificationDeliverImmediately; + if(inPostToAllSessions) + { + theFlags += kCFNotificationPostToAllSessions; + } +#else + // flag unsupported features + Assert(inUserInfo == NULL, "CACFDistributedNotification::PostNotification: distributed notifications do not support a payload"); + Assert(inPostToAllSessions, "CACFDistributedNotification::PostNotification: distributed notifications do not support per-session delivery"); + + CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter(); + CFDictionaryRef theUserInfo = NULL; + CFOptionFlags theFlags = 0; +#endif + + CFNotificationCenterPostNotificationWithOptions(theCenter, inName, NULL, theUserInfo, theFlags); +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h new file mode 100644 index 0000000000..d75e23bd8a --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h @@ -0,0 +1,73 @@ +/* + File: CACFDistributedNotification.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFDistributedNotification_h__) +#define __CACFDistributedNotification_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// System Includes +#include <CoreAudio/CoreAudioTypes.h> +#include <CoreFoundation/CoreFoundation.h> + +//================================================================================================== +// CACFDistributedNotification +//================================================================================================== + +class CACFDistributedNotification +{ + +// Operations +public: + static void AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior = CFNotificationSuspensionBehaviorCoalesce); + static void RemoveObserver(const void* inObserver, CFStringRef inName); + static void PostNotification(CFStringRef inName, CFDictionaryRef inUserInfo, bool inPostToAllSessions); + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp new file mode 100644 index 0000000000..9a33d5dae1 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp @@ -0,0 +1,168 @@ +/* + File: CACFMachPort.cpp + Abstract: CACFMachPort.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +#include "CACFMachPort.h" +#include "CAException.h" +#include "CADebugMacros.h" + +//================================================================================================== +// CACFMachPort +//================================================================================================== + +// This constructor is the short form. The CFMachPort will own the send and receive rights. +CACFMachPort::CACFMachPort(CFMachPortCallBack inCallBack, void* inUserData) +: + mMachPort(NULL), + mRunLoopSource(NULL), + mOwnsPort(true) +{ + CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL }; + mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL); + ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort(s): couldn't create the CFMachPort"); + + mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0); + if(mRunLoopSource == NULL) + { + CFMachPortInvalidate(mMachPort); + CFRelease(mMachPort); + mMachPort = NULL; + DebugMessage("CACFMachPort::CACFMachPort(s): couldn't create the CFRunLoopSource"); + throw CAException('what'); + } +} + +// This constructor is the general form: +// - If inMachPort is MACH_PORT_NULL, the CFMachPort will allocate the port and own the send and +// receive rights. Otherwise, the caller owns the rights and is resposible for cleaning them +// up. +// - If inCallBack is NULL, then received messages will just get swallowed by the CFMachPort. +// This is useful if you are only using the CFMachPort to track port death (aka invalidation). +// - If inInvalidationCallBack is non-NULL, then it will be installed as the invalidation +// callback on the CFMachPort. +CACFMachPort::CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData) +: + mMachPort(NULL), + mRunLoopSource(NULL), + mOwnsPort(false) +{ + CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL }; + + if(inMachPort == MACH_PORT_NULL) + { + mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL); + ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort"); + mOwnsPort = true; + } + else + { + mMachPort = CFMachPortCreateWithPort(NULL, inMachPort, inCallBack, &theContext, NULL); + ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort with a port"); + mOwnsPort = false; + } + + mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0); + if(mRunLoopSource == NULL) + { + if(mOwnsPort) + { + CFMachPortInvalidate(mMachPort); + } + CFRelease(mMachPort); + mMachPort = NULL; + DebugMessage("CACFMachPort::CACFMachPort: couldn't create the CFRunLoopSource"); + throw CAException('what'); + } + + if(inInvalidationCallBack != NULL) + { + CFMachPortSetInvalidationCallBack(mMachPort, inInvalidationCallBack); + } +} + +CACFMachPort::~CACFMachPort() +{ + if(mRunLoopSource != NULL) + { + CFRelease(mRunLoopSource); + } + + if(mMachPort != NULL) + { + if(mOwnsPort) + { + CFMachPortInvalidate(mMachPort); + } + CFRelease(mMachPort); + } +} + +kern_return_t CACFMachPort::ReceiveMessage(UInt32 inMaxMessageSize, mach_msg_header_t* outMessage, mach_msg_timeout_t inTimeOut) +{ + // snag the port + mach_port_t thePort = CFMachPortGetPort(mMachPort); + + // fill out the message header + outMessage->msgh_bits = 0; + outMessage->msgh_size = 0; + outMessage->msgh_remote_port = MACH_PORT_NULL; + outMessage->msgh_local_port = thePort; + outMessage->msgh_reserved = 0; + outMessage->msgh_id = 0; + + // figure the options + mach_msg_options_t theOptions = MACH_RCV_MSG; + if(inTimeOut > 0) + { + theOptions |= MACH_RCV_TIMEOUT; + } + + // receive the messsage + return mach_msg(outMessage, theOptions, 0, inMaxMessageSize, thePort, inTimeOut, MACH_PORT_NULL); +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h new file mode 100644 index 0000000000..18b8ccc6c2 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h @@ -0,0 +1,95 @@ +/* + File: CACFMachPort.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFMachPort_h__) +#define __CACFMachPort_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// System Includes +#include <CoreFoundation/CFMachPort.h> +#include <mach/mach.h> + +//================================================================================================== +// CACFMachPort +// +// This class wraps a CFMachPort. +// +// Note that when you create a CFMachPort object, CF will attach the run loop source for the the +// Mach Port that handles Port Death notifications (aka the Invalidation Callback) to the current +// thread's run loop. This is something over which there is no control, so be sure to create the +// CFMachPort on the thread on which you want to handle Port Death notificaitons on. +//================================================================================================== + +class CACFMachPort +{ + +// Construction/Destruction +public: + CACFMachPort(CFMachPortCallBack inCallBack, void* inUserData = NULL); + CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData); + virtual ~CACFMachPort(); + +// Attributes +public: + CFMachPortRef GetMachPortRef() const { return mMachPort; } + mach_port_t GetMachPort() const { return CFMachPortGetPort(mMachPort); } + CFRunLoopSourceRef GetRunLoopSource() const { return mRunLoopSource; } + +// Operations +public: + kern_return_t ReceiveMessage(UInt32 inMaxMessageSize, mach_msg_header_t* outMessage, mach_msg_timeout_t inTimeOut); + +// Implementation +protected: + CFMachPortRef mMachPort; + CFRunLoopSourceRef mRunLoopSource; + bool mOwnsPort; +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp new file mode 100644 index 0000000000..97b5da1dd9 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp @@ -0,0 +1,163 @@ +/* + File: CACFMessagePort.cpp + Abstract: CACFMessagePort.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CACFMessagePort.h" +#include "CADebugMacros.h" +#include "CAException.h" + +//============================================================================= +// CACFLocalMessagePort +//============================================================================= + +CACFLocalMessagePort::CACFLocalMessagePort(CFStringRef inName, CFMessagePortCallBack inPortCallBack, CFMessagePortInvalidationCallBack inInvalidationCallBack, void* inUserData) +: + mMessagePort(NULL), + mRunLoopSource(NULL), + mDispatchQueue(NULL) +{ + // create the CFMessagePort + CFMessagePortContext theContext = { 0, inUserData, NULL, NULL, NULL }; + mMessagePort = CFMessagePortCreateLocal(NULL, inName, inPortCallBack, &theContext, NULL); + if(mMessagePort != NULL) + { + // add the invalidation callback, if any + if(inInvalidationCallBack != NULL) + { + CFMessagePortSetInvalidationCallBack(mMessagePort, inInvalidationCallBack); + } + } +} + +CACFLocalMessagePort::~CACFLocalMessagePort() +{ + if(mRunLoopSource != NULL) + { + CFRelease(mRunLoopSource); + } + if(mMessagePort != NULL) + { + CFMessagePortInvalidate(mMessagePort); + CFRelease(mMessagePort); + } +} + +CFRunLoopSourceRef CACFLocalMessagePort::GetRunLoopSource() const +{ + Assert(mDispatchQueue == NULL, "CACFLocalMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue"); + if(mRunLoopSource == NULL) + { + const_cast<CACFLocalMessagePort*>(this)->mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0); + } + return mRunLoopSource; +} + +void CACFLocalMessagePort::SetDispatchQueue(dispatch_queue_t inDispatchQueue) +{ + Assert(mRunLoopSource == NULL, "CACFLocalMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue"); + mDispatchQueue = inDispatchQueue; + CFMessagePortSetDispatchQueue(mMessagePort, mDispatchQueue); +} + +//============================================================================= +// CACFRemoteMessagePort +//============================================================================= + +CACFRemoteMessagePort::CACFRemoteMessagePort(CFStringRef inName, CFMessagePortInvalidationCallBack inInvalidationCallBack) +: + mMessagePort(NULL), + mRunLoopSource(NULL), + mDispatchQueue(NULL) +{ + // create the CFMessagePort + mMessagePort = CFMessagePortCreateRemote(NULL, inName); + if(mMessagePort != NULL) + { + // failure to create a remote port does not need to throw an exception + // because it isn't really an error since the port in question may not + // exist and this fact requires a more complex response than an excpeption + // provides for. + + // add the invalidation callback, if any + if(inInvalidationCallBack != NULL) + { + CFMessagePortSetInvalidationCallBack(mMessagePort, inInvalidationCallBack); + } + } +} + +CACFRemoteMessagePort::~CACFRemoteMessagePort() +{ + if(mRunLoopSource != NULL) + { + CFRelease(mRunLoopSource); + } + if(mMessagePort != NULL) + { + //CFMessagePortInvalidate(mMessagePort); + CFRelease(mMessagePort); + } +} + +CFRunLoopSourceRef CACFRemoteMessagePort::GetRunLoopSource() const +{ + Assert(mDispatchQueue == NULL, "CACFRemoteMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue"); + if(mRunLoopSource == NULL) + { + const_cast<CACFRemoteMessagePort*>(this)->mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0); + } + return mRunLoopSource; +} + +void CACFRemoteMessagePort::SetDispatchQueue(dispatch_queue_t inDispatchQueue) +{ + Assert(mRunLoopSource == NULL, "CACFRemoteMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue"); + mDispatchQueue = inDispatchQueue; + CFMessagePortSetDispatchQueue(mMessagePort, mDispatchQueue); +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h new file mode 100644 index 0000000000..c369251664 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h @@ -0,0 +1,119 @@ +/* + File: CACFMessagePort.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFMessagePort_h__) +#define __CACFMessagePort_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreFoundation/CFMessagePort.h> +#else + #include <CFMessagePort.h> +#endif + +//============================================================================= +// CACFLocalMessagePort +//============================================================================= + +class CACFLocalMessagePort +{ + +// Construction/Destruction +public: + CACFLocalMessagePort(CFStringRef inName, CFMessagePortCallBack inPortCallBack, CFMessagePortInvalidationCallBack inInvalidationCallBack, void* inUserData = NULL); + virtual ~CACFLocalMessagePort(); + +// Attributes +public: + bool IsValid() const { return mMessagePort != NULL; } + CFMessagePortRef GetMessagePortRef() const { return mMessagePort; } + CFRunLoopSourceRef GetRunLoopSource() const; + void SetDispatchQueue(dispatch_queue_t inDispatchQueue); + +// Implementation +protected: + CFMessagePortRef mMessagePort; + CFRunLoopSourceRef mRunLoopSource; + dispatch_queue_t mDispatchQueue; + +}; + +//============================================================================= +// CACFRemoteMessagePort +//============================================================================= + +class CACFRemoteMessagePort +{ + +// Construction/Destruction +public: + CACFRemoteMessagePort(CFStringRef inName, CFMessagePortInvalidationCallBack inInvalidationCallBack); + virtual ~CACFRemoteMessagePort(); + +// Attributes +public: + bool IsValid() const { return mMessagePort != NULL; } + CFMessagePortRef GetMessagePortRef() const { return mMessagePort; } + CFRunLoopSourceRef GetRunLoopSource() const; + void SetDispatchQueue(dispatch_queue_t inDispatchQueue); + +// Operations +public: + SInt32 SendRequest(SInt32 inMessageID, CFDataRef inData, CFTimeInterval inSendTimeout, CFTimeInterval inReceiveTimout) const { return CFMessagePortSendRequest(mMessagePort, inMessageID, inData, inSendTimeout, inReceiveTimout, NULL, NULL); } + SInt32 SendRequest(SInt32 inMessageID, CFDataRef inData, CFTimeInterval inSendTimeout, CFTimeInterval inReceiveTimout, CFStringRef inReplyMode, CFDataRef& outReturnData) const { return CFMessagePortSendRequest(mMessagePort, inMessageID, inData, inSendTimeout, inReceiveTimout, inReplyMode, &outReturnData); } + +// Implementation +protected: + CFMessagePortRef mMessagePort; + CFRunLoopSourceRef mRunLoopSource; + dispatch_queue_t mDispatchQueue; + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp new file mode 100644 index 0000000000..36d1c2e2e2 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp @@ -0,0 +1,83 @@ +/* + File: CACFNumber.cpp + Abstract: CACFNumber.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CACFNumber.h" + +//============================================================================= +// CACFNumber +//============================================================================= + +Float32 CACFNumber::GetFixed32() const +{ + SInt32 theFixedValue = GetSInt32(); + + // this is a 16.16 value so convert it to a float + Float32 theSign = theFixedValue < 0 ? -1.0f : 1.0f; + theFixedValue *= (SInt32)theSign; + Float32 theWholePart = (theFixedValue & 0x7FFF0000) >> 16; + Float32 theFractPart = theFixedValue & 0x0000FFFF; + theFractPart /= 65536.0f; + + return theSign * (theWholePart + theFractPart); +} + +Float64 CACFNumber::GetFixed64() const +{ + SInt64 theFixedValue = GetSInt64(); + + // this is a 32.32 value so convert it to a double + Float64 theSign = theFixedValue < 0 ? -1.0 : 1.0; + theFixedValue *= (SInt64)theSign; + Float64 theWholePart = (theFixedValue & 0x7FFFFFFF00000000LL) >> 32; + Float64 theFractPart = theFixedValue & 0x00000000FFFFFFFFLL; + theFractPart /= 4294967296.0; + + return theSign * (theWholePart + theFractPart); +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h new file mode 100644 index 0000000000..25887f6ca1 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h @@ -0,0 +1,151 @@ +/* + File: CACFNumber.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFNumber_h__) +#define __CACFNumber_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> + #include <CoreFoundation/CFNumber.h> +#else + #include <CoreAudioTypes.h> + #include <CFNumber.h> +#endif + +//============================================================================= +// CACFBoolean +//============================================================================= + +class CACFBoolean +{ +// Construction/Destruction +public: + explicit CACFBoolean(CFBooleanRef inCFBoolean) : mCFBoolean(inCFBoolean), mWillRelease(true) {} + CACFBoolean(CFBooleanRef inCFBoolean, bool inWillRelease) : mCFBoolean(inCFBoolean), mWillRelease(inWillRelease) {} + explicit CACFBoolean(bool inValue) : mCFBoolean(inValue ? kCFBooleanTrue : kCFBooleanFalse), mWillRelease(true) { Retain(); } + ~CACFBoolean() { Release(); } + CACFBoolean(const CACFBoolean& inBoolean) : mCFBoolean(inBoolean.mCFBoolean), mWillRelease(inBoolean.mWillRelease) { Retain(); } + CACFBoolean& operator=(const CACFBoolean& inBoolean) { Release(); mCFBoolean = inBoolean.mCFBoolean; mWillRelease = inBoolean.mWillRelease; Retain(); return *this; } + CACFBoolean& operator=(CFBooleanRef inCFBoolean) { Release(); mCFBoolean = inCFBoolean; mWillRelease = true; return *this; } + +private: + void Retain() { if(mWillRelease && (mCFBoolean != NULL)) { CFRetain(mCFBoolean); } } + void Release() { if(mWillRelease && (mCFBoolean != NULL)) { CFRelease(mCFBoolean); } } + + CFBooleanRef mCFBoolean; + bool mWillRelease; + +// Operations +public: + void AllowRelease() { mWillRelease = true; } + void DontAllowRelease() { mWillRelease = false; } + bool IsValid() { return mCFBoolean != NULL; } + +// Value Access +public: + CFBooleanRef GetCFBoolean() const { return mCFBoolean; } + CFBooleanRef CopyCFBoolean() const { if(mCFBoolean != NULL) { CFRetain(mCFBoolean); } return mCFBoolean; } + + bool GetBoolean() const { bool theAnswer = false; if(mCFBoolean != NULL) { theAnswer = CFEqual(mCFBoolean, kCFBooleanTrue); } return theAnswer; } + + CACFBoolean(const void*); // prevent accidental instantiation with a pointer via bool constructor +}; + +//============================================================================= +// CACFNumber +//============================================================================= + +class CACFNumber +{ +// Construction/Destruction +public: + explicit CACFNumber(CFNumberRef inCFNumber) : mCFNumber(inCFNumber), mWillRelease(true) {} + CACFNumber(CFNumberRef inCFNumber, bool inWillRelease) : mCFNumber(inCFNumber), mWillRelease(inWillRelease) {} + CACFNumber(SInt32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt32Type, &inValue)), mWillRelease(true) {} + CACFNumber(UInt32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt32Type, &inValue)), mWillRelease(true) {} + CACFNumber(SInt64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt64Type, &inValue)), mWillRelease(true) {} + CACFNumber(UInt64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt64Type, &inValue)), mWillRelease(true) {} + CACFNumber(Float32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberFloat32Type, &inValue)), mWillRelease(true) {} + CACFNumber(Float64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberFloat64Type, &inValue)), mWillRelease(true) {} + ~CACFNumber() { Release(); } + CACFNumber(const CACFNumber& inNumber) : mCFNumber(inNumber.mCFNumber), mWillRelease(inNumber.mWillRelease) { Retain(); } + CACFNumber& operator=(const CACFNumber& inNumber) { Release(); mCFNumber = inNumber.mCFNumber; mWillRelease = inNumber.mWillRelease; Retain(); return *this; } + CACFNumber& operator=(CFNumberRef inCFNumber) { Release(); mCFNumber = inCFNumber; mWillRelease = true; return *this; } + +private: + void Retain() { if(mWillRelease && (mCFNumber != NULL)) { CFRetain(mCFNumber); } } + void Release() { if(mWillRelease && (mCFNumber != NULL)) { CFRelease(mCFNumber); } } + + CFNumberRef mCFNumber; + bool mWillRelease; + +// Operations +public: + void AllowRelease() { mWillRelease = true; } + void DontAllowRelease() { mWillRelease = false; } + bool IsValid() const { return mCFNumber != NULL; } + +// Value Access +public: + CFNumberRef GetCFNumber() const { return mCFNumber; } + CFNumberRef CopyCFNumber() const { if(mCFNumber != NULL) { CFRetain(mCFNumber); } return mCFNumber; } + + SInt8 GetSInt8() const { SInt8 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt8Type, &theAnswer); } return theAnswer; } + SInt32 GetSInt32() const { SInt32 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt32Type, &theAnswer); } return theAnswer; } + UInt32 GetUInt32() const { UInt32 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt32Type, &theAnswer); } return theAnswer; } + Float32 GetFloat32() const { Float32 theAnswer = 0.0f; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberFloat32Type, &theAnswer); } return theAnswer; } + Float32 GetFixed32() const; + Float64 GetFixed64() const; + SInt64 GetSInt64() const { SInt64 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt64Type, &theAnswer); } return theAnswer; } + + CACFNumber(const void*); // prevent accidental instantiation with a pointer via bool constructor +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFObject.h b/libs/appleutility/CoreAudio/PublicUtility/CACFObject.h new file mode 100644 index 0000000000..748016b48f --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFObject.h @@ -0,0 +1,138 @@ +/* + File: CACFObject.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFObject_h__) +#define __CACFObject_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> + #include <CoreFoundation/CoreFoundation.h> +#else + #include <CoreAudioTypes.h> + #include <CoreFoundation.h> +#endif + +//============================================================================= +// Wrappers for CFRetain and CFRelease that check for NULL +//============================================================================= + +template <typename CFObjectType> +CFObjectType CACFRetain(CFObjectType inObject) +{ + CFObjectType theAnswer = inObject; + if(inObject != NULL) + { + theAnswer = reinterpret_cast<CFObjectType>(CFRetain(inObject)); + } + return theAnswer; +} + +inline void CACFRelease(CFTypeRef inObject) +{ + if(inObject != NULL) + { + CFRelease(inObject); + } +} + +//============================================================================= +// CACFObject +// +// Notes +// - Using the AssignWithoutRetain() method will fool the static analyzer into thinking that the +// CFObject being assigned will be leaked. This is because the static analyzer is not smart +// enough to understand that the destructor will release the object. +//============================================================================= + +template <class CFObjectType> +class CACFObject +{ + +// Construction/Destruction +public: + CACFObject() : mCFObject(NULL), mWillRelease(true) {} + explicit CACFObject(CFObjectType inCFObject) : mCFObject(inCFObject), mWillRelease(true) {} + CACFObject(CFObjectType inCFObject, bool inWillRelease) : mCFObject(inCFObject), mWillRelease(inWillRelease) {} + ~CACFObject() { Release(); } + CACFObject(const CACFObject& inObject) : mCFObject(inObject.mCFObject), mWillRelease(inObject.mWillRelease) { Retain(); } + CACFObject& operator=(const CACFObject& inObject) { Release(); mCFObject = inObject.mCFObject; mWillRelease = inObject.mWillRelease; Retain(); return *this; } + CACFObject& operator=(CFObjectType inCFObject) { Release(); mCFObject = inCFObject; mWillRelease = true; Retain(); return *this; } + void AssignWithoutRetain(CFObjectType inObject) { if (inObject != mCFObject) { Release(); mCFObject = inObject; } mWillRelease = true; } + +private: + void Retain() { if(mWillRelease && (mCFObject != NULL)) { CFRetain(mCFObject); } } + void Release() { if(mWillRelease && (mCFObject != NULL)) { CFRelease(mCFObject); mCFObject = NULL; } } + + CFObjectType mCFObject; + bool mWillRelease; + +// Operations +public: + void AllowRelease() { mWillRelease = true; } + void DontAllowRelease() { mWillRelease = false; } + bool IsValid() const { return mCFObject != NULL; } + CFTypeID GetTypeID() const { return CFGetTypeID(mCFObject); } + bool IsEqual(CFObjectType inCFObject) const { return CFEqual(inCFObject, mCFObject) != 0; } + +// Value Access +public: + CFObjectType GetCFObject() const { return mCFObject; } + CFObjectType CopyCFObject() const { if(mCFObject != NULL) { CFRetain(mCFObject); } return mCFObject; } + const CFObjectType* GetPointerToStorage() const { return &mCFObject; } + +}; + +typedef CACFObject<CFBundleRef> CACFBundle; +typedef CACFObject<CFPropertyListRef> CACFPropertyList; +typedef CACFObject<CFTypeRef> CACFType; +typedef CACFObject<CFUUIDRef> CACFUUID; +typedef CACFObject<CFURLRef> CACFURL; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h b/libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h new file mode 100644 index 0000000000..babde13b90 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h @@ -0,0 +1,101 @@ +/* + File: CACFPlugIn.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFPlugIn_h__) +#define __CACFPlugIn_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// System Includes +#include <CoreAudio/CoreAudioTypes.h> +#include <CoreFoundation/CFPlugIn.h> + +//================================================================================================== +// CACFPlugIn +//================================================================================================== + +class CACFPlugIn +{ + +// Construction/Destruction +public: + CACFPlugIn() : mCFPlugIn(NULL), mWillRelease(true) {} + CACFPlugIn(CFPlugInRef inCFPlugIn, bool inWillRelease = true) : mCFPlugIn(inCFPlugIn), mWillRelease(inWillRelease) {} + CACFPlugIn(CFURLRef inURL, bool inWillRelease = true) : mCFPlugIn(CFPlugInCreate(NULL, inURL)), mWillRelease(inWillRelease) {} + ~CACFPlugIn() { Release(); } + CACFPlugIn(const CACFPlugIn& inObject) : mCFPlugIn(inObject.mCFPlugIn), mWillRelease(inObject.mWillRelease) { Retain(); } + CACFPlugIn& operator=(const CACFPlugIn& inObject) { Release(); mCFPlugIn = inObject.mCFPlugIn; mWillRelease = inObject.mWillRelease; Retain(); return *this; } + CACFPlugIn& operator=(CFPlugInRef inCFPlugIn) { Release(); mCFPlugIn = inCFPlugIn; mWillRelease = true; return *this; } + +private: + void Retain() { if(mWillRelease && (mCFPlugIn != NULL)) { CFRetain(mCFPlugIn); } } + void Release() { if(mWillRelease && (mCFPlugIn != NULL)) { CFRelease(mCFPlugIn); mCFPlugIn = NULL; } } + + CFPlugInRef mCFPlugIn; + bool mWillRelease; + +// Operations +public: + void AllowRelease() { mWillRelease = true; } + void DontAllowRelease() { mWillRelease = false; } + bool IsValid() const { return mCFPlugIn != NULL; } + + CFBundleRef GetBundle() const { CFBundleRef theAnswer = NULL; if(IsValid()) { theAnswer = CFPlugInGetBundle(mCFPlugIn); } return theAnswer; } + CFStringRef CopyBundleID() const { CFStringRef theAnswer = NULL; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetIdentifier(theBundle); if(theAnswer != NULL) { CFRetain(theAnswer); } } return theAnswer; } + UInt32 GetBundleVersion() const { UInt32 theAnswer = 0; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetVersionNumber(theBundle); } return theAnswer; } + CFDictionaryRef CopyBundleInfo() const { CFDictionaryRef theAnswer = NULL; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetInfoDictionary(theBundle); if(theAnswer != NULL) { CFRetain(theAnswer); } } return theAnswer; } + CFArrayRef FindFactoriesForType(CFUUIDRef inTypeUUID) const { CFArrayRef theAnswer = NULL; if(IsValid()) { theAnswer = CFPlugInFindFactoriesForPlugInTypeInPlugIn(inTypeUUID, mCFPlugIn); } return theAnswer; } + +// Value Access +public: + CFPlugInRef GetCFPlugIn() const { return mCFPlugIn; } + CFPlugInRef CopyCFPlugIn() const { if(mCFPlugIn != NULL) { CFRetain(mCFPlugIn); } return mCFPlugIn; } + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp new file mode 100644 index 0000000000..cb2e86c34d --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp @@ -0,0 +1,287 @@ +/* + File: CACFPreferences.cpp + Abstract: CACFPreferences.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CACFPreferences.h" + +// PublicUtility Includes +#include "CACFDistributedNotification.h" +#include "CADebugMacros.h" + +//================================================================================================== +// CACFPreferences +//================================================================================================== + +CFPropertyListRef CACFPreferences::CopyValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost) +{ + // synchronize to make sure that what's in memory matches what's on disk + Synchronize(inCurrentUser, inCurrentHost, false); + + CFPropertyListRef theAnswer = NULL; + CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser; + CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost; + + theAnswer = CFPreferencesCopyValue(inKey, kCFPreferencesAnyApplication, theUser, theHost); + + return theAnswer; +} + +CFStringRef CACFPreferences::CopyStringValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost) +{ + CFStringRef theAnswer = NULL; + + // get the raw value + CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost); + + if(theRawValue != NULL) + { + // get it's type ID and make sure it's a CFString + CFTypeID theTypeID = CFGetTypeID(theRawValue); + if(theTypeID == CFStringGetTypeID()) + { + // cast the value + theAnswer = static_cast<CFStringRef>(theRawValue); + } + else + { + CFRelease(theRawValue); + DebugMessage("CACFPreferences::CopyStringValue: not a CFString"); + } + } + + return theAnswer; +} + +CFNumberRef CACFPreferences::CopyNumberValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost) +{ + CFNumberRef theAnswer = NULL; + + // get the raw value + CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost); + + if(theRawValue != NULL) + { + // get it's type ID and make sure it's a CFNumber + CFTypeID theTypeID = CFGetTypeID(theRawValue); + if(theTypeID == CFNumberGetTypeID()) + { + // cast the value + theAnswer = static_cast<CFNumberRef>(theRawValue); + } + else + { + CFRelease(theRawValue); + DebugMessage("CACFPreferences::CopyNumberValue: not a CFNumber"); + } + } + + return theAnswer; +} + +CFArrayRef CACFPreferences::CopyArrayValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost) +{ + CFArrayRef theAnswer = NULL; + + // get the raw value + CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost); + + if(theRawValue != NULL) + { + // get it's type ID and make sure it's a CFArray + CFTypeID theTypeID = CFGetTypeID(theRawValue); + if(theTypeID == CFArrayGetTypeID()) + { + // cast the value + theAnswer = static_cast<CFArrayRef>(theRawValue); + } + else + { + CFRelease(theRawValue); + DebugMessage("CACFPreferences::CopyArrayValue: not a CFArray"); + } + } + + return theAnswer; +} + +CFDictionaryRef CACFPreferences::CopyDictionaryValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost) +{ + CFDictionaryRef theAnswer = NULL; + + // get the raw value + CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost); + + if(theRawValue != NULL) + { + // get it's type ID and make sure it's a CFDictionary + CFTypeID theTypeID = CFGetTypeID(theRawValue); + if(theTypeID == CFDictionaryGetTypeID()) + { + // cast the value + theAnswer = static_cast<CFDictionaryRef>(theRawValue); + } + else + { + CFRelease(theRawValue); + DebugMessage("CACFPreferences::CopyDictionaryValue: not a CFDictionary"); + } + } + + return theAnswer; +} + +void CACFPreferences::SetValue(CFStringRef inKey, CFPropertyListRef inValue, bool inCurrentUser, bool inCurrentHost, bool inSynchronize) +{ + CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser; + CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost; + CFPreferencesSetValue(inKey, inValue, kCFPreferencesAnyApplication, theUser, theHost); + + if(inSynchronize) + { + Synchronize(inCurrentUser, inCurrentHost, true); + } +} + +void CACFPreferences::DeleteValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost, bool inSynchronize) +{ + CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser; + CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost; + CFPreferencesSetValue(inKey, NULL, kCFPreferencesAnyApplication, theUser, theHost); + + if(inSynchronize) + { + Synchronize(theUser, inCurrentHost, true); + } +} + +void CACFPreferences::Synchronize(bool inCurrentUser, bool inCurrentHost, bool inForce) +{ + if(inForce || ArePrefsOutOfDate(inCurrentUser, inCurrentHost)) + { + CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser; + CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost; + CFPreferencesSynchronize(kCFPreferencesAnyApplication, theUser, theHost); + MarkPrefsClean(inCurrentUser, inCurrentHost); + } +} + +void CACFPreferences::MarkPrefsOutOfDate(bool inCurrentUser, bool inCurrentHost) +{ + if(!inCurrentUser && !inCurrentHost) + { + sAnyUserAnyHostPrefsOutOfDate = true; + } + else if(!inCurrentUser && inCurrentHost) + { + sAnyUserCurrentHostPrefsOutOfDate = true; + } + else if(inCurrentUser && !inCurrentHost) + { + sCurrentUserAnyHostPrefsOutOfDate = true; + } + else if(inCurrentUser && inCurrentHost) + { + sCurrentUserCurrentHostPrefsOutOfDate = true; + } +} + +void CACFPreferences::MarkPrefsClean(bool inCurrentUser, bool inCurrentHost) +{ + if(!inCurrentUser && !inCurrentHost) + { + sAnyUserAnyHostPrefsOutOfDate = false; + } + else if(!inCurrentUser && inCurrentHost) + { + sAnyUserCurrentHostPrefsOutOfDate = false; + } + else if(inCurrentUser && !inCurrentHost) + { + sCurrentUserAnyHostPrefsOutOfDate = false; + } + else if(inCurrentUser && inCurrentHost) + { + sCurrentUserCurrentHostPrefsOutOfDate = false; + } +} + +void CACFPreferences::SendNotification(CFStringRef inName) +{ + CACFDistributedNotification::PostNotification(inName, NULL, true); +} + +bool CACFPreferences::ArePrefsOutOfDate(bool inCurrentUser, bool inCurrentHost) +{ + bool theAnswer = false; + + if(!inCurrentUser && !inCurrentHost) + { + theAnswer = sAnyUserAnyHostPrefsOutOfDate; + } + else if(!inCurrentUser && inCurrentHost) + { + theAnswer = sAnyUserCurrentHostPrefsOutOfDate; + } + else if(inCurrentUser && !inCurrentHost) + { + theAnswer = sCurrentUserAnyHostPrefsOutOfDate; + } + else if(inCurrentUser && inCurrentHost) + { + theAnswer = sCurrentUserCurrentHostPrefsOutOfDate; + } + + return theAnswer; +} + +bool CACFPreferences::sAnyUserAnyHostPrefsOutOfDate = false; +bool CACFPreferences::sAnyUserCurrentHostPrefsOutOfDate = false; +bool CACFPreferences::sCurrentUserAnyHostPrefsOutOfDate = false; +bool CACFPreferences::sCurrentUserCurrentHostPrefsOutOfDate = false; diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h new file mode 100644 index 0000000000..040490f74e --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h @@ -0,0 +1,92 @@ +/* + File: CACFPreferences.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFPreferences_h__) +#define __CACFPreferences_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreFoundation/CoreFoundation.h> +#else + #include <CoreFoundation.h> +#endif + +//================================================================================================== +// CACFPreferences +//================================================================================================== + +class CACFPreferences +{ + +// Operations +public: + static CFPropertyListRef CopyValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost); + static CFStringRef CopyStringValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost); + static CFNumberRef CopyNumberValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost); + static CFArrayRef CopyArrayValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost); + static CFDictionaryRef CopyDictionaryValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost); + static void SetValue(CFStringRef inKey, CFPropertyListRef inValue, bool inCurrentUser, bool inCurrentHost, bool inSynchronize); + static void DeleteValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost, bool inSynchronize); + static void Synchronize(bool inCurrentUser, bool inCurrentHost, bool inForce); + static void MarkPrefsOutOfDate(bool inCurrentUser, bool inCurrentHost); + static void MarkPrefsClean(bool inCurrentUser, bool inCurrentHost); + static void SendNotification(CFStringRef inName); + +private: + static bool ArePrefsOutOfDate(bool inCurrentUser, bool inCurrentHost); + + static bool sAnyUserAnyHostPrefsOutOfDate; + static bool sAnyUserCurrentHostPrefsOutOfDate; + static bool sCurrentUserAnyHostPrefsOutOfDate; + static bool sCurrentUserCurrentHostPrefsOutOfDate; + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp new file mode 100644 index 0000000000..3ce81a56f4 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp @@ -0,0 +1,110 @@ +/* + File: CACFString.cpp + Abstract: CACFString.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CACFString.h" + +//============================================================================= +// CACFString +//============================================================================= + +UInt32 CACFString::GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding) +{ + CFIndex theAnswer = 0; + + if(inCFString != NULL) + { + CFRange theRange = { 0, CFStringGetLength(inCFString) }; + CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, NULL, 0x7FFFFFFF, &theAnswer); + } + + return UInt32(theAnswer); +} + +void CACFString::GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding) +{ + if(ioStringSize > 0) + { + if(inCFString != NULL) + { + CFIndex theLength = 0; + CFRange theRange = { 0, CFStringGetLength(inCFString) }; + CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, (UInt8*)outString, static_cast<CFIndex>(ioStringSize - 1), &theLength); + outString[theLength] = 0; + ioStringSize = ToUInt32(theLength) + 1; + } + else + { + outString[0] = 0; + ioStringSize = 1; + } + } +} + +void CACFString::GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize) +{ + if(ioStringSize > 0) + { + if(inCFString != NULL) + { + CFRange theStringRange = { 0, CFStringGetLength(inCFString) }; + if(static_cast<UInt32>(theStringRange.length) > ioStringSize) + { + theStringRange.length = static_cast<CFIndex>(ioStringSize); + } + CFStringGetCharacters(inCFString, theStringRange, outString); + ioStringSize = ToUInt32(theStringRange.length); + } + else + { + outString[0] = 0; + ioStringSize = 0; + } + } +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFString.h b/libs/appleutility/CoreAudio/PublicUtility/CACFString.h new file mode 100644 index 0000000000..3abce514bf --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CACFString.h @@ -0,0 +1,196 @@ +/* + File: CACFString.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CACFString_h__) +#define __CACFString_h__ + +//============================================================================= +// Includes +//============================================================================= + +#include "CADebugMacros.h" + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> + #include <CoreFoundation/CFString.h> +#else + #include <CoreAudioTypes.h> + #include <CFString.h> +#endif + +//============================================================================= +// CACFString +// +// Notes +// - Using the AssignWithoutRetain() method will fool the static analyzer into thinking that the +// CFString being assigned will be leaked. This is because the static analyzer is not smart +// enough to understand that the destructor will release the object. +//============================================================================= + +class CACFString +{ +// Construction/Destruction +public: + CACFString() : mCFString(NULL), mWillRelease(true) {} + explicit CACFString(CFStringRef inCFString) : mCFString(inCFString), mWillRelease(true) {} + CACFString(const char* inCString) : mCFString(CFStringCreateWithCString(NULL, inCString, kCFStringEncodingASCII)), mWillRelease(true) {} + CACFString(CFStringRef inCFString, bool inWillRelease) : mCFString(inCFString), mWillRelease(inWillRelease) {} + CACFString(const char* inCString, bool inWillRelease) : mCFString(CFStringCreateWithCString(NULL, inCString, kCFStringEncodingASCII)), mWillRelease(inWillRelease) {} + CACFString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFString(CFStringCreateWithCString(NULL, inCString, inCStringEncoding)), mWillRelease(inWillRelease) {} + ~CACFString() { Release(); } + CACFString(const CACFString& inString) : mCFString(inString.mCFString), mWillRelease(inString.mWillRelease) { Retain(); } + CACFString& operator=(const CACFString& inString) { if (inString.mCFString != mCFString) { Release(); mCFString = inString.mCFString; mWillRelease = inString.mWillRelease; Retain(); } return *this; } + CACFString& operator=(CFStringRef inCFString) { if (inCFString != mCFString) { Release(); mCFString = inCFString; } mWillRelease = true; Retain(); return *this; } + void AssignWithoutRetain(CFStringRef inCFString) { if (inCFString != mCFString) { Release(); mCFString = inCFString; } mWillRelease = true; } + +private: + void Retain() { if(mWillRelease && (mCFString != NULL)) { CFRetain(mCFString); } } + void Release() { if(mWillRelease && (mCFString != NULL)) { CFRelease(mCFString); } } + + CFStringRef mCFString; + bool mWillRelease; + +// Operations +public: + void AllowRelease() { mWillRelease = true; } + void DontAllowRelease() { mWillRelease = false; } + bool IsValid() const { return mCFString != NULL; } + bool IsEqualTo(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringCompare(inString, mCFString, 0) == kCFCompareEqualTo; } return theAnswer; } + bool StartsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringHasPrefix(mCFString, inString); } return theAnswer; } + bool EndsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringHasSuffix(mCFString, inString); } return theAnswer; } + +// Value Access +public: + CFStringRef GetCFString() const { return mCFString; } + CFStringRef CopyCFString() const { if(mCFString != NULL) { CFRetain(mCFString); } return mCFString; } + const CFStringRef* GetPointerToStorage() const { return &mCFString; } + CFStringRef& GetStorage() { Release(); mWillRelease = true; return mCFString; } + UInt32 GetLength() const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = ToUInt32(CFStringGetLength(mCFString)); } return theAnswer; } + UInt32 GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = GetStringByteLength(mCFString, inEncoding); } return theAnswer; } + void GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { GetCString(mCFString, outString, ioStringSize, inEncoding); } + void GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { GetUnicodeString(mCFString, outString, ioStringSize); } + SInt32 GetAsInteger() { return GetAsInteger(mCFString); } + Float64 GetAsFloat64() { return GetAsFloat64(mCFString); } + + static UInt32 GetStringLength(CFStringRef inCFString) { UInt32 theAnswer = 0; if(inCFString != NULL) { theAnswer = ToUInt32(CFStringGetLength(inCFString)); } return theAnswer; } + static UInt32 GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding = kCFStringEncodingUTF8); + static void GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8); + static void GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize); + static SInt32 GetAsInteger(CFStringRef inCFString) { SInt32 theAnswer = 0; if(inCFString != NULL){ theAnswer = CFStringGetIntValue(inCFString); } return theAnswer; } + static Float64 GetAsFloat64(CFStringRef inCFString) { Float64 theAnswer = 0; if(inCFString != NULL){ theAnswer = CFStringGetDoubleValue(inCFString); } return theAnswer; } + +}; + +inline bool operator<(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareLessThan; } +inline bool operator==(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareEqualTo; } +inline bool operator!=(const CACFString& x, const CACFString& y) { return !(x == y); } +inline bool operator<=(const CACFString& x, const CACFString& y) { return (x < y) || (x == y); } +inline bool operator>=(const CACFString& x, const CACFString& y) { return !(x < y); } +inline bool operator>(const CACFString& x, const CACFString& y) { return !((x < y) || (x == y)); } + +inline bool operator<(const CACFString& x, CFStringRef y) { return CFStringCompare(x.GetCFString(), y, 0) == kCFCompareLessThan; } +inline bool operator==(const CACFString& x, CFStringRef y) { return CFStringCompare(x.GetCFString(), y, 0) == kCFCompareEqualTo; } +inline bool operator!=(const CACFString& x, CFStringRef y) { return !(x == y); } +inline bool operator<=(const CACFString& x, CFStringRef y) { return (x < y) || (x == y); } +inline bool operator>=(const CACFString& x, CFStringRef y) { return !(x < y); } +inline bool operator>(const CACFString& x, CFStringRef y) { return !((x < y) || (x == y)); } + +inline bool operator<(CFStringRef x, const CACFString& y) { return CFStringCompare(x, y.GetCFString(), 0) == kCFCompareLessThan; } +inline bool operator==(CFStringRef x, const CACFString& y) { return CFStringCompare(x, y.GetCFString(), 0) == kCFCompareEqualTo; } +inline bool operator!=(CFStringRef x, const CACFString& y) { return !(x == y); } +inline bool operator<=(CFStringRef x, const CACFString& y) { return (x < y) || (x == y); } +inline bool operator>=(CFStringRef x, const CACFString& y) { return !(x < y); } +inline bool operator>(CFStringRef x, const CACFString& y) { return !((x < y) || (x == y)); } + +//============================================================================= +// CACFMutableString +//============================================================================= + +class CACFMutableString +{ +// Construction/Destruction +public: + CACFMutableString() : mCFMutableString(NULL), mWillRelease(true) {} + CACFMutableString(CFMutableStringRef inCFMutableString, bool inWillRelease = true) : mCFMutableString(inCFMutableString), mWillRelease(inWillRelease) {} + CACFMutableString(CFStringRef inStringToCopy, bool /*inMakeCopy*/, bool inWillRelease = true) : mCFMutableString(CFStringCreateMutableCopy(NULL, 0, inStringToCopy)), mWillRelease(inWillRelease) {} + CACFMutableString(const char* inCString, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); } + CACFMutableString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString, inCStringEncoding); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); } + ~CACFMutableString() { Release(); } + CACFMutableString(const CACFMutableString& inString) : mCFMutableString(inString.mCFMutableString), mWillRelease(inString.mWillRelease) { Retain(); } + CACFMutableString& operator=(const CACFMutableString& inString) { Release(); mCFMutableString = inString.mCFMutableString; mWillRelease = inString.mWillRelease; Retain(); return *this; } + CACFMutableString& operator=(CFMutableStringRef inCFMutableString) { Release(); mCFMutableString = inCFMutableString; mWillRelease = true; return *this; } + +private: + void Retain() { if(mWillRelease && (mCFMutableString != NULL)) { CFRetain(mCFMutableString); } } + void Release() { if(mWillRelease && (mCFMutableString != NULL)) { CFRelease(mCFMutableString); } } + + CFMutableStringRef mCFMutableString; + bool mWillRelease; + +// Operations +public: + void AllowRelease() { mWillRelease = true; } + void DontAllowRelease() { mWillRelease = false; } + bool IsValid() { return mCFMutableString != NULL; } + bool IsEqualTo(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringCompare(inString, mCFMutableString, 0) == kCFCompareEqualTo; } return theAnswer; } + bool StartsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringHasPrefix(mCFMutableString, inString); } return theAnswer; } + bool EndsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringHasSuffix(mCFMutableString, inString); } return theAnswer; } + void Append(CFStringRef inString) { if(mCFMutableString != NULL) { CFStringAppend(mCFMutableString, inString); } } + +// Value Access +public: + CFMutableStringRef GetCFMutableString() const { return mCFMutableString; } + CFMutableStringRef CopyCFMutableString() const { if(mCFMutableString != NULL) { CFRetain(mCFMutableString); } return mCFMutableString; } + UInt32 GetLength() const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = ToUInt32(CFStringGetLength(mCFMutableString)); } return theAnswer; } + UInt32 GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = CACFString::GetStringByteLength(mCFMutableString, inEncoding); } return theAnswer; } + void GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { CACFString::GetCString(mCFMutableString, outString, ioStringSize, inEncoding); } + void GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { CACFString::GetUnicodeString(mCFMutableString, outString, ioStringSize); } + SInt32 GetAsInteger() { return CACFString::GetAsInteger(mCFMutableString); } + Float64 GetAsFloat64() { return CACFString::GetAsFloat64(mCFMutableString); } + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp new file mode 100644 index 0000000000..04eae545cf --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp @@ -0,0 +1,182 @@ +/* + File: CAComponent.cpp + Abstract: CAComponent.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 "CAComponent.h" +#include "CAComponentDescription.h" +#include "CACFDictionary.h" +#include <stdlib.h> +#include "CAAutoDisposer.h" + +CAComponent::CAComponent (const AudioComponentDescription& inDesc, CAComponent* next) + : mManuName(0), mAUName(0), mCompName(0) +{ + mComp = AudioComponentFindNext ((next ? next->Comp() : NULL), &inDesc); + if (mComp) + AudioComponentGetDescription(Comp(), &mDesc); + else + memcpy (&mDesc, &inDesc, sizeof(AudioComponentDescription)); +} + +CAComponent::CAComponent (const AudioComponent& comp) + : mComp (comp), + mManuName(0), + mAUName(0), + mCompName(0) +{ + AudioComponentGetDescription (Comp(), &mDesc); +} + +CAComponent::CAComponent (const AudioComponentInstance& compInst) + : mComp (NULL), + mManuName(0), + mAUName(0), + mCompName(0) +{ + mComp = AudioComponentInstanceGetComponent (compInst); + AudioComponentGetDescription (Comp(), &mDesc); +} + +CAComponent::CAComponent (OSType inType, OSType inSubtype, OSType inManu) + : mDesc (inType, inSubtype, inManu), + mManuName(0), mAUName(0), mCompName(0) +{ + mComp = AudioComponentFindNext (NULL, &mDesc); + AudioComponentGetDescription (Comp(), &mDesc); +} + +CAComponent::~CAComponent () +{ + Clear(); +} + +OSStatus CAComponent::GetVersion (UInt32 &outVersion) const +{ + return AudioComponentGetVersion (mComp, &outVersion); +} + +void CAComponent::Clear () +{ + if (mManuName) { CFRelease (mManuName); mManuName = 0; } + if (mAUName) { CFRelease (mAUName); mAUName = 0; } + if (mCompName) { CFRelease (mCompName); mCompName = 0; } +} + +CAComponent& CAComponent::operator= (const CAComponent& y) +{ + Clear(); + + mComp = y.mComp; + mDesc = y.mDesc; + + if (y.mManuName) { mManuName = y.mManuName; CFRetain (mManuName); } + if (y.mAUName) { mAUName = y.mAUName; CFRetain (mAUName); } + if (y.mCompName) { mCompName = y.mCompName; CFRetain (mCompName); } + + return *this; +} + +void CAComponent::SetCompNames () const +{ + if (!mCompName) { + + CFStringRef compName; + OSStatus result = AudioComponentCopyName (Comp(), &compName); + if (result) return; + + const_cast<CAComponent*>(this)->mCompName = compName; + if (compName) + { + CFArrayRef splitStrArray = CFStringCreateArrayBySeparatingStrings(NULL, compName, CFSTR(":")); + + // we need to retain these values so the strings are not lost when the array is released + const_cast<CAComponent*>(this)->mManuName = (CFStringRef)CFArrayGetValueAtIndex(splitStrArray, 0); + CFRetain(this->mManuName); + if (CFArrayGetCount(splitStrArray) > 1) + { + CFStringRef str = (CFStringRef)CFArrayGetValueAtIndex(splitStrArray, 1); + + CFMutableStringRef mstr = CFStringCreateMutableCopy (NULL, CFStringGetLength(str), str); + + // this needs to trim out white space: + + CFStringTrimWhitespace (mstr); + + const_cast<CAComponent*>(this)->mAUName = mstr; + } else + const_cast<CAComponent*>(this)->mAUName = NULL; + + CFRelease(splitStrArray); + } + } +} + +static void _ShowCF (FILE* file, CFStringRef str) +{ + if (CFGetTypeID(str) != CFStringGetTypeID()) { + CFShow(str); + return; + } + + CFIndex len = CFStringGetLength(str); + char* chars = (char*)CA_malloc (len * 2); // give us plenty of room for unichar chars + if (CFStringGetCString (str, chars, len * 2, kCFStringEncodingUTF8)) + fprintf (file, "%s", chars); + else + CFShow (str); + + free (chars); +} + +void CAComponent::Print(FILE* file) const +{ + fprintf (file, "CAComponent: %p", Comp()); + if (mManuName) { + fprintf (file, ", Manu:"); _ShowCF (file, mManuName); + if (mAUName) fprintf (file, ", Name:"); _ShowCF (file, mAUName); + } + fprintf (file, ", "); + Desc ().Print(file); +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponent.h b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.h new file mode 100644 index 0000000000..5ff24ee01a --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.h @@ -0,0 +1,121 @@ +/* + File: CAComponent.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAComponent_h__ +#define __CAComponent_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) +#else + #include <ConditionalMacros.h> +#endif + +#include "CAComponentDescription.h" + +class CAComponent +{ +public: + CAComponent () + : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0) {} + + // if next is specifed that is used to find the next component after that one + CAComponent (const AudioComponentDescription& inDesc, CAComponent* next = 0); + + CAComponent (const CAComponent& y) + : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0) { *this = y; } + + CAComponent (const AudioComponent& comp); + + CAComponent (const AudioComponentInstance& compInst); + + CAComponent (OSType inType, OSType inSubtype = 0, OSType inManu = 0); + + ~CAComponent (); + + CAComponent& operator= (const CAComponent& y); + + // returns true if this object references a valid component + bool IsValid () const { return Comp() != 0; } + + bool HasAUStrings() const { SetCompNames (); return mManuName != 0; } + + // CFStringRef should be retained by caller if needed beyond lifetime of this object + + // Can return NULL if component doesn't follow AU naming conventions + CFStringRef GetAUManu () const { SetCompNames (); return mManuName; } + CFStringRef GetAUName () const { SetCompNames (); return mAUName ? mAUName : mCompName; } + + // Return value of NULL indicates a problem getting that information from the component + CFStringRef GetCompName () const { SetCompNames(); return mCompName; } + + const CAComponentDescription& Desc () const { return mDesc; } + + OSStatus Open (AudioComponentInstance& outInst) const + { + return AudioComponentInstanceNew (Comp(), &outInst); + } + + OSStatus GetVersion (UInt32 &outVersion) const; + + const AudioComponent& Comp() const { return mComp; } + + void Print(FILE* file = stdout) const; + + OSStatus Save (CFPropertyListRef *outData) const; + + OSStatus Restore (CFPropertyListRef &inData); + +private: + AudioComponent mComp; + CAComponentDescription mDesc; + + CFStringRef mManuName, mAUName, mCompName; + + void SetCompNames () const; + void SetCompInfo () const; + void Clear (); +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp new file mode 100644 index 0000000000..a3c877b6fe --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp @@ -0,0 +1,110 @@ +/* + File: CAComponentDescription.cpp + Abstract: CAComponentDescription.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 "CAComponentDescription.h" +#include "CAStreamBasicDescription.h" +#include <ctype.h> + +void CAShowComponentDescription(const AudioComponentDescription *desc) +{ + CAComponentDescription::_CAShowComponentDescription (desc, stdout); +} + +void CAComponentDescription::_CAShowComponentDescription(const AudioComponentDescription *desc, FILE* file) +{ + if (desc) + { + char str[24]; + fprintf (file, "AudioComponentDescription: %s - ", CAStringForOSType(desc->componentType, str, sizeof(str))); + fprintf (file, "%s - ", CAStringForOSType(desc->componentSubType, str, sizeof(str))); + fprintf (file, "%s", CAStringForOSType(desc->componentManufacturer, str, sizeof(str))); + fprintf (file, ", 0x%X, 0x%X\n", (int)desc->componentFlags, (int)desc->componentFlagsMask); + } +} + +CAComponentDescription::CAComponentDescription (OSType inType, OSType inSubtype, OSType inManu) +{ + componentType = inType; + componentSubType = inSubtype; + componentManufacturer = inManu; + componentFlags = 0; + componentFlagsMask = 0; +} + +bool CAComponentDescription::IsAU () const +{ + bool flag = IsEffect() || IsMusicDevice() || IsOffline(); + if (flag) return true; + + switch (componentType) { + case kAudioUnitType_Output: + case kAudioUnitType_FormatConverter: + case kAudioUnitType_Mixer: + return true; + } + return false; +} + +inline bool _MatchTest (const OSType &inTypeA, const OSType &inTypeB) +{ + return ((inTypeA == inTypeB) || (!inTypeA && !inTypeB) || (inTypeA && !inTypeB) || (!inTypeA && inTypeB)); +} + +bool CAComponentDescription::Matches (const AudioComponentDescription &desc) const +{ + bool matches = false; + + // see if the type matches + matches = _MatchTest (componentType, desc.componentType); + + if (matches) + matches = _MatchTest (componentSubType, desc.componentSubType); + + if (matches) + matches = _MatchTest (componentManufacturer, desc.componentManufacturer); + + return matches; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h new file mode 100644 index 0000000000..5c756eaebf --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h @@ -0,0 +1,145 @@ +/* + File: CAComponentDescription.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAComponentDescription_h__ +#define __CAComponentDescription_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <AudioUnit/AudioUnit.h> +#else + #include <ConditionalMacros.h> + #include <AudioUnit.h> +#endif + +#include "CACFDictionary.h" +#include <stdio.h> +#include <string.h> + +void CAShowComponentDescription(const AudioComponentDescription *desc); + +// ____________________________________________________________________________ +// +// CAComponentDescription +class CAComponentDescription : public AudioComponentDescription { +public: + CAComponentDescription() { memset (this, 0, sizeof (AudioComponentDescription)); } + + CAComponentDescription (OSType inType, OSType inSubtype = 0, OSType inManu = 0); + + CAComponentDescription(const AudioComponentDescription& desc) { memcpy (this, &desc, sizeof (AudioComponentDescription)); } + + // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + // + // interrogation + + bool IsAU () const; + + bool IsAUFX() const { return componentType == kAudioUnitType_Effect; } + bool IsAUFM() const { return componentType == kAudioUnitType_MusicEffect; } + + bool IsAUMI() const { return componentType == 'aumi' /*kAudioUnitType_MIDIProcessor*/; } + + bool IsAUAX () const { return componentType == 'auax' /*kAudioUnitType_Auxiliary*/; } + + bool IsEffect () const { return IsAUFX() || IsAUFM() || IsPanner(); } + + bool IsOffline () const { return componentType == 'auol' /*kAudioUnitType_Offline*/; } + + bool IsFConv () const { return componentType == kAudioUnitType_FormatConverter; } + + bool IsPanner () const { return componentType == kAudioUnitType_Panner; } + + bool IsMusicDevice () const { return componentType == kAudioUnitType_MusicDevice; } + +#ifndef MAC_OS_X_VERSION_10_4 + bool IsGenerator () const { return componentType =='augn'; } +#else + bool IsGenerator () const { return componentType ==kAudioUnitType_Generator; } +#endif + + bool IsOutput () const { return componentType == kAudioUnitType_Output; } + + bool IsSource () const { return IsMusicDevice() || IsGenerator(); } + + OSType Type () const { return componentType; } + OSType SubType () const { return componentSubType; } + OSType Manu () const { return componentManufacturer; } + + int Count() const { return AudioComponentCount(const_cast<CAComponentDescription*>(this)); } + + // does a semantic match where "wild card" values for type, subtype, manu will match + bool Matches (const AudioComponentDescription &desc) const; + + // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + // + // other + + void Print(FILE* file = stdout) const { _CAShowComponentDescription (this, file); } + + OSStatus Save (CFPropertyListRef *outData) const; + OSStatus Restore (CFPropertyListRef &inData); + +private: + static void _CAShowComponentDescription (const AudioComponentDescription *desc, FILE* file); + friend void CAShowComponentDescription (const AudioComponentDescription *desc); +}; + +inline bool operator< (const AudioComponentDescription& x, const AudioComponentDescription& y) +{ + return memcmp (&x, &y, offsetof (AudioComponentDescription, componentFlags)) < 0; +} + +inline bool operator== (const AudioComponentDescription& x, const AudioComponentDescription& y) +{ + return !memcmp (&x, &y, offsetof (AudioComponentDescription, componentFlags)); +} + +inline bool operator!= (const AudioComponentDescription& x, const AudioComponentDescription& y) +{ + return !(x == y); +} + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp new file mode 100644 index 0000000000..9739e3753c --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp @@ -0,0 +1,90 @@ +/* + File: CADebugMacros.cpp + Abstract: CADebugMacros.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 "CADebugMacros.h" +#include <stdio.h> +#include <stdarg.h> +#if TARGET_API_MAC_OSX + #include <syslog.h> +#endif + +#if DEBUG +#include <stdio.h> + +void DebugPrint(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} +#endif // DEBUG + +void LogError(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); +#if DEBUG + vprintf(fmt, args); +#endif +#if TARGET_API_MAC_OSX + vsyslog(LOG_ERR, fmt, args); +#endif + va_end(args); +} + +void LogWarning(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); +#if DEBUG + vprintf(fmt, args); +#endif +#if TARGET_API_MAC_OSX + vsyslog(LOG_WARNING, fmt, args); +#endif + va_end(args); +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h new file mode 100644 index 0000000000..15af91909f --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h @@ -0,0 +1,581 @@ +/* + File: CADebugMacros.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CADebugMacros_h__) +#define __CADebugMacros_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include "CoreAudioTypes.h" +#endif + +//============================================================================= +// CADebugMacros +//============================================================================= + +//#define CoreAudio_StopOnFailure 1 +//#define CoreAudio_TimeStampMessages 1 +//#define CoreAudio_ThreadStampMessages 1 +//#define CoreAudio_FlushDebugMessages 1 + +#if TARGET_RT_BIG_ENDIAN + #define CA4CCToCString(the4CC) { ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 } + #define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[0]; theCString[1] = ((char*)&the4CC)[1]; theCString[2] = ((char*)&the4CC)[2]; theCString[3] = ((char*)&the4CC)[3]; theCString[4] = 0; } +#else + #define CA4CCToCString(the4CC) { ((char*)&the4CC)[3], ((char*)&the4CC)[2], ((char*)&the4CC)[1], ((char*)&the4CC)[0], 0 } + #define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[3]; theCString[1] = ((char*)&the4CC)[2]; theCString[2] = ((char*)&the4CC)[1]; theCString[3] = ((char*)&the4CC)[0]; theCString[4] = 0; } +#endif + +// This is a macro that does a sizeof and casts the result to a UInt32. This is useful for all the +// places where -wshorten64-32 catches assigning a sizeof expression to a UInt32. +// For want of a better place to park this, we'll park it here. +#define SizeOf32(X) ((UInt32)sizeof(X)) + +// This is a macro that does a offsetof and casts the result to a UInt32. This is useful for all the +// places where -wshorten64-32 catches assigning an offsetof expression to a UInt32. +// For want of a better place to park this, we'll park it here. +#define OffsetOf32(X, Y) ((UInt32)offsetof(X, Y)) + +// This macro casts the expression to a UInt32. It is called out specially to allow us to track casts +// that have been added purely to avert -wshorten64-32 warnings on 64 bit platforms. +// For want of a better place to park this, we'll park it here. +#define ToUInt32(X) ((UInt32)(X)) +#define ToSInt32(X) ((SInt32)(X)) + +#pragma mark Basic Definitions + +#if DEBUG || CoreAudio_Debug + // can be used to break into debugger immediately, also see CADebugger + #define BusError() { long* p=NULL; *p=0; } + + // basic debugging print routines + #if TARGET_OS_MAC && !TARGET_API_MAC_CARBON + extern void DebugStr(const unsigned char* debuggerMsg); + #define DebugMessage(msg) DebugStr("\p"msg) + #define DebugMessageN1(msg, N1) + #define DebugMessageN2(msg, N1, N2) + #define DebugMessageN3(msg, N1, N2, N3) + #else + #include "CADebugPrintf.h" + + #if (CoreAudio_FlushDebugMessages && !CoreAudio_UseSysLog) || defined(CoreAudio_UseSideFile) + #define FlushRtn ,fflush(DebugPrintfFile) + #else + #define FlushRtn + #endif + + #if CoreAudio_ThreadStampMessages + #include <pthread.h> + #include "CAHostTimeBase.h" + #if TARGET_RT_64_BIT + #define DebugPrintfThreadIDFormat "%16p" + #else + #define DebugPrintfThreadIDFormat "%8p" + #endif + #define DebugMsg(inFormat, ...) DebugPrintf("%17qd: " DebugPrintfThreadIDFormat " " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), pthread_self(), ## __VA_ARGS__) FlushRtn + #elif CoreAudio_TimeStampMessages + #include "CAHostTimeBase.h" + #define DebugMsg(inFormat, ...) DebugPrintf("%17qd: " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), ## __VA_ARGS__) FlushRtn + #else + #define DebugMsg(inFormat, ...) DebugPrintf(inFormat, ## __VA_ARGS__) FlushRtn + #endif + #endif + void DebugPrint(const char *fmt, ...); // can be used like printf + #ifndef DEBUGPRINT + #define DEBUGPRINT(msg) DebugPrint msg // have to double-parenthesize arglist (see Debugging.h) + #endif + #if VERBOSE + #define vprint(msg) DEBUGPRINT(msg) + #else + #define vprint(msg) + #endif + + // Original macro keeps its function of turning on and off use of CADebuggerStop() for both asserts and throws. + // For backwards compat, it overrides any setting of the two sub-macros. + #if CoreAudio_StopOnFailure + #include "CADebugger.h" + #undef CoreAudio_StopOnAssert + #define CoreAudio_StopOnAssert 1 + #undef CoreAudio_StopOnThrow + #define CoreAudio_StopOnThrow 1 + #define STOP CADebuggerStop() + #else + #define STOP + #endif + + #if CoreAudio_StopOnAssert + #if !CoreAudio_StopOnFailure + #include "CADebugger.h" + #define STOP + #endif + #define __ASSERT_STOP CADebuggerStop() + #else + #define __ASSERT_STOP + #endif + + #if CoreAudio_StopOnThrow + #if !CoreAudio_StopOnFailure + #include "CADebugger.h" + #define STOP + #endif + #define __THROW_STOP CADebuggerStop() + #else + #define __THROW_STOP + #endif + +#else + #define DebugMsg(inFormat, ...) + #ifndef DEBUGPRINT + #define DEBUGPRINT(msg) + #endif + #define vprint(msg) + #define STOP + #define __ASSERT_STOP + #define __THROW_STOP +#endif + +// Old-style numbered DebugMessage calls are implemented in terms of DebugMsg() now +#define DebugMessage(msg) DebugMsg(msg) +#define DebugMessageN1(msg, N1) DebugMsg(msg, N1) +#define DebugMessageN2(msg, N1, N2) DebugMsg(msg, N1, N2) +#define DebugMessageN3(msg, N1, N2, N3) DebugMsg(msg, N1, N2, N3) +#define DebugMessageN4(msg, N1, N2, N3, N4) DebugMsg(msg, N1, N2, N3, N4) +#define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugMsg(msg, N1, N2, N3, N4, N5) +#define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugMsg(msg, N1, N2, N3, N4, N5, N6) +#define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7) +#define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8) +#define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) + +void LogError(const char *fmt, ...); // writes to syslog (and stderr if debugging) +void LogWarning(const char *fmt, ...); // writes to syslog (and stderr if debugging) + +#define NO_ACTION (void)0 + +#if DEBUG || CoreAudio_Debug + +#pragma mark Debug Macros + +#define Assert(inCondition, inMessage) \ + if(!(inCondition)) \ + { \ + DebugMessage(inMessage); \ + __ASSERT_STOP; \ + } + +#define AssertFileLine(inCondition, inMessage) \ + if(!(inCondition)) \ + { \ + DebugMessageN3("%s, line %d: %s", __FILE__, __LINE__, inMessage); \ + __ASSERT_STOP; \ + } + +#define AssertNoError(inError, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + char __4CC[5] = CA4CCToCString(__Err); \ + DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \ + __ASSERT_STOP; \ + } \ + } + +#define AssertNoKernelError(inError, inMessage) \ + { \ + unsigned int __Err = (unsigned int)(inError); \ + if(__Err != 0) \ + { \ + DebugMessageN1(inMessage ", Error: 0x%X", __Err); \ + __ASSERT_STOP; \ + } \ + } + +#define AssertNotNULL(inPtr, inMessage) \ + { \ + if((inPtr) == NULL) \ + { \ + DebugMessage(inMessage); \ + __ASSERT_STOP; \ + } \ + } + +#define FailIf(inCondition, inHandler, inMessage) \ + if(inCondition) \ + { \ + DebugMessage(inMessage); \ + STOP; \ + goto inHandler; \ + } + +#define FailWithAction(inCondition, inAction, inHandler, inMessage) \ + if(inCondition) \ + { \ + DebugMessage(inMessage); \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \ + if((inPointer) == NULL) \ + { \ + DebugMessage(inMessage); \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfKernelError(inKernelError, inAction, inHandler, inMessage) \ + { \ + unsigned int __Err = (inKernelError); \ + if(__Err != 0) \ + { \ + DebugMessageN1(inMessage ", Error: 0x%X", __Err); \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } \ + } + +#define FailIfError(inError, inAction, inHandler, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + char __4CC[5] = CA4CCToCString(__Err); \ + DebugMessageN2(inMessage ", Error: %ld (%s)", (long int)__Err, __4CC); \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } \ + } + +#define FailIfNoMessage(inCondition, inHandler, inMessage) \ + if(inCondition) \ + { \ + STOP; \ + goto inHandler; \ + } + +#define FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage) \ + if(inCondition) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage) \ + if((inPointer) == NULL) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage) \ + { \ + unsigned int __Err = (inKernelError); \ + if(__Err != 0) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } \ + } + +#define FailIfErrorNoMessage(inError, inAction, inHandler, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } \ + } + +#if defined(__cplusplus) + +#define Throw(inException) __THROW_STOP; throw (inException) + +#define ThrowIf(inCondition, inException, inMessage) \ + if(inCondition) \ + { \ + DebugMessage(inMessage); \ + Throw(inException); \ + } + +#define ThrowIfNULL(inPointer, inException, inMessage) \ + if((inPointer) == NULL) \ + { \ + DebugMessage(inMessage); \ + Throw(inException); \ + } + +#define ThrowIfKernelError(inKernelError, inException, inMessage) \ + { \ + int __Err = (inKernelError); \ + if(__Err != 0) \ + { \ + DebugMessageN1(inMessage ", Error: 0x%X", __Err); \ + Throw(inException); \ + } \ + } + +#define ThrowIfError(inError, inException, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + char __4CC[5] = CA4CCToCString(__Err); \ + DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \ + Throw(inException); \ + } \ + } + +#if TARGET_OS_WIN32 +#define ThrowIfWinError(inError, inException, inMessage) \ + { \ + HRESULT __Err = (inError); \ + if(FAILED(__Err)) \ + { \ + DebugMessageN2(inMessage ", Code: %d, Facility: 0x%X", HRESULT_CODE(__Err), HRESULT_FACILITY(__Err)); \ + Throw(inException); \ + } \ + } +#endif + +#define SubclassResponsibility(inMethodName, inException) \ + { \ + DebugMessage(inMethodName": Subclasses must implement this method"); \ + Throw(inException); \ + } + +#endif // defined(__cplusplus) + +#else + +#pragma mark Release Macros + +#define Assert(inCondition, inMessage) \ + if(!(inCondition)) \ + { \ + __ASSERT_STOP; \ + } + +#define AssertFileLine(inCondition, inMessage) Assert(inCondition, inMessage) + +#define AssertNoError(inError, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + __ASSERT_STOP; \ + } \ + } + +#define AssertNoKernelError(inError, inMessage) \ + { \ + unsigned int __Err = (unsigned int)(inError); \ + if(__Err != 0) \ + { \ + __ASSERT_STOP; \ + } \ + } + +#define AssertNotNULL(inPtr, inMessage) \ + { \ + if((inPtr) == NULL) \ + { \ + __ASSERT_STOP; \ + } \ + } + +#define FailIf(inCondition, inHandler, inMessage) \ + if(inCondition) \ + { \ + STOP; \ + goto inHandler; \ + } + +#define FailWithAction(inCondition, inAction, inHandler, inMessage) \ + if(inCondition) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \ + if((inPointer) == NULL) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfKernelError(inKernelError, inAction, inHandler, inMessage) \ + if((inKernelError) != 0) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfError(inError, inAction, inHandler, inMessage) \ + if((inError) != 0) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfNoMessage(inCondition, inHandler, inMessage) \ + if(inCondition) \ + { \ + STOP; \ + goto inHandler; \ + } + +#define FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage) \ + if(inCondition) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage) \ + if((inPointer) == NULL) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage) \ + { \ + unsigned int __Err = (inKernelError); \ + if(__Err != 0) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } \ + } + +#define FailIfErrorNoMessage(inError, inAction, inHandler, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } \ + } + +#if defined(__cplusplus) + +#define Throw(inException) __THROW_STOP; throw (inException) + +#define ThrowIf(inCondition, inException, inMessage) \ + if(inCondition) \ + { \ + Throw(inException); \ + } + +#define ThrowIfNULL(inPointer, inException, inMessage) \ + if((inPointer) == NULL) \ + { \ + Throw(inException); \ + } + +#define ThrowIfKernelError(inKernelError, inException, inMessage) \ + { \ + int __Err = (inKernelError); \ + if(__Err != 0) \ + { \ + Throw(inException); \ + } \ + } + +#define ThrowIfError(inError, inException, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + Throw(inException); \ + } \ + } + +#if TARGET_OS_WIN32 +#define ThrowIfWinError(inError, inException, inMessage) \ + { \ + HRESULT __Err = (inError); \ + if(FAILED(__Err)) \ + { \ + Throw(inException); \ + } \ + } +#endif + +#define SubclassResponsibility(inMethodName, inException) \ + { \ + Throw(inException); \ + } + +#endif // defined(__cplusplus) + +#endif // DEBUG || CoreAudio_Debug + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp new file mode 100644 index 0000000000..d691de3cd5 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp @@ -0,0 +1,89 @@ +/* + File: CADebugPrintf.cpp + Abstract: CADebugPrintf.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CADebugPrintf.h" + +#if DEBUG || CoreAudio_Debug + + #if TARGET_OS_WIN32 + #include <stdarg.h> + #include <stdio.h> + #include <Windows.h> + extern "C" + int CAWin32DebugPrintf(char* inFormat, ...) + { + char theMessage[1024]; + va_list theArguments; + va_start(theArguments, inFormat); + _vsnprintf(theMessage, 1024, inFormat, theArguments); + va_end(theArguments); + OutputDebugString(theMessage); + return 0; + } + #endif + + #if defined(CoreAudio_UseSideFile) + #include <unistd.h> + FILE* sDebugPrintfSideFile = NULL; + extern "C" + void OpenDebugPrintfSideFile() + { + if(sDebugPrintfSideFile == NULL) + { + char theFileName[1024]; + snprintf(theFileName, sizeof(theFileName), CoreAudio_UseSideFile, getpid()); + sDebugPrintfSideFile = fopen(theFileName, "a+"); + DebugPrintfRtn(DebugPrintfFileComma "\n------------------------------\n"); + } + } + #endif + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h new file mode 100644 index 0000000000..79aa15dafa --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h @@ -0,0 +1,115 @@ +/* + File: CADebugPrintf.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CADebugPrintf_h__) +#define __CADebugPrintf_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include "CoreAudioTypes.h" +#endif + +//============================================================================= +// Macros to redirect debugging output to various logging services +//============================================================================= + +//#define CoreAudio_UseSysLog 1 +//#define CoreAudio_UseSideFile "/CoreAudio-%d.txt" + +#if DEBUG || CoreAudio_Debug + + #if TARGET_OS_WIN32 + #if defined(__cplusplus) + extern "C" + #endif + extern int CAWin32DebugPrintf(char* inFormat, ...); + #define DebugPrintfRtn CAWin32DebugPrintf + #define DebugPrintfFile + #define DebugPrintfLineEnding "\n" + #define DebugPrintfFileComma + #else + #if CoreAudio_UseSysLog + #include <sys/syslog.h> + #define DebugPrintfRtn syslog + #define DebugPrintfFile LOG_NOTICE + #define DebugPrintfLineEnding "" + #define DebugPrintfFileComma DebugPrintfFile, + #elif defined(CoreAudio_UseSideFile) + #include <stdio.h> + #if defined(__cplusplus) + extern "C" + #endif + void OpenDebugPrintfSideFile(); + extern FILE* sDebugPrintfSideFile; + #define DebugPrintfRtn fprintf + #define DebugPrintfFile ((sDebugPrintfSideFile != NULL) ? sDebugPrintfSideFile : stderr) + #define DebugPrintfLineEnding "\n" + #define DebugPrintfFileComma DebugPrintfFile, + #else + #include <stdio.h> + #define DebugPrintfRtn fprintf + #define DebugPrintfFile stderr + #define DebugPrintfLineEnding "\n" + #define DebugPrintfFileComma DebugPrintfFile, + #endif + #endif + + #define DebugPrintf(inFormat, ...) DebugPrintfRtn(DebugPrintfFileComma inFormat DebugPrintfLineEnding, ## __VA_ARGS__) +#else + #define DebugPrintfRtn + #define DebugPrintfFile + #define DebugPrintfLineEnding + #define DebugPrintfFileComma + #define DebugPrintf(inFormat, ...) +#endif + + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp new file mode 100644 index 0000000000..7f0141d206 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp @@ -0,0 +1,103 @@ +/* + File: CADebugger.cpp + Abstract: CADebugger.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CADebugger.h" + +//============================================================================= +// CADebugger +//============================================================================= + +#if TARGET_API_MAC_OSX + +#include <sys/sysctl.h> +#include <stdlib.h> +#include <unistd.h> + +bool CAIsDebuggerAttached(void) +{ + int mib[4]; + struct kinfo_proc info; + size_t size; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + size = sizeof(info); + info.kp_proc.p_flag = 0; + + sysctl(mib, 4, &info, &size, NULL, 0); + + return (info.kp_proc.p_flag & P_TRACED) == P_TRACED; +} + +#endif + +void CADebuggerStop(void) +{ + #if CoreAudio_Debug + #if TARGET_API_MAC_OSX + if(CAIsDebuggerAttached()) + { + #if defined(__i386__) || defined(__x86_64__) + asm("int3"); + #else + __builtin_trap(); + #endif + } + else + { + abort(); + } + #else + __debugbreak(); + #endif + #endif +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugger.h b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.h new file mode 100644 index 0000000000..9391f011a2 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.h @@ -0,0 +1,69 @@ +/* + File: CADebugger.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CADebugger_h__) +#define __CADebugger_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif + +//============================================================================= +// CADebugger +//============================================================================= + +#if TARGET_API_MAC_OSX + extern bool CAIsDebuggerAttached(void); +#endif +extern void CADebuggerStop(void); + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAException.h b/libs/appleutility/CoreAudio/PublicUtility/CAException.h new file mode 100644 index 0000000000..7217001d78 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAException.h @@ -0,0 +1,83 @@ +/* + File: CAException.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAException_h__) +#define __CAException_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include "CoreAudioTypes.h" +#endif + +//============================================================================= +// CAException +//============================================================================= + +class CAException +{ + +public: + CAException(OSStatus inError) : mError(inError) {} + CAException(const CAException& inException) : mError(inException.mError) {} + CAException& operator=(const CAException& inException) { mError = inException.mError; return *this; } + ~CAException() {} + + OSStatus GetError() const { return mError; } + +protected: + OSStatus mError; +}; + +#define CATry try{ +#define CACatch } catch(...) {} +#define CASwallowException(inExpression) try { inExpression; } catch(...) {} + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h b/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h new file mode 100644 index 0000000000..f1aa56fb5e --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h @@ -0,0 +1,300 @@ +/* + File: CAExtAudioFile.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAExtAudioFile_h__ +#define __CAExtAudioFile_h__ + +#include <TargetConditionals.h> + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <AudioToolbox/ExtendedAudioFile.h> + #include <AudioToolbox/AudioConverter.h> +#else + #include "ExtendedAudioFile.h" + #include "AudioConverter.h" +#endif +#include "CAXException.h" +//#include "CAAutoDisposer.h" +#include "CAStreamBasicDescription.h" +#include "CAAudioChannelLayout.h" +#include "CACFObject.h" + +// A C++ wrapper for ExtAudioFile +// Error returns throw CAXExceptions. +class CAExtAudioFile { +public: + // instances are not automatically associated with open files. + CAExtAudioFile() : + mExtAudioFile(NULL) { } + + virtual ~CAExtAudioFile() + { + Close(); + } + + bool IsValid() const { return mExtAudioFile != NULL; } + + void Open(const char* filename) + { + Close(); + CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)filename, strlen(filename), false); + XThrowIf(!url, -1, "couldn't convert path to CFURLRef"); + OSStatus res = ExtAudioFileOpenURL(url, &mExtAudioFile); + if (res) + CFRelease(url); + Check(res, "ExtAudioFileOpenURL"); + CFRelease (url); + } + + // this group of methods maps directly to the API other than OSStatus results translating into exceptions. + // you must explicitly open, wrap or create a file. + void OpenURL(CFURLRef url) + { + Close(); + Check(ExtAudioFileOpenURL(url, &mExtAudioFile), "ExtAudioFileOpenURL"); + } + + void WrapAudioFileID(AudioFileID inFileID, Boolean forWriting) + { + Close(); + Check(ExtAudioFileWrapAudioFileID(inFileID, forWriting, &mExtAudioFile), "ExtAudioFileWrapAudioFileID"); + } + + void Create(const char *filePath, AudioFileTypeID filetype, const AudioStreamBasicDescription &streamDesc, const AudioChannelLayout *channelLayout, UInt32 flags) + { + CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)filePath, strlen(filePath), false); + XThrowIf(!url, -1, "couldn't convert path to CFURLRef"); + Close(); + OSStatus res = ExtAudioFileCreateWithURL(url, filetype, &streamDesc, channelLayout, flags, &mExtAudioFile); + if (res) + CFRelease(url); + Check(res, "ExtAudioFileCreateWithURL"); + CFRelease(url); + } + + void CreateWithURL(CFURLRef url, AudioFileTypeID filetype, const AudioStreamBasicDescription &streamDesc, const AudioChannelLayout *channelLayout, UInt32 flags) + { + Close(); + Check(ExtAudioFileCreateWithURL(url, filetype, &streamDesc, channelLayout, flags, &mExtAudioFile), "ExtAudioFileCreateWithURL"); + } + + // you may explicitly close a file, or have it closed automatically by the destructor. + void Close() + { + if (mExtAudioFile != NULL) { + Check(ExtAudioFileDispose(mExtAudioFile), "ExtAudioFileClose"); + mExtAudioFile = NULL; + } + } + + void Read(UInt32 &ioNumberFrames, AudioBufferList *ioData) + { + Check(ExtAudioFileRead(mExtAudioFile, &ioNumberFrames, ioData), "ExtAudioFileRead"); + } + + OSStatus Write(UInt32 inNumberFrames, const AudioBufferList *ioData) + { + OSStatus err = ExtAudioFileWrite(mExtAudioFile, inNumberFrames, ioData); + switch (err) { + // noErr and certain special errors are returned without an exception + case noErr: + break; + #if TARGET_OS_IPHONE + case kExtAudioFileError_CodecUnavailableInputConsumed: + case kExtAudioFileError_CodecUnavailableInputNotConsumed: + break; + #endif + default: + // throw an exception + Check(err, "ExtAudioFileWrite"); + break; + } + return err; + } + + void WriteAsync(UInt32 inNumberFrames, const AudioBufferList *ioData) + { + Check(ExtAudioFileWriteAsync(mExtAudioFile, inNumberFrames, ioData), "ExtAudioFileWriteAsync"); + } + + void Seek(SInt64 inFrameOffset) + { + Check(ExtAudioFileSeek(mExtAudioFile, inFrameOffset), "ExtAudioFileSeek"); + } + + SInt64 Tell() const + { + SInt64 pos; + Check(ExtAudioFileTell(mExtAudioFile, &pos), "ExtAudioFileTell"); + return pos; + } + + UInt32 GetPropertyInfo(ExtAudioFilePropertyID propid, Boolean *outWritable) const + { + UInt32 size; + CheckProperty(ExtAudioFileGetPropertyInfo(mExtAudioFile, propid, &size, outWritable), "ExtAudioFileGetPropertyInfo", propid); + return size; + } + + void GetProperty(ExtAudioFilePropertyID propid, UInt32 &ioSize, void *outData) const + { + CheckProperty(ExtAudioFileGetProperty(mExtAudioFile, propid, &ioSize, outData), "ExtAudioFileGetProperty", propid); + } + + void SetProperty(ExtAudioFilePropertyID propid, UInt32 size, const void *inData) + { + CheckProperty(ExtAudioFileSetProperty(mExtAudioFile, propid, size, inData), "ExtAudioFileSetProperty", propid); + } + + const CAAudioChannelLayout &GetFileChannelLayout() + { + return FetchChannelLayout(mFileChannelLayout, kExtAudioFileProperty_FileChannelLayout); + } + + void SetFileChannelLayout(const CAAudioChannelLayout &layout) { + SetProperty(kExtAudioFileProperty_FileChannelLayout, layout.Size(), &layout.Layout()); + } + + const CAStreamBasicDescription &GetFileDataFormat() + { + UInt32 size = sizeof(mFileDataFormat); + GetProperty(kExtAudioFileProperty_FileDataFormat, size, &mFileDataFormat); + return mFileDataFormat; + } + + const CAStreamBasicDescription &GetClientDataFormat() { + UInt32 size = sizeof(mClientDataFormat); + GetProperty(kExtAudioFileProperty_ClientDataFormat, size, &mClientDataFormat); + return mClientDataFormat; + } + + + void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL, UInt32 codecManuf=0) { + if (codecManuf != 0) + SetProperty('cman' /*kExtAudioFileProperty_CodecManufacturer*/, sizeof(codecManuf), &codecManuf); + SetProperty(kExtAudioFileProperty_ClientDataFormat, sizeof(dataFormat), &dataFormat); + if (layout) + SetClientChannelLayout(*layout); + } + + void SetClientChannelLayout(const CAAudioChannelLayout &layout) { + SetProperty(kExtAudioFileProperty_ClientChannelLayout, layout.Size(), &layout.Layout()); + } + + AudioConverterRef GetConverter() const { + UInt32 size = sizeof(AudioConverterRef); + AudioConverterRef converter = NULL; + GetProperty(kExtAudioFileProperty_AudioConverter, size, &converter); + return converter; + } + + bool HasConverter() const { return GetConverter() != NULL; } + + OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData, bool inCanFail=false) + { + OSStatus err = AudioConverterSetProperty(GetConverter(), inPropertyID, inPropertyDataSize, inPropertyData); + if (!inCanFail) + XThrowIfError(err, "Couldn't set audio converter property"); + if (!err) { + // must tell the file that we have changed the converter; a NULL converter config is sufficient + CFPropertyListRef config = NULL; + SetProperty(kExtAudioFileProperty_ConverterConfig, sizeof(CFPropertyListRef), &config); + } + return err; + } + + SInt64 GetNumberFrames() { + SInt64 length; + UInt32 size = sizeof(SInt64); + GetProperty(kExtAudioFileProperty_FileLengthFrames, size, &length); + return length; + } + + +protected: + virtual void Check(OSStatus err, const char *func) const + { + if (err) { + char txt[128]; + snprintf(txt, sizeof(txt), "%s failed", func); + throw CAXException(txt, err); + } + } + + virtual void CheckProperty(OSStatus err, const char *func, UInt32 propid) const + { + if (err) { + char txt[128]; + char propstr[] = CA4CCToCString(propid); + snprintf(txt, sizeof(txt), "%s ('%s') failed", func, propstr); + throw CAXException(txt, err); + } + } + + const CAAudioChannelLayout & FetchChannelLayout(CAAudioChannelLayout &layoutObj, ExtAudioFilePropertyID propID) { + UInt32 size = GetPropertyInfo(propID, NULL); + CAAutoFree<AudioChannelLayout> layout; + layout.allocBytes(size); + GetProperty(propID, size, layout); + layoutObj = layout; + return layoutObj; + } + +private: + CAExtAudioFile(const CAExtAudioFile &) { } // prohibit + CAExtAudioFile & operator = (const CAExtAudioFile &) { return *this; } // prohibit + +private: + ExtAudioFileRef mExtAudioFile; + + // for convenience to the client, it helps if we hold onto some storage for these + CAStreamBasicDescription mFileDataFormat; + CAAudioChannelLayout mFileChannelLayout; + CAStreamBasicDescription mClientDataFormat; +}; + + +#endif // __CAExtAudioFile_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp new file mode 100644 index 0000000000..124cb21433 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp @@ -0,0 +1,188 @@ +/* + File: CAFilePathUtils.cpp + Abstract: CAFilePathUtils.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 "CAFilePathUtils.h" +#include <string.h> + +#if !CA_NO_CORE_SERVICES +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreServices/CoreServices.h> // FSRef + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreServices.h> + #include <CoreAudioTypes.h> +#endif + +OSStatus PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName) +{ + // convert C string to CFString +#if !TARGET_OS_WIN32 + CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8); +#else + CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingWindowsLatin1); +#endif + // convert CF string to URL + CFURLRef fullurl = CFURLCreateWithFileSystemPath(NULL, cfFullPath, TARGET_OS_WIN32 ? kCFURLWindowsPathStyle : kCFURLPOSIXPathStyle, false); + CFRelease(cfFullPath); + // get the directory portion of the URL + CFURLRef dirurl = CFURLCreateCopyDeletingLastPathComponent(NULL, fullurl); + // get the directory's FSRef + OSStatus err = CFURLGetFSRef(dirurl, &outParentDir) ? OSStatus(noErr) : OSStatus(kAudio_FileNotFoundError); + CFRelease(dirurl); + + CFStringRef lastPathComponent = CFURLCopyLastPathComponent(fullurl); + CFRelease(fullurl); + CFMutableStringRef filename = CFStringCreateMutableCopy(NULL, 0, lastPathComponent); + CFRelease(lastPathComponent); + // convert colons (legal in POSIX paths, illegal in File Manager) to slashes + CFStringFindAndReplace(filename, CFSTR(":"), CFSTR("/"), CFRangeMake(0, CFStringGetLength(filename)), 0); + + outFileName = filename; + + return err; +} +#endif // !CA_NO_CORE_SERVICES + + +#if TARGET_OS_WIN32 + +char* dirname(const char* inPath) +{ + static char sAnswer[1024]; + + char* theAnswer = NULL; + SInt32 thePathLength = strlen(inPath); + if(thePathLength < 1023) + { + // make a working copy + strlcpy(sAnswer, inPath, sizeof(sAnswer)); + + // start at the end of the string + SInt32 theIndex = thePathLength - 1; + + // walk back over the '\' characters + while((theIndex > 0) && (sAnswer[theIndex] == '\\')) + { + --theIndex; + } + + // now keep walking back until we get to a '\' + while((theIndex > 0) && (sAnswer[theIndex] != '\\')) + { + --theIndex; + } + + // where we are now is either the first character of the path or the '\' that marks the end of the directory name + if(theIndex > 0) + { + // we have a name so put a '\0' in place of the '\' + sAnswer[theIndex] = 0; + } + else + { + // no name, so the answer is "." + sAnswer[0] = '.'; + sAnswer[1] = 0; + } + + // set the return value + theAnswer = sAnswer; + } + + return theAnswer; +} + +char* basename(const char* inPath) +{ + static char sAnswer[1024]; + + char* theAnswer = NULL; + SInt32 thePathLength = strlen(inPath); + if(thePathLength < 1023) + { + // make a working copy + strlcpy(sAnswer, inPath, sizeof(sAnswer)); + + // start at the end of the string + SInt32 theLastIndex = thePathLength - 1; + + // walk back over the '\' characters + while((theLastIndex > 0) && (sAnswer[theLastIndex] == '\\')) + { + --theLastIndex; + } + + // check to see if we're at the beginning now + if(theLastIndex > 0) + { + // there's a name in there now, so start where we are and go back to the next '\' + UInt32 theFirstIndex = theLastIndex; + while((theFirstIndex > 0) && (sAnswer[theFirstIndex] != '\\')) + { + --theFirstIndex; + } + + // we now have a string, so put a '\0' after the last character + sAnswer[theLastIndex + 1] = 0; + + // and set the return value + theAnswer = &sAnswer[theFirstIndex]; + } + else + { + // the path was entirely '\' characters, so the return value is "\" + sAnswer[0] = '\\'; + sAnswer[1] = 0; + + // set the return value + theAnswer = sAnswer; + } + } + + return theAnswer; +} + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h new file mode 100644 index 0000000000..41f1ee00af --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h @@ -0,0 +1,70 @@ +/* + File: CAFilePathUtils.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAFilePathUtils_h__ +#define __CAFilePathUtils_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreFoundation/CoreFoundation.h> + #include <CoreAudio/CoreAudio.h> +#else + #include <TargetConditionals.h> + #include <CoreFoundation.h> + #include <CoreAudio.h> +#endif + +struct FSRef; + +OSStatus PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName); + +#if !TARGET_OS_WIN32 + #include <libgen.h> +#else + char* dirname(const char* inPath); + char* basename(const char* inPath); +#endif + +#endif // __CAFilePathUtils_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp new file mode 100644 index 0000000000..a1c83be9dd --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp @@ -0,0 +1,343 @@ +/* + File: CAGuard.cpp + Abstract: CAGuard.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CAGuard.h" + +#if TARGET_OS_MAC + #include <errno.h> +#endif + +// PublicUtility Inludes +#include "CADebugMacros.h" +#include "CAException.h" +#include "CAHostTimeBase.h" + +//================================================================================================== +// Logging +//================================================================================================== + +#if CoreAudio_Debug +// #define Log_Ownership 1 +// #define Log_WaitOwnership 1 +// #define Log_TimedWaits 1 +// #define Log_Latency 1 +// #define Log_Errors 1 +#endif + +//#warning Need a try-based Locker too +//================================================================================================== +// CAGuard +//================================================================================================== + +CAGuard::CAGuard(const char* inName) +: + CAMutex(inName) +#if Log_Average_Latency + ,mAverageLatencyAccumulator(0.0), + mAverageLatencyCount(0) +#endif +{ +#if TARGET_OS_MAC + OSStatus theError = pthread_cond_init(&mCondVar, NULL); + ThrowIf(theError != 0, CAException(theError), "CAGuard::CAGuard: Could not init the cond var"); +#elif TARGET_OS_WIN32 + mEvent = CreateEvent(NULL, true, false, NULL); + ThrowIfNULL(mEvent, CAException(GetLastError()), "CAGuard::CAGuard: Could not create the event"); +#endif +} + +CAGuard::~CAGuard() +{ +#if TARGET_OS_MAC + pthread_cond_destroy(&mCondVar); +#elif TARGET_OS_WIN32 + if(mEvent != NULL) + { + CloseHandle(mEvent); + } +#endif +} + +void CAGuard::Wait() +{ +#if TARGET_OS_MAC + ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait"); + + mOwner = 0; + + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Wait: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner); + #endif + + OSStatus theError = pthread_cond_wait(&mCondVar, &mMutex); + ThrowIf(theError != 0, CAException(theError), "CAGuard::Wait: Could not wait for a signal"); + mOwner = pthread_self(); + + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Wait: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner); + #endif +#elif TARGET_OS_WIN32 + ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait"); + + mOwner = 0; + + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Wait: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + + ReleaseMutex(mMutex); + HANDLE theHandles[] = { mMutex, mEvent }; + OSStatus theError = WaitForMultipleObjects(2, theHandles, true, INFINITE); + ThrowIfError(theError, CAException(GetLastError()), "CAGuard::Wait: Could not wait for the signal"); + mOwner = GetCurrentThreadId(); + ResetEvent(mEvent); + + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Wait: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif +#endif +} + +bool CAGuard::WaitFor(UInt64 inNanos) +{ + bool theAnswer = false; + +#if TARGET_OS_MAC + ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait"); + + #if Log_TimedWaits + DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos); + #endif + + struct timespec theTimeSpec; + static const UInt64 kNanosPerSecond = 1000000000ULL; + if(inNanos >= kNanosPerSecond) + { + theTimeSpec.tv_sec = static_cast<long>(inNanos / kNanosPerSecond); + theTimeSpec.tv_nsec = static_cast<long>(inNanos % kNanosPerSecond); + } + else + { + theTimeSpec.tv_sec = 0; + theTimeSpec.tv_nsec = static_cast<long>(inNanos); + } + + #if Log_TimedWaits || Log_Latency || Log_Average_Latency + UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos(); + #endif + + mOwner = 0; + + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::WaitFor: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner); + #endif + + OSStatus theError = pthread_cond_timedwait_relative_np(&mCondVar, &mMutex, &theTimeSpec); + ThrowIf((theError != 0) && (theError != ETIMEDOUT), CAException(theError), "CAGuard::WaitFor: Wait got an error"); + mOwner = pthread_self(); + + #if Log_TimedWaits || Log_Latency || Log_Average_Latency + UInt64 theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos(); + #endif + + #if Log_TimedWaits + DebugMessageN1("CAGuard::WaitFor: waited %.0f", (Float64)(theEndNanos - theStartNanos)); + #endif + + #if Log_Latency + DebugMessageN1("CAGuard::WaitFor: latency %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos)); + #endif + + #if Log_Average_Latency + ++mAverageLatencyCount; + mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos; + if(mAverageLatencyCount >= 50) + { + DebugMessageN2("CAGuard::WaitFor: average latency %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount); + mAverageLatencyCount = 0; + mAverageLatencyAccumulator = 0.0; + } + #endif + + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::WaitFor: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner); + #endif + + theAnswer = theError == ETIMEDOUT; +#elif TARGET_OS_WIN32 + ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait"); + + #if Log_TimedWaits + DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos); + #endif + + // the time out is specified in milliseconds(!) + UInt32 theWaitTime = static_cast<UInt32>(inNanos / 1000000ULL); + + #if Log_TimedWaits || Log_Latency || Log_Average_Latency + UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos(); + #endif + + mOwner = 0; + + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::WaitFor: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + + ReleaseMutex(mMutex); + HANDLE theHandles[] = { mMutex, mEvent }; + OSStatus theError = WaitForMultipleObjects(2, theHandles, true, theWaitTime); + ThrowIf((theError != WAIT_OBJECT_0) && (theError != WAIT_TIMEOUT), CAException(GetLastError()), "CAGuard::WaitFor: Wait got an error"); + mOwner = GetCurrentThreadId(); + ResetEvent(mEvent); + // This mutex should be locked again when time out happens.rdar://12270555 + if(theError == WAIT_TIMEOUT) { + DWORD dwError = WaitForSingleObject(mMutex, INFINITE); + ThrowIf((dwError != WAIT_OBJECT_0), CAException(GetLastError()), "CAGuard::WaitFor: failed to acquire the mutex back when timeout happened\n"); + } + #if Log_TimedWaits || Log_Latency || Log_Average_Latency + UInt64 theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos(); + #endif + + #if Log_TimedWaits + DebugMessageN1("CAGuard::WaitFor: waited %.0f", (Float64)(theEndNanos - theStartNanos)); + #endif + + #if Log_Latency + DebugMessageN1("CAGuard::WaitFor: latency %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos)); + #endif + + #if Log_Average_Latency + ++mAverageLatencyCount; + mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos; + if(mAverageLatencyCount >= 50) + { + DebugMessageN2("CAGuard::WaitFor: average latency %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount); + mAverageLatencyCount = 0; + mAverageLatencyAccumulator = 0.0; + } + #endif + + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::WaitFor: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + + theAnswer = theError == WAIT_TIMEOUT; +#endif + + return theAnswer; +} + +bool CAGuard::WaitUntil(UInt64 inNanos) +{ + bool theAnswer = false; + UInt64 theCurrentNanos = CAHostTimeBase::GetCurrentTimeInNanos(); + +#if Log_TimedWaits + DebugMessageN2("CAGuard::WaitUntil: now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos); +#endif + + if(inNanos > theCurrentNanos) + { +#if Log_Errors + if((inNanos - theCurrentNanos) > 1000000000ULL) + { + DebugMessage("CAGuard::WaitUntil: about to wait for more than a second"); + } +#endif + theAnswer = WaitFor(inNanos - theCurrentNanos); + } + else + { +#if Log_Errors + DebugMessageN2("CAGuard::WaitUntil: Time has expired before waiting, now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos); +#endif + theAnswer = true; + } + + return theAnswer; +} + +void CAGuard::Notify() +{ +#if TARGET_OS_MAC + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Notify: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner); + #endif + + OSStatus theError = pthread_cond_signal(&mCondVar); + ThrowIf(theError != 0, CAException(theError), "CAGuard::Notify: failed"); +#elif TARGET_OS_WIN32 + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Notify: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + + SetEvent(mEvent); +#endif +} + +void CAGuard::NotifyAll() +{ +#if TARGET_OS_MAC + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::NotifyAll: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner); + #endif + + OSStatus theError = pthread_cond_broadcast(&mCondVar); + ThrowIf(theError != 0, CAException(theError), "CAGuard::NotifyAll: failed"); +#elif TARGET_OS_WIN32 + #if Log_WaitOwnership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::NotifyAll: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + + SetEvent(mEvent); +#endif +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAGuard.h b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.h new file mode 100644 index 0000000000..ffcb59da8d --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.h @@ -0,0 +1,133 @@ +/* + File: CAGuard.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAGuard_h__) +#define __CAGuard_h__ + +//================================================================================================== +// Includes +//============================================================================= + +// Super Class Includes +#include "CAMutex.h" + +#if CoreAudio_Debug +// #define Log_Average_Latency 1 +#endif + +//================================================================================================== +// CAGuard +// +// This is your typical mutex with signalling implemented via pthreads. +// Lock() will return true if and only if the guard is locked on that call. +// A thread that already has the guard will receive 'false' if it locks it +// again. Use of the stack-based CAGuard::Locker class is highly recommended +// to properly manage the recursive nesting. The Wait calls with timeouts +// will return true if and only if the timeout period expired. They will +// return false if they receive notification any other way. +//================================================================================================== + +class CAGuard : public CAMutex +{ + +// Construction/Destruction +public: + CAGuard(const char* inName); + virtual ~CAGuard(); + +// Actions +public: + virtual void Wait(); + virtual bool WaitFor(UInt64 inNanos); + virtual bool WaitUntil(UInt64 inNanos); + + virtual void Notify(); + virtual void NotifyAll(); + +// Implementation +protected: +#if TARGET_OS_MAC + pthread_cond_t mCondVar; +#else + HANDLE mEvent; +#endif +#if Log_Average_Latency + Float64 mAverageLatencyAccumulator; + UInt32 mAverageLatencyCount; +#endif + +// Helper class to manage taking and releasing recursively +public: + class Locker + { + + // Construction/Destruction + public: + Locker(CAGuard& inGuard) : mGuard(inGuard), mNeedsRelease(false) { mNeedsRelease = mGuard.Lock(); } + ~Locker() { if(mNeedsRelease) { mGuard.Unlock(); } } + + private: + Locker(const Locker&); + Locker& operator=(const Locker&); + + // Actions + public: + void Wait() { mGuard.Wait(); } + bool WaitFor(UInt64 inNanos) { return mGuard.WaitFor(inNanos); } + bool WaitUntil(UInt64 inNanos) { return mGuard.WaitUntil(inNanos); } + + void Notify() { mGuard.Notify(); } + void NotifyAll() { mGuard.NotifyAll(); } + + // Implementation + private: + CAGuard& mGuard; + bool mNeedsRelease; + }; + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp new file mode 100644 index 0000000000..9bce34626a --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp @@ -0,0 +1,1156 @@ +/* + File: CAHALAudioDevice.cpp + Abstract: CAHALAudioDevice.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CAHALAudioDevice.h" + +// PublicUtility Includes +#include "CAAutoDisposer.h" +#include "CAHALAudioStream.h" +#include "CAHALAudioSystemObject.h" +#include "CAPropertyAddress.h" + +//================================================================================================== +// CAHALAudioDevice +//================================================================================================== + +CAHALAudioDevice::CAHALAudioDevice(AudioObjectID inAudioDevice) +: + CAHALAudioObject(inAudioDevice) +{ +} + +CAHALAudioDevice::CAHALAudioDevice(CFStringRef inUID) +: + CAHALAudioObject(CAHALAudioSystemObject().GetAudioDeviceForUID(inUID)) +{ +} + +CAHALAudioDevice::~CAHALAudioDevice() +{ +} + +CFStringRef CAHALAudioDevice::CopyDeviceUID() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDeviceUID); + return GetPropertyData_CFString(theAddress, 0, NULL); +} + +bool CAHALAudioDevice::HasModelUID() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyModelUID); + return HasProperty(theAddress); +} + +CFStringRef CAHALAudioDevice::CopyModelUID() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyModelUID); + return GetPropertyData_CFString(theAddress, 0, NULL); +} + +CFStringRef CAHALAudioDevice::CopyConfigurationApplicationBundleID() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyConfigurationApplication); + return GetPropertyData_CFString(theAddress, 0, NULL); +} + +CFURLRef CAHALAudioDevice::CopyIconLocation() const +{ + CFURLRef theAnswer = NULL; + CAPropertyAddress theAddress(kAudioDevicePropertyIcon); + UInt32 theSize = sizeof(CFURLRef); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + return theAnswer; +} + +UInt32 CAHALAudioDevice::GetTransportType() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyTransportType); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +bool CAHALAudioDevice::CanBeDefaultDevice(bool inIsInput, bool inIsSystem) const +{ + CAPropertyAddress theAddress(inIsSystem ? kAudioDevicePropertyDeviceCanBeDefaultSystemDevice : kAudioDevicePropertyDeviceCanBeDefaultDevice, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + return GetPropertyData_UInt32(theAddress, 0, NULL) != 0; +} + +bool CAHALAudioDevice::HasDevicePlugInStatus() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPlugIn); + return HasProperty(theAddress); +} + +OSStatus CAHALAudioDevice::GetDevicePlugInStatus() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPlugIn); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +bool CAHALAudioDevice::IsAlive() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsAlive); + return GetPropertyData_UInt32(theAddress, 0, NULL) != 0; +} + +bool CAHALAudioDevice::IsHidden() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyIsHidden); + return GetPropertyData_UInt32(theAddress, 0, NULL) != 0; +} + +pid_t CAHALAudioDevice::GetHogModeOwner() const +{ + pid_t theAnswer = -1; + CAPropertyAddress theAddress(kAudioDevicePropertyHogMode); + if(HasProperty(theAddress)) + { + UInt32 theSize = sizeof(pid_t); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + return theAnswer; +} + +bool CAHALAudioDevice::IsHogModeSettable() const +{ + bool theAnswer = false; + CAPropertyAddress theAddress(kAudioDevicePropertyHogMode); + if(HasProperty(theAddress)) + { + theAnswer = IsPropertySettable(theAddress); + } + return theAnswer; +} + +bool CAHALAudioDevice::TakeHogMode() +{ + CAPropertyAddress theAddress(kAudioDevicePropertyHogMode); + pid_t thePID = getpid(); + if(HasProperty(theAddress)) + { + SetPropertyData(theAddress, 0, NULL, sizeof(pid_t), &thePID); + } + return thePID == getpid(); +} + +void CAHALAudioDevice::ReleaseHogMode() +{ + CAPropertyAddress theAddress(kAudioDevicePropertyHogMode); + if(HasProperty(theAddress)) + { + pid_t thePID = -1; + SetPropertyData(theAddress, 0, NULL, sizeof(pid_t), &thePID); + } +} + +bool CAHALAudioDevice::HasPreferredStereoChannels(bool inIsInput) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelsForStereo, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + return HasProperty(theAddress); +} + +void CAHALAudioDevice::GetPreferredStereoChannels(bool inIsInput, UInt32& outLeft, UInt32& outRight) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelsForStereo, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + UInt32 theStereoPair[2] = { 0, 0 }; + UInt32 theSize = 2 * sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, theStereoPair); + outLeft = theStereoPair[0]; + outRight = theStereoPair[1]; +} + +void CAHALAudioDevice::SetPreferredStereoChannels(bool inIsInput, UInt32 inLeft, UInt32 inRight) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelsForStereo, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + UInt32 theStereoPair[2] = { inLeft, inRight }; + SetPropertyData(theAddress, 0, NULL, 2 * sizeof(UInt32), theStereoPair); +} + +bool CAHALAudioDevice::HasPreferredChannelLayout(bool inIsInput) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelLayout, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + return HasProperty(theAddress); +} + +void CAHALAudioDevice::GetPreferredChannelLayout(bool inIsInput, AudioChannelLayout& outChannelLayout) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelLayout, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + UInt32 theSize = (SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription)) + GetTotalNumberChannels(inIsInput) * SizeOf32(AudioChannelDescription); + GetPropertyData(theAddress, 0, NULL, theSize, &outChannelLayout); +} + +void CAHALAudioDevice::SetPreferredStereoChannels(bool inIsInput, AudioChannelLayout& inChannelLayout) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelLayout, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + UInt32 theSize = (SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription)) + GetTotalNumberChannels(inIsInput) * SizeOf32(AudioChannelDescription); + SetPropertyData(theAddress, 0, NULL, theSize, &inChannelLayout); +} + +UInt32 CAHALAudioDevice::GetNumberRelatedAudioDevices() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyRelatedDevices); + UInt32 theAnswer = 0; + if(HasProperty(theAddress)) + { + theAnswer = GetPropertyDataSize(theAddress, 0, NULL); + theAnswer /= SizeOf32(AudioObjectID); + } + return theAnswer; +} + +void CAHALAudioDevice::GetRelatedAudioDevices(UInt32& ioNumberRelatedDevices, AudioObjectID* outRelatedDevices) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyRelatedDevices); + if(HasProperty(theAddress)) + { + UInt32 theSize = ioNumberRelatedDevices * SizeOf32(AudioObjectID); + GetPropertyData(theAddress, 0, NULL, theSize, outRelatedDevices); + ioNumberRelatedDevices = theSize / SizeOf32(AudioObjectID); + } + else + { + UInt32 theSize = ioNumberRelatedDevices * SizeOf32(AudioObjectID); + memset(outRelatedDevices, 0, theSize); + ioNumberRelatedDevices = 0; + } +} + +AudioObjectID CAHALAudioDevice::GetRelatedAudioDeviceByIndex(UInt32 inIndex) const +{ + AudioObjectID theAnswer = kAudioObjectUnknown; + UInt32 theNumberRelatedDevices = GetNumberRelatedAudioDevices(); + if((theNumberRelatedDevices > 0) && (inIndex < theNumberRelatedDevices)) + { + CAAutoArrayDelete<AudioObjectID> theRelatedDeviceList(theNumberRelatedDevices); + GetRelatedAudioDevices(theNumberRelatedDevices, theRelatedDeviceList); + if((theNumberRelatedDevices > 0) && (inIndex < theNumberRelatedDevices)) + { + theAnswer = theRelatedDeviceList[inIndex]; + } + } + return theAnswer; +} + +UInt32 CAHALAudioDevice::GetNumberStreams(bool inIsInput) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyStreams, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL); + theAnswer /= SizeOf32(AudioObjectID); + return theAnswer; +} + +void CAHALAudioDevice::GetStreams(bool inIsInput, UInt32& ioNumberStreams, AudioObjectID* outStreamList) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyStreams, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + UInt32 theSize = ioNumberStreams * SizeOf32(AudioObjectID); + GetPropertyData(theAddress, 0, NULL, theSize, outStreamList); + ioNumberStreams = theSize / SizeOf32(AudioObjectID); +} + +AudioObjectID CAHALAudioDevice::GetStreamByIndex(bool inIsInput, UInt32 inIndex) const +{ + AudioObjectID theAnswer = kAudioObjectUnknown; + UInt32 theNumberStreams = GetNumberStreams(inIsInput); + if((theNumberStreams > 0) && (inIndex < theNumberStreams)) + { + CAAutoArrayDelete<AudioObjectID> theStreamList(theNumberStreams); + GetStreams(inIsInput, theNumberStreams, theStreamList); + if((theNumberStreams > 0) && (inIndex < theNumberStreams)) + { + theAnswer = theStreamList[inIndex]; + } + } + return theAnswer; +} + +UInt32 CAHALAudioDevice::GetTotalNumberChannels(bool inIsInput) const +{ + UInt32 theAnswer = 0; + CAPropertyAddress theAddress(kAudioDevicePropertyStreamConfiguration, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL); + CAAutoFree<AudioBufferList> theBufferList(theSize); + GetPropertyData(theAddress, 0, NULL, theSize, theBufferList); + for(UInt32 theIndex = 0; theIndex < theBufferList->mNumberBuffers; ++theIndex) + { + theAnswer += theBufferList->mBuffers[theIndex].mNumberChannels; + } + return theAnswer; +} + +void CAHALAudioDevice::GetCurrentVirtualFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const +{ + ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inIsInput)); + for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex) + { + CAHALAudioStream theStream(GetStreamByIndex(inIsInput, theIndex)); + theStream.GetCurrentVirtualFormat(outFormats[theIndex]); + } +} + +void CAHALAudioDevice::GetCurrentPhysicalFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const +{ + ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inIsInput)); + for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex) + { + CAHALAudioStream theStream(GetStreamByIndex(inIsInput, theIndex)); + theStream.GetCurrentPhysicalFormat(outFormats[theIndex]); + } +} + +bool CAHALAudioDevice::IsRunning() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsRunning); + UInt32 theAnswer = GetPropertyData_UInt32(theAddress, 0, NULL); + return theAnswer != 0; +} + +bool CAHALAudioDevice::IsRunningSomewhere() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsRunningSomewhere); + UInt32 theAnswer = 0; + if(HasProperty(theAddress)) + { + theAnswer = GetPropertyData_UInt32(theAddress, 0, NULL); + } + return theAnswer != 0; +} + +UInt32 CAHALAudioDevice::GetLatency(bool inIsInput) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyLatency, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +UInt32 CAHALAudioDevice::GetSafetyOffset(bool inIsInput) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySafetyOffset, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +bool CAHALAudioDevice::HasClockDomain() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockDomain); + return HasProperty(theAddress); +} + +UInt32 CAHALAudioDevice::GetClockDomain() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockDomain); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +Float64 CAHALAudioDevice::GetActualSampleRate() const +{ + Float64 theAnswer = 0; + CAPropertyAddress theAddress(kAudioDevicePropertyActualSampleRate); + if(HasProperty(theAddress)) + { + UInt32 theSize = sizeof(Float64); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + else + { + theAnswer = GetNominalSampleRate(); + } + return theAnswer; +} + +Float64 CAHALAudioDevice::GetNominalSampleRate() const +{ + Float64 theAnswer = 0; + CAPropertyAddress theAddress(kAudioDevicePropertyNominalSampleRate); + UInt32 theSize = sizeof(Float64); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + return theAnswer; +} + +void CAHALAudioDevice::SetNominalSampleRate(Float64 inSampleRate) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyNominalSampleRate); + SetPropertyData(theAddress, 0, NULL, sizeof(Float64), &inSampleRate); +} + +UInt32 CAHALAudioDevice::GetNumberAvailableNominalSampleRateRanges() const +{ + UInt32 theAnswer = 0; + CAPropertyAddress theAddress(kAudioDevicePropertyAvailableNominalSampleRates); + if(HasProperty(theAddress)) + { + UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL); + theAnswer = theSize / SizeOf32(AudioValueRange); + } + return theAnswer; +} + +void CAHALAudioDevice::GetAvailableNominalSampleRateRanges(UInt32& ioNumberRanges, AudioValueRange* outRanges) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyAvailableNominalSampleRates); + if(HasProperty(theAddress)) + { + UInt32 theSize = ioNumberRanges * SizeOf32(AudioValueRange); + GetPropertyData(theAddress, 0, NULL, theSize, outRanges); + ioNumberRanges = theSize / SizeOf32(AudioValueRange); + } + else + { + ioNumberRanges = 0; + } +} + +void CAHALAudioDevice::GetAvailableNominalSampleRateRangeByIndex(UInt32 inIndex, Float64& outMinimum, Float64& outMaximum) const +{ + UInt32 theNumberRanges = GetNumberAvailableNominalSampleRateRanges(); + ThrowIf(inIndex >= theNumberRanges, CAException(kAudioHardwareIllegalOperationError), "CAHALAudioDevice::GetAvailableNominalSampleRateRangeByIndex: index out of range"); + CAAutoArrayDelete<AudioValueRange> theRanges(theNumberRanges); + GetAvailableNominalSampleRateRanges(theNumberRanges, theRanges); + outMinimum = theRanges[inIndex].mMinimum; + outMaximum = theRanges[inIndex].mMaximum; +} + +bool CAHALAudioDevice::IsValidNominalSampleRate(Float64 inSampleRate) const +{ + bool theAnswer = false; + UInt32 theNumberRanges = GetNumberAvailableNominalSampleRateRanges(); + CAAutoArrayDelete<AudioValueRange> theRanges(theNumberRanges); + GetAvailableNominalSampleRateRanges(theNumberRanges, theRanges); + for(UInt32 theIndex = 0; !theAnswer && (theIndex < theNumberRanges); ++theIndex) + { + theAnswer = (inSampleRate >= theRanges[theIndex].mMinimum) && (inSampleRate <= theRanges[theIndex].mMinimum); + } + return theAnswer; +} + +bool CAHALAudioDevice::IsIOBufferSizeSettable() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize); + return IsPropertySettable(theAddress); +} + +UInt32 CAHALAudioDevice::GetIOBufferSize() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +void CAHALAudioDevice::SetIOBufferSize(UInt32 inBufferSize) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize); + SetPropertyData(theAddress, 0, NULL, sizeof(UInt32), &inBufferSize); +} + +bool CAHALAudioDevice::UsesVariableIOBufferSizes() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyUsesVariableBufferFrameSizes); + return HasProperty(theAddress); +} + +UInt32 CAHALAudioDevice::GetMaximumVariableIOBufferSize() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyUsesVariableBufferFrameSizes); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +bool CAHALAudioDevice::HasIOBufferSizeRange() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSizeRange); + return HasProperty(theAddress); +} + +void CAHALAudioDevice::GetIOBufferSizeRange(UInt32& outMinimum, UInt32& outMaximum) const +{ + AudioValueRange theAnswer = { 0, 0 }; + CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSizeRange); + UInt32 theSize = sizeof(AudioValueRange); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + outMinimum = static_cast<UInt32>(theAnswer.mMinimum); + outMaximum = static_cast<UInt32>(theAnswer.mMaximum); +} + +AudioDeviceIOProcID CAHALAudioDevice::CreateIOProcID(AudioDeviceIOProc inIOProc, void* inClientData) +{ + AudioDeviceIOProcID theAnswer = NULL; + OSStatus theError = AudioDeviceCreateIOProcID(mObjectID, inIOProc, inClientData, &theAnswer); + ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::CreateIOProcID: got an error creating the IOProc ID"); + return theAnswer; +} + +void CAHALAudioDevice::DestroyIOProcID(AudioDeviceIOProcID inIOProcID) +{ + OSStatus theError = AudioDeviceDestroyIOProcID(mObjectID, inIOProcID); + ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::DestroyIOProcID: got an error destroying the IOProc ID"); +} + +void CAHALAudioDevice::StartIOProc(AudioDeviceIOProcID inIOProcID) +{ + OSStatus theError = AudioDeviceStart(mObjectID, inIOProcID); + ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StartIOProc: got an error starting an IOProc"); +} + +void CAHALAudioDevice::StartIOProcAtTime(AudioDeviceIOProcID inIOProcID, AudioTimeStamp& ioStartTime, bool inIsInput, bool inIgnoreHardware) +{ + UInt32 theFlags = 0; + if(inIsInput) + { + theFlags |= kAudioDeviceStartTimeIsInputFlag; + } + if(inIgnoreHardware) + { + theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag; + } + + OSStatus theError = AudioDeviceStartAtTime(mObjectID, inIOProcID, &ioStartTime, theFlags); + ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StartIOProcAtTime: got an error starting an IOProc"); +} + +void CAHALAudioDevice::StopIOProc(AudioDeviceIOProcID inIOProcID) +{ + OSStatus theError = AudioDeviceStop(mObjectID, inIOProcID); + ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StopIOProc: got an error stopping an IOProc"); +} + +void CAHALAudioDevice::GetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, bool* outStreamUsage) const +{ + // make an AudioHardwareIOProcStreamUsage the right size + UInt32 theNumberStreams = GetNumberStreams(inIsInput); + UInt32 theSize = SizeOf32(void*) + SizeOf32(UInt32) + (theNumberStreams * SizeOf32(UInt32)); + CAAutoFree<AudioHardwareIOProcStreamUsage> theStreamUsage(theSize); + + // set it up + theStreamUsage->mIOProc = reinterpret_cast<void*>(inIOProcID); + theStreamUsage->mNumberStreams = theNumberStreams; + + // get the property + CAPropertyAddress theAddress(kAudioDevicePropertyIOProcStreamUsage, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + GetPropertyData(theAddress, 0, NULL, theSize, theStreamUsage); + + // fill out the return value + for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex) + { + outStreamUsage[theIndex] = (theStreamUsage->mStreamIsOn[theIndex] != 0); + } +} + +void CAHALAudioDevice::SetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, const bool* inStreamUsage) +{ + // make an AudioHardwareIOProcStreamUsage the right size + UInt32 theNumberStreams = GetNumberStreams(inIsInput); + UInt32 theSize = SizeOf32(void*) + SizeOf32(UInt32) + (theNumberStreams * SizeOf32(UInt32)); + CAAutoFree<AudioHardwareIOProcStreamUsage> theStreamUsage(theSize); + + // set it up + theStreamUsage->mIOProc = reinterpret_cast<void*>(inIOProcID); + theStreamUsage->mNumberStreams = theNumberStreams; + for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex) + { + theStreamUsage->mStreamIsOn[theIndex] = (inStreamUsage[theIndex] ? 1 : 0); + } + + // set the property + CAPropertyAddress theAddress(kAudioDevicePropertyIOProcStreamUsage, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput); + SetPropertyData(theAddress, 0, NULL, theSize, theStreamUsage); +} + +Float32 CAHALAudioDevice::GetIOCycleUsage() const +{ + Float32 theAnswer = 0; + CAPropertyAddress theAddress(kAudioDevicePropertyIOCycleUsage); + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + return theAnswer; +} + +void CAHALAudioDevice::SetIOCycleUsage(Float32 inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyIOCycleUsage); + SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue); +} + +void CAHALAudioDevice::GetCurrentTime(AudioTimeStamp& outTime) +{ + OSStatus theError = AudioDeviceGetCurrentTime(mObjectID, &outTime); + ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::GetCurrentTime: got an error getting the current time"); +} + +void CAHALAudioDevice::TranslateTime(const AudioTimeStamp& inTime, AudioTimeStamp& outTime) +{ + OSStatus theError = AudioDeviceTranslateTime(mObjectID, &inTime, &outTime); + ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::TranslateTime: got an error translating time"); +} + +void CAHALAudioDevice::GetNearestStartTime(AudioTimeStamp& ioTime, bool inIsInput, bool inIgnoreHardware) +{ + UInt32 theFlags = 0; + if(inIsInput) + { + theFlags |= kAudioDeviceStartTimeIsInputFlag; + } + if(inIgnoreHardware) + { + theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag; + } + + OSStatus theError = AudioDeviceGetNearestStartTime(mObjectID, &ioTime, theFlags); + ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::GetNearestStartTime: got an error getting the start time"); +} + +bool CAHALAudioDevice::HasVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::VolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel); + return IsPropertySettable(theAddress); +} + +Float32 CAHALAudioDevice::GetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel); + Float32 theValue = 0.0f; + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue; +} + +Float32 CAHALAudioDevice::GetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibels, inScope, inChannel); + Float32 theValue = 0.0f; + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue; +} + +void CAHALAudioDevice::SetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel); + SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue); +} + +void CAHALAudioDevice::SetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibels, inScope, inChannel); + SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue); +} + +Float32 CAHALAudioDevice::GetVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibelsToScalar, inScope, inChannel); + Float32 theValue = inValue; + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue; +} + +Float32 CAHALAudioDevice::GetVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalarToDecibels, inScope, inChannel); + Float32 theValue = inValue; + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue; +} + +bool CAHALAudioDevice::HasSubVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::SubVolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel); + return IsPropertySettable(theAddress); +} + +Float32 CAHALAudioDevice::GetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel); + Float32 theValue = 0.0f; + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue; +} + +Float32 CAHALAudioDevice::GetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibels, inScope, inChannel); + Float32 theValue = 0.0f; + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue; +} + +void CAHALAudioDevice::SetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel); + SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue); +} + +void CAHALAudioDevice::SetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibels, inScope, inChannel); + SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue); +} + +Float32 CAHALAudioDevice::GetSubVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibelsToScalar, inScope, inChannel); + Float32 theValue = inValue; + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue; +} + +Float32 CAHALAudioDevice::GetSubVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalarToDecibels, inScope, inChannel); + Float32 theValue = inValue; + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue; +} + +bool CAHALAudioDevice::HasMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::MuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel); + return IsPropertySettable(theAddress); +} + +bool CAHALAudioDevice::GetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel); + UInt32 theValue = 0; + UInt32 theSize = sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue != 0; +} + +void CAHALAudioDevice::SetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel); + UInt32 theValue = (inValue ? 1 : 0); + UInt32 theSize = sizeof(UInt32); + SetPropertyData(theAddress, 0, NULL, theSize, &theValue); +} + +bool CAHALAudioDevice::HasSoloControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::SoloControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel); + return IsPropertySettable(theAddress); +} + +bool CAHALAudioDevice::GetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel); + UInt32 theValue = 0; + UInt32 theSize = sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue != 0; +} + +void CAHALAudioDevice::SetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel); + UInt32 theValue = (inValue ? 1 : 0); + UInt32 theSize = sizeof(UInt32); + SetPropertyData(theAddress, 0, NULL, theSize, &theValue); +} + +bool CAHALAudioDevice::HasStereoPanControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::StereoPanControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel); + return IsPropertySettable(theAddress); +} + +Float32 CAHALAudioDevice::GetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel); + Float32 theValue = 0.0f; + UInt32 theSize = sizeof(Float32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue; +} + +void CAHALAudioDevice::SetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel); + UInt32 theSize = sizeof(Float32); + SetPropertyData(theAddress, 0, NULL, theSize, &inValue); +} + +void CAHALAudioDevice::GetStereoPanControlChannels(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& outLeftChannel, UInt32& outRightChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyStereoPanChannels, inScope, inChannel); + UInt32 theValue[2] = { 0, 0 }; + UInt32 theSize = 2 * sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, theValue); + outLeftChannel = theValue[0]; + outRightChannel = theValue[1]; +} + +bool CAHALAudioDevice::HasJackControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyJackIsConnected, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::GetJackControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyJackIsConnected, inScope, inChannel); + UInt32 theValue = 0; + UInt32 theSize = sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue != 0; +} + +bool CAHALAudioDevice::HasSubMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::SubMuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel); + return IsPropertySettable(theAddress); +} + +bool CAHALAudioDevice::GetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel); + UInt32 theValue = 0; + UInt32 theSize = sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue != 0; +} + +void CAHALAudioDevice::SetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel); + UInt32 theValue = (inValue ? 1 : 0); + UInt32 theSize = sizeof(UInt32); + SetPropertyData(theAddress, 0, NULL, theSize, &theValue); +} + +bool CAHALAudioDevice::HasiSubOwnerControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::iSubOwnerControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel); + return IsPropertySettable(theAddress); +} + +bool CAHALAudioDevice::GetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel); + UInt32 theValue = 0; + UInt32 theSize = sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theValue != 0; +} + +void CAHALAudioDevice::SetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel); + UInt32 theValue = (inValue ? 1 : 0); + UInt32 theSize = sizeof(UInt32); + SetPropertyData(theAddress, 0, NULL, theSize, &theValue); +} + +bool CAHALAudioDevice::HasDataSourceControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::DataSourceControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel); + return IsPropertySettable(theAddress); +} + +UInt32 CAHALAudioDevice::GetCurrentDataSourceID(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel); + UInt32 theAnswer = 0; + UInt32 theSize = sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + return theAnswer; +} + +void CAHALAudioDevice::SetCurrentDataSourceByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel); + UInt32 theSize = sizeof(UInt32); + SetPropertyData(theAddress, 0, NULL, theSize, &inID); +} + +UInt32 CAHALAudioDevice::GetNumberAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDataSources, inScope, inChannel); + UInt32 theAnswer = 0; + if(HasProperty(theAddress)) + { + UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL); + theAnswer = theSize / SizeOf32(UInt32); + } + return theAnswer; +} + +void CAHALAudioDevice::GetAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberSources, UInt32* outSources) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDataSources, inScope, inChannel); + UInt32 theNumberSources = std::min(GetNumberAvailableDataSources(inScope, inChannel), ioNumberSources); + UInt32 theSize = theNumberSources * SizeOf32(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, outSources); + ioNumberSources = theSize / SizeOf32(UInt32); +} + +UInt32 CAHALAudioDevice::GetAvailableDataSourceByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const +{ + AudioStreamID theAnswer = 0; + UInt32 theNumberSources = GetNumberAvailableDataSources(inScope, inChannel); + if((theNumberSources > 0) && (inIndex < theNumberSources)) + { + CAAutoArrayDelete<UInt32> theSourceList(theNumberSources); + GetAvailableDataSources(inScope, inChannel, theNumberSources, theSourceList); + theAnswer = theSourceList[inIndex]; + } + return theAnswer; +} + +CFStringRef CAHALAudioDevice::CopyDataSourceNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyDataSourceNameForIDCFString, inScope, inChannel); + CFStringRef theAnswer = NULL; + AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) }; + UInt32 theSize = sizeof(AudioValueTranslation); + GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation); + return theAnswer; +} + +bool CAHALAudioDevice::HasDataDestinationControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::DataDestinationControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel); + return IsPropertySettable(theAddress); +} + +UInt32 CAHALAudioDevice::GetCurrentDataDestinationID(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel); + UInt32 theAnswer = 0; + UInt32 theSize = sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + return theAnswer; +} + +void CAHALAudioDevice::SetCurrentDataDestinationByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel); + UInt32 theSize = sizeof(UInt32); + SetPropertyData(theAddress, 0, NULL, theSize, &inID); +} + +UInt32 CAHALAudioDevice::GetNumberAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinations, inScope, inChannel); + UInt32 theAnswer = 0; + if(HasProperty(theAddress)) + { + UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL); + theAnswer = theSize / SizeOf32(UInt32); + } + return theAnswer; +} + +void CAHALAudioDevice::GetAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberDestinations, UInt32* outDestinations) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinations, inScope, inChannel); + UInt32 theNumberDestinations = std::min(GetNumberAvailableDataDestinations(inScope, inChannel), ioNumberDestinations); + UInt32 theSize = theNumberDestinations * SizeOf32(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, outDestinations); + ioNumberDestinations = theSize / SizeOf32(UInt32); +} + +UInt32 CAHALAudioDevice::GetAvailableDataDestinationByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const +{ + AudioStreamID theAnswer = 0; + UInt32 theNumberDestinations = GetNumberAvailableDataDestinations(inScope, inChannel); + if((theNumberDestinations > 0) && (inIndex < theNumberDestinations)) + { + CAAutoArrayDelete<UInt32> theDestinationList(theNumberDestinations); + GetAvailableDataDestinations(inScope, inChannel, theNumberDestinations, theDestinationList); + theAnswer = theDestinationList[inIndex]; + } + return theAnswer; +} + +CFStringRef CAHALAudioDevice::CopyDataDestinationNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinationNameForIDCFString, inScope, inChannel); + CFStringRef theAnswer = NULL; + AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) }; + UInt32 theSize = sizeof(AudioValueTranslation); + GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation); + return theAnswer; +} + +bool CAHALAudioDevice::HasClockSourceControl() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockSource); + return HasProperty(theAddress); +} + +bool CAHALAudioDevice::ClockSourceControlIsSettable() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockSource); + return IsPropertySettable(theAddress); +} + +UInt32 CAHALAudioDevice::GetCurrentClockSourceID() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockSource); + UInt32 theAnswer = 0; + UInt32 theSize = sizeof(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + return theAnswer; +} + +void CAHALAudioDevice::SetCurrentClockSourceByID(UInt32 inID) +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockSource); + UInt32 theSize = sizeof(UInt32); + SetPropertyData(theAddress, 0, NULL, theSize, &inID); +} + +UInt32 CAHALAudioDevice::GetNumberAvailableClockSources() const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockSources); + UInt32 theAnswer = 0; + if(HasProperty(theAddress)) + { + UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL); + theAnswer = theSize / SizeOf32(UInt32); + } + return theAnswer; +} + +void CAHALAudioDevice::GetAvailableClockSources(UInt32& ioNumberSources, UInt32* outSources) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockSources); + UInt32 theNumberSources = std::min(GetNumberAvailableClockSources(), ioNumberSources); + UInt32 theSize = theNumberSources * SizeOf32(UInt32); + GetPropertyData(theAddress, 0, NULL, theSize, outSources); + ioNumberSources = theSize / SizeOf32(UInt32); +} + +UInt32 CAHALAudioDevice::GetAvailableClockSourceByIndex(UInt32 inIndex) const +{ + AudioStreamID theAnswer = 0; + UInt32 theNumberSources = GetNumberAvailableClockSources(); + if((theNumberSources > 0) && (inIndex < theNumberSources)) + { + CAAutoArrayDelete<UInt32> theSourceList(theNumberSources); + GetAvailableClockSources(theNumberSources, theSourceList); + theAnswer = theSourceList[inIndex]; + } + return theAnswer; +} + +CFStringRef CAHALAudioDevice::CopyClockSourceNameForID(UInt32 inID) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockSourceNameForIDCFString); + CFStringRef theAnswer = NULL; + AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) }; + UInt32 theSize = sizeof(AudioValueTranslation); + GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation); + return theAnswer; +} + +UInt32 CAHALAudioDevice::GetClockSourceKindForID(UInt32 inID) const +{ + CAPropertyAddress theAddress(kAudioDevicePropertyClockSourceKindForID); + UInt32 theAnswer = 0; + AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(UInt32) }; + UInt32 theSize = sizeof(AudioValueTranslation); + GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation); + return theAnswer; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h new file mode 100644 index 0000000000..8cfb466886 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h @@ -0,0 +1,238 @@ +/* + File: CAHALAudioDevice.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAHALAudioDevice_h__) +#define __CAHALAudioDevice_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// Super Class Includes +#include "CAHALAudioObject.h" + +// PublicUtility Includes +#include "CADebugMacros.h" +#include "CAException.h" + +//================================================================================================== +// CAHALAudioDevice +//================================================================================================== + +class CAHALAudioDevice +: + public CAHALAudioObject +{ + +// Construction/Destruction +public: + CAHALAudioDevice(AudioObjectID inAudioDevice); + CAHALAudioDevice(CFStringRef inUID); + virtual ~CAHALAudioDevice(); + +// General Stuff +public: + CFStringRef CopyDeviceUID() const; + bool HasModelUID() const; + CFStringRef CopyModelUID() const; + CFStringRef CopyConfigurationApplicationBundleID() const; + CFURLRef CopyIconLocation() const; + UInt32 GetTransportType() const; + bool CanBeDefaultDevice(bool inIsInput, bool inIsSystem) const; + bool HasDevicePlugInStatus() const; + OSStatus GetDevicePlugInStatus() const; + bool IsAlive() const; + bool IsHidden() const; + pid_t GetHogModeOwner() const; + bool IsHogModeSettable() const; + bool TakeHogMode(); + void ReleaseHogMode(); + bool HasPreferredStereoChannels(bool inIsInput) const; + void GetPreferredStereoChannels(bool inIsInput, UInt32& outLeft, UInt32& outRight) const; + void SetPreferredStereoChannels(bool inIsInput, UInt32 inLeft, UInt32 inRight); + bool HasPreferredChannelLayout(bool inIsInput) const; + void GetPreferredChannelLayout(bool inIsInput, AudioChannelLayout& outChannelLayout) const; + void SetPreferredStereoChannels(bool inIsInput, AudioChannelLayout& inChannelLayout); + UInt32 GetNumberRelatedAudioDevices() const; + void GetRelatedAudioDevices(UInt32& ioNumberRelatedDevices, AudioObjectID* outRelatedDevices) const; + AudioObjectID GetRelatedAudioDeviceByIndex(UInt32 inIndex) const; + +// Stream Stuff +public: + UInt32 GetNumberStreams(bool inIsInput) const; + void GetStreams(bool inIsInput, UInt32& ioNumberStreams, AudioObjectID* outStreamList) const; + AudioObjectID GetStreamByIndex(bool inIsInput, UInt32 inIndex) const; + UInt32 GetTotalNumberChannels(bool inIsInput) const; + void GetCurrentVirtualFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const; + void GetCurrentPhysicalFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const; + +// IO Stuff +public: + bool IsRunning() const; + bool IsRunningSomewhere() const; + UInt32 GetLatency(bool inIsInput) const; + UInt32 GetSafetyOffset(bool inIsInput) const; + bool HasClockDomain() const; + UInt32 GetClockDomain() const; + Float64 GetActualSampleRate() const; + Float64 GetNominalSampleRate() const; + void SetNominalSampleRate(Float64 inSampleRate); + UInt32 GetNumberAvailableNominalSampleRateRanges() const; + void GetAvailableNominalSampleRateRanges(UInt32& ioNumberRanges, AudioValueRange* outRanges) const; + void GetAvailableNominalSampleRateRangeByIndex(UInt32 inIndex, Float64& outMinimum, Float64& outMaximum) const; + bool IsValidNominalSampleRate(Float64 inSampleRate) const; + bool IsIOBufferSizeSettable() const; + UInt32 GetIOBufferSize() const; + void SetIOBufferSize(UInt32 inBufferSize); + bool UsesVariableIOBufferSizes() const; + UInt32 GetMaximumVariableIOBufferSize() const; + bool HasIOBufferSizeRange() const; + void GetIOBufferSizeRange(UInt32& outMinimum, UInt32& outMaximum) const; + AudioDeviceIOProcID CreateIOProcID(AudioDeviceIOProc inIOProc, void* inClientData); + AudioDeviceIOProcID CreateIOProcIDWithBlock(dispatch_queue_t inDispatchQueue, AudioDeviceIOBlock inIOBlock); + void DestroyIOProcID(AudioDeviceIOProcID inIOProcID); + void StartIOProc(AudioDeviceIOProcID inIOProcID); + void StartIOProcAtTime(AudioDeviceIOProcID inIOProcID, AudioTimeStamp& ioStartTime, bool inIsInput, bool inIgnoreHardware); + void StopIOProc(AudioDeviceIOProcID inIOProcID); + void GetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, bool* outStreamUsage) const; + void SetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, const bool* inStreamUsage); + Float32 GetIOCycleUsage() const; + void SetIOCycleUsage(Float32 inValue); + +// Time Operations +public: + void GetCurrentTime(AudioTimeStamp& outTime); + void TranslateTime(const AudioTimeStamp& inTime, AudioTimeStamp& outTime); + void GetNearestStartTime(AudioTimeStamp& ioTime, bool inIsInput, bool inIgnoreHardware); + +// Controls +public: + bool HasVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool VolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + Float32 GetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + Float32 GetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void SetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue); + void SetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue); + Float32 GetVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const; + Float32 GetVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const; + + bool HasSubVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool SubVolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + Float32 GetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + Float32 GetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void SetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue); + void SetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue); + Float32 GetSubVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const; + Float32 GetSubVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const; + + bool HasMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool MuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool GetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void SetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue); + + bool HasSoloControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool SoloControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool GetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void SetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue); + + bool HasStereoPanControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool StereoPanControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + Float32 GetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void SetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue); + void GetStereoPanControlChannels(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& outLeftChannel, UInt32& outRightChannel) const; + + bool HasJackControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool GetJackControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + + bool HasSubMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool SubMuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool GetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void SetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue); + + bool HasiSubOwnerControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool iSubOwnerControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool GetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void SetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue); + + bool HasDataSourceControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool DataSourceControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + UInt32 GetCurrentDataSourceID(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void SetCurrentDataSourceByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID); + UInt32 GetNumberAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void GetAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberSources, UInt32* outSources) const; + UInt32 GetAvailableDataSourceByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const; + CFStringRef CopyDataSourceNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const; + + bool HasDataDestinationControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + bool DataDestinationControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + UInt32 GetCurrentDataDestinationID(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void SetCurrentDataDestinationByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID); + UInt32 GetNumberAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel) const; + void GetAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberDestinations, UInt32* outDestinations) const; + UInt32 GetAvailableDataDestinationByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const; + CFStringRef CopyDataDestinationNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const; + + bool HasClockSourceControl() const; + bool ClockSourceControlIsSettable() const; + UInt32 GetCurrentClockSourceID() const; + void SetCurrentClockSourceByID(UInt32 inID); + UInt32 GetNumberAvailableClockSources() const; + void GetAvailableClockSources(UInt32& ioNumberSources, UInt32* outSources) const; + UInt32 GetAvailableClockSourceByIndex(UInt32 inIndex) const; + CFStringRef CopyClockSourceNameForID(UInt32 inID) const; + UInt32 GetClockSourceKindForID(UInt32 inID) const; + +}; + +inline AudioDeviceIOProcID CAHALAudioDevice::CreateIOProcIDWithBlock(dispatch_queue_t inDispatchQueue, AudioDeviceIOBlock inIOBlock) +{ + AudioDeviceIOProcID theAnswer = NULL; + OSStatus theError = AudioDeviceCreateIOProcIDWithBlock(&theAnswer, mObjectID, inDispatchQueue, inIOBlock); + ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::CreateIOProcIDWithBlock: got an error creating the IOProc ID"); + return theAnswer; +} + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp new file mode 100644 index 0000000000..c8f16b4fb3 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp @@ -0,0 +1,370 @@ +/* + File: CAHALAudioObject.cpp + Abstract: CAHALAudioObject.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CAHALAudioObject.h" + +// PublicUtility Includes +#include "CAAutoDisposer.h" +#include "CADebugMacros.h" +#include "CAException.h" +#include "CAPropertyAddress.h" + +//================================================================================================== +// CAHALAudioObject +//================================================================================================== + +CAHALAudioObject::CAHALAudioObject(AudioObjectID inObjectID) +: + mObjectID(inObjectID) +{ +} + +CAHALAudioObject::~CAHALAudioObject() +{ +} + +AudioObjectID CAHALAudioObject::GetObjectID() const +{ + return mObjectID; +} + +void CAHALAudioObject::SetObjectID(AudioObjectID inObjectID) +{ + mObjectID = inObjectID; +} + +AudioClassID CAHALAudioObject::GetClassID() const +{ + // set up the return value + AudioClassID theAnswer = 0; + + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyClass); + + // make sure the property exists + if(HasProperty(theAddress)) + { + UInt32 theSize = sizeof(AudioClassID); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + + return theAnswer; +} + +AudioObjectID CAHALAudioObject::GetOwnerObjectID() const +{ + // set up the return value + AudioObjectID theAnswer = 0; + + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyOwner); + + // make sure the property exists + if(HasProperty(theAddress)) + { + // get the property data + UInt32 theSize = sizeof(AudioObjectID); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + + return theAnswer; +} + +CFStringRef CAHALAudioObject::CopyOwningPlugInBundleID() const +{ + // set up the return value + CFStringRef theAnswer = NULL; + + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyCreator); + + // make sure the property exists + if(HasProperty(theAddress)) + { + // get the property data + UInt32 theSize = sizeof(CFStringRef); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + + return theAnswer; +} + +CFStringRef CAHALAudioObject::CopyName() const +{ + // set up the return value + CFStringRef theAnswer = NULL; + + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyName); + + // make sure the property exists + if(HasProperty(theAddress)) + { + // get the property data + UInt32 theSize = sizeof(CFStringRef); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + + return theAnswer; +} + +CFStringRef CAHALAudioObject::CopyManufacturer() const +{ + // set up the return value + CFStringRef theAnswer = NULL; + + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyManufacturer); + + // make sure the property exists + if(HasProperty(theAddress)) + { + // get the property data + UInt32 theSize = sizeof(CFStringRef); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + + return theAnswer; +} + +CFStringRef CAHALAudioObject::CopyNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const +{ + // set up the return value + CFStringRef theAnswer = NULL; + + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyElementName, inScope, inElement); + + // make sure the property exists + if(HasProperty(theAddress)) + { + // get the property data + UInt32 theSize = sizeof(CFStringRef); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + + return theAnswer; +} + +CFStringRef CAHALAudioObject::CopyCategoryNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const +{ + // set up the return value + CFStringRef theAnswer = NULL; + + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyElementCategoryName, inScope, inElement); + + // make sure the property exists + if(HasProperty(theAddress)) + { + // get the property data + UInt32 theSize = sizeof(CFStringRef); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + + return theAnswer; +} + +CFStringRef CAHALAudioObject::CopyNumberNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const +{ + // set up the return value + CFStringRef theAnswer = NULL; + + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyElementNumberName, inScope, inElement); + + // make sure the property exists + if(HasProperty(theAddress)) + { + // get the property data + UInt32 theSize = sizeof(CFStringRef); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + } + + return theAnswer; +} + +bool CAHALAudioObject::ObjectExists(AudioObjectID inObjectID) +{ + Boolean isSettable; + CAPropertyAddress theAddress(kAudioObjectPropertyClass); + return (inObjectID == 0) || (AudioObjectIsPropertySettable(inObjectID, &theAddress, &isSettable) != 0); +} + +UInt32 CAHALAudioObject::GetNumberOwnedObjects(AudioClassID inClass) const +{ + // set up the return value + UInt32 theAnswer = 0; + + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects); + + // figure out the qualifier + UInt32 theQualifierSize = 0; + void* theQualifierData = NULL; + if(inClass != 0) + { + theQualifierSize = sizeof(AudioObjectID); + theQualifierData = &inClass; + } + + // get the property data size + theAnswer = GetPropertyDataSize(theAddress, theQualifierSize, theQualifierData); + + // calculate the number of object IDs + theAnswer /= SizeOf32(AudioObjectID); + + return theAnswer; +} + +void CAHALAudioObject::GetAllOwnedObjects(AudioClassID inClass, UInt32& ioNumberObjects, AudioObjectID* ioObjectIDs) const +{ + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects); + + // figure out the qualifier + UInt32 theQualifierSize = 0; + void* theQualifierData = NULL; + if(inClass != 0) + { + theQualifierSize = sizeof(AudioObjectID); + theQualifierData = &inClass; + } + + // get the property data + UInt32 theDataSize = ioNumberObjects * SizeOf32(AudioClassID); + GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, ioObjectIDs); + + // set the number of object IDs being returned + ioNumberObjects = theDataSize / SizeOf32(AudioObjectID); +} + +AudioObjectID CAHALAudioObject::GetOwnedObjectByIndex(AudioClassID inClass, UInt32 inIndex) +{ + // set up the property address + CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects); + + // figure out the qualifier + UInt32 theQualifierSize = 0; + void* theQualifierData = NULL; + if(inClass != 0) + { + theQualifierSize = sizeof(AudioObjectID); + theQualifierData = &inClass; + } + + // figure out how much space to allocate + UInt32 theDataSize = GetPropertyDataSize(theAddress, theQualifierSize, theQualifierData); + UInt32 theNumberObjectIDs = theDataSize / SizeOf32(AudioObjectID); + + // set up the return value + AudioObjectID theAnswer = 0; + + // maker sure the index is in range + if(inIndex < theNumberObjectIDs) + { + // allocate it + CAAutoArrayDelete<AudioObjectID> theObjectList(theDataSize / sizeof(AudioObjectID)); + + // get the property data + GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, theObjectList); + + // get the return value + theAnswer = theObjectList[inIndex]; + } + + return theAnswer; +} + +bool CAHALAudioObject::HasProperty(const AudioObjectPropertyAddress& inAddress) const +{ + return AudioObjectHasProperty(mObjectID, &inAddress); +} + +bool CAHALAudioObject::IsPropertySettable(const AudioObjectPropertyAddress& inAddress) const +{ + Boolean isSettable = false; + OSStatus theError = AudioObjectIsPropertySettable(mObjectID, &inAddress, &isSettable); + ThrowIfError(theError, CAException(theError), "CAHALAudioObject::IsPropertySettable: got an error getting info about a property"); + return isSettable != 0; +} + +UInt32 CAHALAudioObject::GetPropertyDataSize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData) const +{ + UInt32 theDataSize = 0; + OSStatus theError = AudioObjectGetPropertyDataSize(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &theDataSize); + ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyDataSize: got an error getting the property data size"); + return theDataSize; +} + +void CAHALAudioObject::GetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32& ioDataSize, void* outData) const +{ + OSStatus theError = AudioObjectGetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &ioDataSize, outData); + ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyData: got an error getting the property data"); +} + +void CAHALAudioObject::SetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData) +{ + OSStatus theError = AudioObjectSetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData); + ThrowIfError(theError, CAException(theError), "CAHALAudioObject::SetPropertyData: got an error setting the property data"); +} + +void CAHALAudioObject::AddPropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData) +{ + OSStatus theError = AudioObjectAddPropertyListener(mObjectID, &inAddress, inListenerProc, inClientData); + ThrowIfError(theError, CAException(theError), "CAHALAudioObject::AddPropertyListener: got an error adding a property listener"); +} + +void CAHALAudioObject::RemovePropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData) +{ + OSStatus theError = AudioObjectRemovePropertyListener(mObjectID, &inAddress, inListenerProc, inClientData); + ThrowIfError(theError, CAException(theError), "CAHALAudioObject::RemovePropertyListener: got an error removing a property listener"); +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h new file mode 100644 index 0000000000..d99ab0d59a --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h @@ -0,0 +1,155 @@ +/* + File: CAHALAudioObject.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAHALAudioObject_h__) +#define __CAHALAudioObject_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// PublicUtility Includes +#include "CADebugMacros.h" +#include "CAException.h" + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudio.h> + #include <CoreFoundation/CoreFoundation.h> +#else + #include <CoreAudio.h> + #include <CoreFoundation.h> +#endif + +//================================================================================================== +// CAHALAudioObject +//================================================================================================== + +class CAHALAudioObject +{ + +// Construction/Destruction +public: + CAHALAudioObject(AudioObjectID inObjectID); + virtual ~CAHALAudioObject(); + +// Attributes +public: + AudioObjectID GetObjectID() const; + void SetObjectID(AudioObjectID inObjectID); + AudioClassID GetClassID() const; + AudioObjectID GetOwnerObjectID() const; + CFStringRef CopyOwningPlugInBundleID() const; + CFStringRef CopyName() const; + CFStringRef CopyManufacturer() const; + CFStringRef CopyNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const; + CFStringRef CopyCategoryNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const; + CFStringRef CopyNumberNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const; + + static bool ObjectExists(AudioObjectID inObjectID); + +// Owned Objects +public: + UInt32 GetNumberOwnedObjects(AudioClassID inClass) const; + void GetAllOwnedObjects(AudioClassID inClass, UInt32& ioNumberObjects, AudioObjectID* ioObjectIDs) const; + AudioObjectID GetOwnedObjectByIndex(AudioClassID inClass, UInt32 inIndex); + +// Property Operations +public: + bool HasProperty(const AudioObjectPropertyAddress& inAddress) const; + bool IsPropertySettable(const AudioObjectPropertyAddress& inAddress) const; + UInt32 GetPropertyDataSize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData) const; + + void GetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32& ioDataSize, void* outData) const; + void SetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData); + + UInt32 GetPropertyData_UInt32(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { UInt32 theAnswer = 0; UInt32 theDataSize = SizeOf32(UInt32); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; } + void SetPropertyData_UInt32(const AudioObjectPropertyAddress& inAddress, UInt32 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(UInt32), &inValue); } + + Float32 GetPropertyData_Float32(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { Float32 theAnswer = 0; UInt32 theDataSize = SizeOf32(Float32); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; } + void SetPropertyData_Float32(const AudioObjectPropertyAddress& inAddress, Float32 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(Float32), &inValue); } + + Float64 GetPropertyData_Float64(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { Float64 theAnswer = 0; UInt32 theDataSize = SizeOf32(Float64); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; } + void SetPropertyData_Float64(const AudioObjectPropertyAddress& inAddress, Float64 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(Float64), &inValue); } + + CFTypeRef GetPropertyData_CFType(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { CFTypeRef theAnswer = NULL; UInt32 theDataSize = SizeOf32(CFTypeRef); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; } + void SetPropertyData_CFType(const AudioObjectPropertyAddress& inAddress, CFTypeRef inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(CFTypeRef), &inValue); } + + CFStringRef GetPropertyData_CFString(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { CFStringRef theAnswer = NULL; UInt32 theDataSize = SizeOf32(CFStringRef); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; } + void SetPropertyData_CFString(const AudioObjectPropertyAddress& inAddress, CFStringRef inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(CFStringRef), &inValue); } + + template <class T> void GetPropertyData_Struct(const AudioObjectPropertyAddress& inAddress, T& outStruct, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { UInt32 theDataSize = SizeOf32(T); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &outStruct); } + template <class T> void SetPropertyData_Struct(const AudioObjectPropertyAddress& inAddress, T& inStruct, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(T), &inStruct); } + + template <class T> UInt32 GetPropertyData_ArraySize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { return GetPropertyDataSize(inAddress, inQualifierDataSize, inQualifierData) / SizeOf32(T); } + template <class T> void GetPropertyData_Array(const AudioObjectPropertyAddress& inAddress, UInt32& ioNumberItems, T* outArray, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { UInt32 theDataSize = ioNumberItems * SizeOf32(T); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, outArray); ioNumberItems = theDataSize / SizeOf32(T); } + template <class T> void SetPropertyData_Array(const AudioObjectPropertyAddress& inAddress, UInt32 inNumberItems, T* inArray, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, inNumberItems * SizeOf32(T), inArray); } + + void AddPropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData); + void RemovePropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData); + + void AddPropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock); + void RemovePropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock); + +// Implementation +protected: + AudioObjectID mObjectID; + +}; + +inline void CAHALAudioObject::AddPropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock) +{ + OSStatus theError = AudioObjectAddPropertyListenerBlock(mObjectID, &inAddress, inDispatchQueue, inListenerBlock); + ThrowIfError(theError, CAException(theError), "CAHALAudioObject::AddPropertyListenerBlock: got an error adding a property listener"); +} + +inline void CAHALAudioObject::RemovePropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock) +{ + OSStatus theError = AudioObjectRemovePropertyListenerBlock(mObjectID, &inAddress, inDispatchQueue, inListenerBlock); + ThrowIfError(theError, CAException(theError), "CAHALAudioObject::RemovePropertyListener: got an error removing a property listener"); +} + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp new file mode 100644 index 0000000000..62b9b3c566 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp @@ -0,0 +1,182 @@ +/* + File: CAHALAudioStream.cpp + Abstract: CAHALAudioStream.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CAHALAudioStream.h" + +// PublicUtility Includes +#include "CAAutoDisposer.h" +#include "CADebugMacros.h" +#include "CAException.h" +#include "CAPropertyAddress.h" + +//================================================================================================== +// CAHALAudioStream +//================================================================================================== + +CAHALAudioStream::CAHALAudioStream(AudioObjectID inAudioStream) +: + CAHALAudioObject(inAudioStream) +{ +} + +CAHALAudioStream::~CAHALAudioStream() +{ +} + +UInt32 CAHALAudioStream::GetDirection() const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyDirection); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +UInt32 CAHALAudioStream::GetTerminalType() const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyTerminalType); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +UInt32 CAHALAudioStream::GetStartingChannel() const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyStartingChannel); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +UInt32 CAHALAudioStream::GetLatency() const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyLatency); + return GetPropertyData_UInt32(theAddress, 0, NULL); +} + +void CAHALAudioStream::GetCurrentVirtualFormat(AudioStreamBasicDescription& outFormat) const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyVirtualFormat); + UInt32 theSize = sizeof(AudioStreamBasicDescription); + GetPropertyData(theAddress, 0, NULL, theSize, &outFormat); +} + +void CAHALAudioStream::SetCurrentVirtualFormat(const AudioStreamBasicDescription& inFormat) +{ + CAPropertyAddress theAddress(kAudioStreamPropertyVirtualFormat); + SetPropertyData(theAddress, 0, NULL, sizeof(AudioStreamBasicDescription), &inFormat); +} + +UInt32 CAHALAudioStream::GetNumberAvailableVirtualFormats() const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyAvailableVirtualFormats); + UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL); + theAnswer /= SizeOf32(AudioStreamRangedDescription); + return theAnswer; +} + +void CAHALAudioStream::GetAvailableVirtualFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyAvailableVirtualFormats); + UInt32 theSize = ioNumberFormats * SizeOf32(AudioStreamRangedDescription); + GetPropertyData(theAddress, 0, NULL, theSize, outFormats); + ioNumberFormats = theSize / SizeOf32(AudioStreamRangedDescription); +} + +void CAHALAudioStream::GetAvailableVirtualFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const +{ + UInt32 theNumberFormats = GetNumberAvailableVirtualFormats(); + if((theNumberFormats > 0) && (inIndex < theNumberFormats)) + { + CAAutoArrayDelete<AudioStreamRangedDescription> theFormats(theNumberFormats); + GetAvailableVirtualFormats(theNumberFormats, theFormats); + if((theNumberFormats > 0) && (inIndex < theNumberFormats)) + { + outFormat = theFormats[inIndex]; + } + } +} + +void CAHALAudioStream::GetCurrentPhysicalFormat(AudioStreamBasicDescription& outFormat) const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyPhysicalFormat); + UInt32 theSize = sizeof(AudioStreamBasicDescription); + GetPropertyData(theAddress, 0, NULL, theSize, &outFormat); +} + +void CAHALAudioStream::SetCurrentPhysicalFormat(const AudioStreamBasicDescription& inFormat) +{ + CAPropertyAddress theAddress(kAudioStreamPropertyPhysicalFormat); + SetPropertyData(theAddress, 0, NULL, sizeof(AudioStreamBasicDescription), &inFormat); +} + +UInt32 CAHALAudioStream::GetNumberAvailablePhysicalFormats() const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyAvailablePhysicalFormats); + UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL); + theAnswer /= SizeOf32(AudioStreamRangedDescription); + return theAnswer; +} + +void CAHALAudioStream::GetAvailablePhysicalFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const +{ + CAPropertyAddress theAddress(kAudioStreamPropertyAvailablePhysicalFormats); + UInt32 theSize = ioNumberFormats * SizeOf32(AudioStreamRangedDescription); + GetPropertyData(theAddress, 0, NULL, theSize, outFormats); + ioNumberFormats = theSize / SizeOf32(AudioStreamRangedDescription); +} + +void CAHALAudioStream::GetAvailablePhysicalFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const +{ + UInt32 theNumberFormats = GetNumberAvailablePhysicalFormats(); + if((theNumberFormats > 0) && (inIndex < theNumberFormats)) + { + CAAutoArrayDelete<AudioStreamRangedDescription> theFormats(theNumberFormats); + GetAvailablePhysicalFormats(theNumberFormats, theFormats); + if((theNumberFormats > 0) && (inIndex < theNumberFormats)) + { + outFormat = theFormats[inIndex]; + } + } +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h new file mode 100644 index 0000000000..0c6cb55a85 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h @@ -0,0 +1,94 @@ +/* + File: CAHALAudioStream.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAHALAudioStream_h__) +#define __CAHALAudioStream_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// Super Class Includes +#include "CAHALAudioObject.h" + +//================================================================================================== +// CAHALAudioStream +//================================================================================================== + +class CAHALAudioStream +: + public CAHALAudioObject +{ + +// Construction/Destruction +public: + CAHALAudioStream(AudioObjectID inAudioStream); + virtual ~CAHALAudioStream(); + +// Attributes +public: + UInt32 GetDirection() const; + UInt32 GetTerminalType() const; + UInt32 GetStartingChannel() const; + UInt32 GetLatency() const; + +// Format Info +public: + void GetCurrentVirtualFormat(AudioStreamBasicDescription& outFormat) const; + void SetCurrentVirtualFormat(const AudioStreamBasicDescription& inFormat); + UInt32 GetNumberAvailableVirtualFormats() const; + void GetAvailableVirtualFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const; + void GetAvailableVirtualFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const; + + void GetCurrentPhysicalFormat(AudioStreamBasicDescription& outFormat) const; + void SetCurrentPhysicalFormat(const AudioStreamBasicDescription& inFormat); + UInt32 GetNumberAvailablePhysicalFormats() const; + void GetAvailablePhysicalFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const; + void GetAvailablePhysicalFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const; + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp new file mode 100644 index 0000000000..404dd98498 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp @@ -0,0 +1,181 @@ +/* + File: CAHALAudioSystemObject.cpp + Abstract: CAHALAudioSystemObject.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CAHALAudioSystemObject.h" + +// PublicUtility Includes +#include "CAAutoDisposer.h" +#include "CACFString.h" +#include "CAHALAudioDevice.h" +#include "CAPropertyAddress.h" + +//================================================================================================== +// CAHALAudioSystemObject +//================================================================================================== + +CAHALAudioSystemObject::CAHALAudioSystemObject() +: + CAHALAudioObject(kAudioObjectSystemObject) +{ +} + +CAHALAudioSystemObject::~CAHALAudioSystemObject() +{ +} + +UInt32 CAHALAudioSystemObject::GetNumberAudioDevices() const +{ + CAPropertyAddress theAddress(kAudioHardwarePropertyDevices); + UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL); + theAnswer /= SizeOf32(AudioObjectID); + return theAnswer; +} + +void CAHALAudioSystemObject::GetAudioDevices(UInt32& ioNumberAudioDevices, AudioObjectID* outAudioDevices) const +{ + CAPropertyAddress theAddress(kAudioHardwarePropertyDevices); + UInt32 theSize = ioNumberAudioDevices * SizeOf32(AudioObjectID); + GetPropertyData(theAddress, 0, NULL, theSize, outAudioDevices); + ioNumberAudioDevices = theSize / SizeOf32(AudioObjectID); +} + +AudioObjectID CAHALAudioSystemObject::GetAudioDeviceAtIndex(UInt32 inIndex) const +{ + AudioObjectID theAnswer = kAudioObjectUnknown; + UInt32 theNumberDevices = GetNumberAudioDevices(); + if((theNumberDevices > 0) && (inIndex < theNumberDevices)) + { + CAAutoArrayDelete<AudioObjectID> theDeviceList(theNumberDevices); + GetAudioDevices(theNumberDevices, theDeviceList); + if((theNumberDevices > 0) && (inIndex < theNumberDevices)) + { + theAnswer = theDeviceList[inIndex]; + } + } + return theAnswer; +} + +AudioObjectID CAHALAudioSystemObject::GetAudioDeviceForUID(CFStringRef inUID) const +{ + AudioObjectID theAnswer = kAudioObjectUnknown; + AudioValueTranslation theValue = { &inUID, sizeof(CFStringRef), &theAnswer, sizeof(AudioObjectID) }; + CAPropertyAddress theAddress(kAudioHardwarePropertyDeviceForUID); + UInt32 theSize = sizeof(AudioValueTranslation); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theAnswer; +} + +void CAHALAudioSystemObject::LogBasicDeviceInfo() +{ + UInt32 theNumberDevices = GetNumberAudioDevices(); + CAAutoArrayDelete<AudioObjectID> theDeviceList(theNumberDevices); + GetAudioDevices(theNumberDevices, theDeviceList); + DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: %d devices", (int)theNumberDevices); + for(UInt32 theDeviceIndex = 0; theDeviceIndex < theNumberDevices; ++theDeviceIndex) + { + char theCString[256]; + UInt32 theCStringSize = sizeof(theCString); + DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: Device %d", (int)theDeviceIndex); + + CAHALAudioDevice theDevice(theDeviceList[theDeviceIndex]); + DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: Object ID: %d", (int)theDeviceList[theDeviceIndex]); + + CACFString theDeviceName(theDevice.CopyName()); + theCStringSize = sizeof(theCString); + theDeviceName.GetCString(theCString, theCStringSize); + DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: Name: %s", theCString); + + CACFString theDeviceUID(theDevice.CopyDeviceUID()); + theCStringSize = sizeof(theCString); + theDeviceUID.GetCString(theCString, theCStringSize); + DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: UID: %s", theCString); + } +} + +static inline AudioObjectPropertySelector CAHALAudioSystemObject_CalculateDefaultDeviceProperySelector(bool inIsInput, bool inIsSystem) +{ + AudioObjectPropertySelector theAnswer = kAudioHardwarePropertyDefaultOutputDevice; + if(inIsInput) + { + theAnswer = kAudioHardwarePropertyDefaultInputDevice; + } + else if(inIsSystem) + { + theAnswer = kAudioHardwarePropertyDefaultSystemOutputDevice; + } + return theAnswer; +} + +AudioObjectID CAHALAudioSystemObject::GetDefaultAudioDevice(bool inIsInput, bool inIsSystem) const +{ + AudioObjectID theAnswer = kAudioObjectUnknown; + CAPropertyAddress theAddress(CAHALAudioSystemObject_CalculateDefaultDeviceProperySelector(inIsInput, inIsSystem)); + UInt32 theSize = sizeof(AudioObjectID); + GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer); + return theAnswer; +} + +void CAHALAudioSystemObject::SetDefaultAudioDevice(bool inIsInput, bool inIsSystem, AudioObjectID inNewDefaultDevice) +{ + CAPropertyAddress theAddress(CAHALAudioSystemObject_CalculateDefaultDeviceProperySelector(inIsInput, inIsSystem)); + UInt32 theSize = sizeof(AudioObjectID); + SetPropertyData(theAddress, 0, NULL, theSize, &inNewDefaultDevice); +} + +AudioObjectID CAHALAudioSystemObject::GetAudioPlugInForBundleID(CFStringRef inUID) const +{ + AudioObjectID theAnswer = kAudioObjectUnknown; + AudioValueTranslation theValue = { &inUID, sizeof(CFStringRef), &theAnswer, sizeof(AudioObjectID) }; + CAPropertyAddress theAddress(kAudioHardwarePropertyPlugInForBundleID); + UInt32 theSize = sizeof(AudioValueTranslation); + GetPropertyData(theAddress, 0, NULL, theSize, &theValue); + return theAnswer; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h new file mode 100644 index 0000000000..0ade7a5098 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h @@ -0,0 +1,90 @@ +/* + File: CAHALAudioSystemObject.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAHALAudioSystemObject_h__) +#define __CAHALAudioSystemObject_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// Super Class Includes +#include "CAHALAudioObject.h" + +//================================================================================================== +// CAHALAudioSystemObject +//================================================================================================== + +class CAHALAudioSystemObject +: + public CAHALAudioObject +{ + +// Construction/Destruction +public: + CAHALAudioSystemObject(); + virtual ~CAHALAudioSystemObject(); + +// Audio Device List Management +public: + UInt32 GetNumberAudioDevices() const; + void GetAudioDevices(UInt32& ioNumberAudioDevices, AudioObjectID* outAudioDevices) const; + AudioObjectID GetAudioDeviceAtIndex(UInt32 inIndex) const; + AudioObjectID GetAudioDeviceForUID(CFStringRef inUID) const; + void LogBasicDeviceInfo(); + +// Default Device Management +public: + AudioObjectID GetDefaultAudioDevice(bool inIsInput, bool inIsSystem) const; + void SetDefaultAudioDevice(bool inIsInput, bool inIsSystem, AudioObjectID inNewDefaultDevice); + +// PlugIns +public: + AudioObjectID GetAudioPlugInForBundleID(CFStringRef inBundleID) const; + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp new file mode 100644 index 0000000000..db78a4afee --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp @@ -0,0 +1,99 @@ +/* + File: CAHostTimeBase.cpp + Abstract: CAHostTimeBase.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CAHostTimeBase.h" + +Float64 CAHostTimeBase::sFrequency = 0; +Float64 CAHostTimeBase::sInverseFrequency = 0; +UInt32 CAHostTimeBase::sMinDelta = 0; +UInt32 CAHostTimeBase::sToNanosNumerator = 0; +UInt32 CAHostTimeBase::sToNanosDenominator = 0; +pthread_once_t CAHostTimeBase::sIsInited = PTHREAD_ONCE_INIT; +#if Track_Host_TimeBase +UInt64 CAHostTimeBase::sLastTime = 0; +#endif + +//============================================================================= +// CAHostTimeBase +// +// This class provides platform independent access to the host's time base. +//============================================================================= + +void CAHostTimeBase::Initialize() +{ + // get the info about Absolute time + #if TARGET_OS_MAC + struct mach_timebase_info theTimeBaseInfo; + mach_timebase_info(&theTimeBaseInfo); + sMinDelta = 1; + sToNanosNumerator = theTimeBaseInfo.numer; + sToNanosDenominator = theTimeBaseInfo.denom; + + // the frequency of that clock is: (sToNanosDenominator / sToNanosNumerator) * 10^9 + sFrequency = static_cast<Float64>(sToNanosDenominator) / static_cast<Float64>(sToNanosNumerator); + sFrequency *= 1000000000.0; + #elif TARGET_OS_WIN32 + LARGE_INTEGER theFrequency; + QueryPerformanceFrequency(&theFrequency); + sMinDelta = 1; + sToNanosNumerator = 1000000000ULL; + sToNanosDenominator = *((UInt64*)&theFrequency); + sFrequency = static_cast<Float64>(*((UInt64*)&theFrequency)); + #endif + sInverseFrequency = 1.0 / sFrequency; + + #if Log_Host_Time_Base_Parameters + DebugPrintf("Host Time Base Parameters"); + DebugPrintf(" Minimum Delta: %lu", (unsigned long)sMinDelta); + DebugPrintf(" Frequency: %f", sFrequency); + DebugPrintf(" To Nanos Numerator: %lu", (unsigned long)sToNanosNumerator); + DebugPrintf(" To Nanos Denominator: %lu", (unsigned long)sToNanosDenominator); + #endif +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h new file mode 100644 index 0000000000..50e3507648 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h @@ -0,0 +1,234 @@ +/* + File: CAHostTimeBase.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAHostTimeBase_h__) +#define __CAHostTimeBase_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif + +#if TARGET_OS_MAC + #include <mach/mach_time.h> + #include <pthread.h> +#elif TARGET_OS_WIN32 + #include <windows.h> + #include "WinPThreadDefs.h" +#else + #error Unsupported operating system +#endif + +#include "CADebugPrintf.h" + +//============================================================================= +// CAHostTimeBase +// +// This class provides platform independent access to the host's time base. +//============================================================================= + +#if CoreAudio_Debug +// #define Log_Host_Time_Base_Parameters 1 +// #define Track_Host_TimeBase 1 +#endif + +class CAHostTimeBase +{ + +public: + static UInt64 ConvertToNanos(UInt64 inHostTime); + static UInt64 ConvertFromNanos(UInt64 inNanos); + + static UInt64 GetTheCurrentTime(); +#if TARGET_OS_MAC + static UInt64 GetCurrentTime() { return GetTheCurrentTime(); } +#endif + static UInt64 GetCurrentTimeInNanos(); + + static Float64 GetFrequency() { pthread_once(&sIsInited, Initialize); return sFrequency; } + static Float64 GetInverseFrequency() { pthread_once(&sIsInited, Initialize); return sInverseFrequency; } + static UInt32 GetMinimumDelta() { pthread_once(&sIsInited, Initialize); return sMinDelta; } + + static UInt64 AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime); + static SInt64 HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime); + + static UInt64 MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator); + +private: + static void Initialize(); + + static pthread_once_t sIsInited; + + static Float64 sFrequency; + static Float64 sInverseFrequency; + static UInt32 sMinDelta; + static UInt32 sToNanosNumerator; + static UInt32 sToNanosDenominator; +#if Track_Host_TimeBase + static UInt64 sLastTime; +#endif +}; + +inline UInt64 CAHostTimeBase::GetTheCurrentTime() +{ + UInt64 theTime = 0; + + #if TARGET_OS_MAC + theTime = mach_absolute_time(); + #elif TARGET_OS_WIN32 + LARGE_INTEGER theValue; + QueryPerformanceCounter(&theValue); + theTime = *((UInt64*)&theValue); + #endif + + #if Track_Host_TimeBase + if(sLastTime != 0) + { + if(theTime <= sLastTime) + { + DebugPrintf("CAHostTimeBase::GetTheCurrentTime: the current time is earlier than the last time, now: %qd, then: %qd", theTime, sLastTime); + } + sLastTime = theTime; + } + else + { + sLastTime = theTime; + } + #endif + + return theTime; +} + +inline UInt64 CAHostTimeBase::ConvertToNanos(UInt64 inHostTime) +{ + pthread_once(&sIsInited, Initialize); + + UInt64 theAnswer = MultiplyByRatio(inHostTime, sToNanosNumerator, sToNanosDenominator); + #if CoreAudio_Debug + if(((sToNanosNumerator > sToNanosDenominator) && (theAnswer < inHostTime)) || ((sToNanosDenominator > sToNanosNumerator) && (theAnswer > inHostTime))) + { + DebugPrintf("CAHostTimeBase::ConvertToNanos: The conversion wrapped"); + } + #endif + + return theAnswer; +} + +inline UInt64 CAHostTimeBase::ConvertFromNanos(UInt64 inNanos) +{ + pthread_once(&sIsInited, Initialize); + + UInt64 theAnswer = MultiplyByRatio(inNanos, sToNanosDenominator, sToNanosNumerator); + #if CoreAudio_Debug + if(((sToNanosDenominator > sToNanosNumerator) && (theAnswer < inNanos)) || ((sToNanosNumerator > sToNanosDenominator) && (theAnswer > inNanos))) + { + DebugPrintf("CAHostTimeBase::ConvertFromNanos: The conversion wrapped"); + } + #endif + + return theAnswer; +} + +inline UInt64 CAHostTimeBase::GetCurrentTimeInNanos() +{ + return ConvertToNanos(GetTheCurrentTime()); +} + +inline UInt64 CAHostTimeBase::AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime) +{ + UInt64 theAnswer; + + if(inStartTime <= inEndTime) + { + theAnswer = inEndTime - inStartTime; + } + else + { + theAnswer = inStartTime - inEndTime; + } + + return ConvertToNanos(theAnswer); +} + +inline SInt64 CAHostTimeBase::HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime) +{ + SInt64 theAnswer; + SInt64 theSign = 1; + + if(inStartTime <= inEndTime) + { + theAnswer = static_cast<SInt64>(inEndTime - inStartTime); + } + else + { + theAnswer = static_cast<SInt64>(inStartTime - inEndTime); + theSign = -1; + } + + return theSign * static_cast<SInt64>(ConvertToNanos(static_cast<UInt64>(theAnswer))); +} + +inline UInt64 CAHostTimeBase::MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator) +{ +#if TARGET_OS_MAC && TARGET_RT_64_BIT + __uint128_t theAnswer = inMuliplicand; +#else + long double theAnswer = inMuliplicand; +#endif + if(inNumerator != inDenominator) + { + theAnswer *= inNumerator; + theAnswer /= inDenominator; + } + return static_cast<UInt64>(theAnswer); +} + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h b/libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h new file mode 100644 index 0000000000..7fd4ac4c21 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h @@ -0,0 +1,140 @@ +/* + File: CALogMacros.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CALogMacros_h__) +#define __CALogMacros_h__ + +//============================================================================= +// Log Macros +//============================================================================= + +#if CoreAudio_Debug + + #include "CADebugMacros.h" + #include "CADebugPrintf.h" + #include <stdio.h> + #include <string.h> + + #define PrintLine(msg) DebugPrintfRtn(DebugPrintfFileComma "%s\n", (msg)) + + #define PrintBool(msg, b) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "true" : "false") + #define PrintIndexedBool(msg, i, b) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (b) ? "true" : "false") + + #define PrintToggle(msg, b) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "on" : "off") + #define PrintIndexedToggle(msg, i, b) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (b) ? "on" : "off") + + #define PrintInt(msg, n) DebugPrintfRtn(DebugPrintfFileComma "%s%ld\n", (msg), (long)(n)) + #define PrintIndexedInt(msg, i, n) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %ld\n", (msg), (long)(i), (long)(n)) + + #define PrintHex(msg, n) DebugPrintfRtn(DebugPrintfFileComma "%s0x%lX\n", (msg), (unsigned long)(n)) + #define PrintIndexedHex(msg, i, n) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: 0x%lX\n", (msg), (long)(i), (unsigned long)(n)) + + #define PrintFloat(msg, f) DebugPrintfRtn(DebugPrintfFileComma "%s%.6f\n", (msg), (f)) + #define PrintIndexedFloat(msg, i, f) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %.6f\n", (msg), (long)(i), (f)) + #define PrintFloatIndexedFloat(msg, i, f) DebugPrintfRtn(DebugPrintfFileComma " %s %.6f: %.6f\n", (msg), (i), (f)) + + #define PrintString(msg, s) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (s)) + #define PrintIndexedString(msg, i, s) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (s)) + + #define PrintPointer(msg, p) DebugPrintfRtn(DebugPrintfFileComma "%s%p\n", (msg), (p)) + #define PrintIndexedPointer(msg, i, p) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %p\n", (msg), (long)(i), (p)) + + #define Print4CharCode(msg, c) { \ + UInt32 __4CC_number = (c); \ + char __4CC_string[5] = CA4CCToCString(__4CC_number); \ + DebugPrintfRtn(DebugPrintfFileComma "%s'%s'\n", (msg), __4CC_string); \ + } + #define PrintIndexed4CharCode(msg, i, c) { \ + UInt32 __4CC_number = (c); \ + char __4CC_string[5] = CA4CCToCString(__4CC_number); \ + DebugPrintfRtn(DebugPrintfFileComma " %s %ld: '%s'\n", (msg), (long)(i), __4CC_string); \ + } + + #define ErrorLine(s) DebugPrintfRtn(DebugPrintfFileComma "%s\n", (s)) + #define OSErrorLine(s, e) { \ + OSStatus __err_number = (e); \ + char __err_string[5] = CA4CCToCString(__err_number); \ + DebugPrintfRtn(DebugPrintfFileComma "%s, OSStatus code: %s\n", (s), __err_string); \ + } + + #define MessageIfOSError(e, s) if((e) != 0) { OSErrorLine(s, e); } + #define MessageIfNULL(p, s) if((p) == 0) { ErrorLine(s); } + +#else + + #define PrintLine(msg) + + #define PrintBool(msg, b) (b) + #define PrintIndexedBool(msg, i, b) (b) + + #define PrintInt(msg, n) (n) + #define PrintIndexedInt(msg, i, n) (n) + + #define PrintHex(msg, n) (n) + #define PrintIndexedHex(msg, i, n) (n) + + #define PrintFloat(msg, f) (f) + #define PrintIndexedFloat(msg, i, f) (f) + #define PrintFloatIndexedFloat(msg, i, f) (f) + + #define PrintString(msg, s) (s) + #define PrintIndexedString(msg, i, s) (s) + + #define PrintPointer(msg, p) (p) + #define PrintIndexedPointer(msg, i, p) (p) + + #define Print4CharCode(msg, c) (c) + #define PrintIndexed4CharCode(msg, i, c) (c) + + #define ErrorLine(s) (s) + #define OSErrorLine(s, e) (e) + + #define MessageIfOSError(e, s) (e) + #define MessageIfNULL(p, s) (p) + +#endif // CoreAudio_Debug + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMath.h b/libs/appleutility/CoreAudio/PublicUtility/CAMath.h new file mode 100644 index 0000000000..eb81f26e95 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAMath.h @@ -0,0 +1,68 @@ +/* + File: CAMath.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAMath_h__ +#define __CAMath_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif + +inline bool fiszero(Float64 f) { return (f == 0.); } +inline bool fiszero(Float32 f) { return (f == 0.f); } + +inline bool fnonzero(Float64 f) { return !fiszero(f); } +inline bool fnonzero(Float32 f) { return !fiszero(f); } + +inline bool fequal(const Float64 &a, const Float64 &b) { return a == b; } +inline bool fequal(const Float32 &a, const Float32 &b) { return a == b; } + +inline bool fnotequal(const Float64 &a, const Float64 &b) { return !fequal(a, b); } +inline bool fnotequal(const Float32 &a, const Float32 &b) { return !fequal(a, b); } + +#endif // __CAMath_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h b/libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h new file mode 100644 index 0000000000..62e95d4aa5 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h @@ -0,0 +1,157 @@ +/* + File: CAMixMap.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAMixMap_h__ +#define __CAMixMap_h__ + + // manages the setting of mix map volumes + +class CAMixMap { +public: + CAMixMap () + : mIns(0), mOuts (0), mMixMap(NULL) + {} + + CAMixMap (const CAMixMap &mm) + : mIns(0), mOuts (0), mMixMap(NULL) + { *this = mm; } + + CAMixMap (UInt32 numIns, UInt32 numOuts) + : mIns(numIns), mOuts (numOuts), mMixMap(NULL) + { + mMixMap = new Float32[numIns * numOuts]; + memset (mMixMap, 0, ByteSize()); + } + + ~CAMixMap () { delete [] mMixMap; } + + CAMixMap& operator=(const CAMixMap& mm) + { + if (mMixMap) { delete [] mMixMap; mMixMap = NULL; } + mIns = mm.mIns; mOuts = mm.mOuts; + if (NumIns() && NumOuts()) { + mMixMap = new Float32 [ NumIns() * NumOuts() ]; + memcpy (mMixMap, mm.mMixMap, ByteSize()); + } + return *this; + } + + UInt32 NumIns () const { return mIns; } + UInt32 NumOuts () const { return mOuts; } + + void SetCrossPoint (UInt32 inputChan, UInt32 outputChan, Float32 val) + { + if (inputChan < NumIns() && outputChan < NumOuts()) + mMixMap[inputChan * NumOuts() + outputChan] = val; + } + Float32 GetCrossPoint (UInt32 inputChan, UInt32 outputChan) const + { + return (inputChan < NumIns() && outputChan < NumOuts()) + ? mMixMap[inputChan * NumOuts() + outputChan] + : 0; + } + + void SetDiagonal (Float32 val) + { + for (UInt32 i = 0; i < NumIns() && i < NumOuts(); ++i) { + mMixMap[i * NumOuts() + i] = val; + } + } + + void Clear () { memset (mMixMap, 0, ByteSize()); } + + + Float32* MM() { return mMixMap; } + const Float32* MM() const { return mMixMap; } + UInt32 ByteSize () const { return NumIns() * NumOuts() * sizeof(Float32); } + + UInt32 CountActiveInputs(UInt32 inOutputChannel) + { + UInt32 sum = 0; + for (UInt32 i = 0, k = inOutputChannel; i < mIns; ++i, k+=mOuts) { + if (mMixMap[k] != 0.f) sum++; + } + return sum; + } + + void Normalize() + { + // ensure that no output channel will sum over unity. + Float32* mixmap = mMixMap; + Float32 maxsum = 0.f; + for (UInt32 j = 0; j < mOuts; ++j) { + Float32 sum = 0.f; + for (UInt32 i = 0, k = j; i < mIns; ++i, k+=mOuts) { + sum += mixmap[k]; + } + if (sum > maxsum) maxsum = sum; + } + + if (maxsum == 0.f) return; + Float32 scale = 1.f / maxsum; + for (UInt32 i = 0; i < mIns * mOuts; ++i) { + mixmap[i] *= scale; + } + } + + void Print () + { + printf ("Num Ins: %d, Num Outs: %d\n", (int)mIns, (int)mOuts); + for (unsigned int ins = 0; ins < mIns; ++ins) { + printf ("\t%d: ", ins); + for (unsigned int outs = 0; outs < mOuts; ++outs) + printf ("(%.3f) ", mMixMap[ins * NumOuts() + outs]); + printf("\n"); + } + } + +private: + UInt32 mIns; + UInt32 mOuts; + Float32 *mMixMap; +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp new file mode 100644 index 0000000000..88cf9b0b02 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp @@ -0,0 +1,345 @@ +/* + File: CAMutex.cpp + Abstract: CAMutex.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CAMutex.h" + +#if TARGET_OS_MAC + #include <errno.h> +#endif + +// PublicUtility Includes +#include "CADebugMacros.h" +#include "CAException.h" +#include "CAHostTimeBase.h" + +//================================================================================================== +// Logging +//================================================================================================== + +#if CoreAudio_Debug +// #define Log_Ownership 1 +// #define Log_Errors 1 +// #define Log_LongLatencies 1 +// #define LongLatencyThreshholdNS 1000000ULL // nanoseconds +#endif + +//================================================================================================== +// CAMutex +//================================================================================================== + +CAMutex::CAMutex(const char* inName) +: + mName(inName), + mOwner(0) +{ +#if TARGET_OS_MAC + OSStatus theError = pthread_mutex_init(&mMutex, NULL); + ThrowIf(theError != 0, CAException(theError), "CAMutex::CAMutex: Could not init the mutex"); + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::CAMutex: creating %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner); + #endif +#elif TARGET_OS_WIN32 + mMutex = CreateMutex(NULL, false, NULL); + ThrowIfNULL(mMutex, CAException(GetLastError()), "CAMutex::CAMutex: could not create the mutex."); + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::CAMutex: creating %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner); + #endif +#endif +} + +CAMutex::~CAMutex() +{ +#if TARGET_OS_MAC + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::~CAMutex: destroying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner); + #endif + pthread_mutex_destroy(&mMutex); +#elif TARGET_OS_WIN32 + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::~CAMutex: destroying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner); + #endif + if(mMutex != NULL) + { + CloseHandle(mMutex); + } +#endif +} + +bool CAMutex::Lock() +{ + bool theAnswer = false; + +#if TARGET_OS_MAC + pthread_t theCurrentThread = pthread_self(); + if(!pthread_equal(theCurrentThread, mOwner)) + { + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p is locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner); + #endif + + #if Log_LongLatencies + UInt64 lockTryTime = CAHostTimeBase::GetCurrentTimeInNanos(); + #endif + + OSStatus theError = pthread_mutex_lock(&mMutex); + ThrowIf(theError != 0, CAException(theError), "CAMutex::Lock: Could not lock the mutex"); + mOwner = theCurrentThread; + theAnswer = true; + + #if Log_LongLatencies + UInt64 lockAcquireTime = CAHostTimeBase::GetCurrentTimeInNanos(); + if (lockAcquireTime - lockTryTime >= LongLatencyThresholdNS) + DebugPrintfRtn(DebugPrintfFileComma "Thread %p took %.6fs to acquire the lock %s\n", theCurrentThread, (lockAcquireTime - lockTryTime) * 1.0e-9 /* nanos to seconds */, mName); + #endif + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p has locked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner); + #endif + } +#elif TARGET_OS_WIN32 + if(mOwner != GetCurrentThreadId()) + { + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu is locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + + OSStatus theError = WaitForSingleObject(mMutex, INFINITE); + ThrowIfError(theError, CAException(theError), "CAMutex::Lock: could not lock the mutex"); + mOwner = GetCurrentThreadId(); + theAnswer = true; + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + } +#endif + + return theAnswer; +} + +void CAMutex::Unlock() +{ +#if TARGET_OS_MAC + if(pthread_equal(pthread_self(), mOwner)) + { + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p is unlocking %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner); + #endif + + mOwner = 0; + OSStatus theError = pthread_mutex_unlock(&mMutex); + ThrowIf(theError != 0, CAException(theError), "CAMutex::Unlock: Could not unlock the mutex"); + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p has unlocked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner); + #endif + } + else + { + DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own"); + } +#elif TARGET_OS_WIN32 + if(mOwner == GetCurrentThreadId()) + { + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu is unlocking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + + mOwner = 0; + bool wasReleased = ReleaseMutex(mMutex); + ThrowIf(!wasReleased, CAException(GetLastError()), "CAMutex::Unlock: Could not unlock the mutex"); + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu has unlocked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + } + else + { + DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own"); + } +#endif +} + +bool CAMutex::Try(bool& outWasLocked) +{ + bool theAnswer = false; + outWasLocked = false; + +#if TARGET_OS_MAC + pthread_t theCurrentThread = pthread_self(); + if(!pthread_equal(theCurrentThread, mOwner)) + { + // this means the current thread doesn't already own the lock + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p is try-locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner); + #endif + + // go ahead and call trylock to see if we can lock it. + int theError = pthread_mutex_trylock(&mMutex); + if(theError == 0) + { + // return value of 0 means we successfully locked the lock + mOwner = theCurrentThread; + theAnswer = true; + outWasLocked = true; + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p has locked %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner); + #endif + } + else if(theError == EBUSY) + { + // return value of EBUSY means that the lock was already locked by another thread + theAnswer = false; + outWasLocked = false; + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p failed to lock %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner); + #endif + } + else + { + // any other return value means something really bad happenned + ThrowIfError(theError, CAException(theError), "CAMutex::Try: call to pthread_mutex_trylock failed"); + } + } + else + { + // this means the current thread already owns the lock + theAnswer = true; + outWasLocked = false; + } +#elif TARGET_OS_WIN32 + if(mOwner != GetCurrentThreadId()) + { + // this means the current thread doesn't own the lock + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu is try-locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + + // try to acquire the mutex + OSStatus theError = WaitForSingleObject(mMutex, 0); + if(theError == WAIT_OBJECT_0) + { + // this means we successfully locked the lock + mOwner = GetCurrentThreadId(); + theAnswer = true; + outWasLocked = true; + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + } + else if(theError == WAIT_TIMEOUT) + { + // this means that the lock was already locked by another thread + theAnswer = false; + outWasLocked = false; + + #if Log_Ownership + DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu failed to lock %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner); + #endif + } + else + { + // any other return value means something really bad happenned + ThrowIfError(theError, CAException(GetLastError()), "CAMutex::Try: call to lock the mutex failed"); + } + } + else + { + // this means the current thread already owns the lock + theAnswer = true; + outWasLocked = false; + } +#endif + + return theAnswer; +} + +bool CAMutex::IsFree() const +{ + return mOwner == 0; +} + +bool CAMutex::IsOwnedByCurrentThread() const +{ + bool theAnswer = true; + +#if TARGET_OS_MAC + theAnswer = pthread_equal(pthread_self(), mOwner); +#elif TARGET_OS_WIN32 + theAnswer = (mOwner == GetCurrentThreadId()); +#endif + + return theAnswer; +} + + +CAMutex::Unlocker::Unlocker(CAMutex& inMutex) +: mMutex(inMutex), + mNeedsLock(false) +{ + Assert(mMutex.IsOwnedByCurrentThread(), "Major problem: Unlocker attempted to unlock a mutex not owned by the current thread!"); + + mMutex.Unlock(); + mNeedsLock = true; +} + +CAMutex::Unlocker::~Unlocker() +{ + if(mNeedsLock) + { + mMutex.Lock(); + } +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMutex.h b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.h new file mode 100644 index 0000000000..093066b400 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.h @@ -0,0 +1,163 @@ +/* + File: CAMutex.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAMutex_h__ +#define __CAMutex_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif + +#if TARGET_OS_MAC + #include <pthread.h> +#elif TARGET_OS_WIN32 + #include <windows.h> +#else + #error Unsupported operating system +#endif + +//================================================================================================== +// A recursive mutex. +//================================================================================================== + +class CAMutex +{ +// Construction/Destruction +public: + CAMutex(const char* inName); + virtual ~CAMutex(); + +// Actions +public: + virtual bool Lock(); + virtual void Unlock(); + virtual bool Try(bool& outWasLocked); // returns true if lock is free, false if not + + virtual bool IsFree() const; + virtual bool IsOwnedByCurrentThread() const; + +// Implementation +protected: + const char* mName; +#if TARGET_OS_MAC + pthread_t mOwner; + pthread_mutex_t mMutex; +#elif TARGET_OS_WIN32 + UInt32 mOwner; + HANDLE mMutex; +#endif + +// Helper class to manage taking and releasing recursively +public: + class Locker + { + + // Construction/Destruction + public: + Locker(CAMutex& inMutex) : mMutex(&inMutex), mNeedsRelease(false) { mNeedsRelease = mMutex->Lock(); } + Locker(CAMutex* inMutex) : mMutex(inMutex), mNeedsRelease(false) { mNeedsRelease = (mMutex != NULL && mMutex->Lock()); } + // in this case the mutex can be null + ~Locker() { if(mNeedsRelease) { mMutex->Unlock(); } } + + + private: + Locker(const Locker&); + Locker& operator=(const Locker&); + + // Implementation + private: + CAMutex* mMutex; + bool mNeedsRelease; + + }; + +// Unlocker + class Unlocker + { + public: + Unlocker(CAMutex& inMutex); + ~Unlocker(); + + private: + CAMutex& mMutex; + bool mNeedsLock; + + // Hidden definitions of copy ctor, assignment operator + Unlocker(const Unlocker& copy); // Not implemented + Unlocker& operator=(const Unlocker& copy); // Not implemented + }; + +// you can use this with Try - if you take the lock in try, pass in the outWasLocked var + class Tryer { + + // Construction/Destruction + public: + Tryer (CAMutex &mutex) : mMutex(mutex), mNeedsRelease(false), mHasLock(false) { mHasLock = mMutex.Try (mNeedsRelease); } + ~Tryer () { if (mNeedsRelease) mMutex.Unlock(); } + + bool HasLock () const { return mHasLock; } + + private: + Tryer(const Tryer&); + Tryer& operator=(const Tryer&); + + // Implementation + private: + CAMutex & mMutex; + bool mNeedsRelease; + bool mHasLock; + }; +}; + + +#endif // __CAMutex_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp new file mode 100644 index 0000000000..3da1058de7 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp @@ -0,0 +1,450 @@ +/* + File: CAPThread.cpp + Abstract: CAPThread.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +// Self Include +#include "CAPThread.h" + +// PublicUtility Includes +#include "CADebugMacros.h" +#include "CAException.h" + +// System Includes +#if TARGET_OS_MAC + #include <mach/mach.h> +#endif + +// Standard Library Includes +#include <stdio.h> + +//================================================================================================== +// CAPThread +//================================================================================================== + +// returns the thread's priority as it was last set by the API +#define CAPTHREAD_SET_PRIORITY 0 +// returns the thread's priority as it was last scheduled by the Kernel +#define CAPTHREAD_SCHEDULED_PRIORITY 1 + +//#define Log_SetPriority 1 + +CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority, bool inFixedPriority, bool inAutoDelete, const char* inThreadName) +: +#if TARGET_OS_MAC + mPThread(0), + mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)), +#elif TARGET_OS_WIN32 + mThreadHandle(NULL), + mThreadID(0), +#endif + mThreadRoutine(inThreadRoutine), + mThreadParameter(inParameter), + mPriority(inPriority), + mPeriod(0), + mComputation(0), + mConstraint(0), + mIsPreemptible(true), + mTimeConstraintSet(false), + mFixedPriority(inFixedPriority), + mAutoDelete(inAutoDelete) +{ + if(inThreadName != NULL) + { + strlcpy(mThreadName, inThreadName, kMaxThreadNameLength); + } + else + { + memset(mThreadName, 0, kMaxThreadNameLength); + } +} + +CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible, bool inAutoDelete, const char* inThreadName) +: +#if TARGET_OS_MAC + mPThread(0), + mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)), +#elif TARGET_OS_WIN32 + mThreadHandle(NULL), + mThreadID(0), +#endif + mThreadRoutine(inThreadRoutine), + mThreadParameter(inParameter), + mPriority(kDefaultThreadPriority), + mPeriod(inPeriod), + mComputation(inComputation), + mConstraint(inConstraint), + mIsPreemptible(inIsPreemptible), + mTimeConstraintSet(true), + mFixedPriority(false), + mAutoDelete(inAutoDelete) +{ + if(inThreadName != NULL) + { + strlcpy(mThreadName, inThreadName, kMaxThreadNameLength); + } + else + { + memset(mThreadName, 0, kMaxThreadNameLength); + } +} + +CAPThread::~CAPThread() +{ +} + +UInt32 CAPThread::GetScheduledPriority() +{ +#if TARGET_OS_MAC + return CAPThread::getScheduledPriority( mPThread, CAPTHREAD_SCHEDULED_PRIORITY ); +#elif TARGET_OS_WIN32 + UInt32 theAnswer = 0; + if(mThreadHandle != NULL) + { + theAnswer = GetThreadPriority(mThreadHandle); + } + return theAnswer; +#endif +} + +UInt32 CAPThread::GetScheduledPriority(NativeThread thread) +{ +#if TARGET_OS_MAC + return getScheduledPriority( thread, CAPTHREAD_SCHEDULED_PRIORITY ); +#elif TARGET_OS_WIN32 + return 0; // ??? +#endif +} + +void CAPThread::SetPriority(UInt32 inPriority, bool inFixedPriority) +{ + mPriority = inPriority; + mTimeConstraintSet = false; + mFixedPriority = inFixedPriority; +#if TARGET_OS_MAC + if(mPThread != 0) + { + SetPriority(mPThread, mPriority, mFixedPriority); + } +#elif TARGET_OS_WIN32 + if(mThreadID != NULL) + { + SetPriority(mThreadID, mPriority, mFixedPriority); + } +#endif +} + +void CAPThread::SetPriority(NativeThread inThread, UInt32 inPriority, bool inFixedPriority) +{ +#if TARGET_OS_MAC + if(inThread != 0) + { + kern_return_t theError = 0; + + // set whether or not this is a fixed priority thread + if (inFixedPriority) + { + thread_extended_policy_data_t theFixedPolicy = { false }; + theError = thread_policy_set(pthread_mach_thread_np(inThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); + AssertNoKernelError(theError, "CAPThread::SetPriority: failed to set the fixed-priority policy"); + } + + // set the thread's absolute priority which is relative to the priority on which thread_policy_set() is called + UInt32 theCurrentThreadPriority = getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY); + thread_precedence_policy_data_t thePrecedencePolicy = { static_cast<integer_t>(inPriority - theCurrentThreadPriority) }; + theError = thread_policy_set(pthread_mach_thread_np(inThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); + AssertNoKernelError(theError, "CAPThread::SetPriority: failed to set the precedence policy"); + + #if Log_SetPriority + DebugMessageN4("CAPThread::SetPriority: requsted: %lu spawning: %lu current: %lu assigned: %d", mPriority, mSpawningThreadPriority, theCurrentThreadPriority, thePrecedencePolicy.importance); + #endif + } +#elif TARGET_OS_WIN32 + if(inThread != NULL) + { + HANDLE hThread = OpenThread(NULL, FALSE, inThread); + if(hThread != NULL) { + SetThreadPriority(hThread, inPriority); + CloseHandle(hThread); + } + } +#endif +} + +void CAPThread::SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible) +{ + mPeriod = inPeriod; + mComputation = inComputation; + mConstraint = inConstraint; + mIsPreemptible = inIsPreemptible; + mTimeConstraintSet = true; +#if TARGET_OS_MAC + if(mPThread != 0) + { + thread_time_constraint_policy_data_t thePolicy; + thePolicy.period = mPeriod; + thePolicy.computation = mComputation; + thePolicy.constraint = mConstraint; + thePolicy.preemptible = mIsPreemptible; + AssertNoError(thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&thePolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT), "CAPThread::SetTimeConstraints: thread_policy_set failed"); + } +#elif TARGET_OS_WIN32 + if(mThreadHandle != NULL) + { + SetThreadPriority(mThreadHandle, THREAD_PRIORITY_TIME_CRITICAL); + } +#endif +} + +void CAPThread::Start() +{ +#if TARGET_OS_MAC + Assert(mPThread == 0, "CAPThread::Start: can't start because the thread is already running"); + if(mPThread == 0) + { + OSStatus theResult; + pthread_attr_t theThreadAttributes; + + theResult = pthread_attr_init(&theThreadAttributes); + ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: Thread attributes could not be created."); + + theResult = pthread_attr_setdetachstate(&theThreadAttributes, PTHREAD_CREATE_DETACHED); + ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: A thread could not be created in the detached state."); + + theResult = pthread_create(&mPThread, &theThreadAttributes, (ThreadRoutine)CAPThread::Entry, this); + ThrowIf(theResult != 0 || !mPThread, CAException(theResult), "CAPThread::Start: Could not create a thread."); + + pthread_attr_destroy(&theThreadAttributes); + + } +#elif TARGET_OS_WIN32 + Assert(mThreadID == 0, "CAPThread::Start: can't start because the thread is already running"); + if(mThreadID == 0) + { + // clean up the existing thread handle + if(mThreadHandle != NULL) + { + CloseHandle(mThreadHandle); + mThreadHandle = NULL; + } + + // create a new thread + mThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Entry, this, 0, &mThreadID); + ThrowIf(mThreadHandle == NULL, CAException(GetLastError()), "CAPThread::Start: Could not create a thread."); + } +#endif +} + +#if TARGET_OS_MAC + +void* CAPThread::Entry(CAPThread* inCAPThread) +{ + void* theAnswer = NULL; + +#if TARGET_OS_MAC + inCAPThread->mPThread = pthread_self(); +#elif TARGET_OS_WIN32 + // do we need to do something here? +#endif + +#if !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) + if(inCAPThread->mThreadName[0] != 0) + { + pthread_setname_np(inCAPThread->mThreadName); + } +#endif + + try + { + if(inCAPThread->mTimeConstraintSet) + { + inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible); + } + else + { + inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority); + } + + if(inCAPThread->mThreadRoutine != NULL) + { + theAnswer = inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter); + } + } + catch (...) + { + // what should be done here? + } + inCAPThread->mPThread = 0; + if (inCAPThread->mAutoDelete) + delete inCAPThread; + return theAnswer; +} + +UInt32 CAPThread::getScheduledPriority(pthread_t inThread, int inPriorityKind) +{ + thread_basic_info_data_t threadInfo; + policy_info_data_t thePolicyInfo; + unsigned int count; + + if (inThread == NULL) + return 0; + + // get basic info + count = THREAD_BASIC_INFO_COUNT; + thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count); + + switch (threadInfo.policy) { + case POLICY_TIMESHARE: + count = POLICY_TIMESHARE_INFO_COUNT; + thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count); + if (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) { + return static_cast<UInt32>(thePolicyInfo.ts.cur_priority); + } + return static_cast<UInt32>(thePolicyInfo.ts.base_priority); + break; + + case POLICY_FIFO: + count = POLICY_FIFO_INFO_COUNT; + thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count); + if ( (thePolicyInfo.fifo.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) { + return static_cast<UInt32>(thePolicyInfo.fifo.depress_priority); + } + return static_cast<UInt32>(thePolicyInfo.fifo.base_priority); + break; + + case POLICY_RR: + count = POLICY_RR_INFO_COUNT; + thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count); + if ( (thePolicyInfo.rr.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) { + return static_cast<UInt32>(thePolicyInfo.rr.depress_priority); + } + return static_cast<UInt32>(thePolicyInfo.rr.base_priority); + break; + } + + return 0; +} + +#elif TARGET_OS_WIN32 + +UInt32 WINAPI CAPThread::Entry(CAPThread* inCAPThread) +{ + UInt32 theAnswer = 0; + + try + { + if(inCAPThread->mTimeConstraintSet) + { + inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible); + } + else + { + inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority); + } + + if(inCAPThread->mThreadRoutine != NULL) + { + theAnswer = reinterpret_cast<UInt32>(inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter)); + } + inCAPThread->mThreadID = 0; + } + catch (...) + { + // what should be done here? + } + CloseHandle(inCAPThread->mThreadHandle); + inCAPThread->mThreadHandle = NULL; + if (inCAPThread->mAutoDelete) + delete inCAPThread; + return theAnswer; +} + +extern "C" +Boolean CompareAndSwap(UInt32 inOldValue, UInt32 inNewValue, UInt32* inOldValuePtr) +{ + return InterlockedCompareExchange((volatile LONG*)inOldValuePtr, inNewValue, inOldValue) == inOldValue; +} + +#endif + +void CAPThread::SetName(const char* inThreadName) +{ + if(inThreadName != NULL) + { + strlcpy(mThreadName, inThreadName, kMaxThreadNameLength); + } + else + { + memset(mThreadName, 0, kMaxThreadNameLength); + } +} + +#if CoreAudio_Debug +void CAPThread::DebugPriority(const char *label) +{ +#if !TARGET_OS_WIN32 + if (mTimeConstraintSet) + printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this, + (int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1); + else + printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "", + (int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1); +#else + if (mTimeConstraintSet) + { + printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this, + (int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1); + } + else + { + printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "", + (int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1); + } +#endif +} +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPThread.h b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.h new file mode 100644 index 0000000000..41451252f8 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.h @@ -0,0 +1,191 @@ +/* + File: CAPThread.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAPThread_h__) +#define __CAPThread_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreFoundation/CFBase.h> +#else + #include <CFBase.h> +#endif + +#if TARGET_OS_MAC + #include <pthread.h> + #include <unistd.h> +#elif TARGET_OS_WIN32 + #include <windows.h> +#else + #error Unsupported operating system +#endif + +//================================================================================================== +// CAPThread +// +// This class wraps a pthread and a Win32 thread. +// caution: long-running fixed priority threads can make the system unresponsive +//================================================================================================== + +class CAPThread +{ + +// Types +public: + typedef void* (*ThreadRoutine)(void* inParameter); + +// Constants +public: + enum + { +#if TARGET_OS_MAC + kMinThreadPriority = 1, + kMaxThreadPriority = 63, + kDefaultThreadPriority = 31, + kMaxThreadNameLength = 64 +#elif TARGET_OS_WIN32 + kMinThreadPriority = 1, + kMaxThreadPriority = 31, + kDefaultThreadPriority = THREAD_PRIORITY_NORMAL, + kMaxThreadNameLength = 256 +#endif + }; + +// Construction/Destruction +public: + CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority = kDefaultThreadPriority, bool inFixedPriority=false, bool inAutoDelete=false, const char* inThreadName = NULL); + CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible, bool inAutoDelete=false, const char* inThreadName = NULL); + virtual ~CAPThread(); + +// Properties +public: +#if TARGET_OS_MAC + typedef pthread_t NativeThread; + + NativeThread GetNativeThread() { return mPThread; } + static NativeThread GetCurrentThread() { return pthread_self(); } + static bool IsNativeThreadsEqual(NativeThread a, NativeThread b) { return (a==b); } + + bool operator==(NativeThread b) { return pthread_equal(mPThread,b); } + + pthread_t GetPThread() const { return mPThread; } + bool IsCurrentThread() const { return (0 != mPThread) && (pthread_self() == mPThread); } + bool IsRunning() const { return 0 != mPThread; } + static UInt32 getScheduledPriority(pthread_t inThread, int inPriorityKind); +#elif TARGET_OS_WIN32 + typedef unsigned long NativeThread; + + NativeThread GetNativeThread() { return mThreadID; } + static NativeThread GetCurrentThread() { return GetCurrentThreadId(); } + static bool IsNativeThreadsEqual(NativeThread a, NativeThread b) { return (a==b); } + + bool operator ==(NativeThread b) { return (mThreadID==b); } + + HANDLE GetThreadHandle() const { return mThreadHandle; } + UInt32 GetThreadID() const { return mThreadID; } + bool IsCurrentThread() const { return (0 != mThreadID) && (GetCurrentThreadId() == mThreadID); } + bool IsRunning() const { return 0 != mThreadID; } +#endif + + bool IsTimeShareThread() const { return !mTimeConstraintSet; } + bool IsTimeConstraintThread() const { return mTimeConstraintSet; } + + UInt32 GetPriority() const { return mPriority; } + UInt32 GetScheduledPriority(); + static UInt32 GetScheduledPriority(NativeThread thread); + void SetPriority(UInt32 inPriority, bool inFixedPriority=false); + static void SetPriority(NativeThread inThread, UInt32 inPriority, bool inFixedPriority = false); + + void GetTimeConstraints(UInt32& outPeriod, UInt32& outComputation, UInt32& outConstraint, bool& outIsPreemptible) const { outPeriod = mPeriod; outComputation = mComputation; outConstraint = mConstraint; outIsPreemptible = mIsPreemptible; } + void SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible); + void ClearTimeConstraints() { SetPriority(mPriority); } + + bool WillAutoDelete() const { return mAutoDelete; } + void SetAutoDelete(bool b) { mAutoDelete = b; } + + void SetName(const char* inThreadName); + +#if CoreAudio_Debug + void DebugPriority(const char *label); +#endif + +// Actions +public: + virtual void Start(); + +// Implementation +protected: +#if TARGET_OS_MAC + static void* Entry(CAPThread* inCAPThread); +#elif TARGET_OS_WIN32 + static UInt32 WINAPI Entry(CAPThread* inCAPThread); +#endif + +#if TARGET_OS_MAC + pthread_t mPThread; + UInt32 mSpawningThreadPriority; +#elif TARGET_OS_WIN32 + HANDLE mThreadHandle; + unsigned long mThreadID; +#endif + ThreadRoutine mThreadRoutine; + void* mThreadParameter; + char mThreadName[kMaxThreadNameLength]; + UInt32 mPriority; + UInt32 mPeriod; + UInt32 mComputation; + UInt32 mConstraint; + bool mIsPreemptible; + bool mTimeConstraintSet; + bool mFixedPriority; + bool mAutoDelete; // delete self when thread terminates +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp new file mode 100644 index 0000000000..d3fe008eeb --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp @@ -0,0 +1,468 @@ +/* + 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; + } + } +} + + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp new file mode 100644 index 0000000000..23ad2c0282 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp @@ -0,0 +1,92 @@ +/* + File: CAProcess.cpp + Abstract: CAProcess.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CAProcess.h" +#include <signal.h> +#include <unistd.h> +#include <errno.h> + +//============================================================================= +// CAProcess +//============================================================================= + +bool CAProcess::ProcessExists(pid_t inPID) +{ + // pids <= 0 are reserved for special purposes and -1 is + // used as a sentinel value by the HAL. + bool theAnswer = inPID > 0; + + if(theAnswer) + { + // according to kill(2), the process exists if kill(pid, 0) returns 0 + int wasKilled = kill(inPID, 0); + if(wasKilled != 0) + { + // The kill call failed for some reason, but there is only one error code that + // that indicates that the process doesn't exist. + theAnswer = errno != ESRCH; + } + } + + + return theAnswer; +} + +pid_t CAProcess::GetPID() +{ + if(sPID == -1) + { + sPID = getpid(); + } + + return sPID; +} + +pid_t CAProcess::sPID = -1; diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAProcess.h b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.h new file mode 100644 index 0000000000..e512d911be --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.h @@ -0,0 +1,75 @@ +/* + File: CAProcess.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAProcess_h__) +#define __CAProcess_h__ + +//============================================================================= +// Includes +//============================================================================= + +#include <sys/types.h> + +//============================================================================= +// CAProcess +// +// Wrapper for utilities for dealing with Unix Processes. +//============================================================================= + +class CAProcess +{ + +// operations +public: + static bool ProcessExists(pid_t inPID); + static pid_t GetPID(); + +private: + static pid_t sPID; + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h b/libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h new file mode 100644 index 0000000000..6df444b0b4 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h @@ -0,0 +1,312 @@ +/* + File: CAPropertyAddress.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAPropertyAddress_h__) +#define __CAPropertyAddress_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// PublicUtility Includes +#include "CADebugMacros.h" + +// System Includes +#include <CoreAudio/AudioHardware.h> + +// Standard Library Includes +#include <algorithm> +#include <functional> +#include <vector> + +//================================================================================================== +// CAPropertyAddress +// +// CAPropertyAddress extends the AudioObjectPropertyAddress structure to C++ including constructors +// and other utility operations. Note that there is no defined operator< or operator== because the +// presence of wildcards for the fields make comparisons ambiguous without specifying whether or +// not to take the wildcards into account. Consequently, if you want to use this struct in an STL +// data structure, you'll need to specify the approriate function object explicitly in the template +// declaration. +//================================================================================================== + +struct CAPropertyAddress +: + public AudioObjectPropertyAddress +{ + +// Construction/Destruction +public: + CAPropertyAddress() : AudioObjectPropertyAddress() { mSelector = 0; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; } + CAPropertyAddress(AudioObjectPropertySelector inSelector) : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; } + CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope) : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = kAudioObjectPropertyElementMaster; } + CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = inElement; } + CAPropertyAddress(const AudioObjectPropertyAddress& inAddress) : AudioObjectPropertyAddress(inAddress){} + CAPropertyAddress(const CAPropertyAddress& inAddress) : AudioObjectPropertyAddress(inAddress){} + CAPropertyAddress& operator=(const AudioObjectPropertyAddress& inAddress) { AudioObjectPropertyAddress::operator=(inAddress); return *this; } + CAPropertyAddress& operator=(const CAPropertyAddress& inAddress) { AudioObjectPropertyAddress::operator=(inAddress); return *this; } + +// Operations +public: + static bool IsSameAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { return (inAddress1.mScope == inAddress2.mScope) && (inAddress1.mSelector == inAddress2.mSelector) && (inAddress1.mElement == inAddress2.mElement); } + static bool IsLessThanAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { bool theAnswer = false; if(inAddress1.mScope != inAddress2.mScope) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(inAddress1.mSelector != inAddress2.mSelector) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; } + static bool IsCongruentSelector(AudioObjectPropertySelector inSelector1, AudioObjectPropertySelector inSelector2) { return (inSelector1 == inSelector2) || (inSelector1 == kAudioObjectPropertySelectorWildcard) || (inSelector2 == kAudioObjectPropertySelectorWildcard); } + static bool IsCongruentScope(AudioObjectPropertyScope inScope1, AudioObjectPropertyScope inScope2) { return (inScope1 == inScope2) || (inScope1 == kAudioObjectPropertyScopeWildcard) || (inScope2 == kAudioObjectPropertyScopeWildcard); } + static bool IsCongruentElement(AudioObjectPropertyElement inElement1, AudioObjectPropertyElement inElement2) { return (inElement1 == inElement2) || (inElement1 == kAudioObjectPropertyElementWildcard) || (inElement2 == kAudioObjectPropertyElementWildcard); } + static bool IsCongruentAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { return IsCongruentScope(inAddress1.mScope, inAddress2.mScope) && IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector) && IsCongruentElement(inAddress1.mElement, inAddress2.mElement); } + static bool IsCongruentLessThanAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { bool theAnswer = false; if(!IsCongruentScope(inAddress1.mScope, inAddress2.mScope)) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(!IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector)) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else if(!IsCongruentElement(inAddress1.mElement, inAddress2.mElement)) { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; } + +// STL Helpers +public: + struct EqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool> + { + bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsSameAddress(inAddress1, inAddress2); } + }; + + struct LessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool> + { + bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsLessThanAddress(inAddress1, inAddress2); } + }; + + struct CongruentEqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool> + { + bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsCongruentAddress(inAddress1, inAddress2); } + }; + + struct CongruentLessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool> + { + bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsCongruentLessThanAddress(inAddress1, inAddress2); } + }; + +}; + +//================================================================================================== +// CAPropertyAddressList +// +// An auto-resizing array of CAPropertyAddress structures. +//================================================================================================== + +class CAPropertyAddressList +{ + +// Construction/Destruction +public: + CAPropertyAddressList() : mAddressList(), mToken(NULL) {} + explicit CAPropertyAddressList(void* inToken) : mAddressList(), mToken(inToken) {} + explicit CAPropertyAddressList(uintptr_t inToken) : mAddressList(), mToken(reinterpret_cast<void*>(inToken)) {} + CAPropertyAddressList(const CAPropertyAddressList& inAddressList) : mAddressList(inAddressList.mAddressList), mToken(inAddressList.mToken) {} + CAPropertyAddressList& operator=(const CAPropertyAddressList& inAddressList) { mAddressList = inAddressList.mAddressList; mToken = inAddressList.mToken; return *this; } + ~CAPropertyAddressList() {} + +// Operations +public: + void* GetToken() const { return mToken; } + void SetToken(void* inToken) { mToken = inToken; } + + uintptr_t GetIntToken() const { return reinterpret_cast<uintptr_t>(mToken); } + void SetIntToken(uintptr_t inToken) { mToken = reinterpret_cast<void*>(inToken); } + + AudioObjectID GetAudioObjectIDToken() const { return static_cast<AudioObjectID>(reinterpret_cast<uintptr_t>(mToken)); } + + bool IsEmpty() const { return mAddressList.empty(); } + UInt32 GetNumberItems() const { return ToUInt32(mAddressList.size()); } + void GetItemByIndex(UInt32 inIndex, AudioObjectPropertyAddress& outAddress) const { if(inIndex < mAddressList.size()) { outAddress = mAddressList.at(inIndex); } } + const AudioObjectPropertyAddress* GetItems() const { return &(*mAddressList.begin()); } + AudioObjectPropertyAddress* GetItems() { return &(*mAddressList.begin()); } + + bool HasItem(const AudioObjectPropertyAddress& inAddress) const { AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::CongruentEqualTo(), inAddress)); return theIterator != mAddressList.end(); } + bool HasExactItem(const AudioObjectPropertyAddress& inAddress) const { AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); return theIterator != mAddressList.end(); } + + void AppendItem(const AudioObjectPropertyAddress& inAddress) { mAddressList.push_back(inAddress); } + void AppendUniqueItem(const AudioObjectPropertyAddress& inAddress) { if(!HasItem(inAddress)) { mAddressList.push_back(inAddress); } } + void AppendUniqueExactItem(const AudioObjectPropertyAddress& inAddress) { if(!HasExactItem(inAddress)) { mAddressList.push_back(inAddress); } } + void InsertItemAtIndex(UInt32 inIndex, const AudioObjectPropertyAddress& inAddress) { if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, static_cast<int>(inIndex)); mAddressList.insert(theIterator, inAddress); } else { mAddressList.push_back(inAddress); } } + void EraseExactItem(const AudioObjectPropertyAddress& inAddress) { AddressList::iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); if(theIterator != mAddressList.end()) { mAddressList.erase(theIterator); } } + void EraseItemAtIndex(UInt32 inIndex) { if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, static_cast<int>(inIndex)); mAddressList.erase(theIterator); } } + void EraseAllItems() { mAddressList.clear(); } + +// Implementation +private: + typedef std::vector<CAPropertyAddress> AddressList; + + AddressList mAddressList; + void* mToken; + +}; + +//================================================================================================== +// CAPropertyAddressListVector +// +// An auto-resizing array of CAPropertyAddressList objects. +//================================================================================================== + +class CAPropertyAddressListVector +{ + +// Construction/Destruction +public: + CAPropertyAddressListVector() : mAddressListVector() {} + CAPropertyAddressListVector(const CAPropertyAddressListVector& inAddressListVector) : mAddressListVector(inAddressListVector.mAddressListVector) {} + CAPropertyAddressListVector& operator=(const CAPropertyAddressListVector& inAddressListVector) { mAddressListVector = inAddressListVector.mAddressListVector; return *this; } + ~CAPropertyAddressListVector() {} + +// Operations +public: + bool IsEmpty() const { return mAddressListVector.empty(); } + bool HasAnyNonEmptyItems() const; + bool HasAnyItemsWithAddress(const AudioObjectPropertyAddress& inAddress) const; + bool HasAnyItemsWithExactAddress(const AudioObjectPropertyAddress& inAddress) const; + + UInt32 GetNumberItems() const { return ToUInt32(mAddressListVector.size()); } + const CAPropertyAddressList& GetItemByIndex(UInt32 inIndex) const { return mAddressListVector.at(inIndex); } + CAPropertyAddressList& GetItemByIndex(UInt32 inIndex) { return mAddressListVector.at(inIndex); } + const CAPropertyAddressList* GetItemByToken(void* inToken) const; + CAPropertyAddressList* GetItemByToken(void* inToken); + const CAPropertyAddressList* GetItemByIntToken(uintptr_t inToken) const; + CAPropertyAddressList* GetItemByIntToken(uintptr_t inToken); + + void AppendItem(const CAPropertyAddressList& inAddressList) { mAddressListVector.push_back(inAddressList); } + void EraseAllItems() { mAddressListVector.clear(); } + +// Implementation +private: + typedef std::vector<CAPropertyAddressList> AddressListVector; + + AddressListVector mAddressListVector; + +}; + +inline bool CAPropertyAddressListVector::HasAnyNonEmptyItems() const +{ + bool theAnswer = false; + for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator) + { + theAnswer = !theIterator->IsEmpty(); + } + return theAnswer; +} + +inline bool CAPropertyAddressListVector::HasAnyItemsWithAddress(const AudioObjectPropertyAddress& inAddress) const +{ + bool theAnswer = false; + for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator) + { + theAnswer = theIterator->HasItem(inAddress); + } + return theAnswer; +} + +inline bool CAPropertyAddressListVector::HasAnyItemsWithExactAddress(const AudioObjectPropertyAddress& inAddress) const +{ + bool theAnswer = false; + for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator) + { + theAnswer = theIterator->HasExactItem(inAddress); + } + return theAnswer; +} + +inline const CAPropertyAddressList* CAPropertyAddressListVector::GetItemByToken(void* inToken) const +{ + const CAPropertyAddressList* theAnswer = NULL; + bool wasFound = false; + for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator) + { + if(theIterator->GetToken() == inToken) + { + wasFound = true; + theAnswer = &(*theIterator); + } + } + return theAnswer; +} + +inline CAPropertyAddressList* CAPropertyAddressListVector::GetItemByToken(void* inToken) +{ + CAPropertyAddressList* theAnswer = NULL; + bool wasFound = false; + for(AddressListVector::iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator) + { + if(theIterator->GetToken() == inToken) + { + wasFound = true; + theAnswer = &(*theIterator); + } + } + return theAnswer; +} + +inline const CAPropertyAddressList* CAPropertyAddressListVector::GetItemByIntToken(uintptr_t inToken) const +{ + const CAPropertyAddressList* theAnswer = NULL; + bool wasFound = false; + for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator) + { + if(theIterator->GetIntToken() == inToken) + { + wasFound = true; + theAnswer = &(*theIterator); + } + } + return theAnswer; +} + +inline CAPropertyAddressList* CAPropertyAddressListVector::GetItemByIntToken(uintptr_t inToken) +{ + CAPropertyAddressList* theAnswer = NULL; + bool wasFound = false; + for(AddressListVector::iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator) + { + if(theIterator->GetIntToken() == inToken) + { + wasFound = true; + theAnswer = &(*theIterator); + } + } + return theAnswer; +} + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h b/libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h new file mode 100644 index 0000000000..f00fc61675 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h @@ -0,0 +1,97 @@ +/* + File: CAReferenceCounted.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAReferenceCounted_h__ +#define __CAReferenceCounted_h__ + +#include "CAAtomic.h" + +// base class for reference-counted objects +class CAReferenceCounted { +public: + CAReferenceCounted() : mRefCount(1) {} + + void retain() { CAAtomicIncrement32(&mRefCount); } + + void release() + { + SInt32 rc = CAAtomicDecrement32(&mRefCount); + if (rc == 0) { + releaseObject(); + } + } + + + class Retainer { + public: + Retainer(CAReferenceCounted *obj) : mObject(obj) { mObject->retain(); } + ~Retainer() { mObject->release(); } + + private: + CAReferenceCounted * mObject; + }; + +protected: + virtual ~CAReferenceCounted() { } + + virtual void releaseObject () + { + delete this; + } + +#if DEBUG +public: +#endif + SInt32 GetReferenceCount() const { return mRefCount; } +private: + SInt32 mRefCount; + + CAReferenceCounted(const CAReferenceCounted &a); + CAReferenceCounted &operator=(const CAReferenceCounted &a); +}; + + +#endif // __CAReferenceCounted_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp new file mode 100644 index 0000000000..c78acd2c2d --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp @@ -0,0 +1,319 @@ +/* + File: CARingBuffer.cpp + Abstract: CARingBuffer.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 "CARingBuffer.h" +#include "CABitOperations.h" +#include "CAAutoDisposer.h" +#include "CAAtomic.h" + +#include <stdlib.h> +#include <string.h> +#include <algorithm> +#include <libkern/OSAtomic.h> + +CARingBuffer::CARingBuffer() : + mBuffers(NULL), mNumberChannels(0), mCapacityFrames(0), mCapacityBytes(0) +{ + +} + +CARingBuffer::~CARingBuffer() +{ + Deallocate(); +} + + +void CARingBuffer::Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames) +{ + Deallocate(); + + capacityFrames = NextPowerOfTwo(capacityFrames); + + mNumberChannels = nChannels; + mBytesPerFrame = bytesPerFrame; + mCapacityFrames = capacityFrames; + mCapacityFramesMask = capacityFrames - 1; + mCapacityBytes = bytesPerFrame * capacityFrames; + + // put everything in one memory allocation, first the pointers, then the deinterleaved channels + UInt32 allocSize = (mCapacityBytes + sizeof(Byte *)) * nChannels; + Byte *p = (Byte *)CA_malloc(allocSize); + memset(p, 0, allocSize); + mBuffers = (Byte **)p; + p += nChannels * sizeof(Byte *); + for (int i = 0; i < nChannels; ++i) { + mBuffers[i] = p; + p += mCapacityBytes; + } + + for (UInt32 i = 0; i<kGeneralRingTimeBoundsQueueSize; ++i) + { + mTimeBoundsQueue[i].mStartTime = 0; + mTimeBoundsQueue[i].mEndTime = 0; + mTimeBoundsQueue[i].mUpdateCounter = 0; + } + mTimeBoundsQueuePtr = 0; +} + +void CARingBuffer::Deallocate() +{ + if (mBuffers) { + free(mBuffers); + mBuffers = NULL; + } + mNumberChannels = 0; + mCapacityBytes = 0; + mCapacityFrames = 0; +} + +inline void ZeroRange(Byte **buffers, int nchannels, int offset, int nbytes) +{ + while (--nchannels >= 0) { + memset(*buffers + offset, 0, nbytes); + ++buffers; + } +} + +inline void StoreABL(Byte **buffers, int destOffset, const AudioBufferList *abl, int srcOffset, int nbytes) +{ + int nchannels = abl->mNumberBuffers; + const AudioBuffer *src = abl->mBuffers; + while (--nchannels >= 0) { + if (srcOffset > (int)src->mDataByteSize) continue; + memcpy(*buffers + destOffset, (Byte *)src->mData + srcOffset, std::min(nbytes, (int)src->mDataByteSize - srcOffset)); + ++buffers; + ++src; + } +} + +inline void FetchABL(AudioBufferList *abl, int destOffset, Byte **buffers, int srcOffset, int nbytes) +{ + int nchannels = abl->mNumberBuffers; + AudioBuffer *dest = abl->mBuffers; + while (--nchannels >= 0) { + if (destOffset > (int)dest->mDataByteSize) continue; + memcpy((Byte *)dest->mData + destOffset, *buffers + srcOffset, std::min(nbytes, (int)dest->mDataByteSize - destOffset)); + ++buffers; + ++dest; + } +} + +inline void ZeroABL(AudioBufferList *abl, int destOffset, int nbytes) +{ + int nBuffers = abl->mNumberBuffers; + AudioBuffer *dest = abl->mBuffers; + while (--nBuffers >= 0) { + if (destOffset > (int)dest->mDataByteSize) continue; + memset((Byte *)dest->mData + destOffset, 0, std::min(nbytes, (int)dest->mDataByteSize - destOffset)); + ++dest; + } +} + + +CARingBufferError CARingBuffer::Store(const AudioBufferList *abl, UInt32 framesToWrite, SampleTime startWrite) +{ + if (framesToWrite == 0) + return kCARingBufferError_OK; + + if (framesToWrite > mCapacityFrames) + return kCARingBufferError_TooMuch; // too big! + + SampleTime endWrite = startWrite + framesToWrite; + + if (startWrite < EndTime()) { + // going backwards, throw everything out + SetTimeBounds(startWrite, startWrite); + } else if (endWrite - StartTime() <= mCapacityFrames) { + // the buffer has not yet wrapped and will not need to + } else { + // advance the start time past the region we are about to overwrite + SampleTime newStart = endWrite - mCapacityFrames; // one buffer of time behind where we're writing + SampleTime newEnd = std::max(newStart, EndTime()); + SetTimeBounds(newStart, newEnd); + } + + // write the new frames + Byte **buffers = mBuffers; + int nchannels = mNumberChannels; + int offset0, offset1, nbytes; + SampleTime curEnd = EndTime(); + + if (startWrite > curEnd) { + // we are skipping some samples, so zero the range we are skipping + offset0 = FrameOffset(curEnd); + offset1 = FrameOffset(startWrite); + if (offset0 < offset1) + ZeroRange(buffers, nchannels, offset0, offset1 - offset0); + else { + ZeroRange(buffers, nchannels, offset0, mCapacityBytes - offset0); + ZeroRange(buffers, nchannels, 0, offset1); + } + offset0 = offset1; + } else { + offset0 = FrameOffset(startWrite); + } + + offset1 = FrameOffset(endWrite); + if (offset0 < offset1) + StoreABL(buffers, offset0, abl, 0, offset1 - offset0); + else { + nbytes = mCapacityBytes - offset0; + StoreABL(buffers, offset0, abl, 0, nbytes); + StoreABL(buffers, 0, abl, nbytes, offset1); + } + + // now update the end time + SetTimeBounds(StartTime(), endWrite); + + return kCARingBufferError_OK; // success +} + +void CARingBuffer::SetTimeBounds(SampleTime startTime, SampleTime endTime) +{ + UInt32 nextPtr = mTimeBoundsQueuePtr + 1; + UInt32 index = nextPtr & kGeneralRingTimeBoundsQueueMask; + + mTimeBoundsQueue[index].mStartTime = startTime; + mTimeBoundsQueue[index].mEndTime = endTime; + mTimeBoundsQueue[index].mUpdateCounter = nextPtr; + CAAtomicCompareAndSwap32Barrier(mTimeBoundsQueuePtr, mTimeBoundsQueuePtr + 1, (SInt32*)&mTimeBoundsQueuePtr); +} + +CARingBufferError CARingBuffer::GetTimeBounds(SampleTime &startTime, SampleTime &endTime) +{ + for (int i=0; i<8; ++i) // fail after a few tries. + { + UInt32 curPtr = mTimeBoundsQueuePtr; + UInt32 index = curPtr & kGeneralRingTimeBoundsQueueMask; + CARingBuffer::TimeBounds* bounds = mTimeBoundsQueue + index; + + startTime = bounds->mStartTime; + endTime = bounds->mEndTime; + UInt32 newPtr = bounds->mUpdateCounter; + + if (newPtr == curPtr) + return kCARingBufferError_OK; + } + return kCARingBufferError_CPUOverload; +} + +CARingBufferError CARingBuffer::ClipTimeBounds(SampleTime& startRead, SampleTime& endRead) +{ + SampleTime startTime, endTime; + + CARingBufferError err = GetTimeBounds(startTime, endTime); + if (err) return err; + + if (startRead > endTime || endRead < startTime) { + endRead = startRead; + return kCARingBufferError_OK; + } + + startRead = std::max(startRead, startTime); + endRead = std::min(endRead, endTime); + endRead = std::max(endRead, startRead); + + return kCARingBufferError_OK; // success +} + +CARingBufferError CARingBuffer::Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime startRead) +{ + if (nFrames == 0) + return kCARingBufferError_OK; + + startRead = std::max(0LL, startRead); + + SampleTime endRead = startRead + nFrames; + + SampleTime startRead0 = startRead; + SampleTime endRead0 = endRead; + + CARingBufferError err = ClipTimeBounds(startRead, endRead); + if (err) return err; + + if (startRead == endRead) { + ZeroABL(abl, 0, nFrames * mBytesPerFrame); + return kCARingBufferError_OK; + } + + SInt32 byteSize = (SInt32)((endRead - startRead) * mBytesPerFrame); + + SInt32 destStartByteOffset = std::max((SInt32)0, (SInt32)((startRead - startRead0) * mBytesPerFrame)); + + if (destStartByteOffset > 0) { + ZeroABL(abl, 0, std::min((SInt32)(nFrames * mBytesPerFrame), destStartByteOffset)); + } + + SInt32 destEndSize = std::max((SInt32)0, (SInt32)(endRead0 - endRead)); + if (destEndSize > 0) { + ZeroABL(abl, destStartByteOffset + byteSize, destEndSize * mBytesPerFrame); + } + + Byte **buffers = mBuffers; + int offset0 = FrameOffset(startRead); + int offset1 = FrameOffset(endRead); + int nbytes; + + if (offset0 < offset1) { + nbytes = offset1 - offset0; + FetchABL(abl, destStartByteOffset, buffers, offset0, nbytes); + } else { + nbytes = mCapacityBytes - offset0; + FetchABL(abl, destStartByteOffset, buffers, offset0, nbytes); + FetchABL(abl, destStartByteOffset + nbytes, buffers, 0, offset1); + nbytes += offset1; + } + + int nchannels = abl->mNumberBuffers; + AudioBuffer *dest = abl->mBuffers; + while (--nchannels >= 0) + { + dest->mDataByteSize = nbytes; + dest++; + } + + return noErr; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h new file mode 100644 index 0000000000..9569e9a2a8 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h @@ -0,0 +1,126 @@ +/* + File: CARingBuffer.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif + + +#ifndef CARingBuffer_Header +#define CARingBuffer_Header + +enum { + kCARingBufferError_OK = 0, + kCARingBufferError_TooMuch = 3, // fetch start time is earlier than buffer start time and fetch end time is later than buffer end time + kCARingBufferError_CPUOverload = 4 // the reader is unable to get enough CPU cycles to capture a consistent snapshot of the time bounds +}; + +typedef SInt32 CARingBufferError; + +const UInt32 kGeneralRingTimeBoundsQueueSize = 32; +const UInt32 kGeneralRingTimeBoundsQueueMask = kGeneralRingTimeBoundsQueueSize - 1; + +class CARingBuffer { +public: + typedef SInt64 SampleTime; + + CARingBuffer(); + ~CARingBuffer(); + + void Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames); + // capacityFrames will be rounded up to a power of 2 + void Deallocate(); + + CARingBufferError Store(const AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber); + // Copy nFrames of data into the ring buffer at the specified sample time. + // The sample time should normally increase sequentially, though gaps + // are filled with zeroes. A sufficiently large gap effectively empties + // the buffer before storing the new data. + + // If frameNumber is less than the previous frame number, the behavior is undefined. + + // Return false for failure (buffer not large enough). + + CARingBufferError Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber); + // will alter mNumDataBytes of the buffers + + CARingBufferError GetTimeBounds(SampleTime &startTime, SampleTime &endTime); + +protected: + + int FrameOffset(SampleTime frameNumber) { return (frameNumber & mCapacityFramesMask) * mBytesPerFrame; } + + CARingBufferError ClipTimeBounds(SampleTime& startRead, SampleTime& endRead); + + // these should only be called from Store. + SampleTime StartTime() const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mStartTime; } + SampleTime EndTime() const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mEndTime; } + void SetTimeBounds(SampleTime startTime, SampleTime endTime); + +protected: + Byte ** mBuffers; // allocated in one chunk of memory + int mNumberChannels; + UInt32 mBytesPerFrame; // within one deinterleaved channel + UInt32 mCapacityFrames; // per channel, must be a power of 2 + UInt32 mCapacityFramesMask; + UInt32 mCapacityBytes; // per channel + + // range of valid sample time in the buffer + typedef struct { + volatile SampleTime mStartTime; + volatile SampleTime mEndTime; + volatile UInt32 mUpdateCounter; + } TimeBounds; + + CARingBuffer::TimeBounds mTimeBoundsQueue[kGeneralRingTimeBoundsQueueSize]; + UInt32 mTimeBoundsQueuePtr; +}; + + + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp new file mode 100644 index 0000000000..69bdffcb72 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp @@ -0,0 +1,737 @@ +/* + File: CASettingsStorage.cpp + Abstract: CASettingsStorage.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CASettingsStorage.h" + +// PublicUtility Includes +#include "CAAutoDisposer.h" +#include "CACFArray.h" +#include "CACFData.h" +#include "CACFDictionary.h" +#include "CACFDistributedNotification.h" +#include "CACFNumber.h" + +// Stamdard Library Includes +#include <string.h> +#include <sys/fcntl.h> + +//================================================================================================== +// CASettingsStorage +//================================================================================================== + +CASettingsStorage::CASettingsStorage(const char* inSettingsFilePath, mode_t inSettingsFileAccessMode, CFPropertyListFormat inSettingsCacheFormat, bool inIsSingleProcessOnly, bool inIsReadOnly) +: + mSettingsFilePath(NULL), + mSettingsFileAccessMode(inSettingsFileAccessMode), + mSettingsCache(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), + mSettingsCacheFormat(inSettingsCacheFormat), + mSettingsCacheTime(), + mSettingsCacheForceRefresh(true), + mIsSingleProcessOnly(inIsSingleProcessOnly), + mIsReadOnly(inIsReadOnly) +{ + size_t theLength = strlen(inSettingsFilePath); + mSettingsFilePath = new char[theLength + 2]; + strlcpy(mSettingsFilePath, inSettingsFilePath, theLength + 2); + + mSettingsCacheTime.tv_sec = 0; + mSettingsCacheTime.tv_nsec = 0; + + mSettingsCacheForceRefresh = true; +} + +CASettingsStorage::~CASettingsStorage() +{ + delete[] mSettingsFilePath; + + if(mSettingsCache != NULL) + { + CFRelease(mSettingsCache); + } +} + +UInt32 CASettingsStorage::GetNumberKeys() const +{ + // make sure our cache is up to date + const_cast<CASettingsStorage*>(this)->RefreshSettings(); + + return ToUInt32(CFDictionaryGetCount(mSettingsCache)); +} + +void CASettingsStorage::GetKeys(UInt32 inNumberKeys, UInt32& outNumberKeys, CFStringRef* outKeys) const +{ + // make sure our cache is up to date + const_cast<CASettingsStorage*>(this)->RefreshSettings(); + + CFDictionaryGetKeysAndValues(mSettingsCache, reinterpret_cast<const void**>(outKeys), NULL); + outNumberKeys = inNumberKeys; +} + +void CASettingsStorage::CopyBoolValue(CFStringRef inKey, bool& outValue, bool inDefaultValue) const +{ + // initialize the return value + outValue = inDefaultValue; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, NULL); + + // for this type, NULL is an invalid value + if(theValue != NULL) + { + // bools can be made from either CFBooleans or CFNumbers + if(CFGetTypeID(theValue) == CFBooleanGetTypeID()) + { + // get the return value from the CF object + outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue)); + } + else if(CFGetTypeID(theValue) == CFNumberGetTypeID()) + { + // get the numeric value + SInt32 theNumericValue = 0; + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue); + + // non-zero indicates true + outValue = theNumericValue != 0; + } + + // release the value since we aren't returning it + CFRelease(theValue); + } +} + +void CASettingsStorage::CopySInt32Value(CFStringRef inKey, SInt32& outValue, SInt32 inDefaultValue) const +{ + // initialize the return value + outValue = inDefaultValue; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, NULL); + + // for this type, NULL is an invalid value + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFNumberGetTypeID()) + { + // get the return value from the CF object + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue); + } + + // release the value since we aren't returning it + CFRelease(theValue); + } +} + +void CASettingsStorage::CopyUInt32Value(CFStringRef inKey, UInt32& outValue, UInt32 inDefaultValue) const +{ + // initialize the return value + outValue = inDefaultValue; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, NULL); + + // for this type, NULL is an invalid value + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFNumberGetTypeID()) + { + // get the return value from the CF object + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue); + } + + // release the value since we aren't returning it + CFRelease(theValue); + } +} + +void CASettingsStorage::CopySInt64Value(CFStringRef inKey, SInt64& outValue, SInt64 inDefaultValue) const +{ + // initialize the return value + outValue = inDefaultValue; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, NULL); + + // for this type, NULL is an invalid value + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFNumberGetTypeID()) + { + // get the return value from the CF object + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue); + } + + // release the value since we aren't returning it + CFRelease(theValue); + } +} + +void CASettingsStorage::CopyUInt64Value(CFStringRef inKey, UInt64& outValue, UInt64 inDefaultValue) const +{ + // initialize the return value + outValue = inDefaultValue; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, NULL); + + // for this type, NULL is an invalid value + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFNumberGetTypeID()) + { + // get the return value from the CF object + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue); + } + + // release the value since we aren't returning it + CFRelease(theValue); + } +} + +void CASettingsStorage::CopyFloat32Value(CFStringRef inKey, Float32& outValue, Float32 inDefaultValue) const +{ + // initialize the return value + outValue = inDefaultValue; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, NULL); + + // for this type, NULL is an invalid value + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFNumberGetTypeID()) + { + // get the return value from the CF object + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue); + } + + // release the value since we aren't returning it + CFRelease(theValue); + } +} + +void CASettingsStorage::CopyFloat64Value(CFStringRef inKey, Float64& outValue, Float64 inDefaultValue) const +{ + // initialize the return value + outValue = inDefaultValue; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, NULL); + + // for this type, NULL is an invalid value + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFNumberGetTypeID()) + { + // get the return value from the CF object + CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue); + } + + // release the value since we aren't returning it + CFRelease(theValue); + } +} + +void CASettingsStorage::CopyNumberValue(CFStringRef inKey, CFNumberRef& outValue, CFNumberRef inDefaultValue) const +{ + // initialize the return value + outValue = NULL; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, inDefaultValue); + + // for this type, NULL is a valid value, but requires less work + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFNumberGetTypeID()) + { + // set the return value to the CF object we are returning + outValue = static_cast<CFNumberRef>(theValue); + } + else + { + // release the value since we aren't returning it + CFRelease(theValue); + + // set the return value to the default value + outValue = inDefaultValue; + + // and retain it + CFRetain(outValue); + } + } +} + +void CASettingsStorage::CopyStringValue(CFStringRef inKey, CFStringRef& outValue, CFStringRef inDefaultValue) const +{ + // initialize the return value + outValue = NULL; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, inDefaultValue); + + // for this type, NULL is a valid value, but requires less work + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFStringGetTypeID()) + { + // set the return value to the CF object we are returning + outValue = static_cast<CFStringRef>(theValue); + } + else + { + // release the value since we aren't returning it + CFRelease(theValue); + + // set the return value to the default value + outValue = inDefaultValue; + + // and retain it + CFRetain(outValue); + } + } +} + +void CASettingsStorage::CopyArrayValue(CFStringRef inKey, CFArrayRef& outValue, CFArrayRef inDefaultValue) const +{ + // initialize the return value + outValue = NULL; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, inDefaultValue); + + // for this type, NULL is a valid value, but requires less work + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFArrayGetTypeID()) + { + // set the return value to the CF object we are returning + outValue = static_cast<CFArrayRef>(theValue); + } + else + { + // release the value since we aren't returning it + CFRelease(theValue); + + // set the return value to the default value + outValue = inDefaultValue; + + // and retain it + CFRetain(outValue); + } + } +} + +void CASettingsStorage::CopyDictionaryValue(CFStringRef inKey, CFDictionaryRef& outValue, CFDictionaryRef inDefaultValue) const +{ + // initialize the return value + outValue = NULL; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, inDefaultValue); + + // for this type, NULL is a valid value, but requires less work + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFDictionaryGetTypeID()) + { + // set the return value to the CF object we are returning + outValue = static_cast<CFDictionaryRef>(theValue); + } + else + { + // release the value since we aren't returning it + CFRelease(theValue); + + // set the return value to the default value + outValue = inDefaultValue; + + // and retain it + CFRetain(outValue); + } + } +} + +void CASettingsStorage::CopyDataValue(CFStringRef inKey, CFDataRef& outValue, CFDataRef inDefaultValue) const +{ + // initialize the return value + outValue = NULL; + + // get the raw value + CFTypeRef theValue = NULL; + CopyCFTypeValue(inKey, theValue, inDefaultValue); + + // for this type, NULL is a valid value, but requires less work + if(theValue != NULL) + { + // make sure we are dealing with the right kind of CF object + if(CFGetTypeID(theValue) == CFDataGetTypeID()) + { + // set the return value to the CF object we are returning + outValue = static_cast<CFDataRef>(theValue); + } + else + { + // release the value since we aren't returning it + CFRelease(theValue); + + // set the return value to the default value + outValue = inDefaultValue; + + // and retain it + CFRetain(outValue); + } + } +} + +void CASettingsStorage::CopyCFTypeValue(CFStringRef inKey, CFTypeRef& outValue, CFTypeRef inDefaultValue) const +{ + // make sure our cache is up to date + const_cast<CASettingsStorage*>(this)->RefreshSettings(); + + // check to see if we have a value for the given key + if(!CFDictionaryGetValueIfPresent(mSettingsCache, inKey, &outValue)) + { + // the key wasn't in the cache, so return the default value + outValue = inDefaultValue; + } + + // make sure we retain the return value + if(outValue != NULL) + { + CFRetain(outValue); + } +} + +void CASettingsStorage::SetSInt32Value(CFStringRef inKey, SInt32 inValue) +{ + CACFNumber theValue(inValue); + SetCFTypeValue(inKey, theValue.GetCFNumber()); +} + +void CASettingsStorage::SetUInt32Value(CFStringRef inKey, UInt32 inValue) +{ + CACFNumber theValue(inValue); + SetCFTypeValue(inKey, theValue.GetCFNumber()); +} + +void CASettingsStorage::SetSInt64Value(CFStringRef inKey, SInt64 inValue) +{ + CACFNumber theValue(inValue); + SetCFTypeValue(inKey, theValue.GetCFNumber()); +} + +void CASettingsStorage::SetUInt64Value(CFStringRef inKey, UInt64 inValue) +{ + CACFNumber theValue(inValue); + SetCFTypeValue(inKey, theValue.GetCFNumber()); +} + +void CASettingsStorage::SetFloat32Value(CFStringRef inKey, Float32 inValue) +{ + CACFNumber theValue(inValue); + SetCFTypeValue(inKey, theValue.GetCFNumber()); +} + +void CASettingsStorage::SetFloat64Value(CFStringRef inKey, Float64 inValue) +{ + CACFNumber theValue(inValue); + SetCFTypeValue(inKey, theValue.GetCFNumber()); +} + +void CASettingsStorage::SetNumberValue(CFStringRef inKey, CFNumberRef inValue) +{ + SetCFTypeValue(inKey, inValue); +} + +void CASettingsStorage::SetStringValue(CFStringRef inKey, CFStringRef inValue) +{ + SetCFTypeValue(inKey, inValue); +} + +void CASettingsStorage::SetArrayValue(CFStringRef inKey, CFArrayRef inValue) +{ + SetCFTypeValue(inKey, inValue); +} + +void CASettingsStorage::SetDictionaryValue(CFStringRef inKey, CFDictionaryRef inValue) +{ + SetCFTypeValue(inKey, inValue); +} + +void CASettingsStorage::SetDataValue(CFStringRef inKey, CFDataRef inValue) +{ + SetCFTypeValue(inKey, inValue); +} + +void CASettingsStorage::SetCFTypeValue(CFStringRef inKey, CFTypeRef inValue) +{ + // make sure our cache is up to date + RefreshSettings(); + + // add the new key/value to the dictionary + CFDictionarySetValue(mSettingsCache, inKey, inValue); + + // write the settings to the file + SaveSettings(); +} + +void CASettingsStorage::RemoveValue(CFStringRef inKey) +{ + // make sure our cache is up to date + RefreshSettings(); + + // remove the given key + CFDictionaryRemoveValue(mSettingsCache, inKey); + + // write the settings to the file + SaveSettings(); +} + +void CASettingsStorage::RemoveAllValues() +{ + // make sure our cache is up to date + RefreshSettings(); + + // remove the given key + CFDictionaryRemoveAllValues(mSettingsCache); + + // write the settings to the file + SaveSettings(); +} + +void CASettingsStorage::SendNotification(CFStringRef inName, CFDictionaryRef inData, bool inPostToAllSessions) const +{ + CACFDistributedNotification::PostNotification(inName, inData, inPostToAllSessions); +} + +void CASettingsStorage::ForceRefresh() +{ + mSettingsCacheForceRefresh = true; +} + +inline bool operator<(const struct timespec& inX, const struct timespec& inY) +{ + return ((inX.tv_sec < inY.tv_sec) || ((inX.tv_sec == inY.tv_sec) && (inX.tv_nsec < inY.tv_nsec))); +} + +void CASettingsStorage::RefreshSettings() +{ + // if this storage is only supporting a single process, there is no need to hit the disk unless + // required to by it being the first time or if the refresh is specifically forced for some reason + if(!mIsSingleProcessOnly || (mSettingsCache == NULL) || ((mSettingsCacheTime.tv_sec == 0) && (mSettingsCacheTime.tv_nsec == 0)) || mSettingsCacheForceRefresh) + { + // first, we need to stat the file to check the mod date, this has the side effect of also + // telling us if the file exisits + struct stat theFileInfo; + int theStatError = stat(mSettingsFilePath, &theFileInfo); + + // we use this boolean to make error recovery easier since we need a case for when there's no file anyway + bool theSettingsWereCached = false; + bool theSettingsNeedSaving = true; + + if(theStatError == 0) + { + // stat says there is something there, only have to do work if we either don't have a cache or the cache is out of date + if((mSettingsCache == NULL) || (mSettingsCacheTime < theFileInfo.st_mtimespec) || mSettingsCacheForceRefresh) + { + // open the file + FILE* theFile = fopen(mSettingsFilePath, "r"); + if(theFile != NULL) + { + // lock the file (this call blocks until the lock is taken) + int theError = flock(fileno(theFile), LOCK_EX); + if(theError == 0) + { + // get the length of the file + fseek(theFile, 0, SEEK_END); + size_t theFileLength = static_cast<size_t>(ftell(theFile)); + fseek(theFile, 0, SEEK_SET); + + if(theFileLength > 0) + { + // allocate a block of memory to hold the data in the file + CAAutoFree<Byte> theRawFileData(theFileLength); + + // read all the data in + fread(static_cast<Byte*>(theRawFileData), theFileLength, 1, theFile); + + // release the lock + flock(fileno(theFile), LOCK_UN); + + // put it into a CFData object + CACFData theRawFileDataCFData(static_cast<Byte*>(theRawFileData), static_cast<UInt32>(theFileLength)); + + // get rid of the existing cache + if(mSettingsCache != NULL) + { + CFRelease(mSettingsCache); + mSettingsCache = NULL; + } + + // parse the data as a property list + mSettingsCache = (CFMutableDictionaryRef)CFPropertyListCreateWithData(NULL, theRawFileDataCFData.GetCFData(), kCFPropertyListMutableContainersAndLeaves, NULL, NULL); + + // check to be sure we parsed a plist out of the file + if(mSettingsCache != NULL) + { + // save the date of the cache + mSettingsCacheTime = theFileInfo.st_mtimespec; + + // mark that we're done + theSettingsWereCached = true; + theSettingsNeedSaving = false; + } + } + } + + // close the file + fclose(theFile); + mSettingsCacheForceRefresh = false; + } + } + else + { + // nothing to do since the file was older than the cached data + theSettingsNeedSaving = false; + theSettingsWereCached = true; + } + } + + // if there was a failure, we need to clean up + if((theStatError != 0) || theSettingsNeedSaving || !theSettingsWereCached) + { + // we get here if either there isn't a file or something wacky happenned while parsing it + // so, make sure we have a valid cache dictionary + if(mSettingsCache == NULL) + { + mSettingsCache = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + + mSettingsCacheTime.tv_sec = 0; + mSettingsCacheTime.tv_nsec = 0; + + if((theStatError != 0) || theSettingsNeedSaving) + { + SaveSettings(); + } + } + } +} + +void CASettingsStorage::SaveSettings() +{ + if(!mIsReadOnly && (mSettingsCache != NULL)) + { + // make a CFData that contains the new settings + CACFData theNewRawPrefsCFData(CFPropertyListCreateData(NULL, mSettingsCache, mSettingsCacheFormat, 0, NULL), true); + + // open the file for writing + FILE* theFile = fopen(mSettingsFilePath, "w+"); + if(theFile != NULL) + { + // lock the file (this call blocks until the lock is taken) + int theError = flock(fileno(theFile), LOCK_EX); + if(theError == 0) + { + // set the file access mode if necessary + if(mSettingsFileAccessMode != 0) + { + fchmod(fileno(theFile), mSettingsFileAccessMode); + } + + // write the data + fwrite(theNewRawPrefsCFData.GetDataPtr(), theNewRawPrefsCFData.GetSize(), 1, theFile); + + // flush the file to be sure it is all on disk + fflush(theFile); + + // release the lock + flock(fileno(theFile), LOCK_UN); + + // close the file + fclose(theFile); + + // stat the file to get the mod date + struct stat theFileInfo; + stat(mSettingsFilePath, &theFileInfo); + + // save the mod date + mSettingsCacheTime = theFileInfo.st_mtimespec; + } + else + { + // close the file + fclose(theFile); + } + } + } +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h new file mode 100644 index 0000000000..d15f87dd16 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h @@ -0,0 +1,128 @@ +/* + File: CASettingsStorage.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CASettingsStorage_h__) +#define __CASettingsStorage_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// System Includes +#include <CoreAudio/CoreAudioTypes.h> +#include <CoreFoundation/CoreFoundation.h> + +// Stamdard Library Includes +#include <stdio.h> +#include <sys/stat.h> + +//================================================================================================== +// CASettingsStorage +//================================================================================================== + +class CASettingsStorage +{ + +// Construction/Destruction +public: + CASettingsStorage(const char* inSettingsFilePath, mode_t inSettingsFileAccessMode = 0, CFPropertyListFormat inSettingsCacheFormat = kCFPropertyListXMLFormat_v1_0, bool inIsSingleProcessOnly = false, bool inIsReadOnly = false); + ~CASettingsStorage(); + +// Operations +public: + UInt32 GetNumberKeys() const; + void GetKeys(UInt32 inNumberKeys, UInt32& outNumberKeys, CFStringRef* outKeys) const; + + void CopyBoolValue(const CFStringRef inKey, bool& outValue, bool inDefaultValue = false) const; + void CopySInt32Value(const CFStringRef inKey, SInt32& outValue, SInt32 inDefaultValue = 0) const; + void CopyUInt32Value(const CFStringRef inKey, UInt32& outValue, UInt32 inDefaultValue = 0) const; + void CopySInt64Value(const CFStringRef inKey, SInt64& outValue, SInt64 inDefaultValue = 0) const; + void CopyUInt64Value(const CFStringRef inKey, UInt64& outValue, UInt64 inDefaultValue = 0) const; + void CopyFloat32Value(const CFStringRef inKey, Float32& outValue, Float32 inDefaultValue = 0) const; + void CopyFloat64Value(const CFStringRef inKey, Float64& outValue, Float64 inDefaultValue = 0) const; + void CopyNumberValue(const CFStringRef inKey, CFNumberRef& outValue, CFNumberRef inDefaultValue = NULL) const; + void CopyStringValue(const CFStringRef inKey, CFStringRef& outValue, CFStringRef inDefaultValue = NULL) const; + void CopyArrayValue(const CFStringRef inKey, CFArrayRef& outValue, CFArrayRef inDefaultValue = NULL) const; + void CopyDictionaryValue(const CFStringRef inKey, CFDictionaryRef& outValue, CFDictionaryRef inDefaultValue = NULL) const; + void CopyDataValue(const CFStringRef inKey, CFDataRef& outValue, CFDataRef inDefaultValue = NULL) const; + void CopyCFTypeValue(const CFStringRef inKey, CFTypeRef& outValue, CFTypeRef inDefaultValue = NULL) const; + + void SetSInt32Value(const CFStringRef inKey, SInt32 inValue); + void SetUInt32Value(const CFStringRef inKey, UInt32 inValue); + void SetSInt64Value(const CFStringRef inKey, SInt64 inValue); + void SetUInt64Value(const CFStringRef inKey, UInt64 inValue); + void SetFloat32Value(const CFStringRef inKey, Float32 inValue); + void SetFloat64Value(const CFStringRef inKey, Float64 inValue); + void SetNumberValue(const CFStringRef inKey, const CFNumberRef inValue); + void SetStringValue(const CFStringRef inKey, const CFStringRef inValue); + void SetArrayValue(const CFStringRef inKey, const CFArrayRef inValue); + void SetDictionaryValue(const CFStringRef inKey, const CFDictionaryRef inValue); + void SetDataValue(const CFStringRef inKey, const CFDataRef inValue); + void SetCFTypeValue(const CFStringRef inKey, const CFTypeRef inValue); + + void RemoveValue(const CFStringRef inKey); + void RemoveAllValues(); + + void SendNotification(const CFStringRef inName, CFDictionaryRef inData = NULL, bool inPostToAllSessions = true) const; + void ForceRefresh(); + +// Implementation +private: + void RefreshSettings(); + void SaveSettings(); + + char* mSettingsFilePath; + mode_t mSettingsFileAccessMode; + CFMutableDictionaryRef mSettingsCache; + CFPropertyListFormat mSettingsCacheFormat; + struct timespec mSettingsCacheTime; + bool mSettingsCacheForceRefresh; + bool mIsSingleProcessOnly; + bool mIsReadOnly; + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp new file mode 100644 index 0000000000..0e39ac7e52 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp @@ -0,0 +1,118 @@ +/* + File: CASharedLibrary.cpp + Abstract: CASharedLibrary.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CASharedLibrary.h" + +//#define CASharedLibrary_Use_DYLD 1 +#if CASharedLibrary_Use_DYLD + #include <mach-o/dyld.h> +#else + #include <dlfcn.h> + #include <stddef.h> +#endif + +//============================================================================= +// CASharedLibrary +//============================================================================= + +void* CASharedLibrary::LoadLibraryAndGetRoutineAddress(const char* inRoutineName, const char* /*inLibraryName*/, const char* inLibraryPath) +{ + void* theRoutine = 0; + +#if CASharedLibrary_Use_DYLD + const struct mach_header* theImage = NSAddImage(inLibraryPath, NSADDIMAGE_OPTION_RETURN_ON_ERROR); + if(theImage != 0) + { + NSSymbol theSymbol = NSLookupSymbolInImage(theImage, inRoutineName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND); + if(theSymbol != 0) + { + theRoutine = NSAddressOfSymbol(theSymbol); + } + } +#else + void* theImage = dlopen(inLibraryPath, RTLD_LAZY); + if(theImage != NULL) + { + // we assume that all routine names passed here have a leading underscore which gets shaved + // off when passed to dlsym + theRoutine = dlsym(theImage, &(inRoutineName[1])); + } + +#endif + + return theRoutine; +} + +void* CASharedLibrary::GetRoutineAddressIfLibraryLoaded(const char* inRoutineName, const char* /*inLibraryName*/, const char* inLibraryPath) +{ + void* theRoutine = 0; + +#if CASharedLibrary_Use_DYLD + const struct mach_header* theImage = NSAddImage(inLibraryPath, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED); + if(theImage != 0) + { + NSSymbol theSymbol = NSLookupSymbolInImage(theImage, inRoutineName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND); + if(theSymbol != 0) + { + theRoutine = NSAddressOfSymbol(theSymbol); + } + } +#else + void* theImage = dlopen(inLibraryPath, RTLD_LAZY | RTLD_NOLOAD); + if(theImage != NULL) + { + // we assume that all routine names passed here have a leading underscore which gets shaved + // off when passed to dlsym + theRoutine = dlsym(theImage, &(inRoutineName[1])); + } +#endif + + return theRoutine; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h new file mode 100644 index 0000000000..d02e70e356 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h @@ -0,0 +1,64 @@ +/* + File: CASharedLibrary.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CASharedLibrary_h__) +#define __CASharedLibrary_h__ + +//============================================================================= +// CASharedLibrary +//============================================================================= + +class CASharedLibrary +{ + +// Symbol Operations +public: + static void* LoadLibraryAndGetRoutineAddress(const char* inRoutineName, const char* inLibraryName, const char* inLibraryPath); + static void* GetRoutineAddressIfLibraryLoaded(const char* inRoutineName, const char* inLibraryName, const char* inLibraryPath); + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp new file mode 100644 index 0000000000..ffb2da8a83 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp @@ -0,0 +1,376 @@ +/* + File: CASpectralProcessor.cpp + Abstract: CASpectralProcessor.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 "AudioFormulas.h" +#include "CASpectralProcessor.h" +#include "CABitOperations.h" + + +#include <Accelerate/Accelerate.h> + + +#define OFFSETOF(class, field)((size_t)&((class*)0)->field) + +CASpectralProcessor::CASpectralProcessor(UInt32 inFFTSize, UInt32 inHopSize, UInt32 inNumChannels, UInt32 inMaxFrames) + : mFFTSize(inFFTSize), mHopSize(inHopSize), mNumChannels(inNumChannels), mMaxFrames(inMaxFrames), + mLog2FFTSize(Log2Ceil(mFFTSize)), + mFFTMask(mFFTSize - 1), + mFFTByteSize(mFFTSize * sizeof(Float32)), + mIOBufSize(NextPowerOfTwo(mFFTSize + mMaxFrames)), + mIOMask(mIOBufSize - 1), + mInputSize(0), + mInputPos(0), mOutputPos(-mFFTSize & mIOMask), + mInFFTPos(0), mOutFFTPos(0), + mSpectralFunction(0), mUserData(0) +{ + mWindow.alloc(mFFTSize, false); + SineWindow(); // set default window. + + mChannels.alloc(mNumChannels); + mSpectralBufferList.allocBytes(OFFSETOF(SpectralBufferList, mDSPSplitComplex[mNumChannels]), true); + mSpectralBufferList->mNumberSpectra = mNumChannels; + for (UInt32 i = 0; i < mNumChannels; ++i) + { + mChannels[i].mInputBuf.alloc(mIOBufSize, true); + mChannels[i].mOutputBuf.alloc(mIOBufSize, true); + mChannels[i].mFFTBuf.alloc(mFFTSize, true); + mChannels[i].mSplitFFTBuf.alloc(mFFTSize, true); + mSpectralBufferList->mDSPSplitComplex[i].realp = mChannels[i].mSplitFFTBuf(); + mSpectralBufferList->mDSPSplitComplex[i].imagp = mChannels[i].mSplitFFTBuf() + (mFFTSize >> 1); + } + + mFFTSetup = vDSP_create_fftsetup (mLog2FFTSize, FFT_RADIX2); + +} + +CASpectralProcessor::~CASpectralProcessor() +{ + mWindow.free(); + mChannels.free(); + mSpectralBufferList.free(); + vDSP_destroy_fftsetup(mFFTSetup); +} + +void CASpectralProcessor::Reset() +{ + mInputPos = 0; + mOutputPos = -mFFTSize & mIOMask; + mInFFTPos = 0; + mOutFFTPos = 0; + + for (UInt32 i = 0; i < mNumChannels; ++i) + { + memset(mChannels[i].mInputBuf(), 0, mIOBufSize * sizeof(Float32)); + memset(mChannels[i].mOutputBuf(), 0, mIOBufSize * sizeof(Float32)); + memset(mChannels[i].mFFTBuf(), 0, mFFTSize * sizeof(Float32)); + } +} + +const double two_pi = 2. * M_PI; + +void CASpectralProcessor::HanningWindow() +{ + // this is also vector optimized + + double w = two_pi / (double)(mFFTSize - 1); + for (UInt32 i = 0; i < mFFTSize; ++i) + { + mWindow[i] = (0.5 - 0.5 * cos(w * (double)i)); + } +} + +void CASpectralProcessor::SineWindow() +{ + double w = M_PI / (double)(mFFTSize - 1); + for (UInt32 i = 0; i < mFFTSize; ++i) + { + mWindow[i] = sin(w * (double)i); + } +} + +void CASpectralProcessor::Process(UInt32 inNumFrames, AudioBufferList* inInput, AudioBufferList* outOutput) +{ + // copy from buffer list to input buffer + CopyInput(inNumFrames, inInput); + + // if enough input to process, then process. + while (mInputSize >= mFFTSize) + { + CopyInputToFFT(); // copy from input buffer to fft buffer + DoWindowing(); + DoFwdFFT(); + ProcessSpectrum(mFFTSize, mSpectralBufferList()); + DoInvFFT(); + DoWindowing(); + OverlapAddOutput(); + } + + // copy from output buffer to buffer list + CopyOutput(inNumFrames, outOutput); +} + +void CASpectralProcessor::DoWindowing() +{ + Float32 *win = mWindow(); + if (!win) return; + for (UInt32 i=0; i<mNumChannels; ++i) { + Float32 *x = mChannels[i].mFFTBuf(); + vDSP_vmul(x, 1, win, 1, x, 1, mFFTSize); + } + //printf("DoWindowing %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]); +} + + + +void CASpectralProcessor::CopyInput(UInt32 inNumFrames, AudioBufferList* inInput) +{ + UInt32 numBytes = inNumFrames * sizeof(Float32); + UInt32 firstPart = mIOBufSize - mInputPos; + + + if (firstPart < inNumFrames) { + UInt32 firstPartBytes = firstPart * sizeof(Float32); + UInt32 secondPartBytes = numBytes - firstPartBytes; + for (UInt32 i=0; i<mNumChannels; ++i) { + memcpy(mChannels[i].mInputBuf + mInputPos, inInput->mBuffers[i].mData, firstPartBytes); + memcpy(mChannels[i].mInputBuf, (UInt8*)inInput->mBuffers[i].mData + firstPartBytes, secondPartBytes); + } + } else { + UInt32 numBytes = inNumFrames * sizeof(Float32); + for (UInt32 i=0; i<mNumChannels; ++i) { + memcpy(mChannels[i].mInputBuf + mInputPos, inInput->mBuffers[i].mData, numBytes); + } + } + //printf("CopyInput %g %g\n", mChannels[0].mInputBuf[mInputPos], mChannels[0].mInputBuf[(mInputPos + 200) & mIOMask]); + //printf("CopyInput mInputPos %u mIOBufSize %u\n", (unsigned)mInputPos, (unsigned)mIOBufSize); + mInputSize += inNumFrames; + mInputPos = (mInputPos + inNumFrames) & mIOMask; +} + +void CASpectralProcessor::CopyOutput(UInt32 inNumFrames, AudioBufferList* outOutput) +{ + //printf("->CopyOutput %g %g\n", mChannels[0].mOutputBuf[mOutputPos], mChannels[0].mOutputBuf[(mOutputPos + 200) & mIOMask]); + //printf("CopyOutput mOutputPos %u\n", (unsigned)mOutputPos); + UInt32 numBytes = inNumFrames * sizeof(Float32); + UInt32 firstPart = mIOBufSize - mOutputPos; + if (firstPart < inNumFrames) { + UInt32 firstPartBytes = firstPart * sizeof(Float32); + UInt32 secondPartBytes = numBytes - firstPartBytes; + for (UInt32 i=0; i<mNumChannels; ++i) { + memcpy(outOutput->mBuffers[i].mData, mChannels[i].mOutputBuf + mOutputPos, firstPartBytes); + memcpy((UInt8*)outOutput->mBuffers[i].mData + firstPartBytes, mChannels[i].mOutputBuf, secondPartBytes); + memset(mChannels[i].mOutputBuf + mOutputPos, 0, firstPartBytes); + memset(mChannels[i].mOutputBuf, 0, secondPartBytes); + } + } else { + for (UInt32 i=0; i<mNumChannels; ++i) { + memcpy(outOutput->mBuffers[i].mData, mChannels[i].mOutputBuf + mOutputPos, numBytes); + memset(mChannels[i].mOutputBuf + mOutputPos, 0, numBytes); + } + } + //printf("<-CopyOutput %g %g\n", ((Float32*)outOutput->mBuffers[0].mData)[0], ((Float32*)outOutput->mBuffers[0].mData)[200]); + mOutputPos = (mOutputPos + inNumFrames) & mIOMask; +} + +void CASpectralProcessor::PrintSpectralBufferList() +{ + UInt32 half = mFFTSize >> 1; + for (UInt32 i=0; i<mNumChannels; ++i) { + DSPSplitComplex &freqData = mSpectralBufferList->mDSPSplitComplex[i]; + + for (UInt32 j=0; j<half; j++){ + printf(" bin[%d]: %lf + %lfi\n", (int) j, freqData.realp[j], freqData.imagp[j]); + } + } +} + + +void CASpectralProcessor::CopyInputToFFT() +{ + //printf("CopyInputToFFT mInFFTPos %u\n", (unsigned)mInFFTPos); + UInt32 firstPart = mIOBufSize - mInFFTPos; + UInt32 firstPartBytes = firstPart * sizeof(Float32); + if (firstPartBytes < mFFTByteSize) { + UInt32 secondPartBytes = mFFTByteSize - firstPartBytes; + for (UInt32 i=0; i<mNumChannels; ++i) { + memcpy(mChannels[i].mFFTBuf(), mChannels[i].mInputBuf() + mInFFTPos, firstPartBytes); + memcpy((UInt8*)mChannels[i].mFFTBuf() + firstPartBytes, mChannels[i].mInputBuf(), secondPartBytes); + } + } else { + for (UInt32 i=0; i<mNumChannels; ++i) { + memcpy(mChannels[i].mFFTBuf(), mChannels[i].mInputBuf() + mInFFTPos, mFFTByteSize); + } + } + mInputSize -= mHopSize; + mInFFTPos = (mInFFTPos + mHopSize) & mIOMask; + //printf("CopyInputToFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]); +} + +void CASpectralProcessor::OverlapAddOutput() +{ + //printf("OverlapAddOutput mOutFFTPos %u\n", (unsigned)mOutFFTPos); + UInt32 firstPart = mIOBufSize - mOutFFTPos; + if (firstPart < mFFTSize) { + UInt32 secondPart = mFFTSize - firstPart; + for (UInt32 i=0; i<mNumChannels; ++i) { + float* out1 = mChannels[i].mOutputBuf() + mOutFFTPos; + vDSP_vadd(out1, 1, mChannels[i].mFFTBuf(), 1, out1, 1, firstPart); + float* out2 = mChannels[i].mOutputBuf(); + vDSP_vadd(out2, 1, mChannels[i].mFFTBuf() + firstPart, 1, out2, 1, secondPart); + } + } else { + for (UInt32 i=0; i<mNumChannels; ++i) { + float* out1 = mChannels[i].mOutputBuf() + mOutFFTPos; + vDSP_vadd(out1, 1, mChannels[i].mFFTBuf(), 1, out1, 1, mFFTSize); + } + } + //printf("OverlapAddOutput %g %g\n", mChannels[0].mOutputBuf[mOutFFTPos], mChannels[0].mOutputBuf[(mOutFFTPos + 200) & mIOMask]); + mOutFFTPos = (mOutFFTPos + mHopSize) & mIOMask; +} + + +void CASpectralProcessor::DoFwdFFT() +{ + //printf("->DoFwdFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]); + UInt32 half = mFFTSize >> 1; + for (UInt32 i=0; i<mNumChannels; ++i) + { + vDSP_ctoz((DSPComplex*)mChannels[i].mFFTBuf(), 2, &mSpectralBufferList->mDSPSplitComplex[i], 1, half); + vDSP_fft_zrip(mFFTSetup, &mSpectralBufferList->mDSPSplitComplex[i], 1, mLog2FFTSize, FFT_FORWARD); + } + //printf("<-DoFwdFFT %g %g\n", direction, mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]); +} + +void CASpectralProcessor::DoInvFFT() +{ + //printf("->DoInvFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]); + UInt32 half = mFFTSize >> 1; + for (UInt32 i=0; i<mNumChannels; ++i) + { + vDSP_fft_zrip(mFFTSetup, &mSpectralBufferList->mDSPSplitComplex[i], 1, mLog2FFTSize, FFT_INVERSE); + vDSP_ztoc(&mSpectralBufferList->mDSPSplitComplex[i], 1, (DSPComplex*)mChannels[i].mFFTBuf(), 2, half); + float scale = 0.5 / mFFTSize; + vDSP_vsmul(mChannels[i].mFFTBuf(), 1, &scale, mChannels[i].mFFTBuf(), 1, mFFTSize ); + } + //printf("<-DoInvFFT %g %g\n", direction, mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]); +} + +void CASpectralProcessor::SetSpectralFunction(SpectralFunction inFunction, void* inUserData) +{ + mSpectralFunction = inFunction; + mUserData = inUserData; +} + +void CASpectralProcessor::ProcessSpectrum(UInt32 inFFTSize, SpectralBufferList* inSpectra) +{ + if (mSpectralFunction) + (mSpectralFunction)(inSpectra, mUserData); +} + +#pragma mark ___Utility___ + +void CASpectralProcessor::GetMagnitude(AudioBufferList* list, Float32* min, Float32* max) +{ + UInt32 half = mFFTSize >> 1; + for (UInt32 i=0; i<mNumChannels; ++i) { + DSPSplitComplex &freqData = mSpectralBufferList->mDSPSplitComplex[i]; + + Float32* b = (Float32*) list->mBuffers[i].mData; + + vDSP_zvabs(&freqData,1,b,1,half); + + vDSP_maxmgv(b, 1, &max[i], half); + vDSP_minmgv(b, 1, &min[i], half); + + } +} + + +void CASpectralProcessor::GetFrequencies(Float32* freqs, Float32 sampleRate) +{ + UInt32 half = mFFTSize >> 1; + + for (UInt32 i=0; i< half; i++){ + freqs[i] = ((Float32)(i))*sampleRate/((Float32)mFFTSize); + } +} + + +bool CASpectralProcessor::ProcessForwards(UInt32 inNumFrames, AudioBufferList* inInput) +{ + // copy from buffer list to input buffer + CopyInput(inNumFrames, inInput); + + bool processed = false; + // if enough input to process, then process. + while (mInputSize >= mFFTSize) + { + CopyInputToFFT(); // copy from input buffer to fft buffer + DoWindowing(); + DoFwdFFT(); + ProcessSpectrum(mFFTSize, mSpectralBufferList()); // here you would copy the fft results out to a buffer indicated in mUserData, say for sonogram drawing + processed = true; + } + + return processed; +} + +bool CASpectralProcessor::ProcessBackwards(UInt32 inNumFrames, AudioBufferList* outOutput) +{ + + ProcessSpectrum(mFFTSize, mSpectralBufferList()); + DoInvFFT(); + DoWindowing(); + OverlapAddOutput(); + + // copy from output buffer to buffer list + CopyOutput(inNumFrames, outOutput); + + return true; +} + + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h new file mode 100644 index 0000000000..d7c285b6a9 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h @@ -0,0 +1,146 @@ +/* + File: CASpectralProcessor.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef _SpectralProcesor_H_ +#define _SpectralProcesor_H_ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) +#include <CoreAudio/CoreAudioTypes.h> +#include <CoreFoundation/CoreFoundation.h> +#else +#include <CoreAudioTypes.h> +#include <CoreFoundation.h> +#endif + +#include <Accelerate/Accelerate.h> + +#include "CAAutoDisposer.h" + +struct SpectralBufferList +{ + UInt32 mNumberSpectra; + DSPSplitComplex mDSPSplitComplex[1]; +}; + +class CASpectralProcessor +{ +public: + CASpectralProcessor(UInt32 inFFTSize, UInt32 inHopSize, UInt32 inNumChannels, UInt32 inMaxFrames); + virtual ~CASpectralProcessor(); + + void Reset(); + + void Process(UInt32 inNumFrames, AudioBufferList* inInput, AudioBufferList* outOutput); + + typedef void (*SpectralFunction)(SpectralBufferList* inSpectra, void* inUserData); + + void SetSpectralFunction(SpectralFunction inFunction, void* inUserData); + + UInt32 FFTSize() const { return mFFTSize; } + UInt32 MaxFrames() const { return mMaxFrames; } + UInt32 NumChannels() const { return mNumChannels; } + UInt32 HopSize() const { return mHopSize; } + Float32* Window() const { return mWindow; } + + + void HanningWindow(); // set up a hanning window + void SineWindow(); + + void GetFrequencies(Float32* freqs, Float32 sampleRate); // only for processed forward + void GetMagnitude(AudioBufferList* inCopy, Float32* min, Float32* max); // only for processed forward + + virtual bool ProcessForwards(UInt32 inNumFrames, AudioBufferList* inInput); + bool ProcessBackwards(UInt32 inNumFrames, AudioBufferList* outOutput); + + + void PrintSpectralBufferList(); + +protected: + void CopyInput(UInt32 inNumFrames, AudioBufferList* inInput); + void CopyInputToFFT(); + void DoWindowing(); + void DoFwdFFT(); + void DoInvFFT(); + void OverlapAddOutput(); + void CopyOutput(UInt32 inNumFrames, AudioBufferList* inOutput); + void ProcessSpectrum(UInt32 inFFTSize, SpectralBufferList* inSpectra); + + UInt32 mFFTSize; + UInt32 mHopSize; + UInt32 mNumChannels; + UInt32 mMaxFrames; + + UInt32 mLog2FFTSize; + UInt32 mFFTMask; + UInt32 mFFTByteSize; + UInt32 mIOBufSize; + UInt32 mIOMask; + UInt32 mInputSize; + UInt32 mInputPos; + UInt32 mOutputPos; + UInt32 mInFFTPos; + UInt32 mOutFFTPos; + FFTSetup mFFTSetup; + + CAAutoFree<Float32> mWindow; + struct SpectralChannel + { + CAAutoFree<Float32> mInputBuf; // log2ceil(FFT size + max frames) + CAAutoFree<Float32> mOutputBuf; // log2ceil(FFT size + max frames) + CAAutoFree<Float32> mFFTBuf; // FFT size + CAAutoFree<Float32> mSplitFFTBuf; // FFT size + }; + CAAutoArrayDelete<SpectralChannel> mChannels; + + CAAutoFree<SpectralBufferList> mSpectralBufferList; + + SpectralFunction mSpectralFunction; + void *mUserData; + +}; + + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp new file mode 100644 index 0000000000..d56947ab59 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp @@ -0,0 +1,879 @@ +/* + File: CAStreamBasicDescription.cpp + Abstract: CAStreamBasicDescription.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 "CAStreamBasicDescription.h" +#include "CAMath.h" + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreFoundation/CFByteOrder.h> +#else + #include <CFByteOrder.h> +#endif + +#pragma mark This file needs to compile on earlier versions of the OS, so please keep that in mind when editing it + +char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize) +{ + if (bufsize > 0) { + char *p = writeLocation, *pend = writeLocation + bufsize; + union { UInt32 i; unsigned char str[4]; } u; + unsigned char *q = u.str; + u.i = CFSwapInt32HostToBig(t); + + bool hasNonPrint = false; + for (int i = 0; i < 4; ++i) { + if (!(isprint(*q) && *q != '\\')) { + hasNonPrint = true; + break; + } + q++; + } + q = u.str; + + if (hasNonPrint) + p += snprintf (p, pend - p, "0x"); + else if (p < pend) + *p++ = '\''; + + for (int i = 0; i < 4 && p < pend; ++i) { + if (hasNonPrint) { + p += snprintf(p, pend - p, "%02X", *q++); + } else { + *p++ = *q++; + } + } + if (!hasNonPrint && p < pend) + *p++ = '\''; + if (p >= pend) p -= 1; + *p = '\0'; + } + return writeLocation; +} + + +const AudioStreamBasicDescription CAStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +CAStreamBasicDescription::CAStreamBasicDescription() +{ + memset (this, 0, sizeof(AudioStreamBasicDescription)); +} + +CAStreamBasicDescription::CAStreamBasicDescription(const AudioStreamBasicDescription &desc) +{ + SetFrom(desc); +} + + +CAStreamBasicDescription::CAStreamBasicDescription(double inSampleRate, UInt32 inFormatID, + UInt32 inBytesPerPacket, UInt32 inFramesPerPacket, + UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame, + UInt32 inBitsPerChannel, UInt32 inFormatFlags) +{ + mSampleRate = inSampleRate; + mFormatID = inFormatID; + mBytesPerPacket = inBytesPerPacket; + mFramesPerPacket = inFramesPerPacket; + mBytesPerFrame = inBytesPerFrame; + mChannelsPerFrame = inChannelsPerFrame; + mBitsPerChannel = inBitsPerChannel; + mFormatFlags = inFormatFlags; + mReserved = 0; +} + +char *CAStreamBasicDescription::AsString(char *buf, size_t _bufsize, bool brief /*=false*/) const +{ + int bufsize = (int)_bufsize; // must be signed to protect against overflow + char *theBuffer = buf; + int nc; + char formatID[24]; + CAStringForOSType(mFormatID, formatID, sizeof(formatID)); + if (brief) { + CommonPCMFormat com; + bool interleaved; + if (IdentifyCommonPCMFormat(com, &interleaved) && com != kPCMFormatOther) { + const char *desc; + switch (com) { + case kPCMFormatInt16: + desc = "Int16"; + break; + case kPCMFormatFixed824: + desc = "Int8.24"; + break; + case kPCMFormatFloat32: + desc = "Float32"; + break; + case kPCMFormatFloat64: + desc = "Float64"; + break; + default: + desc = NULL; + break; + } + if (desc) { + const char *inter =""; + if (mChannelsPerFrame > 1) + inter = !interleaved ? ", non-inter" : ", inter"; + snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s%s", (int)mChannelsPerFrame, mSampleRate, desc, inter); + return theBuffer; + } + } + if (mChannelsPerFrame == 0 && mSampleRate == 0.0 && mFormatID == 0) { + snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz", (int)mChannelsPerFrame, mSampleRate); + return theBuffer; + } + } + + nc = snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s (0x%08X) ", (int)NumberChannels(), mSampleRate, formatID, (int)mFormatFlags); + buf += nc; if ((bufsize -= nc) <= 0) goto exit; + if (mFormatID == kAudioFormatLinearPCM) { + bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat); + int wordSize = static_cast<int>(SampleWordSize()); + const char *endian = (wordSize > 1) ? + ((mFormatFlags & kLinearPCMFormatFlagIsBigEndian) ? " big-endian" : " little-endian" ) : ""; + const char *sign = isInt ? + ((mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) ? " signed" : " unsigned") : ""; + const char *floatInt = isInt ? "integer" : "float"; + char packed[32]; + if (wordSize > 0 && PackednessIsSignificant()) { + if (mFormatFlags & kLinearPCMFormatFlagIsPacked) + snprintf(packed, sizeof(packed), "packed in %d bytes", wordSize); + else + snprintf(packed, sizeof(packed), "unpacked in %d bytes", wordSize); + } else + packed[0] = '\0'; + const char *align = (wordSize > 0 && AlignmentIsSignificant()) ? + ((mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) ? " high-aligned" : " low-aligned") : ""; + const char *deinter = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? ", deinterleaved" : ""; + const char *commaSpace = (packed[0]!='\0') || (align[0]!='\0') ? ", " : ""; + char bitdepth[20]; + + int fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift; + if (fracbits > 0) + snprintf(bitdepth, sizeof(bitdepth), "%d.%d", (int)mBitsPerChannel - fracbits, fracbits); + else + snprintf(bitdepth, sizeof(bitdepth), "%d", (int)mBitsPerChannel); + + /*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%s-bit%s%s %s%s%s%s%s", + bitdepth, endian, sign, floatInt, + commaSpace, packed, align, deinter); + // buf += nc; if ((bufsize -= nc) <= 0) goto exit; + } else if (mFormatID == kAudioFormatAppleLossless) { + int sourceBits = 0; + switch (mFormatFlags) + { + case 1: // kAppleLosslessFormatFlag_16BitSourceData + sourceBits = 16; + break; + case 2: // kAppleLosslessFormatFlag_20BitSourceData + sourceBits = 20; + break; + case 3: // kAppleLosslessFormatFlag_24BitSourceData + sourceBits = 24; + break; + case 4: // kAppleLosslessFormatFlag_32BitSourceData + sourceBits = 32; + break; + } + if (sourceBits) + nc = snprintf(buf, static_cast<size_t>(bufsize), "from %d-bit source, ", sourceBits); + else + nc = snprintf(buf, static_cast<size_t>(bufsize), "from UNKNOWN source bit depth, "); + buf += nc; if ((bufsize -= nc) <= 0) goto exit; + /*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d frames/packet", (int)mFramesPerPacket); + // buf += nc; if ((bufsize -= nc) <= 0) goto exit; + } + else + /*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d bits/channel, %d bytes/packet, %d frames/packet, %d bytes/frame", + (int)mBitsPerChannel, (int)mBytesPerPacket, (int)mFramesPerPacket, (int)mBytesPerFrame); +exit: + return theBuffer; +} + +void CAStreamBasicDescription::NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription) +{ + // the only thing that changes is to make mixable linear PCM into the canonical linear PCM format + if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0)) + { + // the canonical linear PCM format + ioDescription.mFormatFlags = kAudioFormatFlagsCanonical; + ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame; + ioDescription.mFramesPerPacket = 1; + ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame; + ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType); + } +} + +void CAStreamBasicDescription::NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription) +{ + // the only thing that changes is to make mixable linear PCM into the canonical linear PCM format + if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0)) + { + // the canonical linear PCM format + ioDescription.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked; + if(inNativeEndian) + { +#if TARGET_RT_BIG_ENDIAN + ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian; +#endif + } + else + { +#if TARGET_RT_LITTLE_ENDIAN + ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian; +#endif + } + ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame; + ioDescription.mFramesPerPacket = 1; + ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame; + ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType); + } +} + +void CAStreamBasicDescription::ResetFormat(AudioStreamBasicDescription& ioDescription) +{ + ioDescription.mSampleRate = 0; + ioDescription.mFormatID = 0; + ioDescription.mBytesPerPacket = 0; + ioDescription.mFramesPerPacket = 0; + ioDescription.mBytesPerFrame = 0; + ioDescription.mChannelsPerFrame = 0; + ioDescription.mBitsPerChannel = 0; + ioDescription.mFormatFlags = 0; +} + +void CAStreamBasicDescription::FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription) +{ + if(fiszero(ioDescription.mSampleRate)) + { + ioDescription.mSampleRate = inTemplateDescription.mSampleRate; + } + if(ioDescription.mFormatID == 0) + { + ioDescription.mFormatID = inTemplateDescription.mFormatID; + } + if(ioDescription.mFormatFlags == 0) + { + ioDescription.mFormatFlags = inTemplateDescription.mFormatFlags; + } + if(ioDescription.mBytesPerPacket == 0) + { + ioDescription.mBytesPerPacket = inTemplateDescription.mBytesPerPacket; + } + if(ioDescription.mFramesPerPacket == 0) + { + ioDescription.mFramesPerPacket = inTemplateDescription.mFramesPerPacket; + } + if(ioDescription.mBytesPerFrame == 0) + { + ioDescription.mBytesPerFrame = inTemplateDescription.mBytesPerFrame; + } + if(ioDescription.mChannelsPerFrame == 0) + { + ioDescription.mChannelsPerFrame = inTemplateDescription.mChannelsPerFrame; + } + if(ioDescription.mBitsPerChannel == 0) + { + ioDescription.mBitsPerChannel = inTemplateDescription.mBitsPerChannel; + } +} + +void CAStreamBasicDescription::GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate) +{ + if(inIncludeSampleRate) + { + int theCharactersWritten = snprintf(outName, inMaxNameLength, "%.0f ", inDescription.mSampleRate); + outName += theCharactersWritten; + inMaxNameLength -= static_cast<UInt32>(theCharactersWritten); + } + + switch(inDescription.mFormatID) + { + case kAudioFormatLinearPCM: + { + const char* theEndianString = NULL; + if((inDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0) + { + #if TARGET_RT_LITTLE_ENDIAN + theEndianString = "Big Endian"; + #endif + } + else + { + #if TARGET_RT_BIG_ENDIAN + theEndianString = "Little Endian"; + #endif + } + + const char* theKindString = NULL; + if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0) + { + theKindString = (inAbbreviate ? "Float" : "Floating Point"); + } + else if((inDescription.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0) + { + theKindString = (inAbbreviate ? "SInt" : "Signed Integer"); + } + else + { + theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer"); + } + + const char* thePackingString = NULL; + if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0) + { + if((inDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0) + { + thePackingString = "High"; + } + else + { + thePackingString = "Low"; + } + } + + const char* theMixabilityString = NULL; + if((inDescription.mFormatFlags & kIsNonMixableFlag) == 0) + { + theMixabilityString = "Mixable"; + } + else + { + theMixabilityString = "Unmixable"; + } + + if(inAbbreviate) + { + if(theEndianString != NULL) + { + if(thePackingString != NULL) + { + snprintf(outName, inMaxNameLength, "%s %d Ch %s %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8); + } + else + { + snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel); + } + } + else + { + if(thePackingString != NULL) + { + snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)((inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8)); + } + else + { + snprintf(outName, inMaxNameLength, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel); + } + } + } + else + { + if(theEndianString != NULL) + { + if(thePackingString != NULL) + { + snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8); + } + else + { + snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString); + } + } + else + { + if(thePackingString != NULL) + { + snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8); + } + else + { + snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString); + } + } + } + } + break; + + case kAudioFormatAC3: + strlcpy(outName, "AC-3", sizeof(outName)); + break; + + case kAudioFormat60958AC3: + strlcpy(outName, "AC-3 for SPDIF", sizeof(outName)); + break; + + default: + CACopy4CCToCString(outName, inDescription.mFormatID); + break; + }; +} + +#if CoreAudio_Debug +#include "CALogMacros.h" + +void CAStreamBasicDescription::PrintToLog(const AudioStreamBasicDescription& inDesc) +{ + PrintFloat (" Sample Rate: ", inDesc.mSampleRate); + Print4CharCode (" Format ID: ", inDesc.mFormatID); + PrintHex (" Format Flags: ", inDesc.mFormatFlags); + PrintInt (" Bytes per Packet: ", inDesc.mBytesPerPacket); + PrintInt (" Frames per Packet: ", inDesc.mFramesPerPacket); + PrintInt (" Bytes per Frame: ", inDesc.mBytesPerFrame); + PrintInt (" Channels per Frame: ", inDesc.mChannelsPerFrame); + PrintInt (" Bits per Channel: ", inDesc.mBitsPerChannel); +} +#endif + +bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) +{ + bool theAnswer = false; + bool isDone = false; + + // note that if either side is 0, that field is skipped + + // format ID is the first order sort + if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0))) + { + if(x.mFormatID != y.mFormatID) + { + // formats are sorted numerically except that linear + // PCM is always first + if(x.mFormatID == kAudioFormatLinearPCM) + { + theAnswer = true; + } + else if(y.mFormatID == kAudioFormatLinearPCM) + { + theAnswer = false; + } + else + { + theAnswer = x.mFormatID < y.mFormatID; + } + isDone = true; + } + } + + + // mixable is always better than non-mixable for linear PCM and should be the second order sort item + if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM))) + { + if(((x.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormatFlags & kIsNonMixableFlag) != 0)) + { + theAnswer = true; + isDone = true; + } + else if(((x.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormatFlags & kIsNonMixableFlag) == 0)) + { + theAnswer = false; + isDone = true; + } + } + + // floating point vs integer for linear PCM only + if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM))) + { + if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat)) + { + // floating point is better than integer + theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat; + isDone = true; + } + } + + // bit depth + if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0))) + { + if(x.mBitsPerChannel != y.mBitsPerChannel) + { + // deeper bit depths are higher quality + theAnswer = x.mBitsPerChannel < y.mBitsPerChannel; + isDone = true; + } + } + + // sample rate + if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate)) + { + if(fnotequal(x.mSampleRate, y.mSampleRate)) + { + // higher sample rates are higher quality + theAnswer = x.mSampleRate < y.mSampleRate; + isDone = true; + } + } + + // number of channels + if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0))) + { + if(x.mChannelsPerFrame != y.mChannelsPerFrame) + { + // more channels is higher quality + theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame; + //isDone = true; + } + } + + return theAnswer; +} + +void CAStreamBasicDescription::ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly ) +{ + // match wildcards + if (x.mFormatID == 0 || y.mFormatID == 0 || xFlags == 0 || yFlags == 0) + { + // Obliterate all flags. + xFlags = yFlags = 0; + return; + } + + if (x.mFormatID == kAudioFormatLinearPCM) { + // knock off the all clear flag + xFlags = xFlags & ~kAudioFormatFlagsAreAllClear; + yFlags = yFlags & ~kAudioFormatFlagsAreAllClear; + + // if both kAudioFormatFlagIsPacked bits are set, then we don't care about the kAudioFormatFlagIsAlignedHigh bit. + if (xFlags & yFlags & kAudioFormatFlagIsPacked) { + xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh); + yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh); + } + + // if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit. + if (xFlags & yFlags & kAudioFormatFlagIsFloat) { + xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger); + yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger); + } + + // if the bit depth is 8 bits or less and the format is packed, we don't care about endianness + if((x.mBitsPerChannel <= 8) && ((xFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked)) + { + xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian); + } + if((y.mBitsPerChannel <= 8) && ((yFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked)) + { + yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian); + } + + // if the number of channels is 1, we don't care about non-interleavedness + if (x.mChannelsPerFrame == 1 && y.mChannelsPerFrame == 1) { + xFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved); + yFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved); + } + + if (converterOnly) { + CAStreamBasicDescription cas_x = CAStreamBasicDescription(x); + CAStreamBasicDescription cas_y = CAStreamBasicDescription(y); + if (!cas_x.PackednessIsSignificant() && !cas_y.PackednessIsSignificant()) { + xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked); + yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked); + } + if (!cas_x.AlignmentIsSignificant() && !cas_y.AlignmentIsSignificant()) { + xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh); + yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh); + } + // We don't care about whether the streams are mixable in this case + xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable); + yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable); + } + } +} + +static bool MatchFormatFlags(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) +{ + UInt32 xFlags = x.mFormatFlags; + UInt32 yFlags = y.mFormatFlags; + + CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, false); + return xFlags == yFlags; +} + +bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) +{ + // the semantics for equality are: + // 1) Values must match exactly -- except for PCM format flags, see above. + // 2) wildcard's are ignored in the comparison + +#define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name)) + + return + // check all but the format flags + CAStreamBasicDescription::FlagIndependentEquivalence(x, y) + // check the format flags + && MatchFormatFlags(x, y); +} + +bool CAStreamBasicDescription::FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y) +{ + return + // check the sample rate + (fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate)) + + // check the format ids + && MATCH(mFormatID) + + // check the bytes per packet + && MATCH(mBytesPerPacket) + + // check the frames per packet + && MATCH(mFramesPerPacket) + + // check the bytes per frame + && MATCH(mBytesPerFrame) + + // check the channels per frame + && MATCH(mChannelsPerFrame) + + // check the channels per frame + && MATCH(mBitsPerChannel) ; +} + +bool CAStreamBasicDescription::IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards) const +{ + if (interpretingWildcards) + return *this == other; + return memcmp(this, &other, offsetof(AudioStreamBasicDescription, mReserved)) == 0; +} + +bool CAStreamBasicDescription::IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y) +{ + UInt32 xFlags = x.mFormatFlags, yFlags = y.mFormatFlags; + CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, true); + + return + // check all but the format flags + CAStreamBasicDescription::FlagIndependentEquivalence(x, y) + // check the format flags with converter focus + && (xFlags == yFlags); + +} + +bool SanityCheck(const AudioStreamBasicDescription& x) +{ + // This function returns false if there are sufficiently insane values in any field. + // It is very conservative so even some very unlikely values will pass. + // This is just meant to catch the case where the data from a file is corrupted. + + return + (x.mSampleRate >= 0.) + && (x.mSampleRate < 3e6) // SACD sample rate is 2.8224 MHz + && (x.mBytesPerPacket < 1000000) + && (x.mFramesPerPacket < 1000000) + && (x.mBytesPerFrame < 1000000) + && (x.mChannelsPerFrame <= 1024) + && (x.mBitsPerChannel <= 1024) + && (x.mFormatID != 0) + && !(x.mFormatID == kAudioFormatLinearPCM && (x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame)); +} + +bool CAStreamBasicDescription::FromText(const char *inTextDesc, AudioStreamBasicDescription &fmt) +{ + const char *p = inTextDesc; + + memset(&fmt, 0, sizeof(fmt)); + + bool isPCM = true; // until proven otherwise + UInt32 pcmFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; + + if (p[0] == '-') // previously we required a leading dash on PCM formats + ++p; + + if (p[0] == 'B' && p[1] == 'E') { + pcmFlags |= kLinearPCMFormatFlagIsBigEndian; + p += 2; + } else if (p[0] == 'L' && p[1] == 'E') { + p += 2; + } else { + // default is native-endian +#if TARGET_RT_BIG_ENDIAN + pcmFlags |= kLinearPCMFormatFlagIsBigEndian; +#endif + } + if (p[0] == 'F') { + pcmFlags = (pcmFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger)) | kAudioFormatFlagIsFloat; + ++p; + } else { + if (p[0] == 'U') { + pcmFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger); + ++p; + } + if (p[0] == 'I') + ++p; + else { + // it's not PCM; presumably some other format (NOT VALIDATED; use AudioFormat for that) + isPCM = false; + p = inTextDesc; // go back to the beginning + char buf[4] = { ' ',' ',' ',' ' }; + for (int i = 0; i < 4; ++i) { + if (*p != '\\') { + if ((buf[i] = *p++) == '\0') { + // special-case for 'aac' + if (i != 3) return false; + --p; // keep pointing at the terminating null + buf[i] = ' '; + break; + } + } else { + // "\xNN" is a hex byte + if (*++p != 'x') return false; + int x; + if (sscanf(++p, "%02X", &x) != 1) return false; + buf[i] = static_cast<char>(x); + p += 2; + } + } + + if (strchr("-@/#", buf[3])) { + // further special-casing for 'aac' + buf[3] = ' '; + --p; + } + + memcpy(&fmt.mFormatID, buf, 4); + fmt.mFormatID = CFSwapInt32BigToHost(fmt.mFormatID); + } + } + + if (isPCM) { + fmt.mFormatID = kAudioFormatLinearPCM; + fmt.mFormatFlags = pcmFlags; + fmt.mFramesPerPacket = 1; + fmt.mChannelsPerFrame = 1; + UInt32 bitdepth = 0, fracbits = 0; + while (isdigit(*p)) + bitdepth = 10 * bitdepth + static_cast<UInt32>(*p++ - '0'); + if (*p == '.') { + ++p; + if (!isdigit(*p)) { + fprintf(stderr, "Expected fractional bits following '.'\n"); + goto Bail; + } + while (isdigit(*p)) + fracbits = 10 * fracbits + static_cast<UInt32>(*p++ - '0'); + bitdepth += fracbits; + fmt.mFormatFlags |= (fracbits << kLinearPCMFormatFlagsSampleFractionShift); + } + fmt.mBitsPerChannel = bitdepth; + fmt.mBytesPerPacket = fmt.mBytesPerFrame = (bitdepth + 7) / 8; + if (bitdepth & 7) { + // assume unpacked. (packed odd bit depths are describable but not supported in AudioConverter.) + fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked); + // alignment matters; default to high-aligned. use ':L_' for low. + fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh; + } + } + if (*p == '@') { + ++p; + while (isdigit(*p)) + fmt.mSampleRate = 10 * fmt.mSampleRate + (*p++ - '0'); + } + if (*p == '/') { + UInt32 flags = 0; + while (true) { + char c = *++p; + if (c >= '0' && c <= '9') + flags = (flags << 4) | static_cast<UInt32>(c - '0'); + else if (c >= 'A' && c <= 'F') + flags = (flags << 4) | static_cast<UInt32>(c - 'A' + 10); + else if (c >= 'a' && c <= 'f') + flags = (flags << 4) | static_cast<UInt32>(c - 'a' + 10); + else break; + } + fmt.mFormatFlags = flags; + } + if (*p == '#') { + ++p; + while (isdigit(*p)) + fmt.mFramesPerPacket = 10 * fmt.mFramesPerPacket + static_cast<UInt32>(*p++ - '0'); + } + if (*p == ':') { + ++p; + fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked); + if (*p == 'L') + fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsAlignedHigh); + else if (*p == 'H') + fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh; + else + goto Bail; + ++p; + UInt32 bytesPerFrame = 0; + while (isdigit(*p)) + bytesPerFrame = 10 * bytesPerFrame + static_cast<UInt32>(*p++ - '0'); + fmt.mBytesPerFrame = fmt.mBytesPerPacket = bytesPerFrame; + } + if (*p == ',') { + ++p; + int ch = 0; + while (isdigit(*p)) + ch = 10 * ch + (*p++ - '0'); + fmt.mChannelsPerFrame = static_cast<UInt32>(ch); + if (*p == 'D') { + ++p; + if (fmt.mFormatID != kAudioFormatLinearPCM) { + fprintf(stderr, "non-interleaved flag invalid for non-PCM formats\n"); + goto Bail; + } + fmt.mFormatFlags |= kAudioFormatFlagIsNonInterleaved; + } else { + if (*p == 'I') ++p; // default + if (fmt.mFormatID == kAudioFormatLinearPCM) + fmt.mBytesPerPacket = fmt.mBytesPerFrame *= static_cast<UInt32>(ch); + } + } + if (*p != '\0') { + fprintf(stderr, "extra characters at end of format string: %s\n", p); + goto Bail; + } + return true; + +Bail: + fprintf(stderr, "Invalid format string: %s\n", inTextDesc); + fprintf(stderr, "Syntax of format strings is: \n"); + return false; +} + +const char *CAStreamBasicDescription::sTextParsingUsageString = + "format[@sample_rate_hz][/format_flags][#frames_per_packet][:LHbytesPerFrame][,channelsDI].\n" + "Format for PCM is [-][BE|LE]{F|I|UI}{bitdepth}; else a 4-char format code (e.g. aac, alac).\n"; diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h new file mode 100644 index 0000000000..8b81dba69a --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h @@ -0,0 +1,424 @@ +/* + File: CAStreamBasicDescription.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAStreamBasicDescription_h__ +#define __CAStreamBasicDescription_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> + #include <CoreFoundation/CoreFoundation.h> +#else + #include "CoreAudioTypes.h" + #include "CoreFoundation.h" +#endif + +#include "CADebugMacros.h" +#include <string.h> // for memset, memcpy +#include <stdio.h> // for FILE * + +#pragma mark This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it + +extern char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize); + +// define Leopard specific symbols for backward compatibility if applicable +#if COREAUDIOTYPES_VERSION < 1050 +typedef Float32 AudioSampleType; +enum { kAudioFormatFlagsCanonical = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked }; +#endif +#if COREAUDIOTYPES_VERSION < 1051 +typedef Float32 AudioUnitSampleType; +enum { + kLinearPCMFormatFlagsSampleFractionShift = 7, + kLinearPCMFormatFlagsSampleFractionMask = (0x3F << kLinearPCMFormatFlagsSampleFractionShift), +}; +#endif + +// define the IsMixable format flag for all versions of the system +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3) + enum { kIsNonMixableFlag = kAudioFormatFlagIsNonMixable }; +#else + enum { kIsNonMixableFlag = (1L << 6) }; +#endif + +//============================================================================= +// CAStreamBasicDescription +// +// This is a wrapper class for the AudioStreamBasicDescription struct. +// It adds a number of convenience routines, but otherwise adds nothing +// to the footprint of the original struct. +//============================================================================= +class CAStreamBasicDescription : + public AudioStreamBasicDescription +{ + +// Constants +public: + static const AudioStreamBasicDescription sEmpty; + + enum CommonPCMFormat { + kPCMFormatOther = 0, + kPCMFormatFloat32 = 1, + kPCMFormatInt16 = 2, + kPCMFormatFixed824 = 3, + kPCMFormatFloat64 = 4 + }; + +// Construction/Destruction +public: + CAStreamBasicDescription(); + + CAStreamBasicDescription(const AudioStreamBasicDescription &desc); + + CAStreamBasicDescription( double inSampleRate, UInt32 inFormatID, + UInt32 inBytesPerPacket, UInt32 inFramesPerPacket, + UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame, + UInt32 inBitsPerChannel, UInt32 inFormatFlags); + + CAStreamBasicDescription( double inSampleRate, UInt32 inNumChannels, CommonPCMFormat pcmf, bool inIsInterleaved) { + unsigned wordsize; + + mSampleRate = inSampleRate; + mFormatID = kAudioFormatLinearPCM; + mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; + mFramesPerPacket = 1; + mChannelsPerFrame = inNumChannels; + mBytesPerFrame = mBytesPerPacket = 0; + mReserved = 0; + + switch (pcmf) { + default: + return; + case kPCMFormatFloat32: + wordsize = 4; + mFormatFlags |= kAudioFormatFlagIsFloat; + break; + case kPCMFormatFloat64: + wordsize = 8; + mFormatFlags |= kAudioFormatFlagIsFloat; + break; + case kPCMFormatInt16: + wordsize = 2; + mFormatFlags |= kAudioFormatFlagIsSignedInteger; + break; + case kPCMFormatFixed824: + wordsize = 4; + mFormatFlags |= kAudioFormatFlagIsSignedInteger | (24 << kLinearPCMFormatFlagsSampleFractionShift); + break; + } + mBitsPerChannel = wordsize * 8; + if (inIsInterleaved) + mBytesPerFrame = mBytesPerPacket = wordsize * inNumChannels; + else { + mFormatFlags |= kAudioFormatFlagIsNonInterleaved; + mBytesPerFrame = mBytesPerPacket = wordsize; + } + } + +// Assignment + CAStreamBasicDescription& operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; } + + void SetFrom(const AudioStreamBasicDescription &desc) + { + memcpy(this, &desc, sizeof(AudioStreamBasicDescription)); + } + + bool FromText(const char *inTextDesc) { return FromText(inTextDesc, *this); } + static bool FromText(const char *inTextDesc, AudioStreamBasicDescription &outDesc); + // return true if parsing was successful + + static const char *sTextParsingUsageString; + + // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + // + // interrogation + + bool IsPCM() const { return mFormatID == kAudioFormatLinearPCM; } + + bool PackednessIsSignificant() const + { + Assert(IsPCM(), "PackednessIsSignificant only applies for PCM"); + return (SampleWordSize() << 3) != mBitsPerChannel; + } + + bool AlignmentIsSignificant() const + { + return PackednessIsSignificant() || (mBitsPerChannel & 7) != 0; + } + + bool IsInterleaved() const + { + return !(mFormatFlags & kAudioFormatFlagIsNonInterleaved); + } + + bool IsSignedInteger() const + { + return IsPCM() && (mFormatFlags & kAudioFormatFlagIsSignedInteger); + } + + bool IsFloat() const + { + return IsPCM() && (mFormatFlags & kAudioFormatFlagIsFloat); + } + + bool IsNativeEndian() const + { + return (mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian; + } + + // for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these: + UInt32 NumberInterleavedChannels() const { return IsInterleaved() ? mChannelsPerFrame : 1; } + UInt32 NumberChannelStreams() const { return IsInterleaved() ? 1 : mChannelsPerFrame; } + UInt32 NumberChannels() const { return mChannelsPerFrame; } + UInt32 SampleWordSize() const { + return (mBytesPerFrame > 0 && NumberInterleavedChannels()) ? mBytesPerFrame / NumberInterleavedChannels() : 0; + } + + UInt32 FramesToBytes(UInt32 nframes) const { return nframes * mBytesPerFrame; } + UInt32 BytesToFrames(UInt32 nbytes) const { + Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames"); + return nbytes / mBytesPerFrame; + } + + bool SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const + { + return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved(); + } + + bool IdentifyCommonPCMFormat(CommonPCMFormat &outFormat, bool *outIsInterleaved=NULL) const + { // return true if it's a valid PCM format. + + outFormat = kPCMFormatOther; + // trap out patently invalid formats. + if (mFormatID != kAudioFormatLinearPCM || mFramesPerPacket != 1 || mBytesPerFrame != mBytesPerPacket || mBitsPerChannel/8 > mBytesPerFrame || mChannelsPerFrame == 0) + return false; + bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0; + if (outIsInterleaved != NULL) *outIsInterleaved = interleaved; + unsigned wordsize = mBytesPerFrame; + if (interleaved) { + if (wordsize % mChannelsPerFrame != 0) return false; + wordsize /= mChannelsPerFrame; + } + + if ((mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian + && wordsize * 8 == mBitsPerChannel) { + // packed and native endian, good + if (mFormatFlags & kLinearPCMFormatFlagIsFloat) { + // float: reject nonsense bits + if (mFormatFlags & (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagsSampleFractionMask)) + return false; + if (wordsize == 4) + outFormat = kPCMFormatFloat32; + if (wordsize == 8) + outFormat = kPCMFormatFloat64; + } else if (mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) { + // signed int + unsigned fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift; + if (wordsize == 4 && fracbits == 24) + outFormat = kPCMFormatFixed824; + else if (wordsize == 2 && fracbits == 0) + outFormat = kPCMFormatInt16; + } + } + return true; + } + + bool IsCommonFloat32(bool *outIsInterleaved=NULL) const { + CommonPCMFormat fmt; + return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat32; + } + bool IsCommonFloat64(bool *outIsInterleaved=NULL) const { + CommonPCMFormat fmt; + return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat64; + } + bool IsCommonFixed824(bool *outIsInterleaved=NULL) const { + CommonPCMFormat fmt; + return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFixed824; + } + bool IsCommonInt16(bool *outIsInterleaved=NULL) const { + CommonPCMFormat fmt; + return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatInt16; + } + + // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + // + // manipulation + + void SetCanonical(UInt32 nChannels, bool interleaved) + // note: leaves sample rate untouched + { + mFormatID = kAudioFormatLinearPCM; + UInt32 sampleSize = SizeOf32(AudioSampleType); + mFormatFlags = kAudioFormatFlagsCanonical; + mBitsPerChannel = 8 * sampleSize; + mChannelsPerFrame = nChannels; + mFramesPerPacket = 1; + if (interleaved) + mBytesPerPacket = mBytesPerFrame = nChannels * sampleSize; + else { + mBytesPerPacket = mBytesPerFrame = sampleSize; + mFormatFlags |= kAudioFormatFlagIsNonInterleaved; + } + } + + bool IsCanonical() const + { + if (mFormatID != kAudioFormatLinearPCM) return false; + UInt32 reqFormatFlags; + UInt32 flagsMask = (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagsSampleFractionMask); + bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0; + unsigned sampleSize = SizeOf32(AudioSampleType); + reqFormatFlags = kAudioFormatFlagsCanonical; + UInt32 reqFrameSize = interleaved ? (mChannelsPerFrame * sampleSize) : sampleSize; + + return ((mFormatFlags & flagsMask) == reqFormatFlags + && mBitsPerChannel == 8 * sampleSize + && mFramesPerPacket == 1 + && mBytesPerFrame == reqFrameSize + && mBytesPerPacket == reqFrameSize); + } + + void SetAUCanonical(UInt32 nChannels, bool interleaved) + { + mFormatID = kAudioFormatLinearPCM; +#if CA_PREFER_FIXED_POINT + mFormatFlags = kAudioFormatFlagsCanonical | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift); +#else + mFormatFlags = kAudioFormatFlagsCanonical; +#endif + mChannelsPerFrame = nChannels; + mFramesPerPacket = 1; + mBitsPerChannel = 8 * SizeOf32(AudioUnitSampleType); + if (interleaved) + mBytesPerPacket = mBytesPerFrame = nChannels * SizeOf32(AudioUnitSampleType); + else { + mBytesPerPacket = mBytesPerFrame = SizeOf32(AudioUnitSampleType); + mFormatFlags |= kAudioFormatFlagIsNonInterleaved; + } + } + + void ChangeNumberChannels(UInt32 nChannels, bool interleaved) + // alter an existing format + { + Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats"); + UInt32 wordSize = SampleWordSize(); // get this before changing ANYTHING + if (wordSize == 0) + wordSize = (mBitsPerChannel + 7) / 8; + mChannelsPerFrame = nChannels; + mFramesPerPacket = 1; + if (interleaved) { + mBytesPerPacket = mBytesPerFrame = nChannels * wordSize; + mFormatFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonInterleaved); + } else { + mBytesPerPacket = mBytesPerFrame = wordSize; + mFormatFlags |= kAudioFormatFlagIsNonInterleaved; + } + } + + // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + // + // other + + bool IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards=true) const; + static bool FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y); + static bool IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y); + + void Print() const { + Print (stdout); + } + + void Print(FILE* file) const { + PrintFormat (file, "", "AudioStreamBasicDescription:"); + } + + void PrintFormat(FILE *f, const char *indent, const char *name) const { + char buf[256]; + fprintf(f, "%s%s %s\n", indent, name, AsString(buf, sizeof(buf))); + } + + void PrintFormat2(FILE *f, const char *indent, const char *name) const { // no trailing newline + char buf[256]; + fprintf(f, "%s%s %s", indent, name, AsString(buf, sizeof(buf))); + } + + char * AsString(char *buf, size_t bufsize, bool brief=false) const; + + static void Print (const AudioStreamBasicDescription &inDesc) + { + CAStreamBasicDescription desc(inDesc); + desc.Print (); + } + + OSStatus Save(CFPropertyListRef *outData) const; + + OSStatus Restore(CFPropertyListRef &inData); + +// Operations + static bool IsMixable(const AudioStreamBasicDescription& inDescription) { return (inDescription.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormatFlags & kIsNonMixableFlag) == 0); } + static void NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription); + static void NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription); + static void ResetFormat(AudioStreamBasicDescription& ioDescription); + static void FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription); + static void GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate = false); + static void ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly); + +#if CoreAudio_Debug + static void PrintToLog(const AudioStreamBasicDescription& inDesc); +#endif +}; + +bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y); +bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y); +#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600)) +inline bool operator!=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); } +inline bool operator<=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); } +inline bool operator>=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); } +inline bool operator>(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); } +#endif + +bool SanityCheck(const AudioStreamBasicDescription& x); + + +#endif // __CAStreamBasicDescription_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp new file mode 100644 index 0000000000..9b72054101 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp @@ -0,0 +1,183 @@ +/* + File: CAStreamRangedDescription.cpp + Abstract: CAStreamRangedDescription.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. + +*/ +//================================================================================================== +// Includes +//================================================================================================== + +// Self Include +#include "CAStreamRangedDescription.h" +#include "CAMath.h" + +//================================================================================================== +// CAStreamRangedDescription +//================================================================================================== + +const AudioStreamRangedDescription CAStreamRangedDescription::sEmpty = { { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.0, 0.0 } }; + +#if CoreAudio_Debug +#include "CALogMacros.h" + +void CAStreamRangedDescription::PrintToLog(const AudioStreamRangedDescription& inDesc) +{ + PrintFloat (" Sample Rate: ", inDesc.mFormat.mSampleRate); + PrintFloat (" Max Sample Rate: ", inDesc.mSampleRateRange.mMaximum); + PrintFloat (" Min Sample Rate: ", inDesc.mSampleRateRange.mMinimum); + Print4CharCode (" Format ID: ", inDesc.mFormat.mFormatID); + PrintHex (" Format Flags: ", inDesc.mFormat.mFormatFlags); + PrintInt (" Bytes per Packet: ", inDesc.mFormat.mBytesPerPacket); + PrintInt (" Frames per Packet: ", inDesc.mFormat.mFramesPerPacket); + PrintInt (" Bytes per Frame: ", inDesc.mFormat.mBytesPerFrame); + PrintInt (" Channels per Frame: ", inDesc.mFormat.mChannelsPerFrame); + PrintInt (" Bits per Channel: ", inDesc.mFormat.mBitsPerChannel); +} +#endif + +bool CAStreamRangedDescription::Sorter(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) +{ + bool theAnswer = false; + bool isDone = false; + + // note that if either side is 0, that field is skipped + + // format ID is the first order sort + if((!isDone) && ((x.mFormat.mFormatID != 0) && (y.mFormat.mFormatID != 0))) + { + if(x.mFormat.mFormatID != y.mFormat.mFormatID) + { + // formats are sorted numerically except that linear + // PCM is always first + if(x.mFormat.mFormatID == kAudioFormatLinearPCM) + { + theAnswer = true; + } + else if(y.mFormat.mFormatID == kAudioFormatLinearPCM) + { + theAnswer = false; + } + else + { + theAnswer = x.mFormat.mFormatID < y.mFormat.mFormatID; + } + isDone = true; + } + } + + + // mixable is always better than non-mixable for linear PCM and should be the second order sort item + if((!isDone) && ((x.mFormat.mFormatID == kAudioFormatLinearPCM) && (y.mFormat.mFormatID == kAudioFormatLinearPCM))) + { + if(((x.mFormat.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormat.mFormatFlags & kIsNonMixableFlag) != 0)) + { + theAnswer = true; + isDone = true; + } + else if(((x.mFormat.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormat.mFormatFlags & kIsNonMixableFlag) == 0)) + { + theAnswer = false; + isDone = true; + } + } + + // floating point vs integer for linear PCM only + if((!isDone) && ((x.mFormat.mFormatID == kAudioFormatLinearPCM) && (y.mFormat.mFormatID == kAudioFormatLinearPCM))) + { + if((x.mFormat.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormat.mFormatFlags & kAudioFormatFlagIsFloat)) + { + // floating point is better than integer + theAnswer = y.mFormat.mFormatFlags & kAudioFormatFlagIsFloat; + isDone = true; + } + } + + // bit depth + if((!isDone) && ((x.mFormat.mBitsPerChannel != 0) && (y.mFormat.mBitsPerChannel != 0))) + { + if(x.mFormat.mBitsPerChannel != y.mFormat.mBitsPerChannel) + { + // deeper bit depths are higher quality + theAnswer = x.mFormat.mBitsPerChannel > y.mFormat.mBitsPerChannel; + isDone = true; + } + } + + // sample rate range + if((!isDone) && fnonzero(x.mSampleRateRange.mMinimum) && fnonzero(x.mSampleRateRange.mMaximum) && fnonzero(y.mSampleRateRange.mMinimum) && fnonzero(y.mSampleRateRange.mMaximum)) + { + if(x.mSampleRateRange != y.mSampleRateRange) + { + // higher sample rates are higher quality + theAnswer = x.mSampleRateRange > y.mSampleRateRange; + isDone = true; + } + } + + // sample rate + if((!isDone) && fnonzero(x.mFormat.mSampleRate) && fnonzero(y.mFormat.mSampleRate)) + { + if(fnotequal(x.mFormat.mSampleRate, y.mFormat.mSampleRate)) + { + // higher sample rates are higher quality + theAnswer = x.mFormat.mSampleRate > y.mFormat.mSampleRate; + isDone = true; + } + } + + // number of channels + if((!isDone) && ((x.mFormat.mChannelsPerFrame != 0) && (y.mFormat.mChannelsPerFrame != 0))) + { + if(x.mFormat.mChannelsPerFrame != y.mFormat.mChannelsPerFrame) + { + // more channels is higher quality + theAnswer = x.mFormat.mChannelsPerFrame < y.mFormat.mChannelsPerFrame; + // commented out to prevent this from being flagged as a dead store by the static analyzer + //isDone = true; + } + } + + return theAnswer; +} + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h new file mode 100644 index 0000000000..7f8284dee0 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h @@ -0,0 +1,140 @@ +/* + File: CAStreamRangedDescription.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAStreamRangedDescription_h__) +#define __CAStreamRangedDescription_h__ + +//================================================================================================== +// Includes +//================================================================================================== + +// Super Class Includes +#include <CoreAudio/AudioHardware.h> + +// PublicUtility Includes +#include "CAAudioValueRange.h" +#include "CAStreamBasicDescription.h" + +//================================================================================================== +// CAStreamRangedDescription +//================================================================================================== + +class CAStreamRangedDescription +: + public AudioStreamRangedDescription +{ + +// Constants +public: + static const AudioStreamRangedDescription sEmpty; + +// Construction/Destruction +public: + CAStreamRangedDescription() { memset(this, 0, sizeof(AudioStreamRangedDescription)); } + CAStreamRangedDescription(const CAStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; } + CAStreamRangedDescription(const AudioStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; } + CAStreamRangedDescription(const AudioStreamBasicDescription& inFormat) { mFormat = inFormat; mSampleRateRange.mMinimum = inFormat.mSampleRate; mSampleRateRange.mMaximum = inFormat.mSampleRate; } + CAStreamRangedDescription(const AudioStreamBasicDescription& inFormat, const AudioValueRange& inSampleRateRange) { mFormat = inFormat; mSampleRateRange = inSampleRateRange; } + CAStreamRangedDescription& operator=(const CAStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; return *this; } + CAStreamRangedDescription& operator=(const AudioStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; return *this; } + + static bool IsMixable(const AudioStreamRangedDescription& inDescription) { return (inDescription.mFormat.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormat.mFormatFlags & kIsNonMixableFlag) == 0); } +#if CoreAudio_Debug + static void PrintToLog(const AudioStreamRangedDescription& inDesc); +#endif + static bool Sorter(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y); + +}; + +inline bool operator<(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return (x.mFormat.mFormatID == y.mFormat.mFormatID) ? + (x.mFormat < y.mFormat) && (x.mSampleRateRange < y.mSampleRateRange) : + (x.mFormat.mFormatID == kAudioFormatLinearPCM) ? false : (x.mFormat.mFormatID < y.mFormat.mFormatID); } +inline bool operator==(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return (x.mFormat == y.mFormat) && (x.mSampleRateRange == y.mSampleRateRange); } +#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600)) +inline bool operator!=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return !(x == y); } +inline bool operator<=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return (x < y) || (x == y); } +inline bool operator>=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return !(x < y); } +inline bool operator>(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return !((x < y) || (x == y)); } +#endif + +inline bool operator<(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return (x.mFormatID == y.mFormat.mFormatID) ? + (x < y.mFormat) && (x.mSampleRate < y.mSampleRateRange.mMinimum) : + (x.mFormatID == kAudioFormatLinearPCM) ? false : (x.mFormatID < y.mFormat.mFormatID); } +inline bool operator<(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return (x.mFormat.mFormatID == y.mFormatID) ? + (x.mFormat < y) && (x.mSampleRateRange.mMinimum < y.mSampleRate) : + (x.mFormat.mFormatID == kAudioFormatLinearPCM) ? false : (x.mFormat.mFormatID < y.mFormatID); } +inline bool operator==(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return (x == y.mFormat) && CAAudioValueRange::ContainsValue(y.mSampleRateRange, x.mSampleRate); } +inline bool operator==(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return (x.mFormat == y) && CAAudioValueRange::ContainsValue(x.mSampleRateRange, y.mSampleRate); } +#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600)) +inline bool operator!=(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return !(x == y); } +inline bool operator!=(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); } +inline bool operator<=(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return (x < y) || (x == y); } +inline bool operator<=(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); } +inline bool operator>=(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return !(x < y); } +inline bool operator>=(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); } +inline bool operator>(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return !((x < y) || (x == y)); } +inline bool operator>(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); } +#endif + +// STL Functors +struct CAStreamRangedDescription_EqualToASBD +: + public std::unary_function<AudioStreamRangedDescription, bool> +{ + CAStreamRangedDescription_EqualToASBD(const AudioStreamBasicDescription& inFormat) : mFormat(inFormat) {} + bool operator()(const AudioStreamRangedDescription& x) const { return mFormat == x; } + + AudioStreamBasicDescription mFormat; +}; + +struct CAStreamRangedDescription_ReverseSort +: + public std::binary_function<AudioStreamRangedDescription, AudioStreamRangedDescription, bool> +{ + bool operator()(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) const { return CAStreamRangedDescription::Sorter(x, y); } +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h b/libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h new file mode 100644 index 0000000000..d0b7391476 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h @@ -0,0 +1,233 @@ +/* + File: CAThreadSafeList.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAThreadSafeList_h__ +#define __CAThreadSafeList_h__ + +#include "CAAtomicStack.h" + +// linked list of T's +// T must define operator == +template <class T> +class TThreadSafeList { +private: + enum EEventType { kAdd, kRemove, kClear }; + class Node { + public: + Node * mNext; + EEventType mEventType; + T mObject; + + Node *& next() { return mNext; } + }; + +public: + class iterator { + public: + iterator() { } + iterator(Node *n) : mNode(n) { } + + bool operator == (const iterator &other) const { return this->mNode == other.mNode; } + bool operator != (const iterator &other) const { return this->mNode != other.mNode; } + + T & operator * () const { return mNode->mObject; } + + iterator & operator ++ () { mNode = mNode->next(); return *this; } // preincrement + iterator operator ++ (int) { iterator tmp = *this; mNode = mNode->next(); return tmp; } // postincrement + + private: + Node * mNode; + }; + + TThreadSafeList() { } + ~TThreadSafeList() + { + mActiveList.free_all(); + mPendingList.free_all(); + mFreeList.free_all(); + } + + // These may be called on any thread + + void deferred_add(const T &obj) // can be called on any thread + { + Node *node = AllocNode(); + node->mEventType = kAdd; + node->mObject = obj; + mPendingList.push_atomic(node); + //mPendingList.dump("pending after add"); + } + + void deferred_remove(const T &obj) // can be called on any thread + { + Node *node = AllocNode(); + node->mEventType = kRemove; + node->mObject = obj; + mPendingList.push_atomic(node); + //mPendingList.dump("pending after remove"); + } + + void deferred_clear() // can be called on any thread + { + Node *node = AllocNode(); + node->mEventType = kClear; + mPendingList.push_atomic(node); + } + + // These must be called from only one thread + + void update() // must only be called from one thread + { + NodeStack reversed; + Node *event, *node, *next; + bool workDone = false; + + // reverse the events so they are in order + event = mPendingList.pop_all(); + while (event != NULL) { + next = event->mNext; + reversed.push_NA(event); + event = next; + workDone = true; + } + if (workDone) { + //reversed.dump("pending popped"); + //mActiveList.dump("active before update"); + + // now process them + while ((event = reversed.pop_NA()) != NULL) { + switch (event->mEventType) { + case kAdd: + { + Node **pnode; + bool needToInsert = true; + for (pnode = mActiveList.phead(); *pnode != NULL; pnode = &node->mNext) { + node = *pnode; + if (node->mObject == event->mObject) { + //printf("already active!!!\n"); + FreeNode(event); + needToInsert = false; + break; + } + } + if (needToInsert) { + // link the new event in at the end of the active list + *pnode = event; + event->mNext = NULL; + } + } + break; + case kRemove: + // find matching node in the active list, remove it + for (Node **pnode = mActiveList.phead(); *pnode != NULL; ) { + node = *pnode; + if (node->mObject == event->mObject) { + *pnode = node->mNext; // remove from linked list + FreeNode(node); + break; + } + pnode = &node->mNext; + } + // dispose the request node + FreeNode(event); + break; + case kClear: + for (node = mActiveList.head(); node != NULL; ) { + next = node->mNext; + FreeNode(node); + node = next; + } + FreeNode(event); + break; + default: + //printf("invalid node type %d!\n", event->mEventType); + break; + } + } + //mActiveList.dump("active after update"); + } + } + + iterator begin() const { + //mActiveList.dump("active at begin"); + return iterator(mActiveList.head()); + } + iterator end() const { return iterator(NULL); } + + +private: + Node * AllocNode() + { + Node *node = mFreeList.pop_atomic(); + if (node == NULL) + node = (Node *)CA_malloc(sizeof(Node)); + return node; + } + + void FreeNode(Node *node) + { + mFreeList.push_atomic(node); + } + +private: + class NodeStack : public TAtomicStack<Node> { + public: + void free_all() { + Node *node; + while ((node = this->pop_NA()) != NULL) + free(node); + } + + Node ** phead() { return &this->mHead; } + Node * head() const { return this->mHead; } + }; + + NodeStack mActiveList; // what's actually in the container - only accessed on one thread + NodeStack mPendingList; // add or remove requests - threadsafe + NodeStack mFreeList; // free nodes for reuse - threadsafe +}; + +#endif // __CAThreadSafeList_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CATink.h b/libs/appleutility/CoreAudio/PublicUtility/CATink.h new file mode 100644 index 0000000000..f0829359a6 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CATink.h @@ -0,0 +1,146 @@ +/* + File: CATink.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CATink_h__) +#define __CATink_h__ + +//============================================================================= +// Includes +//============================================================================= + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreServices/CoreServices.h> +#else + #include <CoreServices.h> +#endif + + +//============================================================================= +// CATink +// +// A Tink is a small jump island that can make one function appear as if it +// has many addresses. Note that Tinks are not supported for 64 bit environments +// as the APIs that made tinks useful have been replaced by APIs that do away +// with all the reasons for using a tink. +//============================================================================= + +template <class F> +class CATink +{ + +public: + CATink(F proc) { Set(proc); } + + ~CATink() { Set((F)0xDEADDEAD); } // jump to an obviously bad (odd) address if accessed after destruction + +#if TARGET_CPU_PPC + void Set(F proc) + { + /* + lis r11,0x1234 + 00000000: 3D601234 lis r11,4660 + ori r11,r11,0x5678 + 00000004: 616B5678 ori r11,r11,$5678 + mtctr r11 + 00000008: 7D6903A6 mtctr r11 + bctr + 0000000C: 4E800420 bctr + */ + UInt32 p = UInt32(proc); + mCode[0] = 0x3D600000 | (p >> 16); + mCode[1] = 0x616B0000 | (p & 0xFFFF); + mCode[2] = 0x7D6903A6; + mCode[3] = 0x4E800420; + MakeDataExecutable(mCode, sizeof(mCode)); + } + + operator F () { return F(mCode); } + +private: + UInt32 mCode[4]; +#elif TARGET_CPU_X86 + void Set(F proc) + { + /* + <tink>: push $0x12345678 + <tink+5>: ret + <tink>: 0x34567868 + <tink+4>: 0x00e8c312 + */ + UInt32 p = UInt32(proc); + mCode[0] = ((p & 0xFFFFFF) << 8) | 0x00000068; + mCode[1] = 0xCCCCC300 | (p >> 24); + MakeDataExecutable(mCode, sizeof(mCode)); + } + + operator F () { return F(&mCode[0]); } + +private: + UInt32 mCode[2]; +#else + #warning: CPU not directly supported by CATink + + // For other CPU's, just wrap the function pointer for now. + // this bypasses what we're trying to accomplish with the Tink + // (multiple unique "instances" of a function), but it will at + // least compile and run. + + void Set(F proc) { mProcPtr = proc; } + + operator F () { return mProcPtr; } +private: + F mProcPtr; +#endif + +// Tinks cannot be allocated in STL Containers, so we make a few key methods private +private: + CATink(){} + CATink(const CATink&){} + CATink& operator=(const CATink&){ return *this;} +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h b/libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h new file mode 100644 index 0000000000..f85f393022 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h @@ -0,0 +1,212 @@ +/* + File: CATokenMap.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CATokenMap_h__) +#define __CATokenMap_h__ + +//============================================================================= +// Includes +//============================================================================= + +// System Includes +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif + +// PublicUtility Includes +#include "CAMutex.h" + +// Standard Library Includes +#include <map> +#include <iterator> + +//============================================================================= +// CATokenMap +//============================================================================= + +template <class T> +class CATokenMap +{ + +// Types +private: + typedef std::map<UInt32, T*> TokenMap; + +// Construction/Destruction +public: + CATokenMap() : mTokenMap(), mNextToken(256), mTokenMapMutex("CATokenMap Mutex") {} + ~CATokenMap() {} + +// Operations +public: + bool Lock() + { + return mTokenMapMutex.Lock(); + } + + void Unlock() + { + mTokenMapMutex.Unlock(); + } + + UInt32 GetToken(T* inObject) const + { + CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex)); + UInt32 theAnswer = 0; + typename TokenMap::const_iterator i = mTokenMap.begin(); + while((theAnswer == 0) && (i != mTokenMap.end())) + { + if(i->second == inObject) + { + theAnswer = i->first; + } + std::advance(i, 1); + } + return theAnswer; + } + + T* GetObject(UInt32 inToken) const + { + CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex)); + typename TokenMap::const_iterator i = mTokenMap.find(inToken); + return i != mTokenMap.end() ? i->second : NULL; + } + + T* GetObject(const void* inToken) const + { + #if __LP64__ + return GetObject((UInt32)((UInt64)inToken)); + #else + return GetObject((UInt32)inToken); + #endif + } + + UInt32 GetNumberObjects() const + { + CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex)); + return static_cast<UInt32>(mTokenMap.size()); + } + + T* GetObjectByIndex(UInt32 inIndex) const + { + T* theAnswer = NULL; + CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex)); + if(inIndex < mTokenMap.size()) + { + typename TokenMap::const_iterator i = mTokenMap.begin(); + std::advance(i, inIndex); + theAnswer = (i != mTokenMap.end()) ? i->second : NULL; + } + return theAnswer; + } + + void AddMapping(UInt32 inToken, T* inObject) + { + CAMutex::Locker theLocker(mTokenMapMutex); + typename TokenMap::iterator i = mTokenMap.find(inToken); + if(i != mTokenMap.end()) + { + i->second = inObject; + } + else + { + mTokenMap.insert(typename TokenMap::value_type(inToken, inObject)); + } + } + + void RemoveMapping(UInt32 inToken, T* /*inObject*/) + { + CAMutex::Locker theLocker(mTokenMapMutex); + typename TokenMap::iterator i = mTokenMap.find(inToken); + if(i != mTokenMap.end()) + { + mTokenMap.erase(i); + } + } + + UInt32 GetNextToken() + { + return mNextToken++; + } + + UInt32 MapObject(T* inObject) + { + CAMutex::Locker theLocker(mTokenMapMutex); + UInt32 theToken = GetNextToken(); + mTokenMap.insert(typename TokenMap::value_type(theToken, inObject)); + return theToken; + } + + void UnmapObject(T* inObject) + { + CAMutex::Locker theLocker(mTokenMapMutex); + bool isDone = false; + typename TokenMap::iterator i = mTokenMap.begin(); + while(!isDone && (i != mTokenMap.end())) + { + if(i->second == inObject) + { + mTokenMap.erase(i); + isDone = true; + } + else + { + std::advance(i, 1); + } + } + } + +// Implementation +private: + TokenMap mTokenMap; + UInt32 mNextToken; + CAMutex mTokenMapMutex; + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp new file mode 100644 index 0000000000..83bfb8c889 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp @@ -0,0 +1,195 @@ +/* + File: CAVectorUnit.cpp + Abstract: CAVectorUnit.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 "CAVectorUnit.h" + +#if !TARGET_OS_WIN32 + #include <sys/sysctl.h> +#elif HAS_IPP + #include "ippdefs.h" + #include "ippcore.h" +#endif + +int gCAVectorUnitType = kVecUninitialized; + +#if TARGET_OS_WIN32 +// Use cpuid to check if SSE2 is available. +// Before calling this function make sure cpuid is available +static SInt32 IsSSE2Available() +{ + int return_value; + + { + int r_edx; + _asm + { + mov eax, 0x01 + cpuid + mov r_edx, edx + } + return_value = (r_edx >> 26) & 0x1; + } + return return_value; +} + +// Use cpuid to check if SSE3 is available. +// Before calling this function make sure cpuid is available +static SInt32 IsSSE3Available() +{ + SInt32 return_value; + + { + SInt32 r_ecx; + _asm + { + mov eax, 0x01 + cpuid + mov r_ecx, ecx + } + return_value = r_ecx & 0x1; + } + return return_value; +} + +// Return true if the cpuid instruction is available. +// The cpuid instruction is available if bit 21 in the EFLAGS register can be changed +// This function may not work on Intel CPUs prior to Pentium (didn't test) +static bool IsCpuidAvailable() +{ + SInt32 return_value = 0x0; + _asm{ + pushfd ; //push original EFLAGS + pop eax ; //get original EFLAGS + mov ecx, eax ; //save original EFLAGS + xor eax, 200000h ; //flip ID bit in EFLAGS + push eax ; //save new EFLAGS value on stack + popfd ; //replace current EFLAGS value + pushfd ; //get new EFLAGS + pop eax ; //store new EFLAGS in EAX + xor eax, ecx ; + je end_cpuid_identify ; //can't toggle ID bit + mov return_value, 0x1; +end_cpuid_identify: + nop; + } + return return_value; +} + +#endif + +SInt32 CAVectorUnit_Examine() +{ + int result = kVecNone; + +#if TARGET_OS_WIN32 +#if HAS_IPP + // Initialize the static IPP library! This needs to be done before + // any IPP function calls, otherwise we may have a performance penalty + int status = ippStaticInit(); + if ( status == ippStsNonIntelCpu ) + { + IppCpuType cpuType = ippGetCpuType(); + if ( cpuType >= ippCpuSSE || cpuType <= ippCpuSSE42 ) + ippStaticInitCpu( cpuType ); + } +#endif + { + // On Windows we use cpuid to detect the vector unit because it works on Intel and AMD. + // The IPP library does not detect SSE on AMD processors. + if (IsCpuidAvailable()) + { + if(IsSSE3Available()) + { + result = kVecSSE3; + } + else if(IsSSE2Available()) + { + result = kVecSSE2; + } + } + } +#elif TARGET_OS_MAC +#if DEBUG + if (getenv("CA_NoVector")) { + fprintf(stderr, "CA_NoVector set; Vector unit optimized routines will be bypassed\n"); + return result; + } + else +#endif + { + #if (TARGET_CPU_PPC || TARGET_CPU_PPC64) + int sels[2] = { CTL_HW, HW_VECTORUNIT }; + int vType = 0; //0 == scalar only + size_t length = sizeof(vType); + int error = sysctl(sels, 2, &vType, &length, NULL, 0); + if (!error && vType > 0) + result = kVecAltivec; + #elif (TARGET_CPU_X86 || TARGET_CPU_X86_64) + static const struct { const char* kName; const int kVectype; } kStringVectypes[] = { + { "hw.optional.avx1_0", kVecAVX1 }, { "hw.optional.sse3", kVecSSE3 }, { "hw.optional.sse2", kVecSSE2 } + }; + static const size_t kNumStringVectypes = sizeof(kStringVectypes)/sizeof(kStringVectypes[0]); + int i = 0, answer = 0; + while(i != kNumStringVectypes) + { + size_t length = sizeof(answer); + int error = sysctlbyname(kStringVectypes[i].kName, &answer, &length, NULL, 0); + if (!error && answer) + { + result = kStringVectypes[i].kVectype; + break; + } + ++i; + }; + #elif CA_ARM_NEON + result = kVecNeon; + #endif + } +#endif + gCAVectorUnitType = result; + return result; +} + diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h new file mode 100644 index 0000000000..cf3a16c7a9 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h @@ -0,0 +1,101 @@ +/* + File: CAVectorUnit.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAVectorUnit_h__ +#define __CAVectorUnit_h__ + +#include <TargetConditionals.h> +#include "CAVectorUnitTypes.h" +#include <stdlib.h> +#include <stdio.h> + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreFoundation/CFBase.h> +#else + #include "CFBase.h" +#endif + +// Unify checks for vector units. +// Allow setting an environment variable "CA_NoVector" to turn off vectorized code at runtime (very useful for performance testing). + +extern int gCAVectorUnitType; + +#ifdef __cplusplus +extern "C" { +#endif + +extern SInt32 CAVectorUnit_Examine(); // expensive. use GetType() for lazy initialization and caching. + +static inline SInt32 CAVectorUnit_GetType() +{ + int x = gCAVectorUnitType; + return (x != kVecUninitialized) ? x : CAVectorUnit_Examine(); +} + +static inline Boolean CAVectorUnit_HasVectorUnit() +{ + return CAVectorUnit_GetType() > kVecNone; +} + +#ifdef __cplusplus +} +#endif + + +#ifdef __cplusplus +class CAVectorUnit { +public: + static SInt32 GetVectorUnitType() { return CAVectorUnit_GetType(); } + static bool HasVectorUnit() { return GetVectorUnitType() > kVecNone; } + static bool HasAltivec() { return GetVectorUnitType() == kVecAltivec; } + static bool HasSSE2() { return GetVectorUnitType() >= kVecSSE2; } + static bool HasSSE3() { return GetVectorUnitType() >= kVecSSE3; } + static bool HasAVX1() { return GetVectorUnitType() >= kVecAVX1; } + static bool HasNeon() { return GetVectorUnitType() == kVecNeon; } +}; +#endif + +#endif // __CAVectorUnit_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h new file mode 100644 index 0000000000..85ff837afe --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h @@ -0,0 +1,60 @@ +/* + File: CAVectorUnitTypes.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAVectorUnitTypes_h__ +#define __CAVectorUnitTypes_h__ + +enum { + kVecUninitialized = -1, + kVecNone = 0, + kVecAltivec = 1, + kVecSSE2 = 100, + kVecSSE3 = 101, + kVecAVX1 = 110, + kVecNeon = 200 +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp new file mode 100644 index 0000000000..bb6e70cb8e --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp @@ -0,0 +1,482 @@ +/* + File: CAVolumeCurve.cpp + Abstract: CAVolumeCurve.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. + +*/ +//============================================================================= +// Includes +//============================================================================= + +#include "CAVolumeCurve.h" +#include "CADebugMacros.h" +#include <math.h> + +//============================================================================= +// CAVolumeCurve +//============================================================================= + +CAVolumeCurve::CAVolumeCurve() +: + mTag(0), + mCurveMap(), + mIsApplyingTransferFunction(true), + mTransferFunction(kPow2Over1Curve), + mRawToScalarExponentNumerator(2.0f), + mRawToScalarExponentDenominator(1.0f) +{ +} + +CAVolumeCurve::~CAVolumeCurve() +{ +} + +SInt32 CAVolumeCurve::GetMinimumRaw() const +{ + SInt32 theAnswer = 0; + + if(!mCurveMap.empty()) + { + CurveMap::const_iterator theIterator = mCurveMap.begin(); + theAnswer = theIterator->first.mMinimum; + } + + return theAnswer; +} + +SInt32 CAVolumeCurve::GetMaximumRaw() const +{ + SInt32 theAnswer = 0; + + if(!mCurveMap.empty()) + { + CurveMap::const_iterator theIterator = mCurveMap.begin(); + std::advance(theIterator, static_cast<int>(mCurveMap.size() - 1)); + theAnswer = theIterator->first.mMaximum; + } + + return theAnswer; +} + +Float32 CAVolumeCurve::GetMinimumDB() const +{ + Float32 theAnswer = 0; + + if(!mCurveMap.empty()) + { + CurveMap::const_iterator theIterator = mCurveMap.begin(); + theAnswer = theIterator->second.mMinimum; + } + + return theAnswer; +} + +Float32 CAVolumeCurve::GetMaximumDB() const +{ + Float32 theAnswer = 0; + + if(!mCurveMap.empty()) + { + CurveMap::const_iterator theIterator = mCurveMap.begin(); + std::advance(theIterator, static_cast<int>(mCurveMap.size() - 1)); + theAnswer = theIterator->second.mMaximum; + } + + return theAnswer; +} + +void CAVolumeCurve::SetTransferFunction(UInt32 inTransferFunction) +{ + mTransferFunction = inTransferFunction; + + // figure out the co-efficients + switch(inTransferFunction) + { + case kLinearCurve: + mIsApplyingTransferFunction = false; + mRawToScalarExponentNumerator = 1.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow1Over3Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 1.0f; + mRawToScalarExponentDenominator = 3.0f; + break; + + case kPow1Over2Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 1.0f; + mRawToScalarExponentDenominator = 2.0f; + break; + + case kPow3Over4Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 3.0f; + mRawToScalarExponentDenominator = 4.0f; + break; + + case kPow3Over2Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 3.0f; + mRawToScalarExponentDenominator = 2.0f; + break; + + case kPow2Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 2.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow3Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 3.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow4Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 4.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow5Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 5.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow6Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 6.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow7Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 7.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow8Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 8.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow9Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 9.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow10Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 10.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow11Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 11.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + case kPow12Over1Curve: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 12.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + + default: + mIsApplyingTransferFunction = true; + mRawToScalarExponentNumerator = 2.0f; + mRawToScalarExponentDenominator = 1.0f; + break; + }; +} + +void CAVolumeCurve::AddRange(SInt32 inMinRaw, SInt32 inMaxRaw, Float32 inMinDB, Float32 inMaxDB) +{ + CARawPoint theRaw(inMinRaw, inMaxRaw); + CADBPoint theDB(inMinDB, inMaxDB); + + bool isOverlapped = false; + bool isDone = false; + CurveMap::iterator theIterator = mCurveMap.begin(); + while((theIterator != mCurveMap.end()) && !isOverlapped && !isDone) + { + isOverlapped = CARawPoint::Overlap(theRaw, theIterator->first); + isDone = theRaw >= theIterator->first; + + if(!isOverlapped && !isDone) + { + std::advance(theIterator, 1); + } + } + + if(!isOverlapped) + { + mCurveMap.insert(CurveMap::value_type(theRaw, theDB)); + } + else + { + DebugMessage("CAVolumeCurve::AddRange: new point overlaps"); + } +} + +void CAVolumeCurve::ResetRange() +{ + mCurveMap.clear(); +} + +bool CAVolumeCurve::CheckForContinuity() const +{ + bool theAnswer = true; + + CurveMap::const_iterator theIterator = mCurveMap.begin(); + if(theIterator != mCurveMap.end()) + { + SInt32 theRaw = theIterator->first.mMinimum; + Float32 theDB = theIterator->second.mMinimum; + do + { + SInt32 theRawMin = theIterator->first.mMinimum; + SInt32 theRawMax = theIterator->first.mMaximum; + SInt32 theRawRange = theRawMax - theRawMin; + + Float32 theDBMin = theIterator->second.mMinimum; + Float32 theDBMax = theIterator->second.mMaximum; + Float32 theDBRange = theDBMax - theDBMin; + + theAnswer = theRaw == theRawMin; + theAnswer = theAnswer && (theDB == theDBMin); + + theRaw += theRawRange; + theDB += theDBRange; + + std::advance(theIterator, 1); + } + while((theIterator != mCurveMap.end()) && theAnswer); + } + + return theAnswer; +} + +SInt32 CAVolumeCurve::ConvertDBToRaw(Float32 inDB) const +{ + // clamp the value to the dB range + Float32 theOverallDBMin = GetMinimumDB(); + Float32 theOverallDBMax = GetMaximumDB(); + + if(inDB < theOverallDBMin) inDB = theOverallDBMin; + if(inDB > theOverallDBMax) inDB = theOverallDBMax; + + // get the first entry in the curve map; + CurveMap::const_iterator theIterator = mCurveMap.begin(); + + // initialize the answer to the minimum raw of the first item in the curve map + SInt32 theAnswer = theIterator->first.mMinimum; + + // iterate through the curve map until we run out of dB + bool isDone = false; + while(!isDone && (theIterator != mCurveMap.end())) + { + SInt32 theRawMin = theIterator->first.mMinimum; + SInt32 theRawMax = theIterator->first.mMaximum; + SInt32 theRawRange = theRawMax - theRawMin; + + Float32 theDBMin = theIterator->second.mMinimum; + Float32 theDBMax = theIterator->second.mMaximum; + Float32 theDBRange = theDBMax - theDBMin; + + Float32 theDBPerRaw = theDBRange / static_cast<Float32>(theRawRange); + + // figure out how many steps we are into this entry in the curve map + if(inDB > theDBMax) + { + // we're past the end of this one, so add in the whole range for this entry + theAnswer += theRawRange; + } + else + { + // it's somewhere within the current entry + // figure out how many steps it is + Float32 theNumberRawSteps = inDB - theDBMin; + theNumberRawSteps /= theDBPerRaw; + + // only move in whole steps + theNumberRawSteps = roundf(theNumberRawSteps); + + // add this many steps to the answer + theAnswer += static_cast<SInt32>(theNumberRawSteps); + + // mark that we are done + isDone = true; + } + + // go to the next entry in the curve map + std::advance(theIterator, 1); + } + + return theAnswer; +} + +Float32 CAVolumeCurve::ConvertRawToDB(SInt32 inRaw) const +{ + Float32 theAnswer = 0; + + // clamp the raw value + SInt32 theOverallRawMin = GetMinimumRaw(); + SInt32 theOverallRawMax = GetMaximumRaw(); + + if(inRaw < theOverallRawMin) inRaw = theOverallRawMin; + if(inRaw > theOverallRawMax) inRaw = theOverallRawMax; + + // figure out how many raw steps need to be taken from the first one + SInt32 theNumberRawSteps = inRaw - theOverallRawMin; + + // get the first item in the curve map + CurveMap::const_iterator theIterator = mCurveMap.begin(); + + // initialize the answer to the minimum dB of the first item in the curve map + theAnswer = theIterator->second.mMinimum; + + // iterate through the curve map until we run out of steps + while((theNumberRawSteps > 0) && (theIterator != mCurveMap.end())) + { + // compute some values + SInt32 theRawMin = theIterator->first.mMinimum; + SInt32 theRawMax = theIterator->first.mMaximum; + SInt32 theRawRange = theRawMax - theRawMin; + + Float32 theDBMin = theIterator->second.mMinimum; + Float32 theDBMax = theIterator->second.mMaximum; + Float32 theDBRange = theDBMax - theDBMin; + + Float32 theDBPerRaw = theDBRange / static_cast<Float32>(theRawRange); + + // there might be more steps than the current map entry accounts for + SInt32 theRawStepsToAdd = std::min(theRawRange, theNumberRawSteps); + + // add this many steps worth of db to the answer; + theAnswer += theRawStepsToAdd * theDBPerRaw; + + // figure out how many steps are left + theNumberRawSteps -= theRawStepsToAdd; + + // go to the next map entry + std::advance(theIterator, 1); + } + + return theAnswer; +} + +Float32 CAVolumeCurve::ConvertRawToScalar(SInt32 inRaw) const +{ + // get some important values + Float32 theDBMin = GetMinimumDB(); + Float32 theDBMax = GetMaximumDB(); + Float32 theDBRange = theDBMax - theDBMin; + SInt32 theRawMin = GetMinimumRaw(); + SInt32 theRawMax = GetMaximumRaw(); + SInt32 theRawRange = theRawMax - theRawMin; + + // range the raw value + if(inRaw < theRawMin) inRaw = theRawMin; + if(inRaw > theRawMax) inRaw = theRawMax; + + // calculate the distance in the range inRaw is + Float32 theAnswer = static_cast<Float32>(inRaw - theRawMin) / static_cast<Float32>(theRawRange); + + // only apply a curve to the scalar values if the dB range is greater than 30 + if(mIsApplyingTransferFunction && (theDBRange > 30.0f)) + { + theAnswer = powf(theAnswer, mRawToScalarExponentNumerator / mRawToScalarExponentDenominator); + } + + return theAnswer; +} + +Float32 CAVolumeCurve::ConvertDBToScalar(Float32 inDB) const +{ + SInt32 theRawValue = ConvertDBToRaw(inDB); + Float32 theAnswer = ConvertRawToScalar(theRawValue); + return theAnswer; +} + +SInt32 CAVolumeCurve::ConvertScalarToRaw(Float32 inScalar) const +{ + // range the scalar value + inScalar = std::min(1.0f, std::max(0.0f, inScalar)); + + // get some important values + Float32 theDBMin = GetMinimumDB(); + Float32 theDBMax = GetMaximumDB(); + Float32 theDBRange = theDBMax - theDBMin; + SInt32 theRawMin = GetMinimumRaw(); + SInt32 theRawMax = GetMaximumRaw(); + SInt32 theRawRange = theRawMax - theRawMin; + + // have to undo the curve if the dB range is greater than 30 + if(mIsApplyingTransferFunction && (theDBRange > 30.0f)) + { + inScalar = powf(inScalar, mRawToScalarExponentDenominator / mRawToScalarExponentNumerator); + } + + // now we can figure out how many raw steps this is + Float32 theNumberRawSteps = inScalar * static_cast<Float32>(theRawRange); + theNumberRawSteps = roundf(theNumberRawSteps); + + // the answer is the minimum raw value plus the number of raw steps + SInt32 theAnswer = theRawMin + static_cast<SInt32>(theNumberRawSteps); + + return theAnswer; +} + +Float32 CAVolumeCurve::ConvertScalarToDB(Float32 inScalar) const +{ + SInt32 theRawValue = ConvertScalarToRaw(inScalar); + Float32 theAnswer = ConvertRawToDB(theRawValue); + return theAnswer; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h new file mode 100644 index 0000000000..4f9544682a --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h @@ -0,0 +1,178 @@ +/* + File: CAVolumeCurve.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#if !defined(__CAVolumeCurve_h__) +#define __CAVolumeCurve_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> +#else + #include <CoreAudioTypes.h> +#endif +#include <map> + +//============================================================================= +// Types +//============================================================================= + +struct CARawPoint +{ + SInt32 mMinimum; + SInt32 mMaximum; + + CARawPoint() : mMinimum(0), mMaximum(0) {} + CARawPoint(const CARawPoint& inPoint) : mMinimum(inPoint.mMinimum), mMaximum(inPoint.mMaximum) {} + CARawPoint(SInt32 inMinimum, SInt32 inMaximum) : mMinimum(inMinimum), mMaximum(inMaximum) {} + CARawPoint& operator=(const CARawPoint& inPoint) { mMinimum = inPoint.mMinimum; mMaximum = inPoint.mMaximum; return *this; } + + static bool Overlap(const CARawPoint& x, const CARawPoint& y) { return (x.mMinimum < y.mMaximum) && (x.mMaximum > y.mMinimum); } +}; + +inline bool operator<(const CARawPoint& x, const CARawPoint& y) { return x.mMinimum < y.mMinimum; } +inline bool operator==(const CARawPoint& x, const CARawPoint& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); } +inline bool operator!=(const CARawPoint& x, const CARawPoint& y) { return !(x == y); } +inline bool operator<=(const CARawPoint& x, const CARawPoint& y) { return (x < y) || (x == y); } +inline bool operator>=(const CARawPoint& x, const CARawPoint& y) { return !(x < y); } +inline bool operator>(const CARawPoint& x, const CARawPoint& y) { return !((x < y) || (x == y)); } + +struct CADBPoint +{ + Float32 mMinimum; + Float32 mMaximum; + + CADBPoint() : mMinimum(0), mMaximum(0) {} + CADBPoint(const CADBPoint& inPoint) : mMinimum(inPoint.mMinimum), mMaximum(inPoint.mMaximum) {} + CADBPoint(Float32 inMinimum, Float32 inMaximum) : mMinimum(inMinimum), mMaximum(inMaximum) {} + CADBPoint& operator=(const CADBPoint& inPoint) { mMinimum = inPoint.mMinimum; mMaximum = inPoint.mMaximum; return *this; } + + static bool Overlap(const CADBPoint& x, const CADBPoint& y) { return (x.mMinimum < y.mMaximum) && (x.mMaximum >= y.mMinimum); } +}; + +inline bool operator<(const CADBPoint& x, const CADBPoint& y) { return x.mMinimum < y.mMinimum; } +inline bool operator==(const CADBPoint& x, const CADBPoint& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); } +inline bool operator!=(const CADBPoint& x, const CADBPoint& y) { return !(x == y); } +inline bool operator<=(const CADBPoint& x, const CADBPoint& y) { return (x < y) || (x == y); } +inline bool operator>=(const CADBPoint& x, const CADBPoint& y) { return !(x < y); } +inline bool operator>(const CADBPoint& x, const CADBPoint& y) { return !((x < y) || (x == y)); } + +//============================================================================= +// CAVolumeCurve +//============================================================================= + +class CAVolumeCurve +{ + +// Constants +public: + enum + { + kLinearCurve = 0, + kPow1Over3Curve = 1, + kPow1Over2Curve = 2, + kPow3Over4Curve = 3, + kPow3Over2Curve = 4, + kPow2Over1Curve = 5, + kPow3Over1Curve = 6, + kPow4Over1Curve = 7, + kPow5Over1Curve = 8, + kPow6Over1Curve = 9, + kPow7Over1Curve = 10, + kPow8Over1Curve = 11, + kPow9Over1Curve = 12, + kPow10Over1Curve = 13, + kPow11Over1Curve = 14, + kPow12Over1Curve = 15 + }; + +// Construction/Destruction +public: + CAVolumeCurve(); + virtual ~CAVolumeCurve(); + +// Attributes +public: + UInt32 GetTag() const { return mTag; } + void SetTag(UInt32 inTag) { mTag = inTag; } + SInt32 GetMinimumRaw() const; + SInt32 GetMaximumRaw() const; + Float32 GetMinimumDB() const; + Float32 GetMaximumDB() const; + + void SetIsApplyingTransferFunction(bool inIsApplyingTransferFunction) { mIsApplyingTransferFunction = inIsApplyingTransferFunction; } + UInt32 GetTransferFunction() const { return mTransferFunction; } + void SetTransferFunction(UInt32 inTransferFunction); + +// Operations +public: + void AddRange(SInt32 mMinRaw, SInt32 mMaxRaw, Float32 inMinDB, Float32 inMaxDB); + void ResetRange(); + bool CheckForContinuity() const; + + SInt32 ConvertDBToRaw(Float32 inDB) const; + Float32 ConvertRawToDB(SInt32 inRaw) const; + Float32 ConvertRawToScalar(SInt32 inRaw) const; + Float32 ConvertDBToScalar(Float32 inDB) const; + SInt32 ConvertScalarToRaw(Float32 inScalar) const; + Float32 ConvertScalarToDB(Float32 inScalar) const; + +// Implementation +private: + typedef std::map<CARawPoint, CADBPoint> CurveMap; + + UInt32 mTag; + CurveMap mCurveMap; + bool mIsApplyingTransferFunction; + UInt32 mTransferFunction; + Float32 mRawToScalarExponentNumerator; + Float32 mRawToScalarExponentDenominator; + +}; + +#endif diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp new file mode 100644 index 0000000000..c2dbac5d60 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp @@ -0,0 +1,49 @@ +/* + File: CAXException.cpp + Abstract: CAXException.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 "CAXException.h" + +CAXException::WarningHandler CAXException::sWarningHandler = NULL; diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAXException.h b/libs/appleutility/CoreAudio/PublicUtility/CAXException.h new file mode 100644 index 0000000000..90dabe97de --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/CAXException.h @@ -0,0 +1,361 @@ +/* + File: CAXException.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __CAXException_h__ +#define __CAXException_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreFoundation/CoreFoundation.h> +#else + #include <ConditionalMacros.h> + #include <CoreFoundation.h> +#endif +#include "CADebugMacros.h" +#include <ctype.h> +//#include <stdio.h> +#include <string.h> + + +class CAX4CCString { +public: + CAX4CCString(OSStatus error) { + // see if it appears to be a 4-char-code + UInt32 beErr = CFSwapInt32HostToBig(error); + char *str = mStr; + memcpy(str + 1, &beErr, 4); + if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) { + str[0] = str[5] = '\''; + str[6] = '\0'; + } else if (error > -200000 && error < 200000) + // no, format it as an integer + snprintf(str, sizeof(mStr), "%d", (int)error); + else + snprintf(str, sizeof(mStr), "0x%x", (int)error); + } + const char *get() const { return mStr; } + operator const char *() const { return mStr; } +private: + char mStr[16]; +}; + +class CAX4CCStringNoQuote { +public: + CAX4CCStringNoQuote(OSStatus error) { + // see if it appears to be a 4-char-code + UInt32 beErr = CFSwapInt32HostToBig(error); + char *str = mStr; + memcpy(str, &beErr, 4); + if (isprint(str[0]) && isprint(str[1]) && isprint(str[2]) && isprint(str[3])) { + str[4] = '\0'; + } else if (error > -200000 && error < 200000) + // no, format it as an integer + snprintf(str, sizeof(mStr), "%d", (int)error); + else + snprintf(str, sizeof(mStr), "0x%x", (int)error); + } + const char *get() const { return mStr; } + operator const char *() const { return mStr; } +private: + char mStr[16]; +}; + + +// An extended exception class that includes the name of the failed operation +class CAXException { +public: + CAXException(const char *operation, OSStatus err) : + mError(err) + { + if (operation == NULL) + mOperation[0] = '\0'; + else if (strlen(operation) >= sizeof(mOperation)) { + memcpy(mOperation, operation, sizeof(mOperation) - 1); + mOperation[sizeof(mOperation) - 1] = '\0'; + } else + + strlcpy(mOperation, operation, sizeof(mOperation)); + } + + char *FormatError(char *str, size_t strsize) const + { + return FormatError(str, strsize, mError); + } + + char mOperation[256]; + const OSStatus mError; + + // ------------------------------------------------- + + typedef void (*WarningHandler)(const char *msg, OSStatus err); + + static char *FormatError(char *str, size_t strsize, OSStatus error) + { + strlcpy(str, CAX4CCString(error), strsize); + return str; + } + + static void Warning(const char *s, OSStatus error) + { + if (sWarningHandler) + (*sWarningHandler)(s, error); + } + + static void SetWarningHandler(WarningHandler f) { sWarningHandler = f; } +private: + static WarningHandler sWarningHandler; +}; + +#if DEBUG || CoreAudio_Debug + #define XThrowIfError(error, operation) \ + do { \ + OSStatus __err = error; \ + if (__err) { \ + DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\ + __THROW_STOP; \ + throw CAXException(operation, __err); \ + } \ + } while (0) + + #define XThrowIf(condition, error, operation) \ + do { \ + if (condition) { \ + OSStatus __err = error; \ + DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\ + __THROW_STOP; \ + throw CAXException(operation, __err); \ + } \ + } while (0) + + #define XRequireNoError(error, label) \ + do { \ + OSStatus __err = error; \ + if (__err) { \ + DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\ + STOP; \ + goto label; \ + } \ + } while (0) + + #define XAssert(assertion) \ + do { \ + if (!(assertion)) { \ + DebugMessageN3("%s:%d: error: failed assertion: %s", __FILE__, __LINE__, #assertion); \ + __ASSERT_STOP; \ + } \ + } while (0) + + #define XAssertNoError(error) \ + do { \ + OSStatus __err = error; \ + if (__err) { \ + DebugMessageN4("%s:%d: error %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\ + STOP; \ + } \ + } while (0) + + #define ca_require_noerr(errorCode, exceptionLabel) \ + do \ + { \ + int evalOnceErrorCode = (errorCode); \ + if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \ + { \ + DebugMessageN5("ca_require_noerr: [%s, %d] (goto %s;) %s:%d", \ + #errorCode, evalOnceErrorCode, \ + #exceptionLabel, \ + __FILE__, \ + __LINE__); \ + goto exceptionLabel; \ + } \ + } while ( 0 ) + + #define ca_verify_noerr(errorCode) \ + do \ + { \ + int evalOnceErrorCode = (errorCode); \ + if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \ + { \ + DebugMessageN4("ca_verify_noerr: [%s, %d] %s:%d", \ + #errorCode, evalOnceErrorCode, \ + __FILE__, \ + __LINE__); \ + } \ + } while ( 0 ) + + #define ca_debug_string(message) \ + do \ + { \ + DebugMessageN3("ca_debug_string: %s %s:%d", \ + message, \ + __FILE__, \ + __LINE__); \ + } while ( 0 ) + + + #define ca_verify(assertion) \ + do \ + { \ + if ( __builtin_expect(!(assertion), 0) ) \ + { \ + DebugMessageN3("ca_verify: %s %s:%d", \ + #assertion, \ + __FILE__, \ + __LINE__); \ + } \ + } while ( 0 ) + + #define ca_require(assertion, exceptionLabel) \ + do \ + { \ + if ( __builtin_expect(!(assertion), 0) ) \ + { \ + DebugMessageN4("ca_require: %s %s %s:%d", \ + #assertion, \ + #exceptionLabel, \ + __FILE__, \ + __LINE__); \ + goto exceptionLabel; \ + } \ + } while ( 0 ) + + #define ca_check(assertion) \ + do \ + { \ + if ( __builtin_expect(!(assertion), 0) ) \ + { \ + DebugMessageN3("ca_check: %s %s:%d", \ + #assertion, \ + __FILE__, \ + __LINE__); \ + } \ + } while ( 0 ) + +#else + #define XThrowIfError(error, operation) \ + do { \ + OSStatus __err = error; \ + if (__err) { \ + throw CAXException(operation, __err); \ + } \ + } while (0) + + #define XThrowIf(condition, error, operation) \ + do { \ + if (condition) { \ + OSStatus __err = error; \ + throw CAXException(operation, __err); \ + } \ + } while (0) + + #define XRequireNoError(error, label) \ + do { \ + OSStatus __err = error; \ + if (__err) { \ + goto label; \ + } \ + } while (0) + + #define XAssert(assertion) \ + do { \ + if (!(assertion)) { \ + } \ + } while (0) + + #define XAssertNoError(error) \ + do { \ + /*OSStatus __err =*/ error; \ + } while (0) + + #define ca_require_noerr(errorCode, exceptionLabel) \ + do \ + { \ + if ( __builtin_expect(0 != (errorCode), 0) ) \ + { \ + goto exceptionLabel; \ + } \ + } while ( 0 ) + + #define ca_verify_noerr(errorCode) \ + do \ + { \ + if ( 0 != (errorCode) ) \ + { \ + } \ + } while ( 0 ) + + #define ca_debug_string(message) + + #define ca_verify(assertion) \ + do \ + { \ + if ( !(assertion) ) \ + { \ + } \ + } while ( 0 ) + + #define ca_require(assertion, exceptionLabel) \ + do \ + { \ + if ( __builtin_expect(!(assertion), 0) ) \ + { \ + goto exceptionLabel; \ + } \ + } while ( 0 ) + + #define ca_check(assertion) \ + do \ + { \ + if ( !(assertion) ) \ + { \ + } \ + } while ( 0 ) + + +#endif + +#define XThrow(error, operation) XThrowIf(true, error, operation) +#define XThrowIfErr(error) XThrowIfError(error, #error) + +#endif // __CAXException_h__ diff --git a/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp new file mode 100644 index 0000000000..98d868eb73 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp @@ -0,0 +1,149 @@ +/* + File: MatrixMixerVolumes.cpp + Abstract: MatrixMixerVolumes.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 "MatrixMixerVolumes.h" +#include "CAXException.h" + +OSStatus NumberChannels (AudioUnit au, + AudioUnitScope inScope, + AudioUnitElement inEl, + UInt32 &outChans); + + +OSStatus PrintBuses (FILE* file, const char* str, AudioUnit au, AudioUnitScope inScope) +{ + OSStatus result; + UInt32 busCount; + UInt32 theSize = sizeof(busCount); + + ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_ElementCount, + inScope, 0, &busCount, &theSize), home); + + fprintf (file, "\t%s Elements:\n\t\t", str); + for (UInt32 i = 0; i < busCount; ++i) { + Float32 val; + ca_require_noerr (result = AudioUnitGetParameter (au, kMatrixMixerParam_Enable, inScope, i, &val), home); + UInt32 numChans; + ca_require_noerr (result = NumberChannels (au, inScope, i, numChans), home); + char frameCharStart = (val != 0 ? '[' : '{'); + char frameCharEnd = (val != 0 ? ']' : '}'); + fprintf (file, "%d:%c%d, %c%c ", (int)i, frameCharStart, (int)numChans, (val != 0 ? 'T' : 'F'), frameCharEnd); + } + fprintf (file, "\n"); +home: + return result; +} + +void PrintMatrixMixerVolumes (FILE* file, AudioUnit au) +{ + UInt32 dims[2]; + UInt32 theSize = sizeof(UInt32) * 2; + Float32 *theVols = NULL; + OSStatus result; + +// this call will fail if the unit is NOT initialized as it would present an incomplete state + ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_MatrixDimensions, + kAudioUnitScope_Global, 0, dims, &theSize), home); + + theSize = ((dims[0] + 1) * (dims[1] + 1)) * sizeof(Float32); + + theVols = static_cast<Float32*> (malloc (theSize)); + + ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_MatrixLevels, + kAudioUnitScope_Global, 0, theVols, &theSize), home); + +home: + if (result) { + if (theVols) + free(theVols); + return; + } + + theSize /= sizeof(Float32); + + unsigned int inputs = dims[0]; + unsigned int outputs = dims[1]; + + fprintf (file, "\tInput Channels = %d, Output Channels = %d\n", (int)dims[0], (int)dims[1]); + PrintBuses (file, "Input", au, kAudioUnitScope_Input); + PrintBuses (file, "Output", au, kAudioUnitScope_Output); + fprintf (file, "\tGlobal Volume: %.3f\n", theVols [theSize - 1]); + for (unsigned int i = 0; i < (inputs + 1); ++i) { + if (i < inputs) { + fprintf (file, "\t%.3f ", theVols[(i + 1) * (outputs + 1) - 1]); + + for (unsigned int j = 0; j < outputs; ++j) + fprintf (file, "(%.3f) ", theVols[(i * (outputs + 1)) + j]); + } else { + fprintf (file, "\t "); + for (unsigned int j = 0; j < outputs; ++j) + fprintf (file, " %.3f ", theVols[(i * (outputs + 1)) + j]); + } + fprintf (file, "\n"); + } + +#if 0 + for (unsigned int i = 0; i < theSize; ++i) + printf ("%f, ", theVols[i]); +#endif + free(theVols); +} + +// Utility routine that gets the number of channels from an audio unit +OSStatus NumberChannels (AudioUnit au, + AudioUnitScope inScope, + AudioUnitElement inEl, + UInt32 &outChans) +{ + AudioStreamBasicDescription desc; + UInt32 dataSize = sizeof (AudioStreamBasicDescription); + OSStatus result = AudioUnitGetProperty (au, kAudioUnitProperty_StreamFormat, + inScope, inEl, + &desc, &dataSize); + if (!result) + outChans = desc.mChannelsPerFrame; + return result; +} diff --git a/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h new file mode 100644 index 0000000000..06854f0774 --- /dev/null +++ b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h @@ -0,0 +1,71 @@ +/* + File: MatrixMixerVolumes.h + Abstract: Part of CoreAudio Utility Classes + 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. + +*/ +#ifndef __MatrixMixerVolumes_h__ +#define __MatrixMixerVolumes_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <AudioUnit/AudioUnit.h> +#else + #include <AudioUnit.h> +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// prints the matrix mixer volumes of a specific audio unit to the given file +void PrintMatrixMixerVolumes (FILE* file, AudioUnit au); + +// prints the mixer volumes for the specific scope of the audio unit +// results will be printed to the speficied file "file" with identifiying string tag "str" +OSStatus PrintBuses (FILE* file, char* str, AudioUnit au, AudioUnitScope inScope); +#if defined(__cplusplus) +} +#endif + +#endif |