1/********************************************************************************************************************************** 2* 3* OpenAL cross platform audio library 4* Copyright (c) 2004, Apple Computer, Inc., Copyright (c) 2012, Apple Inc. All rights reserved. 5* 6* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following 7* conditions are met: 8* 9* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 11* disclaimer in the documentation and/or other materials provided with the distribution. 12* 3. Neither the name of Apple Inc. ("Apple") nor the names of its contributors may be used to endorse or promote products derived 13* from this software without specific prior written permission. 14* 15* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS 17* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 18* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 19* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 20* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21* 22**********************************************************************************************************************************/ 23 24#ifndef __OAL_DEVICE__ 25#define __OAL_DEVICE__ 26 27#include <Carbon/Carbon.h> 28#include <CoreAudio/AudioHardware.h> 29#include <AudioToolbox/AudioToolbox.h> 30#include <AudioUnit/AudioUnit.h> 31#include <libkern/OSAtomic.h> 32#include <map> 33 34#include "oalImp.h" 35 36#include "CAStreamBasicDescription.h" 37 38 39class OALContext; // forward declaration 40 41// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 42// Some build flags for gathering performance and data flow information 43 44#if USE_AU_TRACER 45 #include "AUTracer.h" 46#endif 47 48#if DEBUG 49 #define AUHAL_LOG_OUTPUT 0 50#endif 51 52#if AUHAL_LOG_OUTPUT 53 #include "AudioLogger.h" 54#endif 55 56// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 57// Device Constants 58// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 59 60// Default Mixer Output Sample Rate Setting: 61#define kDefaultMixerRate 44100.0 62 63// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 64// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 65// OALDevices 66// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 67// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 69#pragma mark _____OALDevice_____ 70class OALDevice 71{ 72 public: 73 74 OALDevice(const char* inDeviceName, uintptr_t inSelfToken, UInt32 inRenderChannelSetting); 75 ~OALDevice(); 76 77 void ConnectContext (OALContext* inContext); 78 void DisconnectContext (OALContext* inContext); 79 void RemoveContext (OALContext* inContext); 80 void StopGraph(); 81 82 // thread safety 83 volatile int32_t IsInUse() { return mInUseFlag; } 84 void SetInUseFlag() { OSAtomicIncrement32Barrier(&mInUseFlag); } 85 void ClearInUseFlag() { OSAtomicDecrement32Barrier(&mInUseFlag); } 86 87 // set info 88 void SetRenderChannelSetting (UInt32 inRenderChannelSetting); 89 void SetError(ALenum errorCode); 90 91 // get info 92 uintptr_t GetDeviceToken () const { return mSelfToken; } 93 Float64 GetDeviceSampleRate () const { return mDeviceSampleRate; } 94 UInt32 GetRenderChannelSetting() { return mRenderChannelSetting; } 95 ALenum GetError(); 96 UInt32 GetFramesPerSlice() { return mFramesPerSlice;} 97 AUGraph GetGraph () {return mAUGraph;} 98 AudioUnit GetOutputAU(){return mOutputUnit;} 99 OSStatus UpdateDeviceChannelLayout(); 100 UInt32 GetDesiredRenderChannelCount (); 101 102 // misc. 103 bool IsValidRenderQuality (UInt32 inRenderQuality); 104 static void GraphFormatPropertyListener ( void *inRefCon, 105 AudioUnit ci, 106 AudioUnitPropertyID inID, 107 AudioUnitScope inScope, 108 AudioUnitElement inElement); 109 110 bool IsGraphStillRunning () 111 { 112 Boolean running; 113 OSStatus result = AUGraphIsRunning (mAUGraph, &running); 114 THROW_RESULT 115 return bool(running); 116 } 117 118 void Print () const 119 { 120#if DEBUG || CoreAudio_Debug 121 CAShow (mAUGraph); 122#endif 123 } 124 125 private: 126 uintptr_t mSelfToken; 127 ALenum mCurrentError; 128 AudioDeviceID mHALDevice; // the HAL device used to render audio to the user 129 bool mDistanceScalingRequired; 130 bool mGraphInitialized; 131 AUGraph mAUGraph; 132 AUNode mOutputNode; 133 AudioUnit mOutputUnit; 134 AUNode mMixerNode; 135 AudioChannelLayoutTag mChannelLayoutTag; 136 OALContext* mConnectedContext; 137 Float64 mDeviceSampleRate; 138 UInt32 mRenderChannelCount; 139 UInt32 mRenderChannelSetting; // currently either stereo or multichannel 140 UInt32 mFramesPerSlice; 141 volatile int32_t mInUseFlag; // flag to indicate if the device is currently being edited by one or more threads 142#if AUHAL_LOG_OUTPUT 143 AudioLogger mLogger; 144#endif 145#if USE_AU_TRACER 146 AUTracer mAUTracer; 147#endif 148 149 void InitializeGraph (const char* inDeviceName); 150 void TeardownGraph(); 151 void ResetRenderChannelSettings(); 152 AudioChannelLayoutTag GetLayoutTagForLayout(AudioChannelLayout *inLayout, UInt32 inNumChannels); 153 UInt32 GetChannelLayoutTag(); 154}; 155 156// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 157#pragma mark _____OALDeviceMap_____ 158// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 159class OALDeviceMap : std::multimap<uintptr_t, OALDevice*, std::less<uintptr_t> > { 160public: 161 162 void Add (const uintptr_t inDeviceToken, OALDevice **inDevice) { 163 iterator it = upper_bound(inDeviceToken); 164 insert(it, value_type (inDeviceToken, *inDevice)); 165 } 166 167 OALDevice* Get(uintptr_t inDeviceToken) { 168 iterator it = find(inDeviceToken); 169 if (it != end()) 170 return ((*it).second); 171 return (NULL); 172 } 173 174 OALDevice* GetDeviceByIndex(UInt32 inIndex, uintptr_t &outDeviceToken) { 175 iterator it = begin(); 176 std::advance(it, inIndex); 177 if (it != end()) 178 { 179 outDeviceToken = (*it).first; 180 return (*it).second; 181 } 182 return (NULL); 183 } 184 185 void Remove (const uintptr_t inDeviceToken) { 186 iterator it = find(inDeviceToken); 187 if (it != end()) 188 erase(it); 189 } 190 191 UInt32 Size () const { return size(); } 192 bool Empty () const { return empty(); } 193}; 194 195#endif 196