summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2006-08-10 01:22:45 +0000
committerDavid Robillard <d@drobilla.net>2006-08-10 01:22:45 +0000
commitab6f1ed9bafa869648b6e94ee5186ff317b32c3e (patch)
treed61dba7f9b6f1ae755803afc4b79bcff06a36005 /libs
parent38c7d34d8c449c7ce5f7da9575c24e60c6b31b1a (diff)
Merged with trunk R776
git-svn-id: svn://localhost/ardour2/branches/midi@777 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/appleutility/AUOutputBL.cpp160
-rw-r--r--libs/appleutility/AUOutputBL.h115
-rw-r--r--libs/appleutility/CAAudioChannelLayout.cpp138
-rw-r--r--libs/appleutility/CAAudioChannelLayout.h162
-rw-r--r--libs/appleutility/CAAudioChannelLayoutObject.cpp199
-rw-r--r--libs/appleutility/CAAudioUnit.cpp1202
-rw-r--r--libs/appleutility/CAAudioUnit.h383
-rw-r--r--libs/appleutility/CACFDictionary.cpp478
-rw-r--r--libs/appleutility/CACFDictionary.h141
-rw-r--r--libs/appleutility/CACFNumber.cpp65
-rw-r--r--libs/appleutility/CACFNumber.h102
-rw-r--r--libs/appleutility/CACFString.cpp106
-rw-r--r--libs/appleutility/CACFString.h156
-rw-r--r--libs/appleutility/CAComponent.cpp257
-rw-r--r--libs/appleutility/CAComponent.h120
-rw-r--r--libs/appleutility/CAComponentDescription.cpp123
-rw-r--r--libs/appleutility/CAComponentDescription.h148
-rw-r--r--libs/appleutility/CAConditionalMacros.h74
-rw-r--r--libs/appleutility/CADebugMacros.cpp84
-rw-r--r--libs/appleutility/CADebugMacros.h414
-rw-r--r--libs/appleutility/CAMath.h64
-rw-r--r--libs/appleutility/CAReferenceCounted.h83
-rw-r--r--libs/appleutility/CAStreamBasicDescription.cpp520
-rw-r--r--libs/appleutility/CAStreamBasicDescription.h224
-rw-r--r--libs/appleutility/SConscript23
-rw-r--r--libs/ardour/SConscript4
-rw-r--r--libs/ardour/ardour/ardour.h2
-rw-r--r--libs/ardour/ardour/audio_unit.h76
-rw-r--r--libs/ardour/ardour/automation_event.h8
-rw-r--r--libs/ardour/ardour/ladspa_plugin.h15
-rw-r--r--libs/ardour/ardour/location.h6
-rw-r--r--libs/ardour/ardour/playlist.h3
-rw-r--r--libs/ardour/ardour/plugin.h30
-rw-r--r--libs/ardour/ardour/plugin_manager.h12
-rw-r--r--libs/ardour/ardour/route.h2
-rw-r--r--libs/ardour/ardour/session.h75
-rw-r--r--libs/ardour/ardour/state_manager.h2
-rw-r--r--libs/ardour/ardour/tempo.h3
-rw-r--r--libs/ardour/ardour/track.h2
-rw-r--r--libs/ardour/ardour/vst_plugin.h11
-rw-r--r--libs/ardour/audio_diskstream.cc6
-rw-r--r--libs/ardour/audio_unit.cc388
-rw-r--r--libs/ardour/automation_event.cc14
-rw-r--r--libs/ardour/globals.cc6
-rw-r--r--libs/ardour/insert.cc26
-rw-r--r--libs/ardour/io.cc2
-rw-r--r--libs/ardour/ladspa_plugin.cc25
-rw-r--r--libs/ardour/plugin.cc42
-rw-r--r--libs/ardour/plugin_manager.cc96
-rw-r--r--libs/ardour/session.cc4
-rw-r--r--libs/ardour/session_command.cc101
-rw-r--r--libs/ardour/session_state.cc70
-rw-r--r--libs/ardour/session_transport.cc8
-rw-r--r--libs/ardour/state_manager.cc3
-rw-r--r--libs/ardour/track.cc21
-rw-r--r--libs/ardour/vst_plugin.cc30
-rw-r--r--libs/libsndfile/src/flac.c12
-rw-r--r--libs/pbd/SConscript1
-rw-r--r--libs/pbd/command.cc10
-rw-r--r--libs/pbd/id.cc8
-rw-r--r--libs/pbd/pbd/command.h37
-rw-r--r--libs/pbd/pbd/id.h1
-rw-r--r--libs/pbd/pbd/memento_command.h99
-rw-r--r--libs/pbd/pbd/undo.h29
-rw-r--r--libs/pbd/undo.cc88
-rw-r--r--libs/surfaces/control_protocol/basic_ui.cc1
66 files changed, 6623 insertions, 297 deletions
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/SConscript b/libs/ardour/SConscript
index fc94a13888..feb93ec293 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -83,6 +83,7 @@ send.cc
session.cc
session_butler.cc
session_click.cc
+session_command.cc
session_events.cc
session_export.cc
session_midi.cc
@@ -215,6 +216,9 @@ ardour.Merge ([
if ardour['LIBLO']:
ardour.Merge ([ libraries['lo'] ])
+if ardour['COREAUDIO']:
+ ardour.Merge ([ libraries['appleutility'] ])
+
ardour.VersionBuild(['version.cc', 'ardour/version.h'], 'SConscript')
def SharedAsmObjectEmitter(target, source, env):
diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h
index ba92416339..c138cbf32f 100644
--- a/libs/ardour/ardour/ardour.h
+++ b/libs/ardour/ardour/ardour.h
@@ -45,7 +45,7 @@ namespace ARDOUR {
static const jack_nframes_t max_frames = JACK_MAX_FRAMES;
- int init (AudioEngine&, bool with_vst, bool try_optimization);
+ int init (AudioEngine& engine, bool with_vst, bool try_optimization);
int cleanup ();
diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h
index ec437109a4..1c8d6cbc2d 100644
--- a/libs/ardour/ardour/audio_unit.h
+++ b/libs/ardour/ardour/audio_unit.h
@@ -21,36 +21,93 @@
#ifndef __ardour_audio_unit_h__
#define __ardour_audio_unit_h__
+#include <stdint.h>
+
#include <list>
+#include <set>
+#include <string>
+#include <vector>
#include <ardour/plugin.h>
#include <boost/shared_ptr.hpp>
-struct ComponentDescription;
+class CAComponent;
+class CAAudioUnit;
+class CAComponentDescription;
+struct AudioBufferList;
namespace ARDOUR {
+class AudioEngine;
+class Session;
+
class AUPlugin : public ARDOUR::Plugin
{
public:
- AUPlugin (AudioEngine& engine, Session& session) : Plugin(engine, session) {};
- virtual ~AUPlugin () {};
+ AUPlugin (AudioEngine& engine, Session& session, CAComponent* comp);
+ virtual ~AUPlugin ();
+
+ uint32_t unique_id () const;
+ const char * label () const;
+ const char * name () const { return _info->name.c_str(); }
+ const char * maker () const;
+ uint32_t parameter_count () const;
+ float default_value (uint32_t port);
+ jack_nframes_t latency () const;
+ void set_parameter (uint32_t which, float val);
+ float get_parameter (uint32_t which) const;
+
+ int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
+ uint32_t nth_parameter (uint32_t which, bool& ok) const;
+ void activate ();
+ void deactivate ();
+ void set_block_size (jack_nframes_t nframes);
+
+ int connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset);
+ std::set<uint32_t> automatable() const;
+ void store_state (ARDOUR::PluginState&);
+ void restore_state (ARDOUR::PluginState&);
+ string describe_parameter (uint32_t);
+ string state_node_name () const { return "audiounit"; }
+ void print_parameter (uint32_t, char*, uint32_t len) const;
+
+ bool parameter_is_audio (uint32_t) const;
+ bool parameter_is_control (uint32_t) const;
+ bool parameter_is_input (uint32_t) const;
+ bool parameter_is_output (uint32_t) const;
+
+ XMLNode& get_state();
+ int set_state(const XMLNode& node);
+
+ bool save_preset (string name);
+ bool load_preset (const string preset_label);
+ std::vector<std::string> get_presets ();
+
+ bool has_editor () const;
+
+ private:
+ CAComponent* comp;
+ CAAudioUnit* unit;
+
+ AudioBufferList* in_list;
+ AudioBufferList* out_list;
+
+ std::vector<std::pair<uint32_t, uint32_t> > parameter_map;
};
class AUPluginInfo : public PluginInfo {
- public:
- typedef boost::shared_ptr<ComponentDescription> CompDescPtr;
-
+ public:
AUPluginInfo () { };
- ~AUPluginInfo () { };
+ ~AUPluginInfo ();
- CompDescPtr desc;
+ CAComponentDescription* desc;
static PluginInfoList discover ();
+ PluginPtr load (Session& session);
private:
- friend class PluginManager;
+ static std::string get_name (CAComponentDescription&);
};
typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
@@ -58,4 +115,3 @@ typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
} // namespace ARDOUR
#endif // __ardour_audio_unit_h__
-
diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h
index 78daa531dd..5864de73c6 100644
--- a/libs/ardour/ardour/automation_event.h
+++ b/libs/ardour/ardour/automation_event.h
@@ -51,7 +51,7 @@ struct ControlEvent {
};
-class AutomationList : public StateManager
+class AutomationList : public StateManager, public Stateful
{
public:
typedef std::list<ControlEvent*> AutomationEventList;
@@ -153,6 +153,11 @@ class AutomationList : public StateManager
virtual void store_state (XMLNode& node) const;
virtual void load_state (const XMLNode&);
+ XMLNode &get_state(void);
+ int set_state (const XMLNode &s);
+
+ PBD::ID id() { return _id; }
+
void set_max_xval (double);
double get_max_xval() const { return max_xval; }
@@ -179,6 +184,7 @@ class AutomationList : public StateManager
};
protected:
+ PBD::ID _id;
struct State : public ARDOUR::StateManager::State {
AutomationEventList events;
diff --git a/libs/ardour/ardour/ladspa_plugin.h b/libs/ardour/ardour/ladspa_plugin.h
index e4aba93ef6..99fc884898 100644
--- a/libs/ardour/ardour/ladspa_plugin.h
+++ b/libs/ardour/ardour/ladspa_plugin.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000 Paul Davis
+ Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -137,6 +137,17 @@ class LadspaPlugin : public ARDOUR::Plugin
void run (jack_nframes_t nsamples);
void latency_compute_run ();
};
-}
+
+class LadspaPluginInfo : public PluginInfo {
+ public:
+ LadspaPluginInfo () { };
+ ~LadspaPluginInfo () { };
+
+ PluginPtr load (Session& session);
+};
+
+typedef boost::shared_ptr<LadspaPluginInfo> LadspaPluginInfoPtr;
+
+} // namespace ARDOUR
#endif /* __ardour_ladspa_plugin_h__ */
diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h
index 30c02a80a1..ff953d1d78 100644
--- a/libs/ardour/ardour/location.h
+++ b/libs/ardour/ardour/location.h
@@ -119,7 +119,10 @@ class Location : public Stateful, public sigc::trackable
XMLNode& get_state (void);
int set_state (const XMLNode&);
+ PBD::ID id() { return _id; }
+
private:
+ PBD::ID _id;
string _name;
jack_nframes_t _start;
jack_nframes_t _end;
@@ -145,6 +148,7 @@ class Locations : public Stateful, public StateManager
XMLNode& get_state (void);
int set_state (const XMLNode&);
+ PBD::ID id() { return _id; }
Location* auto_loop_location () const;
Location* auto_punch_location () const;
@@ -197,6 +201,8 @@ class Locations : public Stateful, public StateManager
Change restore_state (StateManager::State&);
StateManager::State* state_factory (std::string why) const;
+
+ PBD::ID _id;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index 9fb5b0eb2b..b389258860 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -76,6 +76,7 @@ class Playlist : public Stateful, public StateManager {
EditMode get_edit_mode() const { return _edit_mode; }
void set_edit_mode (EditMode);
+ PBD::ID id() { return _id; }
/* Editing operations */
void add_region (const Region&, jack_nframes_t position, float times = 1, bool with_save = true);
@@ -273,6 +274,8 @@ class Playlist : public Stateful, public StateManager {
void unset_freeze_child (Playlist*);
void timestamp_layer_op (Region&);
+
+ PBD::ID _id;
};
} /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h
index 86666c19af..6b11a975ca 100644
--- a/libs/ardour/ardour/plugin.h
+++ b/libs/ardour/ardour/plugin.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000 Paul Davis
+ Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,8 +18,8 @@
$Id$
*/
-#ifndef __ardour_ladspa_h__
-#define __ardour_ladspa_h__
+#ifndef __ardour_plugin_h__
+#define __ardour_plugin_h__
#include <boost/shared_ptr.hpp>
#include <sigc++/signal.h>
@@ -46,6 +46,9 @@ namespace ARDOUR {
class AudioEngine;
class Session;
+class Plugin;
+typedef boost::shared_ptr<Plugin> PluginPtr;
+
class PluginInfo {
public:
enum Type {
@@ -54,11 +57,12 @@ class PluginInfo {
VST
};
- PluginInfo () { };
+ PluginInfo () { }
PluginInfo (const PluginInfo &o)
: name(o.name), n_inputs(o.n_inputs), n_outputs(o.n_outputs),
unique_id(o.unique_id), path (o.path), index(o.index) {}
- ~PluginInfo () { };
+ virtual ~PluginInfo () { }
+
string name;
string category;
uint32_t n_inputs;
@@ -67,7 +71,9 @@ class PluginInfo {
long unique_id;
- private:
+ virtual PluginPtr load (Session& session) = 0;
+
+ protected:
friend class PluginManager;
string path;
uint32_t index;
@@ -82,7 +88,7 @@ class Plugin : public Stateful, public sigc::trackable
public:
Plugin (ARDOUR::AudioEngine&, ARDOUR::Session&);
Plugin (const Plugin&);
- ~Plugin ();
+ virtual ~Plugin ();
struct ParameterDescriptor {
@@ -143,8 +149,8 @@ class Plugin : public Stateful, public sigc::trackable
PBD::Controllable *get_nth_control (uint32_t);
- PluginInfo & get_info() { return _info; }
- void set_info (const PluginInfo &inf) { _info = inf; }
+ PluginInfoPtr get_info() { return _info; }
+ void set_info (const PluginInfoPtr inf) { _info = inf; }
ARDOUR::AudioEngine& engine() const { return _engine; }
ARDOUR::Session& session() const { return _session; }
@@ -155,7 +161,7 @@ class Plugin : public Stateful, public sigc::trackable
protected:
ARDOUR::AudioEngine& _engine;
ARDOUR::Session& _session;
- PluginInfo _info;
+ PluginInfoPtr _info;
uint32_t _cycles;
map<string,string> presets;
bool save_preset(string name, string domain /* vst, ladspa etc. */);
@@ -181,9 +187,7 @@ class Plugin : public Stateful, public sigc::trackable
vector<PortControllable*> controls;
};
-/* this is actually defined in plugin_manager.cc */
-
-boost::shared_ptr<Plugin> find_plugin(ARDOUR::Session&, string name, long unique_id, PluginInfo::Type);
+PluginPtr find_plugin(ARDOUR::Session&, string name, long unique_id, PluginInfo::Type);
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h
index 8543ad5285..8e6c0bd1c7 100644
--- a/libs/ardour/ardour/plugin_manager.h
+++ b/libs/ardour/ardour/plugin_manager.h
@@ -5,42 +5,34 @@
#include <map>
#include <string>
-#include <boost/shared_ptr.hpp>
-
#include <ardour/types.h>
#include <ardour/plugin.h>
#include <ardour/audio_unit.h>
namespace ARDOUR {
-class PluginInfo;
class Plugin;
class Session;
class AudioEngine;
class PluginManager {
public:
- PluginManager (ARDOUR::AudioEngine&);
+ PluginManager ();
~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 ();
int add_ladspa_directory (std::string dirpath);
int add_vst_directory (std::string dirpath);
- boost::shared_ptr<Plugin> load (ARDOUR::Session& s, PluginInfoPtr info);
-
static PluginManager* the_manager() { return _manager; }
private:
- 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 +52,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/ardour/route.h b/libs/ardour/ardour/route.h
index 8271c1cf6a..d1db818e40 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -97,7 +97,7 @@ class Route : public IO
virtual int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame,
jack_nframes_t offset, bool can_record, bool rec_monitors_input);
virtual void toggle_monitor_input ();
- virtual bool can_record() const { return false; }
+ virtual bool can_record() { return false; }
virtual void set_record_enable (bool yn, void *src) {}
virtual bool record_enabled() const { return false; }
virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_redirects);
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index d39807be3f..6eb025f076 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -489,6 +489,7 @@ class Session : public sigc::trackable, public Stateful
int save_state (string snapshot_name, bool pending = false);
int restore_state (string snapshot_name);
int save_template (string template_name);
+ int save_history ();
static int rename_template (string old_name, string new_name);
@@ -501,7 +502,7 @@ class Session : public sigc::trackable, public Stateful
static vector<string*>* possible_states(string path);
XMLNode& get_state();
- int set_state(const XMLNode& node);
+ int set_state(const XMLNode& node); // not idempotent
XMLNode& get_template();
void add_instant_xml (XMLNode&, const std::string& dir);
@@ -844,23 +845,65 @@ class Session : public sigc::trackable, public Stateful
string next_undo() const { return history.next_undo(); }
string next_redo() const { return history.next_redo(); }
- void begin_reversible_command (string cmd_name, UndoAction *private_undo = 0);
- void commit_reversible_command (UndoAction* private_redo = 0);
+ void begin_reversible_command (string cmd_name);
+ void commit_reversible_command (Command* cmd = 0);
- void add_undo (const UndoAction& ua) {
- current_cmd.add_undo (ua);
- }
- void add_redo (const UndoAction& ua) {
- current_cmd.add_redo (ua);
- }
- void add_redo_no_execute (const UndoAction& ua) {
- current_cmd.add_redo_no_execute (ua);
+ void add_command (Command *const cmd) {
+ current_trans.add_command (cmd);
}
- UndoAction global_solo_memento (void *src);
- UndoAction global_mute_memento (void *src);
- UndoAction global_record_enable_memento (void *src);
- UndoAction global_metering_memento (void *src);
+ // these commands are implemented in libs/ardour/session_command.cc
+ class GlobalSoloStateCommand : public Command
+ {
+ GlobalRouteBooleanState before, after;
+ Session &sess;
+ void *src;
+ public:
+ GlobalSoloStateCommand(Session &, void *src);
+ void operator()();
+ void undo();
+ XMLNode &get_state();
+ void mark();
+ };
+
+ class GlobalMuteStateCommand : public Command
+ {
+ GlobalRouteBooleanState before, after;
+ Session &sess;
+ void *src;
+ public:
+ GlobalMuteStateCommand(Session &, void *src);
+ void operator()();
+ void undo();
+ XMLNode &get_state();
+ void mark();
+ };
+
+ class GlobalRecordEnableStateCommand : public Command
+ {
+ GlobalRouteBooleanState before, after;
+ Session &sess;
+ void *src;
+ public:
+ GlobalRecordEnableStateCommand(Session &, void *src);
+ void operator()();
+ void undo();
+ XMLNode &get_state();
+ void mark();
+ };
+
+ class GlobalMeteringStateCommand : public Command
+ {
+ GlobalRouteMeterState before, after;
+ Session &sess;
+ void *src;
+ public:
+ GlobalMeteringStateCommand(Session &, void *src);
+ void operator()();
+ void undo();
+ XMLNode &get_state();
+ void mark();
+ };
/* edit mode */
@@ -1635,7 +1678,7 @@ class Session : public sigc::trackable, public Stateful
void reverse_diskstream_buffers ();
UndoHistory history;
- UndoCommand current_cmd;
+ UndoTransaction current_trans;
GlobalRouteBooleanState get_global_route_boolean (bool (Route::*method)(void) const);
GlobalRouteMeterState get_global_route_metering ();
diff --git a/libs/ardour/ardour/state_manager.h b/libs/ardour/ardour/state_manager.h
index 19ee2e624a..99bfcfc3ce 100644
--- a/libs/ardour/ardour/state_manager.h
+++ b/libs/ardour/ardour/state_manager.h
@@ -35,6 +35,8 @@ class StateManager : public sigc::trackable
state_id_t _current_state_id;
+ virtual bool should_save_state () const { return true; }
+
static void prohibit_save ();
static void allow_save (const char* why, bool dosave);
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h
index db06894607..bfd3e429c3 100644
--- a/libs/ardour/ardour/tempo.h
+++ b/libs/ardour/ardour/tempo.h
@@ -238,6 +238,7 @@ class TempoMap : public Stateful, public StateManager {
XMLNode& get_state (void);
int set_state (const XMLNode&);
+ PBD::ID id() { return _id; }
void dump (std::ostream&) const;
void clear ();
@@ -315,6 +316,8 @@ class TempoMap : public Stateful, public StateManager {
void save_state (std::string why);
+ PBD::ID _id;
+
};
}; /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index f16e9d29d9..4e2af5c80e 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -48,7 +48,7 @@ class Track : public Route
void toggle_monitor_input ();
- bool can_record() const { return true; }
+ virtual bool can_record();
Diskstream& diskstream() const { return *_diskstream; }
diff --git a/libs/ardour/ardour/vst_plugin.h b/libs/ardour/ardour/vst_plugin.h
index 3cb10d1779..5253da7b0a 100644
--- a/libs/ardour/ardour/vst_plugin.h
+++ b/libs/ardour/ardour/vst_plugin.h
@@ -104,6 +104,15 @@ class VSTPlugin : public ARDOUR::Plugin
bool been_resumed;
};
-}
+class VSTPluginInfo : public PluginInfo
+{
+ public:
+ VSTPluginInfo () {}
+ ~VSTPluginInfo () {}
+
+ PluginPtr load (Session& session);
+};
+
+} // namespace ARDOUR
#endif /* __ardour_vst_plugin_h__ */
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 7f0cb55821..7d2a2103bb 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -34,6 +34,7 @@
#include <pbd/basename.h>
#include <glibmm/thread.h>
#include <pbd/xml++.h>
+#include <pbd/memento_command.h>
#include <ardour/ardour.h>
#include <ardour/audioengine.h>
@@ -1594,7 +1595,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
// cerr << _name << ": there are " << capture_info.size() << " capture_info records\n";
- _session.add_undo (_playlist->get_memento());
+ XMLNode &before = _playlist->get_state();
_playlist->freeze ();
for (buffer_position = channels[0].write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
@@ -1625,7 +1626,8 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
}
_playlist->thaw ();
- _session.add_redo_no_execute (_playlist->get_memento());
+ XMLNode &after = _playlist->get_state();
+ _session.add_command (new MementoCommand<Playlist>(*_playlist, before, after));
}
mark_write_completed = true;
diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc
index 52cfc187af..25c8aeb53b 100644
--- a/libs/ardour/audio_unit.cc
+++ b/libs/ardour/audio_unit.cc
@@ -18,95 +18,361 @@
*/
+#include <pbd/transmitter.h>
+#include <pbd/xml++.h>
+
+#include <ardour/audioengine.h>
#include <ardour/audio_unit.h>
+#include <ardour/session.h>
#include <ardour/utils.h>
+#include <appleutility/CAAudioUnit.h>
+
#include <CoreServices/CoreServices.h>
#include <AudioUnit/AudioUnit.h>
+#include "i18n.h"
+
+using namespace std;
+using namespace PBD;
using namespace ARDOUR;
-PluginInfoList
-AUPluginInfo::discover ()
+AUPlugin::AUPlugin (AudioEngine& engine, Session& session, CAComponent* _comp)
+ :
+ Plugin (engine, session),
+ comp (_comp),
+ unit (new CAAudioUnit)
+{
+ OSErr err = CAAudioUnit::Open (*comp, *unit);
+ if (err != noErr) {
+ error << _("AudioUnit: Could not convert CAComponent to CAAudioUnit") << endmsg;
+ delete unit;
+ delete comp;
+ throw failed_constructor ();
+ }
+
+ unit->Initialize ();
+}
+
+AUPlugin::~AUPlugin ()
{
- PluginInfoList plugs;
+ if (unit) {
+ unit->Uninitialize ();
+ delete unit;
+ }
+
+ if (comp) {
+ delete comp;
+ }
+
+ if (in_list) {
+ delete in_list;
+ }
+
+ if (out_list) {
+ delete out_list;
+ }
+}
+
+AUPluginInfo::~AUPluginInfo ()
+{
+ if (desc) {
+ delete desc;
+ }
+}
- int numTypes = 2; // this magic number was retrieved from the apple AUHost example.
+uint32_t
+AUPlugin::unique_id () const
+{
+ return 0;
+}
- ComponentDescription desc;
- desc.componentFlags = 0;
- desc.componentFlagsMask = 0;
- desc.componentSubType = 0;
- desc.componentManufacturer = 0;
+const char *
+AUPlugin::label () const
+{
+ return "AUPlugin label";
+}
- vector<ComponentDescription> vCompDescs;
+const char *
+AUPlugin::maker () const
+{
+ return "AUplugin maker";
+}
- for (int i = 0; i < numTypes; ++i) {
- if (i == 1) {
- desc.componentType = kAudioUnitType_MusicEffect;
- } else {
- desc.componentType = kAudioUnitType_Effect;
- }
+uint32_t
+AUPlugin::parameter_count () const
+{
+ return 0;
+}
+
+float
+AUPlugin::default_value (uint32_t port)
+{
+ // AudioUnits don't have default values. Maybe presets though?
+ return 0;
+}
+
+jack_nframes_t
+AUPlugin::latency () const
+{
+ return unit->Latency ();
+}
+
+void
+AUPlugin::set_parameter (uint32_t which, float val)
+{
+ unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val);
+}
+
+float
+AUPlugin::get_parameter (uint32_t which) const
+{
+ float outValue = 0.0;
+
+ unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue);
+
+ return outValue;
+}
+
+int
+AUPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const
+{
+ return -1;
+}
+
+uint32_t
+AUPlugin::nth_parameter (uint32_t which, bool& ok) const
+{
+ return 0;
+}
+
+void
+AUPlugin::activate ()
+{
+ unit->GlobalReset ();
+}
+
+void
+AUPlugin::deactivate ()
+{
+ // not needed. GlobalReset () takes care of it.
+}
- Component comp = 0;
+void
+AUPlugin::set_block_size (jack_nframes_t nframes)
+{
+
+}
+
+int
+AUPlugin::connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset)
+{
+ AudioUnitRenderActionFlags flags = 0;
+ AudioTimeStamp ts;
+
+ AudioBufferList abl;
+ abl.mNumberBuffers = 1;
+ abl.mBuffers[0].mNumberChannels = 1;
+ abl.mBuffers[0].mDataByteSize = nframes * sizeof(Sample);
+ abl.mBuffers[0].mData = &bufs[0];
+
+
+ unit->Render (&flags, &ts, 0, 0, &abl);
+
+ return 0;
+}
+
+set<uint32_t>
+AUPlugin::automatable() const
+{
+ set<uint32_t> automates;
+
+ return automates;
+}
- comp = FindNextComponent (NULL, &desc);
- while (comp != NULL) {
- ComponentDescription temp;
- GetComponentInfo (comp, &temp, NULL, NULL, NULL);
- vCompDescs.push_back(temp);
- comp = FindNextComponent (comp, &desc);
+void
+AUPlugin::store_state (ARDOUR::PluginState&)
+{
+
+}
+
+void
+AUPlugin::restore_state (ARDOUR::PluginState&)
+{
+
+}
+
+string
+AUPlugin::describe_parameter (uint32_t)
+{
+ return "";
+}
+
+void
+AUPlugin::print_parameter (uint32_t, char*, uint32_t len) const
+{
+
+}
+
+bool
+AUPlugin::parameter_is_audio (uint32_t) const
+{
+ return false;
+}
+
+bool
+AUPlugin::parameter_is_control (uint32_t) const
+{
+ return false;
+}
+
+bool
+AUPlugin::parameter_is_input (uint32_t) const
+{
+ return false;
+}
+
+bool
+AUPlugin::parameter_is_output (uint32_t) const
+{
+ return false;
+}
+
+XMLNode&
+AUPlugin::get_state()
+{
+ XMLNode* root = new XMLNode (state_node_name());
+
+ return *root;
+}
+
+int
+AUPlugin::set_state(const XMLNode& node)
+{
+ return -1;
+}
+
+bool
+AUPlugin::save_preset (string name)
+{
+ return false;
+}
+
+bool
+AUPlugin::load_preset (const string preset_label)
+{
+ return false;
+}
+
+vector<string>
+AUPlugin::get_presets ()
+{
+ vector<string> presets;
+
+ return presets;
+}
+
+bool
+AUPlugin::has_editor () const
+{
+ return false;
+}
+
+PluginPtr
+AUPluginInfo::load (Session& session)
+{
+ try {
+ PluginPtr plugin;
+
+ CAComponent* comp = new CAComponent(*desc);
+
+ if (!comp->IsValid()) {
+ error << ("AudioUnit: not a valid Component") << endmsg;
+ } else {
+ plugin.reset (new AUPlugin (session.engine(), session, comp));
}
+
+ plugin->set_info(PluginInfoPtr(new AUPluginInfo(*this)));
+ return plugin;
}
- for (unsigned int i = 0; i < vCompDescs.size(); ++i) {
-
- // the following large block is just for determining the name of the plugin.
- CFStringRef itemName = NULL;
- // Marc Poirier -style item name
- Component auComponent = FindNextComponent (0, &(vCompDescs[i]));
- if (auComponent != NULL) {
- ComponentDescription dummydesc;
- Handle nameHandle = NewHandle(sizeof(void*));
- if (nameHandle != NULL) {
- OSErr err = GetComponentInfo(auComponent, &dummydesc, nameHandle, NULL, NULL);
- if (err == noErr) {
- ConstStr255Param nameString = (ConstStr255Param) (*nameHandle);
- if (nameString != NULL) {
- itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding());
- }
- }
- DisposeHandle(nameHandle);
- }
- }
+ catch (failed_constructor &err) {
+ return PluginPtr ((Plugin*) 0);
+ }
+}
- // 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);
-
- itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"),
- compTypeString, compManufacturerString, compSubTypeString);
-
- if (compTypeString != NULL)
- CFRelease(compTypeString);
- if (compSubTypeString != NULL)
- CFRelease(compSubTypeString);
- if (compManufacturerString != NULL)
- CFRelease(compManufacturerString);
- }
- string realname = CFStringRefToStdString(itemName);
+PluginInfoList
+AUPluginInfo::discover ()
+{
+ PluginInfoList plugs;
+
+ CAComponentDescription desc;
+ desc.componentFlags = 0;
+ desc.componentFlagsMask = 0;
+ desc.componentSubType = 0;
+ desc.componentManufacturer = 0;
+ desc.componentType = kAudioUnitType_Effect;
+
+ Component comp = 0;
+ comp = FindNextComponent (NULL, &desc);
+ while (comp != NULL) {
+ CAComponentDescription temp;
+ GetComponentInfo (comp, &temp, NULL, NULL, NULL);
+
AUPluginInfoPtr plug(new AUPluginInfo);
- plug->name = realname;
+ plug->name = AUPluginInfo::get_name (temp);
plug->type = PluginInfo::AudioUnit;
plug->n_inputs = 0;
plug->n_outputs = 0;
plug->category = "AudioUnit";
+ plug->desc = new CAComponentDescription(temp);
plugs.push_back(plug);
+
+ comp = FindNextComponent (comp, &desc);
}
return plugs;
}
+
+string
+AUPluginInfo::get_name (CAComponentDescription& comp_desc)
+{
+ CFStringRef itemName = NULL;
+ // Marc Poirier -style item name
+ CAComponent auComponent (comp_desc);
+ if (auComponent.IsValid()) {
+ CAComponentDescription dummydesc;
+ Handle nameHandle = NewHandle(sizeof(void*));
+ if (nameHandle != NULL) {
+ OSErr err = GetComponentInfo(auComponent.Comp(), &dummydesc, nameHandle, NULL, NULL);
+ if (err == noErr) {
+ ConstStr255Param nameString = (ConstStr255Param) (*nameHandle);
+ if (nameString != NULL) {
+ itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding());
+ }
+ }
+ DisposeHandle(nameHandle);
+ }
+ }
+
+ // if Marc-style fails, do the original way
+ if (itemName == NULL) {
+ 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);
+
+ if (compTypeString != NULL)
+ CFRelease(compTypeString);
+ if (compSubTypeString != NULL)
+ CFRelease(compSubTypeString);
+ if (compManufacturerString != NULL)
+ CFRelease(compManufacturerString);
+ }
+
+ return CFStringRefToStdString(itemName);
+}
diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc
index 63492b375b..dc1767d1e7 100644
--- a/libs/ardour/automation_event.cc
+++ b/libs/ardour/automation_event.cc
@@ -1246,3 +1246,17 @@ AutomationList::load_state (const XMLNode& node)
add (x, y);
}
}
+
+XMLNode &AutomationList::get_state ()
+{
+ XMLNode *node = new XMLNode("AutomationList");
+ store_state(*node);
+ return *node;
+}
+
+int AutomationList::set_state(const XMLNode &s)
+{
+ load_state(s);
+ return 0;
+}
+
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index 4eafbbe9a1..6f3b772ece 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -193,9 +193,9 @@ setup_midi (AudioEngine& engine )
}
int
-ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization)
+ARDOUR::init (ARDOUR::AudioEngine& engine, bool use_vst, bool try_optimization)
{
- bool generic_mix_functions = true;
+ bool generic_mix_functions = true;
(void) bindtextdomain(PACKAGE, LOCALEDIR);
@@ -303,7 +303,7 @@ ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization)
}
/* singleton - first object is "it" */
- new PluginManager (engine);
+ new PluginManager ();
/* singleton - first object is "it" */
new ControlProtocolManager ();
diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc
index 11b1e25a74..a057fef931 100644
--- a/libs/ardour/insert.cc
+++ b/libs/ardour/insert.cc
@@ -186,25 +186,25 @@ PluginInsert::auto_state_changed (uint32_t which)
uint32_t
PluginInsert::output_streams() const
{
- return _plugins[0]->get_info().n_outputs * _plugins.size();
+ return _plugins[0]->get_info()->n_outputs * _plugins.size();
}
uint32_t
PluginInsert::input_streams() const
{
- return _plugins[0]->get_info().n_inputs * _plugins.size();
+ return _plugins[0]->get_info()->n_inputs * _plugins.size();
}
uint32_t
PluginInsert::natural_output_streams() const
{
- return _plugins[0]->get_info().n_outputs;
+ return _plugins[0]->get_info()->n_outputs;
}
uint32_t
PluginInsert::natural_input_streams() const
{
- return _plugins[0]->get_info().n_inputs;
+ return _plugins[0]->get_info()->n_inputs;
}
bool
@@ -214,7 +214,7 @@ PluginInsert::is_generator() const
a specific "instrument" flag, for example.
*/
- return _plugins[0]->get_info().n_inputs == 0;
+ return _plugins[0]->get_info()->n_inputs == 0;
}
void
@@ -350,7 +350,7 @@ PluginInsert::silence (jack_nframes_t nframes, jack_nframes_t offset)
if (active()) {
for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
- n = (*i) -> get_info().n_inputs;
+ n = (*i) -> get_info()->n_inputs;
(*i)->connect_and_run (_session.get_silent_buffers (n), n, in_index, out_index, nframes, offset);
}
}
@@ -367,8 +367,8 @@ PluginInsert::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframe
connect_and_run (bufs, nbufs, nframes, offset, false);
}
} else {
- uint32_t in = _plugins[0]->get_info().n_inputs;
- uint32_t out = _plugins[0]->get_info().n_outputs;
+ uint32_t in = _plugins[0]->get_info()->n_inputs;
+ uint32_t out = _plugins[0]->get_info()->n_outputs;
if (out > in) {
@@ -524,7 +524,7 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
int32_t
PluginInsert::compute_output_streams (int32_t cnt) const
{
- return _plugins[0]->get_info().n_outputs * cnt;
+ return _plugins[0]->get_info()->n_outputs * cnt;
}
int32_t
@@ -536,8 +536,8 @@ PluginInsert::configure_io (int32_t magic, int32_t in, int32_t out)
int32_t
PluginInsert::can_support_input_configuration (int32_t in) const
{
- int32_t outputs = _plugins[0]->get_info().n_outputs;
- int32_t inputs = _plugins[0]->get_info().n_inputs;
+ int32_t outputs = _plugins[0]->get_info()->n_outputs;
+ int32_t inputs = _plugins[0]->get_info()->n_inputs;
if (inputs == 0) {
@@ -591,7 +591,7 @@ PluginInsert::state (bool full)
node->add_property("id", string(buf));
if (_plugins[0]->state_node_name() == "ladspa") {
char buf[32];
- snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info().unique_id);
+ snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info()->unique_id);
node->add_property("unique-id", string(buf));
}
node->add_property("count", string_compose("%1", _plugins.size()));
@@ -761,7 +761,7 @@ PluginInsert::set_state(const XMLNode& node)
}
// The name of the PluginInsert comes from the plugin, nothing else
- set_name(plugin->get_info().name,this);
+ set_name(plugin->get_info()->name,this);
return 0;
}
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 2dfd735a6b..4d2d26f801 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -170,7 +170,7 @@ IO::silence (jack_nframes_t nframes, jack_nframes_t offset)
void
IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity)
{
- jack_nframes_t declick = min ((jack_nframes_t)4096, nframes);
+ jack_nframes_t declick = min ((jack_nframes_t)128, nframes);
gain_t delta;
Sample *buffer;
double fractional_shift;
diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc
index fa19a682e7..6b773b9e0b 100644
--- a/libs/ardour/ladspa_plugin.cc
+++ b/libs/ardour/ladspa_plugin.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000-2002 Paul Davis
+ Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -641,3 +641,26 @@ LadspaPlugin::latency_compute_run ()
run (bufsize);
deactivate ();
}
+
+PluginPtr
+LadspaPluginInfo::load (Session& session)
+{
+ try {
+ PluginPtr plugin;
+ void *module;
+
+ if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
+ error << string_compose(_("LADSPA: cannot load module from \"%1\""), path) << endmsg;
+ error << dlerror() << endmsg;
+ } else {
+ plugin.reset (new LadspaPlugin (module, session.engine(), session, index, session.frame_rate()));
+ }
+
+ plugin->set_info(PluginInfoPtr(new LadspaPluginInfo(*this)));
+ return plugin;
+ }
+
+ catch (failed_constructor &err) {
+ return PluginPtr ((Plugin*) 0);
+ }
+}
diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc
index 6763e7f508..8ea95b8903 100644
--- a/libs/ardour/plugin.cc
+++ b/libs/ardour/plugin.cc
@@ -39,6 +39,8 @@
#include <ardour/session.h>
#include <ardour/audioengine.h>
#include <ardour/plugin.h>
+#include <ardour/ladspa_plugin.h>
+#include <ardour/plugin_manager.h>
#include <pbd/stl_delete.h>
@@ -240,3 +242,43 @@ Plugin::save_preset (string name, string domain)
return true;
}
+
+PluginPtr
+ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginInfo::Type type)
+{
+ PluginManager *mgr = PluginManager::the_manager();
+ PluginInfoList plugs;
+
+ switch (type) {
+ case PluginInfo::LADSPA:
+ plugs = mgr->ladspa_plugin_info();
+ break;
+
+#ifdef VST_SUPPORT
+ case PluginInfo::VST:
+ plugs = mgr->vst_plugin_info();
+ unique_id = 0; // VST plugins don't have a unique id.
+ break;
+#endif
+
+#ifdef HAVE_COREAUDIO
+ case PluginInfo::AudioUnit:
+ plugs = AUPluginInfo::discover ();
+ unique_id = 0; // Neither do AU.
+ break;
+#endif
+
+ default:
+ return PluginPtr ((Plugin *) 0);
+ }
+
+ PluginInfoList::iterator i;
+ for (i = plugs.begin(); i != plugs.end(); ++i) {
+ if ((name == "" || (*i)->name == name) &&
+ (unique_id == 0 || (*i)->unique_id == unique_id)) {
+ return (*i)->load (session);
+ }
+ }
+
+ return PluginPtr ((Plugin*) 0);
+}
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index 06a944189a..2a753617e8 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000-2004 Paul Davis
+ Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -36,8 +36,10 @@
#include <ardour/plugin_manager.h>
#include <ardour/plugin.h>
#include <ardour/ladspa_plugin.h>
+
+#ifdef VST_SUPPORT
#include <ardour/vst_plugin.h>
-#include <ardour/audio_unit.h>
+#endif
#include <pbd/error.h>
#include <pbd/stl_delete.h>
@@ -49,8 +51,7 @@ using namespace PBD;
PluginManager* PluginManager::_manager = 0;
-PluginManager::PluginManager (AudioEngine& e)
- : _engine (e)
+PluginManager::PluginManager ()
{
char* s;
string lrdf_path;
@@ -97,10 +98,6 @@ PluginManager::refresh ()
vst_refresh ();
}
#endif // VST_SUPPORT
-
-#ifdef HAVE_COREAUDIO
- _au_plugin_info = AUPluginInfo::discover ();
-#endif // HAVE_COREAUDIO
}
void
@@ -250,7 +247,7 @@ PluginManager::ladspa_discover (string path)
break;
}
- PluginInfoPtr info(new PluginInfo);
+ PluginInfoPtr info(new LadspaPluginInfo);
info->name = descriptor->Name;
info->category = get_ladspa_category(descriptor->UniqueID);
info->path = path;
@@ -280,85 +277,6 @@ PluginManager::ladspa_discover (string path)
return 0;
}
-boost::shared_ptr<Plugin>
-PluginManager::load (Session& session, PluginInfoPtr info)
-{
- void *module;
-
- try {
- boost::shared_ptr<Plugin> plugin;
-
- if (info->type == PluginInfo::VST) {
-
-#ifdef VST_SUPPORT
- if (Config->get_use_vst()) {
- FSTHandle* handle;
-
- if ((handle = fst_load (info->path.c_str())) == 0) {
- error << string_compose(_("VST: cannot load module from \"%1\""), info->path) << endmsg;
- } else {
- plugin.reset (new VSTPlugin (_engine, session, handle));
- }
- } else {
- error << _("You asked ardour to not use any VST plugins") << endmsg;
- }
-#else // !VST_SUPPORT
- error << _("This version of ardour has no support for VST plugins") << endmsg;
- return boost::shared_ptr<Plugin> ((Plugin*) 0);
-#endif // !VST_SUPPORT
-
- } else {
-
- if ((module = dlopen (info->path.c_str(), RTLD_NOW)) == 0) {
- error << string_compose(_("LADSPA: cannot load module from \"%1\""), info->path) << endmsg;
- error << dlerror() << endmsg;
- } else {
- plugin.reset (new LadspaPlugin (module, _engine, session, info->index, session.frame_rate()));
- }
- }
-
- plugin->set_info(*info);
- return plugin;
- }
-
- catch (failed_constructor &err) {
- return boost::shared_ptr<Plugin> ((Plugin*) 0);
- }
-}
-
-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;
-
- switch (type) {
- case PluginInfo::LADSPA:
- plugs = &mgr->ladspa_plugin_info();
- break;
- case PluginInfo::VST:
- 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;
- break;
- default:
- return boost::shared_ptr<Plugin> ((Plugin *) 0);
- }
-
- PluginInfoList::iterator 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);
- }
- }
-
- return boost::shared_ptr<Plugin> ((Plugin*) 0);
-}
-
string
PluginManager::get_ladspa_category (uint32_t plugin_id)
{
@@ -464,7 +382,7 @@ PluginManager::vst_discover (string path)
<< endl;
}
- PluginInfoPtr info(new PluginInfo);
+ PluginInfoPtr info(new VSTPluginInfo);
/* what a goddam joke freeware VST is */
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 902da43d91..bfcb69572a 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -1023,6 +1023,7 @@ Session::auto_punch_start_changed (Location* location)
if (get_record_enabled() && get_punch_in()) {
/* capture start has been changed, so save new pending state */
save_state ("", true);
+ save_history();
}
}
@@ -1344,6 +1345,7 @@ Session::maybe_enable_record ()
*/
save_state ("", true);
+ save_history();
if (_transport_speed) {
if (!punch_in) {
@@ -2131,6 +2133,7 @@ Session::add_diskstream (Diskstream* dstream)
set_dirty();
save_state (_current_snapshot_name);
+ save_history();
DiskstreamAdded (dstream); /* EMIT SIGNAL */
}
@@ -2882,6 +2885,7 @@ Session::remove_source (Source* source)
*/
save_state (_current_snapshot_name);
+ save_history();
}
SourceRemoved(source); /* EMIT SIGNAL */
diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc
new file mode 100644
index 0000000000..9a43de55de
--- /dev/null
+++ b/libs/ardour/session_command.cc
@@ -0,0 +1,101 @@
+#include <ardour/session.h>
+#include <ardour/route.h>
+
+namespace ARDOUR {
+// solo
+Session::GlobalSoloStateCommand::GlobalSoloStateCommand(Session &sess, void *src)
+ : sess(sess), src(src)
+{
+ after = before = sess.get_global_route_boolean(&Route::soloed);
+}
+void Session::GlobalSoloStateCommand::mark()
+{
+ after = sess.get_global_route_boolean(&Route::soloed);
+}
+void Session::GlobalSoloStateCommand::operator()()
+{
+ sess.set_global_solo(after, src);
+}
+void Session::GlobalSoloStateCommand::undo()
+{
+ sess.set_global_solo(before, src);
+}
+XMLNode &Session::GlobalSoloStateCommand::get_state()
+{
+ XMLNode *node = new XMLNode("GlobalSoloStateCommand");
+ return *node;
+}
+
+// mute
+Session::GlobalMuteStateCommand::GlobalMuteStateCommand(Session &sess, void *src)
+ : sess(sess), src(src)
+{
+ after = before = sess.get_global_route_boolean(&Route::muted);
+}
+void Session::GlobalMuteStateCommand::mark()
+{
+ after = sess.get_global_route_boolean(&Route::muted);
+}
+void Session::GlobalMuteStateCommand::operator()()
+{
+ sess.set_global_mute(after, src);
+}
+void Session::GlobalMuteStateCommand::undo()
+{
+ sess.set_global_mute(before, src);
+}
+XMLNode &Session::GlobalMuteStateCommand::get_state()
+{
+ XMLNode *node = new XMLNode("GlobalMuteStateCommand");
+ return *node;
+}
+
+// record enable
+Session::GlobalRecordEnableStateCommand::GlobalRecordEnableStateCommand(Session &sess, void *src)
+ : sess(sess), src(src)
+{
+ after = before = sess.get_global_route_boolean(&Route::record_enabled);
+}
+void Session::GlobalRecordEnableStateCommand::mark()
+{
+ after = sess.get_global_route_boolean(&Route::record_enabled);
+}
+void Session::GlobalRecordEnableStateCommand::operator()()
+{
+ sess.set_global_record_enable(after, src);
+}
+void Session::GlobalRecordEnableStateCommand::undo()
+{
+ sess.set_global_record_enable(before, src);
+}
+XMLNode &Session::GlobalRecordEnableStateCommand::get_state()
+{
+ XMLNode *node = new XMLNode("GlobalRecordEnableStateCommand");
+ return *node;
+}
+
+// metering
+Session::GlobalMeteringStateCommand::GlobalMeteringStateCommand(Session &sess, void *src)
+ : sess(sess), src(src)
+{
+ after = before = sess.get_global_route_metering();
+}
+void Session::GlobalMeteringStateCommand::mark()
+{
+ after = sess.get_global_route_metering();
+}
+void Session::GlobalMeteringStateCommand::operator()()
+{
+ sess.set_global_route_metering(after, src);
+}
+void Session::GlobalMeteringStateCommand::undo()
+{
+ sess.set_global_route_metering(before, src);
+}
+XMLNode &Session::GlobalMeteringStateCommand::get_state()
+{
+ XMLNode *node = new XMLNode("GlobalMeteringStateCommand");
+ return *node;
+}
+
+} // namespace ARDOUR
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 8d11fd3b3f..bb319511b7 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -611,6 +611,7 @@ Session::create (bool& new_session, string* mix_template, jack_nframes_t initial
_state_of_the_state = Clean;
if (save_state (_current_snapshot_name)) {
+ save_history();
return -1;
}
}
@@ -1697,6 +1698,7 @@ Session::set_state (const XMLNode& node)
if (state_was_pending) {
save_state (_current_snapshot_name);
+ save_history();
remove_pending_capture_state ();
state_was_pending = false;
}
@@ -2498,6 +2500,7 @@ void
Session::auto_save()
{
save_state (_current_snapshot_name);
+ save_history();
}
RouteGroup *
@@ -2590,29 +2593,25 @@ Session::set_meter_falloff (float val)
void
-Session::begin_reversible_command (string name, UndoAction* private_undo)
+Session::begin_reversible_command (string name)
{
- current_cmd.clear ();
- current_cmd.set_name (name);
-
- if (private_undo) {
- current_cmd.add_undo (*private_undo);
- }
+ current_trans.clear ();
+ current_trans.set_name (name);
}
void
-Session::commit_reversible_command (UndoAction* private_redo)
+Session::commit_reversible_command (Command *cmd)
{
struct timeval now;
- if (private_redo) {
- current_cmd.add_redo_no_execute (*private_redo);
+ if (cmd) {
+ current_trans.add_command (cmd);
}
gettimeofday (&now, 0);
- current_cmd.set_timestamp (now);
+ current_trans.set_timestamp (now);
- history.add (current_cmd);
+ history.add (current_trans);
}
Session::GlobalRouteBooleanState
@@ -2691,6 +2690,7 @@ Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
set_global_route_boolean (s, &Route::set_record_enable, src);
}
+#if 0
UndoAction
Session::global_mute_memento (void* src)
{
@@ -2714,6 +2714,7 @@ Session::global_record_enable_memento (void* src)
{
return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
}
+#endif
static bool
template_filter (const string &str, void *arg)
@@ -3301,3 +3302,48 @@ Session::add_instant_xml (XMLNode& node, const std::string& dir)
Stateful::add_instant_xml (node, dir);
Config->add_instant_xml (node, get_user_ardour_path());
}
+
+
+int
+Session::save_history ()
+{
+ XMLTree tree;
+ string xml_path;
+ string bak_path;
+
+ tree.set_root (&history.get_state());
+
+ xml_path = _path + _current_snapshot_name + ".history";
+
+ bak_path = xml_path + ".bak";
+
+ if ((access (xml_path.c_str(), F_OK) == 0) &&
+ (rename (xml_path.c_str(), bak_path.c_str())))
+ {
+ error << _("could not backup old history file, current history not saved.") << endmsg;
+ return -1;
+ }
+
+ if (!tree.write (xml_path))
+ {
+ error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
+
+ /* don't leave a corrupt file lying around if it is
+ * possible to fix.
+ */
+
+ if (unlink (xml_path.c_str()))
+ {
+ error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
+ } else {
+ if (rename (bak_path.c_str(), xml_path.c_str()))
+ {
+ error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
+ }
+ }
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index bff8ae5955..592f9c86c6 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -29,6 +29,7 @@
#include <pbd/error.h>
#include <glibmm/thread.h>
#include <pbd/pthread_utils.h>
+#include <pbd/memento_command.h>
#include <midi++/mmc.h>
#include <midi++/port.h>
@@ -325,8 +326,10 @@ Session::non_realtime_stop (bool abort)
}
if (change_end) {
- add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
- add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
+ XMLNode &before = loc->get_state();
+ loc->set_end(_transport_frame);
+ XMLNode &after = loc->get_state();
+ add_command (new MementoCommand<Location>(*loc, before, after));
}
_end_location_is_free = false;
@@ -410,6 +413,7 @@ Session::non_realtime_stop (bool abort)
if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
/* capture start has been changed, so save pending state */
save_state ("", true);
+ save_history();
}
/* always try to get rid of this */
diff --git a/libs/ardour/state_manager.cc b/libs/ardour/state_manager.cc
index bcffe381c3..153773ed30 100644
--- a/libs/ardour/state_manager.cc
+++ b/libs/ardour/state_manager.cc
@@ -72,6 +72,9 @@ StateManager::use_state (state_id_t id)
void
StateManager::save_state (std::string why)
{
+ if (!should_save_state())
+ return;
+
if (!_allow_save) {
SaveAllowed.connect (mem_fun (*this, &StateManager::save_state));
return;
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index 3b3b705a87..f81ef9de4d 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -31,6 +31,7 @@
#include <ardour/audioplaylist.h>
#include <ardour/panner.h>
#include <ardour/utils.h>
+#include <ardour/connection.h>
#include "i18n.h"
@@ -146,6 +147,18 @@ Track::record_enabled () const
{
return _diskstream->record_enabled ();
}
+
+bool
+Track::can_record()
+{
+ bool will_record = true;
+ for (size_t i = 0; i < _inputs.size() && will_record; i++) {
+ if (!_inputs[i]->connected())
+ will_record = false;
+ }
+
+ return will_record;
+}
void
Track::set_record_enable (bool yn, void *src)
@@ -159,8 +172,13 @@ Track::set_record_enable (bool yn, void *src)
return;
}
- /* keep track of the meter point as it was before we rec-enabled */
+ // Do not set rec enabled if the track can't record.
+ if (yn && !can_record()) {
+ error << string_compose( _("Can not arm track '%1'. Check the input connections"), name() ) << endmsg;
+ return;
+ }
+ /* keep track of the meter point as it was before we rec-enabled */
if (!_diskstream->record_enabled()) {
_saved_meter_point = _meter_point;
}
@@ -206,6 +224,7 @@ Track::set_name (string str, void *src)
if ((ret = IO::set_name (str, src)) == 0) {
_session.save_state ("");
+ _session.save_history();
}
return ret;
}
diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc
index 352b887e13..4c09ba3440 100644
--- a/libs/ardour/vst_plugin.cc
+++ b/libs/ardour/vst_plugin.cc
@@ -479,3 +479,33 @@ VSTPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
memmove (buf, first_nonws, strlen (buf) - (first_nonws - buf) + 1);
}
+
+PluginPtr
+VSTPluginInfo::load (Session& session)
+{
+ try {
+ PluginPtr plugin;
+
+ if (Config->get_use_vst()) {
+ FSTHandle* handle;
+
+ handle = fst_load(path.c_str());
+
+ if ( (int)handle == -1) {
+ error << string_compose(_("VST: cannot load module from \"%1\""), path) << endmsg;
+ } else {
+ plugin.reset (new VSTPlugin (session.engine(), session, handle));
+ }
+ } else {
+ error << _("You asked ardour to not use any VST plugins") << endmsg;
+ return PluginPtr ((Plugin*) 0);
+ }
+
+ plugin->set_info(PluginInfoPtr(new VSTPluginInfo(*this)));
+ return plugin;
+ }
+
+ catch (failed_constructor &err) {
+ return PluginPtr ((Plugin*) 0);
+ }
+}
diff --git a/libs/libsndfile/src/flac.c b/libs/libsndfile/src/flac.c
index 1f0872f0bd..b74a4e3253 100644
--- a/libs/libsndfile/src/flac.c
+++ b/libs/libsndfile/src/flac.c
@@ -128,38 +128,38 @@ static const int legal_sample_rates [] =
{ 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000
} ;
-static inline void
+static void
s2flac8_array (const short *src, FLAC__int32 *dest, int count)
{ while (--count >= 0)
dest [count] = src [count] >> 8 ;
} /* s2flac8_array */
-static inline void
+static void
s2flac16_array (const short *src, FLAC__int32 *dest, int count)
{ while (--count >= 0)
dest [count] = src [count] ;
} /* s2flac16_array */
-static inline void
+static void
s2flac24_array (const short *src, FLAC__int32 *dest, int count)
{ while (--count >= 0)
dest [count] = src [count] << 8 ;
} /* s2flac24_array */
-static inline void
+static void
i2flac8_array (const int *src, FLAC__int32 *dest, int count)
{ while (--count >= 0)
dest [count] = src [count] >> 24 ;
} /* i2flac8_array */
-static inline void
+static void
i2flac16_array (const int *src, FLAC__int32 *dest, int count)
{
while (--count >= 0)
dest [count] = src [count] >> 16 ;
} /* i2flac16_array */
-static inline void
+static void
i2flac24_array (const int *src, FLAC__int32 *dest, int count)
{ while (--count >= 0)
dest [count] = src [count] >> 8 ;
diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript
index 36fb02885f..4b15dd70d1 100644
--- a/libs/pbd/SConscript
+++ b/libs/pbd/SConscript
@@ -21,6 +21,7 @@ pbd_files = Split("""
basename.cc
base_ui.cc
convert.cc
+command.cc
controllable.cc
dmalloc.cc
error.cc
diff --git a/libs/pbd/command.cc b/libs/pbd/command.cc
new file mode 100644
index 0000000000..5b41691c07
--- /dev/null
+++ b/libs/pbd/command.cc
@@ -0,0 +1,10 @@
+#include <pbd/command.h>
+#include <pbd/xml++.h>
+
+
+XMLNode &Command::get_state()
+{
+ XMLNode *node = new XMLNode ("Command");
+ node->add_content("WARNING: Somebody forgot to subclass Command.");
+ return *node;
+}
diff --git a/libs/pbd/id.cc b/libs/pbd/id.cc
index f9afa72c98..0de0d052c3 100644
--- a/libs/pbd/id.cc
+++ b/libs/pbd/id.cc
@@ -8,6 +8,7 @@
#include <inttypes.h>
#include <pbd/id.h>
+#include <string>
using namespace std;
using namespace PBD;
@@ -45,6 +46,13 @@ ID::print (char* buf) const
snprintf (buf, 16, "%" PRIu64, id);
}
+string ID::to_s() const
+{
+ char buf[16]; // see print()
+ print(buf);
+ return string(buf);
+}
+
ID&
ID::operator= (string str)
{
diff --git a/libs/pbd/pbd/command.h b/libs/pbd/pbd/command.h
new file mode 100644
index 0000000000..cd9bf0e08a
--- /dev/null
+++ b/libs/pbd/pbd/command.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2006 Hans Fugal & Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id: /local/undo/libs/pbd3/pbd/undo.h 80 2006-06-22T22:37:01.079855Z fugalh $
+*/
+
+#ifndef __lib_pbd_command_h__
+#define __lib_pbd_command_h__
+
+#include <pbd/stateful.h>
+
+class Command : public Stateful
+{
+ public:
+ virtual ~Command() {}
+ virtual void operator() () = 0;
+ virtual void undo() = 0;
+ virtual void redo() { (*this)(); }
+ virtual XMLNode &get_state();
+ virtual int set_state(const XMLNode&) { /* noop */ return 0; }
+};
+
+#endif // __lib_pbd_command_h_
diff --git a/libs/pbd/pbd/id.h b/libs/pbd/pbd/id.h
index 9a3f10478d..1ce448d58b 100644
--- a/libs/pbd/pbd/id.h
+++ b/libs/pbd/pbd/id.h
@@ -28,6 +28,7 @@ class ID {
}
void print (char* buf) const;
+ std::string to_s() const;
static uint64_t counter() { return _counter; }
static void init_counter (uint64_t val) { _counter = val; }
diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h
new file mode 100644
index 0000000000..46c724e9ea
--- /dev/null
+++ b/libs/pbd/pbd/memento_command.h
@@ -0,0 +1,99 @@
+/*
+ Copyright (C) 2006 Hans Fugal & Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id: /local/undo/libs/pbd3/pbd/undo.h 132 2006-06-29T18:45:16.609763Z fugalh $
+*/
+
+#ifndef __lib_pbd_memento_command_h__
+#define __lib_pbd_memento_command_h__
+
+#include <pbd/command.h>
+#include <pbd/xml++.h>
+#include <sigc++/slot.h>
+
+/** This command class is initialized with before and after mementos
+ * (from Stateful::get_state()), so undo becomes restoring the before
+ * memento, and redo is restoring the after memento.
+ */
+template <class obj_T>
+class MementoCommand : public Command
+{
+ public:
+ MementoCommand(obj_T &obj,
+ XMLNode &before,
+ XMLNode &after
+ )
+ : obj(obj), before(before), after(after) {}
+ void operator() () { obj.set_state(after); }
+ void undo() { obj.set_state(before); }
+ virtual XMLNode &get_state()
+ {
+ XMLNode *node = new XMLNode("MementoCommand");
+ node->add_property("obj_id", obj.id().to_s());
+ node->add_child_nocopy(before);
+ node->add_child_nocopy(after);
+ return *node;
+ }
+ // TODO does this need a copy constructor?
+ protected:
+ obj_T &obj;
+ XMLNode &before, &after;
+};
+
+template <class obj_T>
+class MementoUndoCommand : public Command
+{
+public:
+ MementoUndoCommand(obj_T &obj,
+ XMLNode &before)
+ : obj(obj), before(before) {}
+ void operator() () { /* noop */ }
+ void undo() { obj.set_state(before); }
+ virtual XMLNode &get_state()
+ {
+ XMLNode *node = new XMLNode("MementoUndoCommand");
+ node->add_property("obj_id", obj.id().to_s());
+ node->add_child_nocopy(before);
+ return *node;
+ }
+protected:
+ obj_T &obj;
+ XMLNode &before;
+};
+
+template <class obj_T>
+class MementoRedoCommand : public Command
+{
+public:
+ MementoRedoCommand(obj_T &obj,
+ XMLNode &after)
+ : obj(obj), after(after) {}
+ void operator() () { obj.set_state(after); }
+ void undo() { /* noop */ }
+ virtual XMLNode &get_state()
+ {
+ XMLNode *node = new XMLNode("MementoRedoCommand");
+ node->add_property("obj_id", obj.id().to_s());
+ node->add_child_nocopy(after);
+ return *node;
+ }
+protected:
+ obj_T &obj;
+ XMLNode &after;
+};
+
+#endif // __lib_pbd_memento_h__
diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h
index f067635ed3..724e86aaa0 100644
--- a/libs/pbd/pbd/undo.h
+++ b/libs/pbd/pbd/undo.h
@@ -23,29 +23,33 @@
#include <string>
#include <list>
+#include <map>
#include <sigc++/slot.h>
+#include <sigc++/bind.h>
#include <sys/time.h>
+#include <pbd/command.h>
using std::string;
using std::list;
typedef sigc::slot<void> UndoAction;
-class UndoCommand
+class UndoTransaction : public Command
{
public:
- UndoCommand ();
- UndoCommand (const UndoCommand&);
- UndoCommand& operator= (const UndoCommand&);
+ UndoTransaction ();
+ UndoTransaction (const UndoTransaction&);
+ UndoTransaction& operator= (const UndoTransaction&);
void clear ();
- void add_undo (const UndoAction&);
- void add_redo (const UndoAction&);
- void add_redo_no_execute (const UndoAction&);
+ void add_command (Command *const);
+ void operator() ();
void undo();
void redo();
+
+ XMLNode &get_state();
void set_name (const string& str) {
_name = str;
@@ -61,8 +65,7 @@ class UndoCommand
}
private:
- list<UndoAction> redo_actions;
- list<UndoAction> undo_actions;
+ list<Command*> actions;
struct timeval _timestamp;
string _name;
};
@@ -73,7 +76,7 @@ class UndoHistory
UndoHistory() {}
~UndoHistory() {}
- void add (UndoCommand uc);
+ void add (UndoTransaction ut);
void undo (unsigned int n);
void redo (unsigned int n);
@@ -87,9 +90,11 @@ class UndoHistory
void clear_undo ();
void clear_redo ();
+ XMLNode &get_state();
+ void save_state();
private:
- list<UndoCommand> UndoList;
- list<UndoCommand> RedoList;
+ list<UndoTransaction> UndoList;
+ list<UndoTransaction> RedoList;
};
diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc
index f2f11b1c5c..8d1b416c16 100644
--- a/libs/pbd/undo.cc
+++ b/libs/pbd/undo.cc
@@ -21,81 +21,84 @@
#include <iostream>
#include <pbd/undo.h>
+#include <pbd/xml++.h>
+#include <string>
using namespace std;
using namespace sigc;
-UndoCommand::UndoCommand ()
+UndoTransaction::UndoTransaction ()
{
}
-UndoCommand::UndoCommand (const UndoCommand& rhs)
+UndoTransaction::UndoTransaction (const UndoTransaction& rhs)
{
_name = rhs._name;
clear ();
- undo_actions.insert(undo_actions.end(),rhs.undo_actions.begin(),rhs.undo_actions.end());
- redo_actions.insert(redo_actions.end(),rhs.redo_actions.begin(),rhs.redo_actions.end());
+ actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
}
-UndoCommand&
-UndoCommand::operator= (const UndoCommand& rhs)
+UndoTransaction&
+UndoTransaction::operator= (const UndoTransaction& rhs)
{
if (this == &rhs) return *this;
_name = rhs._name;
clear ();
- undo_actions.insert(undo_actions.end(),rhs.undo_actions.begin(),rhs.undo_actions.end());
- redo_actions.insert(redo_actions.end(),rhs.redo_actions.begin(),rhs.redo_actions.end());
+ actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
return *this;
}
void
-UndoCommand::add_undo (const UndoAction& action)
+UndoTransaction::add_command (Command *const action)
{
- undo_actions.push_back (action);
+ actions.push_back (action);
}
void
-UndoCommand::add_redo (const UndoAction& action)
+UndoTransaction::clear ()
{
- redo_actions.push_back (action);
- redo_actions.back()(); // operator()
+ actions.clear ();
}
void
-UndoCommand::add_redo_no_execute (const UndoAction& action)
+UndoTransaction::operator() ()
{
- redo_actions.push_back (action);
-}
-
-void
-UndoCommand::clear ()
-{
- undo_actions.clear ();
- redo_actions.clear ();
+ for (list<Command*>::iterator i = actions.begin(); i != actions.end(); ++i) {
+ (*(*i))();
+ }
}
void
-UndoCommand::undo ()
+UndoTransaction::undo ()
{
cerr << "Undo " << _name << endl;
- for (list<UndoAction>::reverse_iterator i = undo_actions.rbegin(); i != undo_actions.rend(); ++i) {
- (*i)();
+ for (list<Command*>::reverse_iterator i = actions.rbegin(); i != actions.rend(); ++i) {
+ (*i)->undo();
}
}
void
-UndoCommand::redo ()
+UndoTransaction::redo ()
{
cerr << "Redo " << _name << endl;
- for (list<UndoAction>::iterator i = redo_actions.begin(); i != redo_actions.end(); ++i) {
- (*i)();
- }
+ (*this)();
+}
+
+XMLNode &UndoTransaction::get_state()
+{
+ XMLNode *node = new XMLNode ("UndoTransaction");
+
+ list<Command*>::iterator it;
+ for (it=actions.begin(); it!=actions.end(); it++)
+ node->add_child_nocopy((*it)->get_state());
+
+ return *node;
}
void
-UndoHistory::add (UndoCommand uc)
+UndoHistory::add (UndoTransaction ut)
{
- UndoList.push_back (uc);
+ UndoList.push_back (ut);
}
void
@@ -105,10 +108,10 @@ UndoHistory::undo (unsigned int n)
if (UndoList.size() == 0) {
return;
}
- UndoCommand uc = UndoList.back ();
+ UndoTransaction ut = UndoList.back ();
UndoList.pop_back ();
- uc.undo ();
- RedoList.push_back (uc);
+ ut.undo ();
+ RedoList.push_back (ut);
}
}
@@ -119,10 +122,10 @@ UndoHistory::redo (unsigned int n)
if (RedoList.size() == 0) {
return;
}
- UndoCommand cmd = RedoList.back ();
+ UndoTransaction ut = RedoList.back ();
RedoList.pop_back ();
- cmd.redo ();
- UndoList.push_back (cmd);
+ ut.redo ();
+ UndoList.push_back (ut);
}
}
@@ -144,3 +147,14 @@ UndoHistory::clear ()
RedoList.clear ();
UndoList.clear ();
}
+
+XMLNode & UndoHistory::get_state()
+{
+ XMLNode *node = new XMLNode ("UndoHistory");
+
+ list<UndoTransaction>::iterator it;
+ for (it=UndoList.begin(); it != UndoList.end(); it++)
+ node->add_child_nocopy(it->get_state());
+
+ return *node;
+}
diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc
index 3dc93cc64a..47401c8cfe 100644
--- a/libs/surfaces/control_protocol/basic_ui.cc
+++ b/libs/surfaces/control_protocol/basic_ui.cc
@@ -145,6 +145,7 @@ void
BasicUI::save_state ()
{
session->save_state ("");
+ session->save_history();
}
void