From a82b8be5e91d34193e06f1014371601e308cc05b Mon Sep 17 00:00:00 2001 From: Memphiz Date: Thu, 16 Feb 2012 21:13:42 +0100 Subject: [PATCH] [ios] - My personal present for the users (no worries - it defaults to off!) - add code for allowing volume control on ios by using CoreAudios MixerUnit and Audio Graphs (thx gimli for letting me dig into your code) --- xbmc/osx/IOSCoreAudio.cpp | 383 +++++++++++++++++++++++++++----------- xbmc/osx/IOSCoreAudio.h | 14 +- 2 files changed, 289 insertions(+), 108 deletions(-) diff --git a/xbmc/osx/IOSCoreAudio.cpp b/xbmc/osx/IOSCoreAudio.cpp index 7106a9e82fa42..0f61610edcc2c 100644 --- a/xbmc/osx/IOSCoreAudio.cpp +++ b/xbmc/osx/IOSCoreAudio.cpp @@ -25,6 +25,7 @@ #include "IOSCoreAudio.h" #include "PlatformDefs.h" #include "utils/log.h" +#include "settings/Settings.h" #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -129,6 +130,9 @@ UInt32 CIOSCoreAudioHardware::GetOutputDevices(IOSCoreAudioDeviceList* pList) // CIOSCoreAudioDevice ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CIOSCoreAudioDevice::CIOSCoreAudioDevice() : + m_AudioGraph(0), + m_OutputNode(0), + m_MixerNode(0), m_AudioUnit(0), m_MixerUnit(0) { @@ -154,37 +158,29 @@ void CIOSCoreAudioDevice::SetupInfo() if(!GetFormat(m_AudioUnit, kAudioUnitScope_Output, kInputBus, &pDesc)) return; - CLog::Log(LOGDEBUG, "CIOSCoreAudioDevice::SetupInfo: Remote/IO Output Stream Bus %d Format %s", + CLog::Log(LOGDEBUG, "CIOSCoreAudioDevice::SetupInfo: Remote/IO Output Stream Bus %d Format %s", kInputBus, (char*)IOSStreamDescriptionToString(pDesc, formatString)); if(!GetFormat(m_AudioUnit, kAudioUnitScope_Input, kOutputBus, &pDesc)) return; - CLog::Log(LOGDEBUG, "CIOSCoreAudioDevice::SetupInfo: Remote/IO Input Stream Bus %d Format %s", - kInputBus, (char*)IOSStreamDescriptionToString(pDesc, formatString)); + CLog::Log(LOGDEBUG, "CIOSCoreAudioDevice::SetupInfo: Remote/IO Input Stream Bus %d Format %s", + kOutputBus, (char*)IOSStreamDescriptionToString(pDesc, formatString)); } if(m_MixerUnit) { - if(!GetFormat(m_AudioUnit, kAudioUnitScope_Input, kOutputBus, &pDesc)) - return; - - CLog::Log(LOGDEBUG, "CIOSCoreAudioDevice::SetupInfo: Remote/IO Output Stream Bus %d Format %s", - kInputBus, (char*)IOSStreamDescriptionToString(pDesc, formatString)); - if(!GetFormat(m_MixerUnit, kAudioUnitScope_Input, kOutputBus, &pDesc)) return; - + CLog::Log(LOGDEBUG, "CIOSCoreAudioDevice::SetupInfo: Mixer Input Stream Bus %d Format %s", kOutputBus, (char*)IOSStreamDescriptionToString(pDesc, formatString)); - - if(!GetFormat(m_MixerUnit, kAudioUnitScope_Input, kInputBus, &pDesc)) + if(!GetFormat(m_MixerUnit, kAudioUnitScope_Output, kOutputBus, &pDesc)) return; - CLog::Log(LOGDEBUG, "CIOSCoreAudioDevice::SetupInfo: Mixer Input Stream Bus %d Format %s", - kInputBus, (char*)IOSStreamDescriptionToString(pDesc, formatString)); + CLog::Log(LOGDEBUG, "CIOSCoreAudioDevice::SetupInfo: Mixer Output Stream Bus %d Format %s", + kOutputBus, (char*)IOSStreamDescriptionToString(pDesc, formatString)); } - } bool CIOSCoreAudioDevice::Init(bool bPassthrough, AudioStreamBasicDescription* pDesc, AURenderCallback renderCallback, void *pClientData) @@ -195,8 +191,16 @@ bool CIOSCoreAudioDevice::Init(bool bPassthrough, AudioStreamBasicDescription* p m_AudioUnit = 0; m_MixerUnit = 0; + m_OutputNode = 0; + m_MixerNode = 0; + m_AudioGraph = 0; m_Passthrough = bPassthrough; + if (!m_Passthrough) + { + return InitWithGraph(pDesc, renderCallback, pClientData); + } + /* ret = AudioSessionInitialize(NULL, NULL, NULL, NULL); if (ret) { @@ -238,143 +242,300 @@ bool CIOSCoreAudioDevice::Init(bool bPassthrough, AudioStreamBasicDescription* p if(!SetFormat(m_AudioUnit, kAudioUnitScope_Output, kInputBus, pDesc)) return false; - if(!m_Passthrough) { - // Describe audio component - desc.componentType = kAudioUnitType_Mixer; - desc.componentSubType = kAudioUnitSubType_AU3DMixerEmbedded; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; + if(!SetRenderProc(m_AudioUnit, kOutputBus, renderCallback, pClientData)) + return false; + + SetupInfo(); + + return true; +} + +bool CIOSCoreAudioDevice::OpenUnit(OSType type, OSType subType, OSType manufacturer, AudioComponentInstance &unit, AUNode &node) +{ + OSStatus ret; + AudioComponentDescription desc; + desc.componentType = type; + desc.componentSubType = subType; + desc.componentManufacturer = manufacturer; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + ret = AUGraphAddNode(m_AudioGraph, &desc, &node); + if(ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Open: Error add m_outputNode. Error = %4.4s", CONVERT_OSSTATUS(ret)); + return false; + } - // Get component - audioComponent = AudioComponentFindNext(NULL, &desc); + ret = AUGraphNodeInfo(m_AudioGraph, node, NULL, &unit); + if(ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Open: Error getting m_outputNode. Error = %4.4s", CONVERT_OSSTATUS(ret)); + return false; + } - // Get mixer unit - ret = AudioComponentInstanceNew(audioComponent, &m_MixerUnit); - if (ret) { - CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Init: Unable to open Mixer device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + return true; +} + +bool CIOSCoreAudioDevice::EnableInputOuput(AudioComponentInstance &unit) +{ + if (!unit) + return false; + + OSStatus ret; + UInt32 enable; + UInt32 hasio; + UInt32 size=sizeof(UInt32); + + ret = AudioUnitGetProperty(unit,kAudioOutputUnitProperty_HasIO,kAudioUnitScope_Input, 1, &hasio, &size); + + if(hasio) + { + enable = 1; + ret = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &enable, sizeof(enable)); + if (ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::EnableInputOuput:: Unable to enable input on bus 1. Error = %4.4s", CONVERT_OSSTATUS(ret)); return false; } - - if(!SetFormat(m_MixerUnit, kAudioUnitScope_Input, kOutputBus, pDesc)) + + enable = 1; + ret = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &enable, sizeof(enable)); + if (ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::EnableInputOuput:: Unable to disable output on bus 0. Error = %4.4s", CONVERT_OSSTATUS(ret)); return false; + } + } + + return true; +} - if(!SetFormat(m_MixerUnit, kAudioUnitScope_Input, kInputBus, pDesc)) - return false; +bool CIOSCoreAudioDevice::InitWithGraph(AudioStreamBasicDescription* pDesc, AURenderCallback renderCallback, void *pClientData) +{ + OSStatus ret; + UInt32 busCount = 1; - if(!SetRenderProc(m_MixerUnit, kOutputBus, renderCallback, pClientData)) - return false; + if(!pDesc) + return false; - // Connect mixer to output - AudioUnitConnection connection; - connection.sourceAudioUnit = m_MixerUnit; - connection.sourceOutputNumber = kOutputBus; - connection.destInputNumber = kOutputBus; + ret = NewAUGraph(&m_AudioGraph); + if(ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Open: Error create audio grpah. Error = %4.4s", CONVERT_OSSTATUS(ret)); + return false; + } + ret = AUGraphOpen(m_AudioGraph); + if(ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Open: Error open audio grpah. Error = %4.4s", CONVERT_OSSTATUS(ret)); + return false; + } - ret = AudioUnitSetProperty(m_AudioUnit, kAudioUnitProperty_MakeConnection, - kAudioUnitScope_Input, kOutputBus, &connection, sizeof(connection)); - if (ret) - { - CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Init: Unable to make IO connections. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); - return false; - } + // get output unit + if(m_AudioUnit) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Open: Error audio unit already open. double call ?"); + return false; + } + + if(!OpenUnit(kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple, m_AudioUnit, m_OutputNode)) + return false; + + if(!EnableInputOuput(m_AudioUnit)) + return false; + + if(!SetFormat(m_AudioUnit, kAudioUnitScope_Input, kOutputBus, pDesc)) + return false; + + if(!SetFormat(m_AudioUnit, kAudioUnitScope_Output, kInputBus, pDesc)) + return false; - } else { - if(!SetRenderProc(m_AudioUnit, kOutputBus, renderCallback, pClientData)) - return false; + // get mixer unit + if(m_MixerUnit) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Open: Error mixer unit already open. double call ?"); + return false; } + + if(!OpenUnit(kAudioUnitType_Mixer, kAudioUnitSubType_MultiChannelMixer, kAudioUnitManufacturer_Apple, m_MixerUnit, m_MixerNode)) + return false; + + // set number of input buses + ret = AudioUnitSetProperty(m_MixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &busCount, sizeof(UInt32)); + if (ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::SetInputBusCount: Unable to set input bus count. Error = %4.4s", CONVERT_OSSTATUS(ret)); + return false; + } + + if(!SetFormat(m_MixerUnit,kAudioUnitScope_Input, kOutputBus, pDesc)) + return false; - SetupInfo(); + if(!SetFormat(m_MixerUnit,kAudioUnitScope_Output, kOutputBus, pDesc)) + return false; + + //connect output of mixer to input of output unit + ret = AUGraphConnectNodeInput(m_AudioGraph, m_MixerNode, 0, m_OutputNode, 0); + if(ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Open: Error connecting m_m_mixerNode. Error = %4.4s", CONVERT_OSSTATUS(ret)); + return false; + } + + ret = AUGraphUpdate(m_AudioGraph, NULL); + if(ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Open: Error update graph. Error = %4.4s", CONVERT_OSSTATUS(ret)); + return false; + } + + SetupInfo(); + + //feed data into mixer via callback + AURenderCallbackStruct callbackInfo; + callbackInfo.inputProc = renderCallback; // Function to be called each time the AudioUnit needs data + callbackInfo.inputProcRefCon = pClientData; // Pointer to be returned in the callback proc + ret = AudioUnitSetProperty(m_MixerUnit, kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, 0, &callbackInfo, sizeof(AURenderCallbackStruct)); + if (ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::SetRenderProc: Unable to set InputUnit render callback. Error = %4.4s", CONVERT_OSSTATUS(ret)); + return false; + } + + //prints the graph into stdout + CAShow(m_AudioGraph); return true; } bool CIOSCoreAudioDevice::Open() { - if(!m_AudioUnit) - return false; - OSStatus ret; - if(!m_Passthrough) { - ret = AudioUnitInitialize(m_MixerUnit); + if(m_Passthrough) + { + if(!m_AudioUnit) + return false; + + ret = AudioUnitInitialize(m_AudioUnit); if (ret) { - CLog::Log(LOGERROR, "CIOSCoreAudioUnit::Open: Unable to Open Mixer device. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + CLog::Log(LOGERROR, "CIOSCoreAudioUnit::Open: Unable to Open AudioComponentInstance. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); return false; - } + } } + else + { + if(!m_AudioGraph) + return false; - ret = AudioUnitInitialize(m_AudioUnit); - if (ret) - { - CLog::Log(LOGERROR, "CIOSCoreAudioUnit::Open: Unable to Open AudioUnit. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); - return false; - } + ret = AUGraphInitialize(m_AudioGraph); + if(ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Open: Error initialize graph. Error = %4.4s", CONVERT_OSSTATUS(ret)); + return false; + } + } return true; } void CIOSCoreAudioDevice::Close() { - if (!m_AudioUnit) - return; + OSStatus ret; + + if (m_Passthrough) + { + if (!m_AudioUnit) + return; - Stop(); + Stop(); - OSStatus ret = AudioUnitUninitialize(m_AudioUnit); + ret = AudioUnitUninitialize(m_AudioUnit); - if (ret) - CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Close: Unable to close Audio device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + if (ret) + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Close: Unable to close Audio device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); - ret = AudioComponentInstanceDispose(m_AudioUnit); + ret = AudioComponentInstanceDispose(m_AudioUnit); - if (ret) - CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Close: Unable to dispose Audio device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + if (ret) + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Close: Unable to dispose Audio device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); - m_AudioUnit = 0; - - if(!m_Passthrough) { - ret = AudioUnitUninitialize(m_MixerUnit); + m_AudioUnit = 0; + } + else + { + if (!m_AudioGraph) + return; + + Stop(); + + ret = AUGraphUninitialize(m_AudioGraph); if (ret) - CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Close: Unable to close Mixer device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Close: Unable to close audiograph. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); - ret = AudioComponentInstanceDispose(m_MixerUnit); + ret = DisposeAUGraph(m_AudioGraph); if (ret) - CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Close: Unable to dispose Mixer device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Close: Unable to dispose audiograph. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); - m_MixerUnit = 0; + m_AudioGraph = 0; } } void CIOSCoreAudioDevice::Start() { - if (!m_AudioUnit) - return; - - OSStatus ret ; - - ret = AudioOutputUnitStart(m_AudioUnit); - if (ret) - CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Start: Unable to start device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + OSStatus ret; + + if (m_Passthrough) + { + if (!m_AudioUnit) + return; + ret = AudioOutputUnitStart(m_AudioUnit); + if (ret) + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Start: Unable to start device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + } + else + { + if(!m_AudioGraph) + return; + ret = AUGraphStart(m_AudioGraph); + if (ret) + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Start: Unable to start audiograph. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + } } void CIOSCoreAudioDevice::Stop() { - if (!m_AudioUnit) - return; + OSStatus ret; + + if (m_Passthrough) + { + if (!m_AudioUnit) + return; - OSStatus ret = AudioOutputUnitStop(m_AudioUnit); - if (ret) - CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Stop: Unable to stop device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + ret = AudioOutputUnitStop(m_AudioUnit); + if (ret) + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Stop: Unable to stop device. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + } + else + { + if (!m_AudioGraph) + return; + + ret = AUGraphStop(m_AudioGraph); + if (ret) + CLog::Log(LOGERROR, "CIOSCoreAudioDevice::Stop: Unable to audiograph. Error = 0x%08x (%4.4s).", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + } } const char* CIOSCoreAudioDevice::GetName(CStdString& name) { - if (!m_AudioUnit) + if (!m_AudioUnit && !m_AudioGraph) return NULL; return name.c_str(); @@ -412,7 +573,7 @@ bool CIOSCoreAudioDevice::EnableOutput(AudioComponentInstance componentInstance, return true; } -Float32 CIOSCoreAudioDevice::GetCurrentVolume() +Float32 CIOSCoreAudioDevice::GetCurrentVolume() const { if (!m_MixerUnit) @@ -431,18 +592,15 @@ Float32 CIOSCoreAudioDevice::GetCurrentVolume() bool CIOSCoreAudioDevice::SetCurrentVolume(Float32 vol) { - - if (!m_MixerUnit && m_Passthrough) - return false; - - OSStatus ret = AudioUnitSetParameter(m_MixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, kInputBus, vol, 0); - if (ret) - { - CLog::Log(LOGERROR, "CIOSCoreAudioDevice::SetCurrentVolume: Unable to set Mixer volume. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + if (!m_MixerUnit || m_Passthrough) return false; - } - ret = AudioUnitSetParameter(m_MixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, kInputBus, vol, 0); + //calc from db to vol 0.0 - 1.0 + Float32 iVol = (vol - VOLUME_MINIMUM)/(Float32)(VOLUME_MAXIMUM - VOLUME_MINIMUM); + + OSStatus ret = AudioUnitSetParameter(m_MixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, kInputBus, iVol, 0); + ret = AudioUnitSetParameter(m_MixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, kInputBus, iVol, 0); + ret = AudioUnitSetParameter(m_MixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, kOutputBus, iVol, 0); if (ret) { CLog::Log(LOGERROR, "CIOSCoreAudioDevice::SetCurrentVolume: Unable to set Mixer volume. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); @@ -500,6 +658,18 @@ int CIOSCoreAudioDevice::FramesPerSlice(int nSlices) CLog::Log(LOGERROR, "CIOSCoreAudioUnit::FramesPerSlice: Unable to setFramesPerSlice. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); return false; } + + if(!m_Passthrough && m_MixerUnit) + { + ret = AudioUnitSetProperty(m_MixerUnit, kAudioUnitProperty_MaximumFramesPerSlice, + kAudioUnitScope_Global, kOutputBus, &maximumFramesPerSlice, sizeof (maximumFramesPerSlice)); + if (ret) + { + CLog::Log(LOGERROR, "CIOSCoreAudioUnit::FramesPerSlice: Unable to setFramesPerSlice on input unit. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + return false; + } + } + return maximumFramesPerSlice; @@ -535,7 +705,7 @@ bool CIOSCoreAudioDevice::SetRenderProc(AudioComponentInstance componentInstance if (ret) { - CLog::Log(LOGERROR, "CIOSCoreAudioUnit::SetRenderProc: Unable to set AudioUnit render callback. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); + CLog::Log(LOGERROR, "CIOSCoreAudioUnit::SetRenderProc: Unable to set AudioComponentInstance render callback. Error = 0x%08x (%4.4s)", (uint32_t)ret, CONVERT_OSSTATUS(ret)); return false; } @@ -557,3 +727,4 @@ bool CIOSCoreAudioDevice::SetSessionListener(AudioSessionPropertyID inID, } #endif + diff --git a/xbmc/osx/IOSCoreAudio.h b/xbmc/osx/IOSCoreAudio.h index 1c6f6b477515c..6bf5c9b323fa1 100644 --- a/xbmc/osx/IOSCoreAudio.h +++ b/xbmc/osx/IOSCoreAudio.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -63,7 +64,7 @@ class CIOSCoreAudioDevice CIOSCoreAudioDevice(AudioComponentInstance deviceId); UInt32 GetTotalOutputChannels(); - void Attach(AudioUnit audioUnit) {m_AudioUnit = audioUnit;} + void Attach(AudioComponentInstance audioUnit) {m_AudioUnit = audioUnit;} AudioComponentInstance GetComponent(){return m_AudioUnit;} void SetupInfo(); @@ -79,7 +80,7 @@ class CIOSCoreAudioDevice AudioUnitElement bus, AudioStreamBasicDescription* pDesc); bool SetFormat(AudioComponentInstance componentInstance, AudioUnitScope scope, AudioUnitElement bus, AudioStreamBasicDescription* pDesc); - Float32 GetCurrentVolume(); + Float32 GetCurrentVolume() const; bool SetCurrentVolume(Float32 vol); int FramesPerSlice(int nSlices); void AudioChannelLayout(int layoutTag); @@ -88,9 +89,17 @@ class CIOSCoreAudioDevice bool SetSessionListener(AudioSessionPropertyID inID, AudioSessionPropertyListener inProc, void* pClientData); + AUGraph m_AudioGraph; + AUNode m_OutputNode; + AUNode m_MixerNode; AudioComponentInstance m_AudioUnit; AudioComponentInstance m_MixerUnit; bool m_Passthrough; +private: + bool SetFormat(AudioComponentInstance &unit, AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus); + bool EnableInputOuput(AudioComponentInstance &unit); + bool OpenUnit(OSType type, OSType subType, OSType manufacturer, AudioComponentInstance &unit, AUNode &node); + bool InitWithGraph(AudioStreamBasicDescription* pDesc, AURenderCallback renderCallback, void *pClientData); }; // Helper Functions @@ -101,3 +110,4 @@ const char* IOSStreamDescriptionToString(AudioStreamBasicDescription desc, CStdS #endif #endif // __COREAUDIO_H__ +