diff options
author | Taybin Rutkin <taybin@taybin.com> | 2006-08-02 20:17:00 +0000 |
---|---|---|
committer | Taybin Rutkin <taybin@taybin.com> | 2006-08-02 20:17:00 +0000 |
commit | 58b71b15d85fc23eb377bb629ba31811c20d0c32 (patch) | |
tree | fb073b136be5f208aa2e1f8de5b6284cdb992770 | |
parent | c3a00bf1e9662751f65b0dc22b27bc1a6ddcc1cd (diff) |
Added libappleutility from /Developer/Examples/CoreAudio/PublicUtility
More PluginManager refactoring
Rearranged AUPluginInfo for better maintainability
git-svn-id: svn://localhost/ardour2/trunk@748 d708f5d6-7413-0410-9779-e7cbd77b26cf
31 files changed, 5586 insertions, 39 deletions
diff --git a/SConstruct b/SConstruct index 90c426300d..91754b33a7 100644 --- a/SConstruct +++ b/SConstruct @@ -554,6 +554,9 @@ if env['SYSLIBS']: if env['VST']: subdirs = ['libs/fst'] + subdirs + ['vst'] + + if env['COREAUDIO']: + subdirs = subdirs + ['libs/appleutility'] gtk_subdirs = [ # 'libs/flowcanvas', @@ -609,6 +612,9 @@ else: if env['VST']: subdirs = ['libs/fst'] + subdirs + ['vst'] + + if env['COREAUDIO']: + subdirs = subdirs + ['libs/appleutility'] gtk_subdirs = [ 'libs/glibmm2', diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc index a34533ade9..e2e6aa2add 100644 --- a/gtk2_ardour/plugin_selector.cc +++ b/gtk2_ardour/plugin_selector.cc @@ -305,7 +305,7 @@ void PluginSelector::au_refiller () { guint row; - PluginInfoList &plugs = manager->au_plugin_info (); + PluginInfoList plugs (AUPluginInfo::discover ()); PluginInfoList::iterator i; char ibuf[16], obuf[16]; aumodel->clear(); diff --git a/libs/appleutility/AUOutputBL.cpp b/libs/appleutility/AUOutputBL.cpp new file mode 100644 index 0000000000..8509f46288 --- /dev/null +++ b/libs/appleutility/AUOutputBL.cpp @@ -0,0 +1,160 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + AUOutputBL.h + +=============================================================================*/ +#include "AUOutputBL.h" + +/* +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[sizeof(UInt32) + (mNumberBuffers * sizeof(AudioBuffer))]); +} + +AUOutputBL::~AUOutputBL() +{ + if (mBufferMemory) + delete[] mBufferMemory; + + if (mBufferList) + delete [] 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(-10874);//(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:%ld, mFrames:%ld, allocatedMemory:%c\n", mBufferList->mNumberBuffers, mFrames, (mBufferMemory != NULL ? 'T' : 'F')); + AudioBuffer *buf = &mBufferList->mBuffers[0]; + for (UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i, ++buf) + printf ("\tBuffer:%ld, Size:%ld, Chans:%ld, Buffer:%X\n", i, buf->mDataByteSize, buf->mNumberChannels, int(buf->mData)); +} +#endif + diff --git a/libs/appleutility/AUOutputBL.h b/libs/appleutility/AUOutputBL.h new file mode 100644 index 0000000000..b80588abac --- /dev/null +++ b/libs/appleutility/AUOutputBL.h @@ -0,0 +1,115 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + AUOutputBL.h + +=============================================================================*/ + +#ifndef __AUOutputBL_h__ +#define __AUOutputBL_h__ + +#include "CAStreamBasicDescription.h" +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreServices/CoreServices.h> +#else + #include <AssertMacros.h> +#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 (const AUOutputBL &c) {} + AUOutputBL& operator= (const AUOutputBL& c) { return *this; } +}; + +#endif // __AUOutputBL_h__ diff --git a/libs/appleutility/CAAudioChannelLayout.cpp b/libs/appleutility/CAAudioChannelLayout.cpp new file mode 100644 index 0000000000..585ff44fb7 --- /dev/null +++ b/libs/appleutility/CAAudioChannelLayout.cpp @@ -0,0 +1,138 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAAudioChannelLayout.cpp + +=============================================================================*/ + +//============================================================================= +// Includes +//============================================================================= + +// Self Include +#include "CAAudioChannelLayout.h" +#include <stdlib.h> +#include <string.h> + +//============================================================================= +// CAAudioChannelLayout +//============================================================================= + +AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions) +{ + UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions); + AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(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); +} + +// 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) +{ + fprintf (file, "\tTag=0x%lX, ", layout->mChannelLayoutTag); + if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) + fprintf (file, "Using Bitmap:0x%lX\n", layout->mChannelBitmap); + else { + fprintf (file, "Num Chan Descs=%ld\n", layout->mNumberChannelDescriptions); + const AudioChannelDescription *desc = layout->mChannelDescriptions; + for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; ++i, ++desc) { + fprintf (file, "\t\tLabel=%ld, Flags=0x%lX, ", desc->mChannelLabel, 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/CAAudioChannelLayout.h b/libs/appleutility/CAAudioChannelLayout.h new file mode 100644 index 0000000000..8f995b8614 --- /dev/null +++ b/libs/appleutility/CAAudioChannelLayout.h @@ -0,0 +1,162 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAAudioChannelLayout.h + +=============================================================================*/ +#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> + +#if !HAL_Build + #include "CAReferenceCounted.h" +#endif + +//============================================================================= +// CAAudioChannelLayout +//============================================================================= + +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 offsetof(AudioChannelLayout, mChannelDescriptions) + inNumberChannelDescriptions * sizeof(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; + + void SetWithTag(AudioChannelLayoutTag inTag); + + bool IsValid() const { return NumberChannels() > 0; } + UInt32 Size() const { return mLayoutHolder ? mLayoutHolder->Size() : 0; } + + UInt32 NumberChannels() const { return NumberChannels(Layout()); } + + AudioChannelLayoutTag Tag() const { return Layout().mChannelLayoutTag; } + const AudioChannelLayout& Layout() const { return mLayoutHolder->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 ACLRefCounter : public CAReferenceCounted { + public: + ACLRefCounter (UInt32 inDataSize) + { + if (inDataSize < offsetof(AudioChannelLayout, mChannelDescriptions)) + inDataSize = offsetof(AudioChannelLayout, mChannelDescriptions); + + mLayout = static_cast<AudioChannelLayout*>(malloc (inDataSize)); + memset (mLayout, 0, inDataSize); + mByteSize = inDataSize; + } + + const AudioChannelLayout & Layout() const { return *mLayout; } + + UInt32 Size () const { return mByteSize; } + + private: + AudioChannelLayout *mLayout; + UInt32 mByteSize; + + // 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 mLayout; } + ~ACLRefCounter() { if (mLayout) { free(mLayout); mLayout = NULL; } } + + private: + ACLRefCounter () : mLayout(NULL) { } + ACLRefCounter(const ACLRefCounter& c) : mLayout(NULL) { } + ACLRefCounter& operator=(const ACLRefCounter& c) { return *this; } + }; + + ACLRefCounter *mLayoutHolder; +#endif // HAL_Build + +}; + +#endif diff --git a/libs/appleutility/CAAudioChannelLayoutObject.cpp b/libs/appleutility/CAAudioChannelLayoutObject.cpp new file mode 100644 index 0000000000..8c4030048d --- /dev/null +++ b/libs/appleutility/CAAudioChannelLayoutObject.cpp @@ -0,0 +1,199 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAAudioChannelLayoutObject.cpp + +=============================================================================*/ + +#include "CAAudioChannelLayout.h" +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreServices/CoreServices.h> + #include <AudioToolbox/AudioFormat.h> +#else + #include <CoreServices.h> + #include <AudioFormat.h> +#endif + + +CAAudioChannelLayout::CAAudioChannelLayout () +{ + mLayoutHolder = new ACLRefCounter (offsetof(AudioChannelLayout, mChannelDescriptions)); +} + +//============================================================================= +// CAAudioChannelLayout::CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround) +{ + // this chooses default layouts based on the number of channels... + UInt32 theSize = CalculateByteSize (inNumberChannels); + + mLayoutHolder = new ACLRefCounter (theSize); + + AudioChannelLayout* layout = mLayoutHolder->GetLayout(); + + layout->mNumberChannelDescriptions = inNumberChannels; + + switch (inNumberChannels) + { + case 1: + layout->mChannelLayoutTag = kAudioChannelLayoutTag_Mono; + break; + case 2: + layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_Binaural : kAudioChannelLayoutTag_Stereo; + break; + case 4: + layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_Ambisonic_B_Format : kAudioChannelLayoutTag_AudioUnit_4; + break; + case 5: + layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_5_0 : kAudioChannelLayoutTag_AudioUnit_5; + break; + case 6: + layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_6_0 : kAudioChannelLayoutTag_AudioUnit_6; + break; + case 7: + layout->mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_7_0; + break; + case 8: + layout->mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_8; + break; + default: + // here we have a "broken" layout, in the sense that we haven't any idea how to lay this out + // the layout itself is all set to zeros + // ### no longer true ### + SetAllToUnknown(*layout, inNumberChannels); + break; + } +} + +//============================================================================= +// CAAudioChannelLayout::CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout::CAAudioChannelLayout (AudioChannelLayoutTag inLayoutTag) + : mLayoutHolder(NULL) +{ + SetWithTag(inLayoutTag); +} + +//============================================================================= +// CAAudioChannelLayout::CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout::CAAudioChannelLayout (const CAAudioChannelLayout &c) + : mLayoutHolder(NULL) +{ + *this = c; +} + + +//============================================================================= +// CAAudioChannelLayout::AudioChannelLayout +//============================================================================= +CAAudioChannelLayout::CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout) + : mLayoutHolder(NULL) +{ + *this = inChannelLayout; +} + +//============================================================================= +// CAAudioChannelLayout::~CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout::~CAAudioChannelLayout () +{ + if (mLayoutHolder) { + mLayoutHolder->release(); + mLayoutHolder = NULL; + } +} + +//============================================================================= +// CAAudioChannelLayout::CAAudioChannelLayout +//============================================================================= +CAAudioChannelLayout& CAAudioChannelLayout::operator= (const CAAudioChannelLayout &c) +{ + if (mLayoutHolder != c.mLayoutHolder) { + if (mLayoutHolder) + mLayoutHolder->release(); + + if ((mLayoutHolder = c.mLayoutHolder) != NULL) + mLayoutHolder->retain(); + } + + return *this; +} + +CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout) +{ + if (mLayoutHolder) + mLayoutHolder->release(); + + UInt32 theSize = CalculateByteSize (inChannelLayout->mNumberChannelDescriptions); + + mLayoutHolder = new ACLRefCounter (theSize); + + memcpy(mLayoutHolder->mLayout, inChannelLayout, theSize); + return *this; +} + +void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag) +{ + if (mLayoutHolder) + mLayoutHolder->release(); + + mLayoutHolder = new ACLRefCounter(offsetof(AudioChannelLayout, mChannelDescriptions[0])); + AudioChannelLayout* layout = mLayoutHolder->GetLayout(); + layout->mChannelLayoutTag = inTag; +} + +//============================================================================= +// CAAudioChannelLayout::operator== +//============================================================================= +bool CAAudioChannelLayout::operator== (const CAAudioChannelLayout &c) const +{ + if (mLayoutHolder == c.mLayoutHolder) + return true; + return Layout() == c.Layout(); +} + +//============================================================================= +// CAAudioChannelLayout::Print +//============================================================================= +void CAAudioChannelLayout::Print (FILE* file) const +{ + CAShowAudioChannelLayout (file, &Layout()); +} + diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CAAudioUnit.cpp new file mode 100644 index 0000000000..9244877d29 --- /dev/null +++ b/libs/appleutility/CAAudioUnit.cpp @@ -0,0 +1,1202 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAAudioUnit.cpp + +=============================================================================*/ + +#include "CAAudioUnit.h" + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <AudioUnit/MusicDevice.h> +#else + #include <MusicDevice.h> +#endif + +#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; +}; + + + +class CAAudioUnit::AUState : public CAReferenceCounted { +public: + AUState (Component inComp) + : mUnit(0), mNode (0) + { + OSStatus result = ::OpenAComponent (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 (mGetParamProc != NULL) { + return reinterpret_cast<AudioUnitGetParameterProc>(mGetParamProc) (mConnInstanceStorage, + inID, scope, element, &outValue); + } + return AudioUnitGetParameter(mUnit, inID, scope, element, &outValue); + } + + OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 value, UInt32 bufferOffsetFrames) + { + if (mSetParamProc != NULL) { + return reinterpret_cast<AudioUnitSetParameterProc>(mSetParamProc) (mConnInstanceStorage, + inID, scope, element, value, bufferOffsetFrames); + } + return AudioUnitSetParameter(mUnit, inID, scope, element, value, bufferOffsetFrames); + } + + OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags, + const AudioTimeStamp * inTimeStamp, + UInt32 inOutputBusNumber, + UInt32 inNumberFrames, + AudioBufferList * ioData) + { + if (mRenderProc != NULL) { + return reinterpret_cast<AudioUnitRenderProc>(mRenderProc) (mConnInstanceStorage, + ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData); + } + return AudioUnitRender(mUnit, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData); + } + + OSStatus MIDIEvent (UInt32 inStatus, + UInt32 inData1, + UInt32 inData2, + UInt32 inOffsetSampleFrame) + { +#if !TARGET_OS_WIN32 + if (mMIDIEventProc != NULL) { + return reinterpret_cast<MusicDeviceMIDIEventProc>(mMIDIEventProc) (mConnInstanceStorage, + inStatus, inData1, inData2, inOffsetSampleFrame); + } + return MusicDeviceMIDIEvent (mUnit, inStatus, inData1, inData2, inOffsetSampleFrame); +#else + return paramErr; +#endif + } + + OSStatus StartNote (MusicDeviceInstrumentID inInstrument, + MusicDeviceGroupID inGroupID, + NoteInstanceID * outNoteInstanceID, + UInt32 inOffsetSampleFrame, + const MusicDeviceNoteParams * inParams) + { +#if !TARGET_OS_WIN32 + return MusicDeviceStartNote (mUnit, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams); +#else + return paramErr; +#endif + } + OSStatus StopNote (MusicDeviceGroupID inGroupID, + NoteInstanceID inNoteInstanceID, + UInt32 inOffsetSampleFrame) + { +#if !TARGET_OS_WIN32 + return MusicDeviceStopNote (mUnit, inGroupID, inNoteInstanceID, inOffsetSampleFrame); +#else + return paramErr; +#endif + } + +private: + // get the fast dispatch pointers + void Init() + { + UInt32 size = sizeof(AudioUnitRenderProc); + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kAudioUnitRenderSelect, + &mRenderProc, &size) != noErr) + mRenderProc = NULL; + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kAudioUnitGetParameterSelect, + &mGetParamProc, &size) != noErr) + mGetParamProc = NULL; + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kAudioUnitSetParameterSelect, + &mSetParamProc, &size) != noErr) + mSetParamProc = NULL; + + if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, + kAudioUnitScope_Global, kMusicDeviceMIDIEventSelect, + &mMIDIEventProc, &size) != noErr) + mMIDIEventProc = NULL; + + if (mRenderProc || mGetParamProc || mSetParamProc || mMIDIEventProc) + mConnInstanceStorage = GetComponentInstanceStorage(mUnit); + else + mConnInstanceStorage = NULL; + } + + ProcPtr mRenderProc, mGetParamProc, mSetParamProc, mMIDIEventProc; + + void * mConnInstanceStorage; + +private: + // get the compiler to tell us when we do a bad thing!!! + AUState () {} + AUState (const AUState&) {} + AUState& operator= (const AUState&) { return *this; } +}; + + +CAAudioUnit::AUState::~AUState () +{ + if (mUnit && (mNode == 0)) { + ::CloseComponent (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 (-1, inUnit)) +{ +} + +CAAudioUnit::CAAudioUnit (const CAComponent& inComp) + : mComp (inComp), mDataPtr (0) +{ + mDataPtr = new AUState (mComp.Comp()); +} + +CAAudioUnit::CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit) + : mComp (inUnit), mDataPtr(new AUState (inNode, inUnit)) +{ +} + +CAAudioUnit::~CAAudioUnit () +{ + 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; +} + +#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))); +} + +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 (inChannelsOut == inChannelsIn) { + return true; + } + } + 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; +} + +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; +} + +bool CAAudioUnit::GetChannelLayouts (AudioUnitScope inScope, + AudioUnitElement inEl, + ChannelTagVector &outChannelVector) const +{ + if (HasChannelLayouts (inScope, inEl) == false) return false; + + UInt32 dataSize; + OSStatus result = AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_SupportedChannelLayoutTags, + inScope, inEl, + &dataSize, NULL); + + if (result == kAudioUnitErr_InvalidProperty) { + // if we get here we can do layouts but we've got the speaker config property + outChannelVector.erase (outChannelVector.begin(), outChannelVector.end()); + outChannelVector.push_back (kAudioChannelLayoutTag_Stereo); + outChannelVector.push_back (kAudioChannelLayoutTag_StereoHeadphones); + outChannelVector.push_back (kAudioChannelLayoutTag_Quadraphonic); + outChannelVector.push_back (kAudioChannelLayoutTag_AudioUnit_5_0); + return true; + } + + if (result) return false; + + bool canDo = false; + // 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 canDo; +} + +bool CAAudioUnit::HasChannelLayouts (AudioUnitScope inScope, + AudioUnitElement inEl) const +{ + OSStatus result = AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_SupportedChannelLayoutTags, + inScope, inEl, + NULL, NULL); + return !result; +} + +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); + + 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, + CAAudioChannelLayout &inLayout) +{ + OSStatus result = AudioUnitSetProperty (AU(), + kAudioUnitProperty_AudioChannelLayout, + inScope, inEl, + inLayout, inLayout.Size()); + return result; +} + +OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + 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; + require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home); + if (elCount) { + for (unsigned int i = 0; i < elCount; ++i) { + require_noerr (result = SetSampleRate (kAudioUnitScope_Input, i, inSampleRate), home); + } + } + + require_noerr (result = GetElementCount(kAudioUnitScope_Output, elCount), home); + if (elCount) { + for (unsigned int i = 0; i < elCount; ++i) { + 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.SetCanonical (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; + + CAStreamBasicDescription desc; + desc.mSampleRate = inSampleRate; + for (unsigned int i = 0; i < inNumElements; ++i) { + desc.SetCanonical (inChannelsPerElement[i], false); + 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)); +} + +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)); +} + +OSStatus CAAudioUnit::GetPresentPreset (AUPreset &outData) const +{ + UInt32 dataSize = sizeof(outData); + OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_PresentPreset, + kAudioUnitScope_Global, 0, + &outData, &dataSize); + 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); + } + } + return result; +} + +OSStatus CAAudioUnit::SetPresentPreset (AUPreset &inData) +{ + OSStatus result = AudioUnitSetProperty (AU(), kAudioUnitProperty_PresentPreset, + kAudioUnitScope_Global, 0, + &inData, sizeof (AUPreset)); + if (result == kAudioUnitErr_InvalidProperty) { + result = AudioUnitSetProperty (AU(), kAudioUnitProperty_CurrentPreset, + kAudioUnitScope_Global, 0, + &inData, sizeof (AUPreset)); + } + return result; +} + +bool CAAudioUnit::HasCustomView () const +{ + UInt32 dataSize = 0; + OSStatus result = GetPropertyInfo(kAudioUnitProperty_GetUIComponentList, + kAudioUnitScope_Global, 0, + &dataSize, NULL); + if (result || !dataSize) { + dataSize = 0; + result = GetPropertyInfo(kAudioUnitProperty_CocoaUI, + kAudioUnitScope_Global, 0, + &dataSize, NULL); + if (result || !dataSize) + return false; + } + return true; +} + +OSStatus CAAudioUnit::GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 &outValue) const +{ + return mDataPtr ? mDataPtr->GetParameter (inID, scope, element, outValue) : paramErr; +} + +OSStatus CAAudioUnit::SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, + Float32 value, UInt32 bufferOffsetFrames) +{ + return mDataPtr ? mDataPtr->SetParameter (inID, scope, element, value, bufferOffsetFrames) : 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) : paramErr; +} + +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 CAAudioUnit::Preroll (UInt32 inFrameSize) +{ + CAStreamBasicDescription desc; + OSStatus result = GetFormat (kAudioUnitScope_Input, 0, desc); + bool hasInput = false; + //we have input + if (result == noErr) + { + sRenderCallback.inputProc = PrerollRenderProc; + sRenderCallback.inputProcRefCon = 0; + + result = 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; + require_noerr (result = GetFormat (kAudioUnitScope_Output, 0, outputFormat), home); + { + AUOutputBL list (outputFormat, inFrameSize); + list.Prepare (); + + require_noerr (result = Render (&flags, &time, 0, inFrameSize, list.ABL()), home); + require_noerr (result = GlobalReset(), home); + } + +home: + if (hasInput) { + // remove our installed callback + sRenderCallback.inputProc = 0; + sRenderCallback.inputProcRefCon = 0; + + SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, + 0, &sRenderCallback, sizeof(sRenderCallback)); + } + return result; +} + +#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 > 8) { + mChans = new UInt32[elCount]; + mDidAllocate = true; + memset (mChans, 0, sizeof(int) * elCount); + } else { + mChans = mStaticChans; + memset (mChans, 0, sizeof(int) * 8); + } + for (unsigned int i = 0; i < elCount; ++i) { + UInt32 numChans; + if (inAU.NumberChannels (inScope, i, numChans)) return; + mChans[i] = numChans; + } + mNumEls = elCount; +} + +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); + } +} diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CAAudioUnit.h new file mode 100644 index 0000000000..6bc31bf30b --- /dev/null +++ b/libs/appleutility/CAAudioUnit.h @@ -0,0 +1,383 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAAudioUnit.h + +=============================================================================*/ + +#ifndef __CAAudioUnit_h__ +#define __CAAudioUnit_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreServices/CoreServices.h> + #include <CoreAudio/CoreAudio.h> + #include <AudioUnit/AudioUnit.h> + #include <AudioToolbox/AUGraph.h> +#else + #include <ConditionalMacros.h> + #include <CoreServices.h> + #include <CoreAudioTypes.h> + #include <AudioUnit.h> + #include <AUGraph.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 { +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 (); + + + 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; } + + bool FromAUGraph () const { return GetAUNode() != 0 || GetAUNode() != -1; } + + 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 Reset (AudioUnitScope scope, AudioUnitElement element) + { + return AudioUnitReset (AU(), scope, element); + } + OSStatus GlobalReset () + { + return AudioUnitReset (AU(), kAudioUnitScope_Global, 0); + } + + OSStatus Preroll (UInt32 inFrameSize); + + OSStatus AddRenderNotify (AURenderCallback inProc, void *inProcRefCon) + { + return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon); + } + + OSStatus RemoveRenderNotify (AURenderCallback inProc, void *inProcRefCon) + { + return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon); + } + + +// Fast dispatch support for MIDI Effects or Music Devices + 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; + + bool GetChannelLayouts (AudioUnitScope inScope, + AudioUnitElement inEl, + ChannelTagVector &outChannelVector) const; + + OSStatus GetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + CAAudioChannelLayout &outLayout) const; + + OSStatus SetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + CAAudioChannelLayout &inLayout); + + OSStatus SetChannelLayout (AudioUnitScope inScope, + AudioUnitElement inEl, + 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; + + 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 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; + +}; + +class CAAUChanHelper { +public: + CAAUChanHelper() + : mChans(mStaticChans), mNumEls(0), mDidAllocate(false) + { + memset (mChans, 0, sizeof(UInt32) * 8); + } + 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: + UInt32 mStaticChans[8]; + bool mDidAllocate; +}; + +#endif diff --git a/libs/appleutility/CACFDictionary.cpp b/libs/appleutility/CACFDictionary.cpp new file mode 100644 index 0000000000..c209b5fc36 --- /dev/null +++ b/libs/appleutility/CACFDictionary.cpp @@ -0,0 +1,478 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CACFDictionary.cpp + CAAudioEngine + +=============================================================================*/ + +//============================================================================= +// Includes +//============================================================================= + +// Self Include +#include "CACFDictionary.h" + +// PublicUtility Includes +#include "CACFString.h" +#include "CACFNumber.h" + +//============================================================================= +// CACFDictionary +//============================================================================= + +bool CACFDictionary::HasKey(const CFStringRef inKey) const +{ + return CFDictionaryContainsKey(mCFDictionary, inKey) != 0; +} + +UInt32 CACFDictionary::Size () const +{ + return CFDictionaryGetCount(mCFDictionary); +} + +void CACFDictionary::GetKeys (const void **keys) const +{ + CFDictionaryGetKeysAndValues(mCFDictionary, keys, NULL); +} + +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::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::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::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; +} + +bool CACFDictionary::AddSInt32(const CFStringRef inKey, SInt32 inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + CACFNumber theValue(inValue); + theAnswer = AddCFType(inKey, theValue.GetCFNumber()); + } + + return theAnswer; +} + +bool CACFDictionary::AddUInt32(const CFStringRef inKey, UInt32 inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + CACFNumber theValue(inValue); + theAnswer = AddCFType(inKey, theValue.GetCFNumber()); + } + + return theAnswer; +} + +bool CACFDictionary::AddSInt64(const CFStringRef inKey, SInt64 inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + CACFNumber theValue(inValue); + theAnswer = AddCFType(inKey, theValue.GetCFNumber()); + } + + return theAnswer; +} + +bool CACFDictionary::AddUInt64(const CFStringRef inKey, UInt64 inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + CACFNumber theValue(inValue); + theAnswer = AddCFType(inKey, theValue.GetCFNumber()); + } + + return theAnswer; +} + +bool CACFDictionary::AddFloat32(const CFStringRef inKey, Float32 inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + CACFNumber theValue(inValue); + theAnswer = AddCFType(inKey, theValue.GetCFNumber()); + } + + return theAnswer; +} + +bool CACFDictionary::AddFloat64(const CFStringRef inKey, Float64 inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + CACFNumber theValue(inValue); + theAnswer = AddCFType(inKey, theValue.GetCFNumber()); + } + + return theAnswer; +} + +bool CACFDictionary::AddNumber(const CFStringRef inKey, const CFNumberRef inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + theAnswer = AddCFType(inKey, inValue); + } + + return theAnswer; +} + +bool CACFDictionary::AddString(const CFStringRef inKey, const CFStringRef inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + theAnswer = AddCFType(inKey, inValue); + } + + return theAnswer; +} + +bool CACFDictionary::AddArray(const CFStringRef inKey, const CFArrayRef inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + theAnswer = AddCFType(inKey, inValue); + } + + return theAnswer; +} + +bool CACFDictionary::AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + theAnswer = AddCFType(inKey, inValue); + } + + return theAnswer; +} + +bool CACFDictionary::AddData(const CFStringRef inKey, const CFDataRef inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + theAnswer = AddCFType(inKey, inValue); + } + + return theAnswer; +} + +bool CACFDictionary::AddCFType(const CFStringRef inKey, const CFTypeRef inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + CFDictionarySetValue(mCFDictionary, inKey, inValue); + theAnswer = true; + } + + return theAnswer; +} + +bool CACFDictionary::AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue) +{ + bool theAnswer = false; + + if(mMutable && (mCFDictionary != NULL)) + { + 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(mMutable && (mCFDictionary != NULL)) + { + CACFString theValue(inValue); + if(theValue.IsValid()) + { + theAnswer = AddCFType(inKey, theValue.GetCFString()); + } + } + + return theAnswer; +} diff --git a/libs/appleutility/CACFDictionary.h b/libs/appleutility/CACFDictionary.h new file mode 100644 index 0000000000..362b1c8821 --- /dev/null +++ b/libs/appleutility/CACFDictionary.h @@ -0,0 +1,141 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CACFDictionary.h + +=============================================================================*/ +#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 + +//============================================================================= +// CACFDictionary +//============================================================================= + +class CACFDictionary +{ + +// Construction/Destruction +public: + CACFDictionary(bool inRelease) : mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(inRelease), mMutable(true) {} + CACFDictionary(const CFDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(const_cast<CFMutableDictionaryRef>(inCFDictionary)), mRelease(inRelease), mMutable(true) {} + CACFDictionary(const CFMutableDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(inCFDictionary), mRelease(inRelease), mMutable(true) {} + CACFDictionary(const CACFDictionary& inDictionary) : mCFDictionary(inDictionary.mCFDictionary), mRelease(inDictionary.mRelease), mMutable(inDictionary.mMutable) { if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } } + CACFDictionary& operator=(const CACFDictionary& inDictionary) { mCFDictionary = inDictionary.mCFDictionary; mRelease = inDictionary.mRelease; mMutable = inDictionary.mMutable; if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } return *this; } + ~CACFDictionary() { 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) { if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } mCFDictionary = CFDictionaryCreateMutableCopy(NULL, 0, inDictionary); 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; + + 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 GetSInt64(const CFStringRef inKey, SInt64& outValue) const; + bool GetUInt64(const CFStringRef inKey, UInt64& outValue) const; + bool GetFloat32(const CFStringRef inKey, Float32& outValue) const; + bool GetFloat64(const CFStringRef inKey, Float64& 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 GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const; + + 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 AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue); + bool AddCString(const CFStringRef inKey, const char* inValue); + + void Clear() { if(CanModify()) { CFDictionaryRemoveAllValues(mCFDictionary); } } + + void Show() { CFShow(mCFDictionary); } + +// Implementation +private: + CFMutableDictionaryRef mCFDictionary; + bool mRelease; + bool mMutable; +}; + +#endif //__CACFDictionary_h__ diff --git a/libs/appleutility/CACFNumber.cpp b/libs/appleutility/CACFNumber.cpp new file mode 100644 index 0000000000..3b6160c8bb --- /dev/null +++ b/libs/appleutility/CACFNumber.cpp @@ -0,0 +1,65 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CACFNumber.cp + +=============================================================================*/ + +//============================================================================= +// 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.0 : 1.0; + theFixedValue *= (SInt32)theSign; + Float32 theWholePart = (theFixedValue & 0x7FFF0000) >> 16; + Float32 theFractPart = theFixedValue & 0x0000FFFF; + theFractPart /= 65536.0; + + return theSign * (theWholePart + theFractPart); +} diff --git a/libs/appleutility/CACFNumber.h b/libs/appleutility/CACFNumber.h new file mode 100644 index 0000000000..3991637bac --- /dev/null +++ b/libs/appleutility/CACFNumber.h @@ -0,0 +1,102 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CACFNumber.h + +=============================================================================*/ +#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 + +//============================================================================= +// CACFNumber +//============================================================================= + +class CACFNumber +{ +// Construction/Destruction +public: + CACFNumber(CFNumberRef inCFNumber, bool inWillRelease = true) : 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() { 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; } + Float32 GetFloat32() const { Float32 theAnswer = 0.0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberFloat32Type, &theAnswer); } return theAnswer; } + Float32 GetFixed32() const; + SInt64 GetSInt64() const { SInt64 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt64Type, &theAnswer); } return theAnswer; } +}; + +#endif diff --git a/libs/appleutility/CACFString.cpp b/libs/appleutility/CACFString.cpp new file mode 100644 index 0000000000..ec3b18a8b6 --- /dev/null +++ b/libs/appleutility/CACFString.cpp @@ -0,0 +1,106 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CACFString.cp + +=============================================================================*/ + +//============================================================================= +// Includes +//============================================================================= + +#include "CACFString.h" + +//============================================================================= +// CACFString +//============================================================================= + +UInt32 CACFString::GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding) +{ + UInt32 theAnswer = 0; + + if(inCFString != NULL) + { + CFRange theRange = { 0, CFStringGetLength(inCFString) }; + CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, NULL, 0x7FFFFFFF, (CFIndex*)&theAnswer); + } + + return 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, ioStringSize - 1, &theLength); + outString[theLength] = 0; + ioStringSize = 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 = ioStringSize; + } + CFStringGetCharacters(inCFString, theStringRange, outString); + ioStringSize = theStringRange.length; + } + else + { + outString[0] = 0; + ioStringSize = 0; + } + } +} diff --git a/libs/appleutility/CACFString.h b/libs/appleutility/CACFString.h new file mode 100644 index 0000000000..51fa64ebff --- /dev/null +++ b/libs/appleutility/CACFString.h @@ -0,0 +1,156 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CACFString.h + +=============================================================================*/ +#if !defined(__CACFString_h__) +#define __CACFString_h__ + +//============================================================================= +// Includes +//============================================================================= + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreAudio/CoreAudioTypes.h> + #include <CoreFoundation/CFString.h> +#else + #include <CoreAudioTypes.h> + #include <CFString.h> +#endif + +//============================================================================= +// CACFString +//============================================================================= + +class CACFString +{ +// Construction/Destruction +public: + CACFString() : mCFString(NULL), mWillRelease(true) {} + CACFString(CFStringRef inCFString, bool inWillRelease = true) : mCFString(inCFString), mWillRelease(inWillRelease) {} + CACFString(const char* inCString, bool inWillRelease = true) : 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) { Release(); mCFString = inString.mCFString; mWillRelease = inString.mWillRelease; Retain(); return *this; } + CACFString& operator=(CFStringRef inCFString) { Release(); mCFString = inCFString; mWillRelease = true; return *this; } + +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 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; } + UInt32 GetLength() const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = 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); } + + 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); + +}; + +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)); } + +//============================================================================= +// 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 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 = 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); } + +}; + +#endif diff --git a/libs/appleutility/CAComponent.cpp b/libs/appleutility/CAComponent.cpp new file mode 100644 index 0000000000..700d9e2b3e --- /dev/null +++ b/libs/appleutility/CAComponent.cpp @@ -0,0 +1,257 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAComponent.cpp + +=============================================================================*/ + +#include "CAComponent.h" +#include "CAComponentDescription.h" +#include "CACFDictionary.h" +#include <stdlib.h> + +CAComponent::CAComponent (const ComponentDescription& inDesc, CAComponent* next) + : mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) +{ + mComp = FindNextComponent ((next ? next->Comp() : NULL), const_cast<ComponentDescription*>(&inDesc)); + if (mComp) + GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL); + else + memcpy (&mDesc, &inDesc, sizeof(ComponentDescription)); +} + +CAComponent::CAComponent (const Component& comp) + : mComp (comp), + mManuName(0), + mAUName(0), + mCompName(0), + mCompInfo (0) +{ + GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL); +} + +CAComponent::CAComponent (const ComponentInstance& compInst) + : mComp (Component(compInst)), + mManuName(0), + mAUName(0), + mCompName(0), + mCompInfo (0) +{ + GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL); +} + +CAComponent::CAComponent (OSType inType, OSType inSubtype, OSType inManu) + : mDesc (inType, inSubtype, inManu), + mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) +{ + mComp = FindNextComponent (NULL, &mDesc); + GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL); +} + +CAComponent::~CAComponent () +{ + Clear(); +} + +OSStatus CAComponent::GetResourceVersion (UInt32 &outVersion) const +{ + bool versionFound = false; + short componentResFileID = kResFileNotOpened; + OSStatus result; + short thngResourceCount; + + short curRes = CurResFile(); + require_noerr (result = OpenAComponentResFile( mComp, &componentResFileID), home); + require_noerr (result = componentResFileID <= 0, home); + + UseResFile(componentResFileID); + + thngResourceCount = Count1Resources(kComponentResourceType); + + require_noerr (result = ResError(), home); + // only go on if we successfully found at least 1 thng resource + require_noerr (thngResourceCount <= 0 ? -1 : 0, home); + + // loop through all of the Component thng resources trying to + // find one that matches this Component description + for (short i = 0; i < thngResourceCount && (!versionFound); i++) + { + // try to get a handle to this code resource + Handle thngResourceHandle = Get1IndResource(kComponentResourceType, i+1); + if (thngResourceHandle != NULL && ((*thngResourceHandle) != NULL)) + { + if (UInt32(GetHandleSize(thngResourceHandle)) >= sizeof(ExtComponentResource)) + { + ExtComponentResource * componentThng = (ExtComponentResource*) (*thngResourceHandle); + + // check to see if this is the thng resource for the particular Component that we are looking at + // (there often is more than one Component described in the resource) + if ((componentThng->cd.componentType == mDesc.Type()) + && (componentThng->cd.componentSubType == mDesc.SubType()) + && (componentThng->cd.componentManufacturer == mDesc.Manu())) + { + outVersion = componentThng->componentVersion; + versionFound = true; + } + } + ReleaseResource(thngResourceHandle); + } + } + + if (!versionFound) + result = resNotFound; + + UseResFile(curRes); // revert + + if ( componentResFileID != kResFileNotOpened ) + CloseComponentResFile(componentResFileID); + +home: + return result; +} + +void CAComponent::Clear () +{ + if (mManuName) { CFRelease (mManuName); mManuName = 0; } + if (mAUName) { CFRelease (mAUName); mAUName = 0; } + if (mCompName) { CFRelease (mCompName); mCompName = 0; } + if (mCompInfo) { CFRelease (mCompInfo); mCompInfo = 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); } + if (y.mCompInfo) { mCompInfo = y.mCompInfo; CFRetain (mCompInfo); } + + return *this; +} + +void CAComponent::SetCompNames () const +{ + if (!mCompName) { + Handle h1 = NewHandle(4); + CAComponentDescription desc; + OSStatus err = GetComponentInfo (Comp(), &desc, h1, 0, 0); + + if (err) { DisposeHandle(h1); return; } + + HLock(h1); + char* ptr1 = *h1; + // Get the manufacturer's name... look for the ':' character convention + int len = *ptr1++; + char* displayStr = 0; + + const_cast<CAComponent*>(this)->mCompName = CFStringCreateWithPascalString(NULL, (const unsigned char*)*h1, kCFStringEncodingMacRoman); + + for (int i = 0; i < len; ++i) { + if (ptr1[i] == ':') { // found the name + ptr1[i] = 0; + displayStr = ptr1; + break; + } + } + + if (displayStr) + { + const_cast<CAComponent*>(this)->mManuName = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingMacRoman); + + //move displayStr ptr past the manu, to the name + // we move the characters down a index, because the handle doesn't have any room + // at the end for the \0 + int i = strlen(displayStr), j = 0; + while (displayStr[++i] == ' ' && i < len) + ; + while (i < len) + displayStr[j++] = displayStr[i++]; + displayStr[j] = 0; + + const_cast<CAComponent*>(this)->mAUName = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingMacRoman); + } + + DisposeHandle (h1); + } +} + +void CAComponent::SetCompInfo () const +{ + if (!mCompInfo) { + Handle h1 = NewHandle(4); + CAComponentDescription desc; + OSStatus err = GetComponentInfo (Comp(), &desc, 0, h1, 0); + if (err) return; + HLock (h1); + const_cast<CAComponent*>(this)->mCompInfo = CFStringCreateWithPascalString(NULL, (const unsigned char*)*h1, kCFStringEncodingMacRoman); + + DisposeHandle (h1); + } +} + +void _ShowCF (FILE* file, CFStringRef str) +{ + if (CFGetTypeID(str) != CFStringGetTypeID()) { + CFShow(str); + return; + } + + UInt32 len = CFStringGetLength(str); + char* chars = (char*)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: 0x%X", int(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/CAComponent.h b/libs/appleutility/CAComponent.h new file mode 100644 index 0000000000..2ace42532d --- /dev/null +++ b/libs/appleutility/CAComponent.h @@ -0,0 +1,120 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAComponent.h + +=============================================================================*/ + +#ifndef __CAComponent_h__ +#define __CAComponent_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreServices/CoreServices.h> +#else + #include <ConditionalMacros.h> + #include <CoreServices.h> +#endif + +#include "CAComponentDescription.h" + +class CAComponent +{ +public: + CAComponent () + : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) {} + + // if next is specifed that is used to find the next component after that one + CAComponent (const ComponentDescription& inDesc, CAComponent* next = 0); + + CAComponent (const CAComponent& y) + : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) { *this = y; } + + CAComponent (const Component& comp); + + CAComponent (const ComponentInstance& 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; } + CFStringRef GetCompInfo () const { SetCompInfo(); return mCompInfo; } + + const CAComponentDescription& Desc () const { return mDesc; } + + OSStatus Open (ComponentInstance& outInst) const + { + return OpenAComponent (Comp(), &outInst); + } + + OSStatus GetResourceVersion (UInt32 &outVersion) const; + + const Component& Comp() const { return mComp; } + + void Print(FILE* file = stdout) const; + + OSStatus Save (CFPropertyListRef *outData) const; + + OSStatus Restore (CFPropertyListRef &inData); + +private: + Component mComp; + CAComponentDescription mDesc; + + CFStringRef mManuName, mAUName, mCompName, mCompInfo; + + void SetCompNames () const; + void SetCompInfo () const; + void Clear (); +}; + +#endif diff --git a/libs/appleutility/CAComponentDescription.cpp b/libs/appleutility/CAComponentDescription.cpp new file mode 100644 index 0000000000..261a2b881c --- /dev/null +++ b/libs/appleutility/CAComponentDescription.cpp @@ -0,0 +1,123 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAComponentDescription.cpp + +=============================================================================*/ + +#include "CAComponentDescription.h" +#include <ctype.h> + +extern "C" void CAShowComponentDescription(const ComponentDescription *desc) +{ + CAComponentDescription::_CAShowComponentDescription (desc, stdout); +} + +char *StringForOSType (OSType t, char *writeLocation) +{ + char *p = writeLocation; + unsigned char str[4], *q = str; + *(UInt32 *)str = EndianU32_NtoB(t); + for (int i = 0; i < 4; ++i) { + if (isprint(*q) && *q != '\\') + *p++ = *q++; + else { + sprintf(p, "\\x%02X", *q++); + p += 4; + } + } + *p = '\0'; + return writeLocation; +} + + +void CAComponentDescription::_CAShowComponentDescription(const ComponentDescription *desc, FILE* file) +{ + if (desc) + { + char str[24]; + fprintf (file, "ComponentDescription: %s - ", StringForOSType(desc->componentType, str)); + fprintf (file, "%s - ", StringForOSType(desc->componentSubType, str)); + fprintf (file, "%s", StringForOSType(desc->componentManufacturer, str)); + fprintf (file, ", 0x%lX, 0x%lX\n", desc->componentFlags, 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 ComponentDescription &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/CAComponentDescription.h b/libs/appleutility/CAComponentDescription.h new file mode 100644 index 0000000000..a681902b91 --- /dev/null +++ b/libs/appleutility/CAComponentDescription.h @@ -0,0 +1,148 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAComponentDescription.h + +=============================================================================*/ + +#ifndef __CAComponentDescription_h__ +#define __CAComponentDescription_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreServices/CoreServices.h> + #include <AudioUnit/AudioUnit.h> +#else + #include <ConditionalMacros.h> + #include <CoreServices.h> + #include <AudioUnit.h> +#endif + +#include "CACFDictionary.h" +#include <stdio.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif + +void CAShowComponentDescription(const ComponentDescription *desc); + +#ifdef __cplusplus +} +#endif + + +// ____________________________________________________________________________ +// +// CAComponentDescription +class CAComponentDescription : public ComponentDescription { +public: + CAComponentDescription() { memset (this, 0, sizeof (ComponentDescription)); } + + CAComponentDescription (OSType inType, OSType inSubtype = 0, OSType inManu = 0); + + CAComponentDescription(const ComponentDescription& desc) { memcpy (this, &desc, sizeof (ComponentDescription)); } + + // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + // + // interrogation + + bool IsAU () const; + + bool IsAUFX() const { return componentType == kAudioUnitType_Effect; } + bool IsAUFM() const { return componentType == kAudioUnitType_MusicEffect; } + + bool IsEffect () const { return IsAUFX() || IsAUFM() || IsPanner(); } + + bool IsOffline () const { return componentType == 'auol'; } + + 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 CountComponents(const_cast<CAComponentDescription*>(this)); } + + // does a semantic match where "wild card" values for type, subtype, manu will match + bool Matches (const ComponentDescription &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 ComponentDescription *desc, FILE* file); + friend void CAShowComponentDescription (const ComponentDescription *desc); +}; + +inline bool operator< (const ComponentDescription& x, const ComponentDescription& y) +{ + return memcmp (&x, &y, offsetof (ComponentDescription, componentFlags)) < 0; +} + +inline bool operator== (const ComponentDescription& x, const ComponentDescription& y) +{ + return !memcmp (&x, &y, offsetof (ComponentDescription, componentFlags)); +} + +inline bool operator!= (const ComponentDescription& x, const ComponentDescription& y) +{ + return !(x == y); +} + +#endif diff --git a/libs/appleutility/CAConditionalMacros.h b/libs/appleutility/CAConditionalMacros.h new file mode 100644 index 0000000000..62f642709a --- /dev/null +++ b/libs/appleutility/CAConditionalMacros.h @@ -0,0 +1,74 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAConditionalMacros.h + +=============================================================================*/ +#if !defined(__CAConditionalMacros_h__) +#define __CAConditionalMacros_h__ + +//============================================================================= +// This file exists to make figuring out how to include system headers +// easier in a cross platform world. We throw in an include of the standard +// ConditionalMacros too. +//============================================================================= + +// ########## THIS FILE SHOULD GO AWAY SOON, replaced by __COREAUDIO_USE_FLAT_INCLUDES__ +// but for now, use this as a way to define __COREAUDIO_USE_FLAT_INCLUDES__ programmatically + +// TargetConditionals.h defines the bare minimum we need +#include "TargetConditionals.h" + +// Determine whether or not to use framework style includes for system headers +#if !defined(CoreAudio_Use_Framework_Includes) && !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #if TARGET_RT_MAC_MACHO + #define CoreAudio_Use_Framework_Includes 1 + #else + #define CoreAudio_Use_Framework_Includes 0 + #endif +#endif + +// Include the regular ConditionalMacros.h too, since it has useful stuff that +// TargetConditionals.h lacks for some reason. +#if CoreAudio_Use_Framework_Includes + #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/ConditionalMacros.h> +#else + #include "ConditionalMacros.h" +#endif + +#endif diff --git a/libs/appleutility/CADebugMacros.cpp b/libs/appleutility/CADebugMacros.cpp new file mode 100644 index 0000000000..edee1f3d51 --- /dev/null +++ b/libs/appleutility/CADebugMacros.cpp @@ -0,0 +1,84 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CADebugMacros.cp + +=============================================================================*/ + +#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 + +#if TARGET_API_MAC_OSX +void LogError(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); +#if DEBUG + vprintf(fmt, args); +#endif + vsyslog(LOG_ERR, fmt, args); + va_end(args); +} + +void LogWarning(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); +#if DEBUG + vprintf(fmt, args); +#endif + vsyslog(LOG_WARNING, fmt, args); + va_end(args); +} +#endif diff --git a/libs/appleutility/CADebugMacros.h b/libs/appleutility/CADebugMacros.h new file mode 100644 index 0000000000..1abae40187 --- /dev/null +++ b/libs/appleutility/CADebugMacros.h @@ -0,0 +1,414 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CADebugMacros.h + +=============================================================================*/ +#if !defined(__CADebugMacros_h__) +#define __CADebugMacros_h__ + +//============================================================================= +// CADebugMacros +//============================================================================= + +//#define CoreAudio_StopOnFailure 1 +//#define CoreAudio_TimeStampMessages 1 +//#define CoreAudio_ThreadStampMessages 1 +//#define CoreAudio_FlushDebugMessages 1 + +#define CA4CCToCString(the4CC) { ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 } + +#pragma mark Basic Definitions + +#if DEBUG || CoreAudio_Debug + + // can be used to break into debugger immediately, also see CADebugger + #define BusError() (*(long *)0 = 0) + + // basic debugging print routines + #if TARGET_OS_MAC && !TARGET_API_MAC_CARBON + extern pascal 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" + #define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: %s"DebugPrintfLineEnding, pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn + #define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn + #define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn + #define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn + #define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4) FlushRtn + #define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5) FlushRtn + #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6) FlushRtn + #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7) FlushRtn + #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn + #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn + #elif CoreAudio_TimeStampMessages + #include "CAHostTimeBase.h" + #define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFile, "%.4f: %s"DebugPrintfLineEnding, pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn + #define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn + #define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn + #define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn + #define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4) FlushRtn + #define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5) FlushRtn + #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6) FlushRtn + #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7) FlushRtn + #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn + #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn + #else + #define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFile, "%s"DebugPrintfLineEnding, msg) FlushRtn + #define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1) FlushRtn + #define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2) FlushRtn + #define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3) FlushRtn + #define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4) FlushRtn + #define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5) FlushRtn + #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6) FlushRtn + #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7) FlushRtn + #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn + #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn + #endif + #endif + void DebugPrint(const char *fmt, ...); // can be used like printf + #define DEBUGPRINT(msg) DebugPrint msg // have to double-parenthesize arglist (see Debugging.h) + #if VERBOSE + #define vprint(msg) DEBUGPRINT(msg) + #else + #define vprint(msg) + #endif + + #if CoreAudio_StopOnFailure + #include "CADebugger.h" + #define STOP CADebuggerStop() + #else + #define STOP + #endif + +#else + #define DebugMessage(msg) + #define DebugMessageN1(msg, N1) + #define DebugMessageN2(msg, N1, N2) + #define DebugMessageN3(msg, N1, N2, N3) + #define DebugMessageN4(msg, N1, N2, N3, N4) + #define DebugMessageN5(msg, N1, N2, N3, N4, N5) + #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) + #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) + #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) + #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) + #define DEBUGPRINT(msg) + #define vprint(msg) + #define STOP +#endif + +void LogError(const char *fmt, ...); // writes to syslog (and stderr if debugging) +void LogWarning(const char *fmt, ...); // writes to syslog (and stderr if debugging) + +#if DEBUG || CoreAudio_Debug + +#pragma mark Debug Macros + +#define Assert(inCondition, inMessage) \ + if(!(inCondition)) \ + { \ + DebugMessage(inMessage); \ + STOP; \ + } + +#define AssertNoError(inError, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + char __4CC[5] = CA4CCToCString(__Err); \ + DebugMessageN2(inMessage ", Error: %ld (%s)", __Err, __4CC); \ + STOP; \ + } \ + } + +#define AssertNoKernelError(inError, inMessage) \ + { \ + unsigned int __Err = (unsigned int)(inError); \ + if(__Err != 0) \ + { \ + DebugMessageN1(inMessage ", Error: 0x%X", __Err); \ + 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, inException, inMessage) \ + { \ + kern_return_t __Err = (inKernelError); \ + if(__Err != 0) \ + { \ + DebugMessageN1(inMessage ", Error: 0x%X", __Err); \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } \ + } + +#define FailIfError(inError, inException, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + char __4CC[5] = CA4CCToCString(__Err); \ + DebugMessageN2(inMessage ", Error: %ld (%s)", __Err, __4CC); \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } \ + } + +#if defined(__cplusplus) + +#define Throw(inException) 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) \ + { \ + kern_return_t __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: %ld (%s)", __Err, __4CC); \ + Throw(inException); \ + } \ + } + +#if TARGET_OS_WIN32 +#define ThrowIfWinError(inError, inException, inMessage) \ + { \ + HRESULT __Err = (inError); \ + if(FAILED(__Err)) \ + { \ + DebugMessageN1(inMessage ", Error: 0x%X", __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)) \ + { \ + STOP; \ + } + +#define AssertNoError(inError, inMessage) \ + { \ + SInt32 __Err = (inError); \ + if(__Err != 0) \ + { \ + STOP; \ + } \ + } + +#define AssertNoKernelError(inError, inMessage) \ + { \ + unsigned int __Err = (unsigned int)(inError); \ + if(__Err != 0) \ + { \ + 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, inException, inMessage) \ + if((inKernelError) != 0) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#define FailIfError(inError, inException, inMessage) \ + if((inError) != 0) \ + { \ + STOP; \ + { inAction; } \ + goto inHandler; \ + } + +#if defined(__cplusplus) + +#define Throw(inException) 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) \ + { \ + kern_return_t __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/CAMath.h b/libs/appleutility/CAMath.h new file mode 100644 index 0000000000..32b4e7f0b3 --- /dev/null +++ b/libs/appleutility/CAMath.h @@ -0,0 +1,64 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAMath.h + +=============================================================================*/ + +#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/CAReferenceCounted.h b/libs/appleutility/CAReferenceCounted.h new file mode 100644 index 0000000000..d57f97c31f --- /dev/null +++ b/libs/appleutility/CAReferenceCounted.h @@ -0,0 +1,83 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAReferenceCounted.h + +=============================================================================*/ + +#ifndef __CAReferenceCounted_h__ +#define __CAReferenceCounted_h__ + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include <CoreServices/CoreServices.h> +#else + #include <CoreServices.h> +#endif + +#if TARGET_OS_WIN32 + #include "CAWindows.h" +#endif + +// base class for reference-counted objects +class CAReferenceCounted { +public: + CAReferenceCounted() : mRefCount(1) {} + + void retain() { IncrementAtomic(&mRefCount); } + + void release() + { + // this returns the ORIGINAL value, not the new one. + SInt32 rc = DecrementAtomic(&mRefCount); + if (rc == 1) { + delete this; + } + } + +protected: + virtual ~CAReferenceCounted() { } + +private: + SInt32 mRefCount; + + CAReferenceCounted(const CAReferenceCounted &a) : mRefCount(0) { } + CAReferenceCounted operator=(const CAReferenceCounted &a) { return *this; } +}; + + +#endif // __CAReferenceCounted_h__ diff --git a/libs/appleutility/CAStreamBasicDescription.cpp b/libs/appleutility/CAStreamBasicDescription.cpp new file mode 100644 index 0000000000..f65bdd99ac --- /dev/null +++ b/libs/appleutility/CAStreamBasicDescription.cpp @@ -0,0 +1,520 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAStreamBasicDescription.cpp + +=============================================================================*/ + +#include "CAConditionalMacros.h" + +#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 more earlier versions of the OS, so please keep that in mind when editing it + +const AudioStreamBasicDescription CAStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +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; +} + +void CAStreamBasicDescription::PrintFormat(FILE *f, const char *indent, const char *name) const +{ + fprintf(f, "%s%s ", indent, name); + char formatID[5]; + *(UInt32 *)formatID = CFSwapInt32HostToBig(mFormatID); + formatID[4] = '\0'; + fprintf(f, "%2ld ch, %6.0f Hz, '%-4.4s' (0x%08lX) ", + NumberChannels(), mSampleRate, formatID, + mFormatFlags); + if (mFormatID == kAudioFormatLinearPCM) { + bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat); + int wordSize = 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) + sprintf(packed, "packed in %d bytes", wordSize); + else + sprintf(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') ? ", " : ""; + + fprintf(f, "%ld-bit%s%s %s%s%s%s%s\n", + mBitsPerChannel, endian, sign, floatInt, + commaSpace, packed, align, deinter); + } else if (mFormatID == 'alac') { // 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) + fprintf(f, "from %d-bit source, ", sourceBits); + else + fprintf(f, "from UNKNOWN source bit depth, "); + + fprintf(f, "%ld frames/packet\n", mFramesPerPacket); + } + else + fprintf(f, "%ld bits/channel, %ld bytes/packet, %ld frames/packet, %ld bytes/frame\n", + mBitsPerChannel, mBytesPerPacket, mFramesPerPacket, mBytesPerFrame); +} + +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 is 32 bit native endian floats + ioDescription.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; + ioDescription.mBytesPerPacket = sizeof(Float32) * ioDescription.mChannelsPerFrame; + ioDescription.mFramesPerPacket = 1; + ioDescription.mBytesPerFrame = sizeof(Float32) * ioDescription.mChannelsPerFrame; + ioDescription.mBitsPerChannel = 8 * sizeof(Float32); + } +} + +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, bool inAbbreviate) +{ + 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) + { + sprintf(outName, "%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 + { + sprintf(outName, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel); + } + } + else + { + if(thePackingString != NULL) + { + sprintf(outName, "%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 + { + sprintf(outName, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel); + } + } + } + else + { + if(theEndianString != NULL) + { + if(thePackingString != NULL) + { + sprintf(outName, "%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 + { + sprintf(outName, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString); + } + } + else + { + if(thePackingString != NULL) + { + sprintf(outName, "%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 + { + sprintf(outName, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString); + } + } + } + } + break; + + case kAudioFormatAC3: + strcpy(outName, "AC-3"); + break; + + case kAudioFormat60958AC3: + strcpy(outName, "AC-3 for SPDIF"); + break; + + default: + { + char* the4CCString = (char*)&inDescription.mFormatID; + outName[0] = the4CCString[0]; + outName[1] = the4CCString[1]; + outName[2] = the4CCString[2]; + outName[3] = the4CCString[3]; + outName[4] = 0; + } + 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; +} + +static bool MatchFormatFlags(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) +{ + UInt32 xFlags = x.mFormatFlags; + UInt32 yFlags = y.mFormatFlags; + + // match wildcards + if (x.mFormatID == 0 || y.mFormatID == 0 || xFlags == 0 || yFlags == 0) + return true; + + 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 & ~kAudioFormatFlagIsAlignedHigh; + yFlags = yFlags & ~kAudioFormatFlagIsAlignedHigh; + } + + // if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit. + if (xFlags & yFlags & kAudioFormatFlagIsFloat) { + xFlags = xFlags & ~kAudioFormatFlagIsSignedInteger; + yFlags = yFlags & ~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 & ~kAudioFormatFlagIsBigEndian; + } + if((y.mBitsPerChannel <= 8) && ((yFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked)) + { + yFlags = yFlags & ~kAudioFormatFlagIsBigEndian; + } + + // if the number of channels is 0 or 1, we don't care about non-interleavedness + if (x.mChannelsPerFrame <= 1 && y.mChannelsPerFrame <= 1) { + xFlags &= ~kLinearPCMFormatFlagIsNonInterleaved; + yFlags &= ~kLinearPCMFormatFlagIsNonInterleaved; + } + } + return xFlags == yFlags; +} + +bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) +{ + // the semantics for equality are: + // 1) Values must match exactly + // 2) wildcard's are ignored in the comparison + +#define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name)) + + return + // check the sample rate + (fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate)) + + // check the format ids + && MATCH(mFormatID) + + // check the format flags + && MatchFormatFlags(x, y) + + // 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 SanityCheck(const AudioStreamBasicDescription& x) +{ + return (x.mSampleRate >= 0.); +} diff --git a/libs/appleutility/CAStreamBasicDescription.h b/libs/appleutility/CAStreamBasicDescription.h new file mode 100644 index 0000000000..aa41c40fe4 --- /dev/null +++ b/libs/appleutility/CAStreamBasicDescription.h @@ -0,0 +1,224 @@ +/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. +*/ +/*============================================================================= + CAStreamBasicDescription.h + +=============================================================================*/ + +#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 + +// 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; + +// Construction/Destruction +public: + CAStreamBasicDescription() { memset (this, 0, sizeof(AudioStreamBasicDescription)); } + + CAStreamBasicDescription(const AudioStreamBasicDescription &desc) + { + SetFrom(desc); + } + + CAStreamBasicDescription( double inSampleRate, UInt32 inFormatID, + UInt32 inBytesPerPacket, UInt32 inFramesPerPacket, + UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame, + UInt32 inBitsPerChannel, UInt32 inFormatFlags); + +// Assignment + CAStreamBasicDescription& operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; } + + void SetFrom(const AudioStreamBasicDescription &desc) + { + memcpy(this, &desc, sizeof(AudioStreamBasicDescription)); + } + + // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + // + // 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 !IsPCM() || !(mFormatFlags & kAudioFormatFlagIsNonInterleaved); + } + + // 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) ? 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(); + } + + // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + // + // manipulation + + void SetCanonical(UInt32 nChannels, bool interleaved) + // note: leaves sample rate untouched + { + mFormatID = kAudioFormatLinearPCM; + mFormatFlags = kAudioFormatFlagsNativeFloatPacked; + mBitsPerChannel = 32; + mChannelsPerFrame = nChannels; + mFramesPerPacket = 1; + if (interleaved) + mBytesPerPacket = mBytesPerFrame = nChannels * sizeof(Float32); + else { + mBytesPerPacket = mBytesPerFrame = sizeof(Float32); + 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 &= ~kAudioFormatFlagIsNonInterleaved; + } else { + mBytesPerPacket = mBytesPerFrame = wordSize; + mFormatFlags |= kAudioFormatFlagIsNonInterleaved; + } + } + + // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + // + // other + + void Print() const + { + Print (stdout); + } + + void Print(FILE* file) const + { + PrintFormat (file, "", "AudioStreamBasicDescription:"); + } + + void PrintFormat(FILE *f, const char *indent, const char *name) const; + + 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 ResetFormat(AudioStreamBasicDescription& ioDescription); + static void FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription); + static void GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, bool inAbbreviate); +#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/SConscript b/libs/appleutility/SConscript new file mode 100644 index 0000000000..2f3280f8b6 --- /dev/null +++ b/libs/appleutility/SConscript @@ -0,0 +1,23 @@ +# -*- python -*- + +import os +import os.path +import glob + +appleutility_files = glob.glob('*.cpp') + +Import('env install_prefix') +appleutility = env.Copy() + +appleutility.Append(LINKFLAGS='-framework AudioToolbox') +appleutility.Append(LINKFLAGS='-framework AudioUnit') +appleutility.Append(LINKFLAGS='-framework CoreFoundation') +appleutility.Append(LINKFLAGS='-framework CoreServices') + +libappleutility = appleutility.SharedLibrary('appleutility', appleutility_files) + +Default(libappleutility) + +env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), libappleutility)) + +env.Alias('tarball', env.Distribute (env['DISTTREE'], ['SConscript'] + appleutility_files + glob.glob('*.h') )) diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h index ec437109a4..51ef00c592 100644 --- a/libs/ardour/ardour/audio_unit.h +++ b/libs/ardour/ardour/audio_unit.h @@ -50,7 +50,7 @@ class AUPluginInfo : public PluginInfo { static PluginInfoList discover (); private: - friend class PluginManager; + static std::string get_name (ComponentDescription&); }; typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr; diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h index 8543ad5285..e051eb2a58 100644 --- a/libs/ardour/ardour/plugin_manager.h +++ b/libs/ardour/ardour/plugin_manager.h @@ -25,7 +25,6 @@ class PluginManager { ARDOUR::PluginInfoList &vst_plugin_info () { return _vst_plugin_info; } ARDOUR::PluginInfoList &ladspa_plugin_info () { return _ladspa_plugin_info; } - ARDOUR::PluginInfoList &au_plugin_info () { return _au_plugin_info; } void refresh (); @@ -40,7 +39,6 @@ class PluginManager { ARDOUR::AudioEngine& _engine; ARDOUR::PluginInfoList _vst_plugin_info; ARDOUR::PluginInfoList _ladspa_plugin_info; - ARDOUR::PluginInfoList _au_plugin_info; std::map<uint32_t, std::string> rdf_type; std::string ladspa_path; @@ -60,8 +58,6 @@ class PluginManager { int ladspa_discover_from_path (std::string path); int ladspa_discover (std::string path); - int au_discover (); - std::string get_ladspa_category (uint32_t id); static PluginManager* _manager; // singleton diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index 52cfc187af..4cc97a510e 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -39,8 +39,6 @@ AUPluginInfo::discover () desc.componentSubType = 0; desc.componentManufacturer = 0; - vector<ComponentDescription> vCompDescs; - for (int i = 0; i < numTypes; ++i) { if (i == 1) { desc.componentType = kAudioUnitType_MusicEffect; @@ -54,17 +52,30 @@ AUPluginInfo::discover () while (comp != NULL) { ComponentDescription temp; GetComponentInfo (comp, &temp, NULL, NULL, NULL); - vCompDescs.push_back(temp); + + AUPluginInfoPtr plug(new AUPluginInfo); + plug->name = AUPluginInfo::get_name (temp); + plug->type = PluginInfo::AudioUnit; + plug->n_inputs = 0; + plug->n_outputs = 0; + plug->category = "AudioUnit"; + plug->desc = CompDescPtr(new ComponentDescription(temp)); + + plugs.push_back(plug); + comp = FindNextComponent (comp, &desc); } } - for (unsigned int i = 0; i < vCompDescs.size(); ++i) { + return plugs; +} - // the following large block is just for determining the name of the plugin. +std::string +AUPluginInfo::get_name (ComponentDescription& comp_desc) +{ CFStringRef itemName = NULL; // Marc Poirier -style item name - Component auComponent = FindNextComponent (0, &(vCompDescs[i])); + Component auComponent = FindNextComponent (0, &comp_desc); if (auComponent != NULL) { ComponentDescription dummydesc; Handle nameHandle = NewHandle(sizeof(void*)); @@ -82,9 +93,9 @@ AUPluginInfo::discover () // if Marc-style fails, do the original way if (itemName == NULL) { - CFStringRef compTypeString = UTCreateStringForOSType(vCompDescs[i].componentType); - CFStringRef compSubTypeString = UTCreateStringForOSType(vCompDescs[i].componentSubType); - CFStringRef compManufacturerString = UTCreateStringForOSType(vCompDescs[i].componentManufacturer); + CFStringRef compTypeString = UTCreateStringForOSType(comp_desc.componentType); + CFStringRef compSubTypeString = UTCreateStringForOSType(comp_desc.componentSubType); + CFStringRef compManufacturerString = UTCreateStringForOSType(comp_desc.componentManufacturer); itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"), compTypeString, compManufacturerString, compSubTypeString); @@ -96,17 +107,6 @@ AUPluginInfo::discover () if (compManufacturerString != NULL) CFRelease(compManufacturerString); } - string realname = CFStringRefToStdString(itemName); - - AUPluginInfoPtr plug(new AUPluginInfo); - plug->name = realname; - plug->type = PluginInfo::AudioUnit; - plug->n_inputs = 0; - plug->n_outputs = 0; - plug->category = "AudioUnit"; - - plugs.push_back(plug); - } - - return plugs; + + return CFStringRefToStdString(itemName); } diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index 06a944189a..16d6b12981 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -97,10 +97,6 @@ PluginManager::refresh () vst_refresh (); } #endif // VST_SUPPORT - -#ifdef HAVE_COREAUDIO - _au_plugin_info = AUPluginInfo::discover (); -#endif // HAVE_COREAUDIO } void @@ -307,7 +303,7 @@ PluginManager::load (Session& session, PluginInfoPtr info) return boost::shared_ptr<Plugin> ((Plugin*) 0); #endif // !VST_SUPPORT - } else { + } else if (info->type == PluginInfo::LADSPA) { if ((module = dlopen (info->path.c_str(), RTLD_NOW)) == 0) { error << string_compose(_("LADSPA: cannot load module from \"%1\""), info->path) << endmsg; @@ -315,6 +311,14 @@ PluginManager::load (Session& session, PluginInfoPtr info) } else { plugin.reset (new LadspaPlugin (module, _engine, session, info->index, session.frame_rate())); } + } else if (info->type == PluginInfo::AudioUnit) { + +#ifdef HAVE_COREAUDIO + +#else // !HAVE_COREAUDIO + error << _("This version of ardour has no support for AudioUnit plugins") << endmsg; + return boost::shared_ptr<Plugin> ((Plugin*) 0); +#endif } plugin->set_info(*info); @@ -330,26 +334,26 @@ boost::shared_ptr<Plugin> ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginInfo::Type type) { PluginManager *mgr = PluginManager::the_manager(); - PluginInfoList* plugs = 0; + PluginInfoList plugs; switch (type) { case PluginInfo::LADSPA: - plugs = &mgr->ladspa_plugin_info(); + plugs = mgr->ladspa_plugin_info(); break; case PluginInfo::VST: - plugs = &mgr->vst_plugin_info(); + plugs = mgr->vst_plugin_info(); unique_id = 0; // VST plugins don't have a unique id. break; case PluginInfo::AudioUnit: - plugs = &mgr->au_plugin_info(); - unique_id = 0; + plugs = AUPluginInfo::discover (); + unique_id = 0; // Neither do AU. break; default: return boost::shared_ptr<Plugin> ((Plugin *) 0); } PluginInfoList::iterator i; - for (i = plugs->begin(); i != plugs->end(); ++i) { + for (i = plugs.begin(); i != plugs.end(); ++i) { if ((name == "" || (*i)->name == name) && (unique_id == 0 || (*i)->unique_id == unique_id)) { return mgr->load (session, *i); |