1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 113b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org#pragma warning(disable: 4995) // name was marked as #pragma deprecated 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#if (_MSC_VER >= 1310) && (_MSC_VER < 1400) 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Reports the major and minor versions of the compiler. 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// For example, 1310 for Microsoft Visual C++ .NET 2003. 1310 represents version 13 and a 1.0 point release. 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// The Visual C++ 2005 compiler version is 1400. 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Type cl /? at the command line to see the major and minor versions of your compiler along with the build number. 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#pragma message(">> INFO: Windows Core Audio is not supported in VS 2003") 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 21bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/modules/audio_device/audio_device_config.h" 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef WEBRTC_WINDOWS_CORE_AUDIO_BUILD 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 25bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/modules/audio_device/win/audio_device_core_win.h" 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <assert.h> 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string.h> 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <windows.h> 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <comdef.h> 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <dmo.h> 33bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include <Functiondiscoverykeys_devpkey.h> 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <mmsystem.h> 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <strsafe.h> 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <uuids.h> 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 38bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/modules/audio_device/audio_device_utility.h" 39bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/system_wrappers/interface/sleep.h" 40bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace.h" 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Macro that calls a COM method returning HRESULT value. 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define EXIT_ON_ERROR(hres) do { if (FAILED(hres)) goto Exit; } while(0) 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 45531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org// Macro that continues to a COM error. 46531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org#define CONTINUE_ON_ERROR(hres) do { if (FAILED(hres)) goto Next; } while(0) 47531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Macro that releases a COM object if not NULL. 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SAFE_RELEASE(p) do { if ((p)) { (p)->Release(); (p) = NULL; } } while(0) 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define ROUND(x) ((x) >=0 ? (int)((x) + 0.5) : (int)((x) - 0.5)) 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// REFERENCE_TIME time units per millisecond 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define REFTIMES_PER_MILLISEC 10000 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgtypedef struct tagTHREADNAME_INFO 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD dwType; // must be 0x1000 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LPCSTR szName; // pointer to name (in user addr space) 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD dwThreadID; // thread ID (-1=caller thread) 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD dwFlags; // reserved for future use, must be zero 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} THREADNAME_INFO; 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace { 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgenum { COM_THREADING_MODEL = COINIT_MULTITHREADED }; 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgenum 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kAecCaptureStreamIndex = 0, 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kAecRenderStreamIndex = 1 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}; 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// An implementation of IMediaBuffer, as required for 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// IMediaObject::ProcessOutput(). After consuming data provided by 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ProcessOutput(), call SetLength() to update the buffer availability. 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Example implementation: 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// http://msdn.microsoft.com/en-us/library/dd376684(v=vs.85).aspx 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass MediaBufferImpl : public IMediaBuffer 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgpublic: 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org explicit MediaBufferImpl(DWORD maxLength) 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : _data(new BYTE[maxLength]), 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _length(0), 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _maxLength(maxLength), 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _refCount(0) 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org {} 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // IMediaBuffer methods. 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org STDMETHOD(GetBufferAndLength(BYTE** ppBuffer, DWORD* pcbLength)) 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!ppBuffer || !pcbLength) 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return E_POINTER; 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *ppBuffer = _data; 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *pcbLength = _length; 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return S_OK; 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org STDMETHOD(GetMaxLength(DWORD* pcbMaxLength)) 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!pcbMaxLength) 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return E_POINTER; 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *pcbMaxLength = _maxLength; 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return S_OK; 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org STDMETHOD(SetLength(DWORD cbLength)) 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (cbLength > _maxLength) 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return E_INVALIDARG; 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _length = cbLength; 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return S_OK; 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // IUnknown methods. 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org STDMETHOD_(ULONG, AddRef()) 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return InterlockedIncrement(&_refCount); 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org STDMETHOD(QueryInterface(REFIID riid, void** ppv)) 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!ppv) 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return E_POINTER; 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (riid != IID_IMediaBuffer && riid != IID_IUnknown) 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return E_NOINTERFACE; 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *ppv = static_cast<IMediaBuffer*>(this); 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AddRef(); 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return S_OK; 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org STDMETHOD_(ULONG, Release()) 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LONG refCount = InterlockedDecrement(&_refCount); 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (refCount == 0) 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete this; 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return refCount; 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprivate: 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ~MediaBufferImpl() 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] _data; 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BYTE* _data; 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD _length; 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const DWORD _maxLength; 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LONG _refCount; 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}; 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Static Methods 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// CoreAudioIsSupported 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::CoreAudioIsSupported() 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, -1, "%s", __FUNCTION__); 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool MMDeviceIsAvailable(false); 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool coreAudioIsSupported(false); 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr(S_OK); 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org TCHAR buf[MAXERRORLENGTH]; 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org TCHAR errorText[MAXERRORLENGTH]; 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1) Check if Windows version is Vista SP1 or later. 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // CoreAudio is only available on Vista SP1 and later. 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org OSVERSIONINFOEX osvi; 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORDLONG dwlConditionMask = 0; 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int op = VER_LESS_EQUAL; 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize the OSVERSIONINFOEX structure. 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org osvi.dwMajorVersion = 6; 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org osvi.dwMinorVersion = 0; 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org osvi.wServicePackMajor = 0; 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org osvi.wServicePackMinor = 0; 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org osvi.wProductType = VER_NT_WORKSTATION; 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize the condition mask. 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op); 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op); 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, op); 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMINOR, op); 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL); 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD dwTypeMask = VER_MAJORVERSION | VER_MINORVERSION | 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR | 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VER_PRODUCT_TYPE; 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Perform the test. 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BOOL isVistaRTMorXP = VerifyVersionInfo(&osvi, dwTypeMask, 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dwlConditionMask); 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (isVistaRTMorXP != 0) 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, -1, 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "*** Windows Core Audio is only supported on Vista SP1 or later " 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "=> will revert to the Wave API ***"); 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 2) Initializes the COM library for use by the calling thread. 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The COM init wrapper sets the thread's concurrency model to MTA, 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // and creates a new apartment for the thread if one is required. The 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // wrapper also ensures that each call to CoInitializeEx is balanced 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // by a corresponding call to CoUninitialize. 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ScopedCOMInitializer comInit(ScopedCOMInitializer::kMTA); 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!comInit.succeeded()) { 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Things will work even if an STA thread is calling this method but we 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // want to ensure that MTA is used and therefore return false here. 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 244d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3) Check if the MMDevice API is available. 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The Windows Multimedia Device (MMDevice) API enables audio clients to 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // discover audio endpoint devices, determine their capabilities, and create 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // driver instances for those devices. 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Header file Mmdeviceapi.h defines the interfaces in the MMDevice API. 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The MMDevice API consists of several interfaces. The first of these is the 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // IMMDeviceEnumerator interface. To access the interfaces in the MMDevice API, 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // a client obtains a reference to the IMMDeviceEnumerator interface of a 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // device-enumerator object by calling the CoCreateInstance function. 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Through the IMMDeviceEnumerator interface, the client can obtain references 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // to the other interfaces in the MMDevice API. The MMDevice API implements 258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the following interfaces: 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // IMMDevice Represents an audio device. 261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // IMMDeviceCollection Represents a collection of audio devices. 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // IMMDeviceEnumerator Provides methods for enumerating audio devices. 263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // IMMEndpoint Represents an audio endpoint device. 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDeviceEnumerator* pIMMD(NULL); 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = CoCreateInstance( 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSID_MMDeviceEnumerator, // GUID value of MMDeviceEnumerator coclass 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSCTX_ALL, 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IID_IMMDeviceEnumerator, // GUID value of the IMMDeviceEnumerator interface 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void**)&pIMMD ); 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, -1, 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AudioDeviceWindowsCore::CoreAudioIsSupported() Failed to create the required COM object", hr); 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, -1, 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AudioDeviceWindowsCore::CoreAudioIsSupported() CoCreateInstance(MMDeviceEnumerator) failed (hr=0x%x)", hr); 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org FORMAT_MESSAGE_IGNORE_INSERTS; 285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const DWORD dwLangID = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); 286d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Gets the system's human readable message string for this HRESULT. 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // All error message in English by default. 289d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org DWORD messageLength = ::FormatMessageW(dwFlags, 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr, 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dwLangID, 293d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org errorText, 294d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org MAXERRORLENGTH, 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL); 296d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(messageLength <= MAXERRORLENGTH); 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Trims tailing white space (FormatMessage() leaves a trailing cr-lf.). 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (; messageLength && ::isspace(errorText[messageLength - 1]); 301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org --messageLength) 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errorText[messageLength - 1] = '\0'; 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: ")); 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StringCchCat(buf, MAXERRORLENGTH, errorText); 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, -1, "%S", buf); 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MMDeviceIsAvailable = true; 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, -1, 314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AudioDeviceWindowsCore::CoreAudioIsSupported() CoCreateInstance(MMDeviceEnumerator) succeeded", hr); 315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pIMMD); 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 4) Verify that we can create and initialize our Core Audio class. 319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Also, perform a limited "API test" to ensure that Core Audio is supported for all devices. 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (MMDeviceIsAvailable) 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org coreAudioIsSupported = false; 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioDeviceWindowsCore* p = new AudioDeviceWindowsCore(-1); 327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (p == NULL) 328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int ok(0); 333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int temp_ok(0); 334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool available(false); 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= p->Init(); 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 33864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int16_t numDevsRec = p->RecordingDevices(); 33964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org for (uint16_t i = 0; i < numDevsRec; i++) 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= p->SetRecordingDevice(i); 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp_ok = p->RecordingIsAvailable(available); 343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= temp_ok; 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= (available == false); 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (available) 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= p->InitMicrophone(); 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ok) 350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, -1, 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AudioDeviceWindowsCore::CoreAudioIsSupported() Failed to use Core Audio Recording for device id=%i", i); 353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 35664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int16_t numDevsPlay = p->PlayoutDevices(); 35764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org for (uint16_t i = 0; i < numDevsPlay; i++) 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= p->SetPlayoutDevice(i); 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp_ok = p->PlayoutIsAvailable(available); 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= temp_ok; 362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= (available == false); 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (available) 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= p->InitSpeaker(); 366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ok) 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, -1 , 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AudioDeviceWindowsCore::CoreAudioIsSupported() Failed to use Core Audio Playout for device id=%i", i); 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ok |= p->Terminate(); 375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ok == 0) 377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org coreAudioIsSupported = true; 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete p; 382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (coreAudioIsSupported) 385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, -1, "*** Windows Core Audio is supported ***"); 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, -1, "*** Windows Core Audio is NOT supported => will revert to the Wave API ***"); 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (coreAudioIsSupported); 394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Construction & Destruction 398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// AudioDeviceWindowsCore() - ctor 402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 40464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgAudioDeviceWindowsCore::AudioDeviceWindowsCore(const int32_t id) : 405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _comInit(ScopedCOMInitializer::kMTA), 406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _critSect(*CriticalSectionWrapper::CreateCriticalSection()), 407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _volumeMutex(*CriticalSectionWrapper::CreateCriticalSection()), 408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id(id), 409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer(NULL), 410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrEnumerator(NULL), 411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrRenderCollection(NULL), 412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrCaptureCollection(NULL), 413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrDeviceOut(NULL), 414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrDeviceIn(NULL), 415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrClientOut(NULL), 416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrClientIn(NULL), 417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrRenderClient(NULL), 418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrCaptureClient(NULL), 419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrCaptureVolume(NULL), 420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrRenderSimpleVolume(NULL), 421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _dmo(NULL), 422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mediaBuffer(NULL), 423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _builtInAecEnabled(false), 424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playAudioFrameSize(0), 425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playSampleRate(0), 426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBlockSize(0), 427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels(2), 428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sndCardPlayDelay(0), 429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sndCardRecDelay(0), 430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _writtenSamples(0), 431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _readSamples(0), 432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playAcc(0), 433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recAudioFrameSize(0), 434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recSampleRate(0), 435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recBlockSize(0), 436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels(2), 437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _avrtLibrary(NULL), 438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _winSupportAvrt(false), 439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRenderSamplesReadyEvent(NULL), 440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hPlayThread(NULL), 441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hCaptureSamplesReadyEvent(NULL), 442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRecThread(NULL), 443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hShutdownRenderEvent(NULL), 444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hShutdownCaptureEvent(NULL), 445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRenderStartedEvent(NULL), 446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hCaptureStartedEvent(NULL), 447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hGetCaptureVolumeThread(NULL), 448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hSetCaptureVolumeThread(NULL), 449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hSetCaptureVolumeEvent(NULL), 450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hMmTask(NULL), 451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _initialized(false), 452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording(false), 453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing(false), 454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recIsInitialized(false), 455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playIsInitialized(false), 456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _speakerIsInitialized(false), 457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _microphoneIsInitialized(false), 458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _AGC(false), 459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playWarning(0), 460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playError(0), 461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recWarning(0), 462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recError(0), 463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufType(AudioDeviceModule::kAdaptiveBufferSize), 464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufDelay(80), 465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufDelayFixed(80), 466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _usingInputDeviceIndex(false), 467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _usingOutputDeviceIndex(false), 468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDevice(AudioDeviceModule::kDefaultCommunicationDevice), 469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputDevice(AudioDeviceModule::kDefaultCommunicationDevice), 470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDeviceIndex(0), 471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputDeviceIndex(0), 472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _newMicLevel(0) 473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "%s created", __FUNCTION__); 475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_comInit.succeeded()); 476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Try to load the Avrt DLL 478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_avrtLibrary) 479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get handle to the Avrt DLL module. 481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _avrtLibrary = LoadLibrary(TEXT("Avrt.dll")); 482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_avrtLibrary) 483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Handle is valid (should only happen if OS larger than vista & win7). 485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Try to get the function addresses. 486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWindowsCore::AudioDeviceWindowsCore() The Avrt DLL module is now loaded"); 487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _PAvRevertMmThreadCharacteristics = (PAvRevertMmThreadCharacteristics)GetProcAddress(_avrtLibrary, "AvRevertMmThreadCharacteristics"); 489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _PAvSetMmThreadCharacteristicsA = (PAvSetMmThreadCharacteristicsA)GetProcAddress(_avrtLibrary, "AvSetMmThreadCharacteristicsA"); 490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _PAvSetMmThreadPriority = (PAvSetMmThreadPriority)GetProcAddress(_avrtLibrary, "AvSetMmThreadPriority"); 491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ( _PAvRevertMmThreadCharacteristics && 493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _PAvSetMmThreadCharacteristicsA && 494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _PAvSetMmThreadPriority) 495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWindowsCore::AudioDeviceWindowsCore() AvRevertMmThreadCharacteristics() is OK"); 497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWindowsCore::AudioDeviceWindowsCore() AvSetMmThreadCharacteristicsA() is OK"); 498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWindowsCore::AudioDeviceWindowsCore() AvSetMmThreadPriority() is OK"); 499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _winSupportAvrt = true; 500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Create our samples ready events - we want auto reset events that start in the not-signaled state. 505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The state of an auto-reset event object remains signaled until a single waiting thread is released, 506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // at which time the system automatically sets the state to nonsignaled. If no threads are waiting, 507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the event object's state remains signaled. 508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // (Except for _hShutdownCaptureEvent, which is used to shutdown multiple threads). 509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRenderSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hCaptureSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hShutdownRenderEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hShutdownCaptureEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRenderStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hCaptureStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hSetCaptureVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _perfCounterFreq.QuadPart = 1; 518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _perfCounterFactor = 0.0; 519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _avgCPULoad = 0.0; 520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // list of number of channels to use on recording side 522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannelsPrioList[0] = 2; // stereo is prio 1 523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannelsPrioList[1] = 1; // mono is prio 2 524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // list of number of channels to use on playout side 526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannelsPrioList[0] = 2; // stereo is prio 1 527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannelsPrioList[1] = 1; // mono is prio 2 528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr; 530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We know that this API will work since it has already been verified in 532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // CoreAudioIsSupported, hence no need to check for errors here as well. 533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Retrive the IMMDeviceEnumerator API (should load the MMDevAPI.dll) 535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(henrika): we should probably move this allocation to Init() instead 536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // and deallocate in Terminate() to make the implementation more symmetric. 537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoCreateInstance( 538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __uuidof(MMDeviceEnumerator), 539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, 540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSCTX_ALL, 541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __uuidof(IMMDeviceEnumerator), 542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org reinterpret_cast<void**>(&_ptrEnumerator)); 543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(NULL != _ptrEnumerator); 544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // DMO initialization for built-in WASAPI AEC. 546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMediaObject* ptrDMO = NULL; 548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = CoCreateInstance(CLSID_CWMAudioAEC, 549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, 550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSCTX_INPROC_SERVER, 551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IID_IMediaObject, 552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org reinterpret_cast<void**>(&ptrDMO)); 553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr) || ptrDMO == NULL) 554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Since we check that _dmo is non-NULL in EnableBuiltInAEC(), the 556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // feature is prevented from being enabled. 557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _builtInAecEnabled = false; 558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _dmo = ptrDMO; 561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(ptrDMO); 562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// AudioDeviceWindowsCore() - dtor 567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgAudioDeviceWindowsCore::~AudioDeviceWindowsCore() 570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__); 572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Terminate(); 574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The IMMDeviceEnumerator is created during construction. Must release 576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // it here and not in Terminate() since we don't recreate it in Init(). 577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrEnumerator); 578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer = NULL; 580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (NULL != _hRenderSamplesReadyEvent) 582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hRenderSamplesReadyEvent); 584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRenderSamplesReadyEvent = NULL; 585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (NULL != _hCaptureSamplesReadyEvent) 588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hCaptureSamplesReadyEvent); 590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hCaptureSamplesReadyEvent = NULL; 591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (NULL != _hRenderStartedEvent) 594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hRenderStartedEvent); 596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRenderStartedEvent = NULL; 597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (NULL != _hCaptureStartedEvent) 600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hCaptureStartedEvent); 602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hCaptureStartedEvent = NULL; 603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (NULL != _hShutdownRenderEvent) 606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hShutdownRenderEvent); 608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hShutdownRenderEvent = NULL; 609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (NULL != _hShutdownCaptureEvent) 612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hShutdownCaptureEvent); 614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hShutdownCaptureEvent = NULL; 615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (NULL != _hSetCaptureVolumeEvent) 618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hSetCaptureVolumeEvent); 620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hSetCaptureVolumeEvent = NULL; 621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_avrtLibrary) 624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BOOL freeOK = FreeLibrary(_avrtLibrary); 626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!freeOK) 627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AudioDeviceWindowsCore::~AudioDeviceWindowsCore() failed to free the loaded Avrt DLL module correctly"); 630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AudioDeviceWindowsCore::~AudioDeviceWindowsCore() the Avrt DLL module is now unloaded"); 635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete &_critSect; 639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete &_volumeMutex; 640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// API 644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// AttachAudioBuffer 648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceWindowsCore::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) 651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer = audioBuffer; 654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Inform the AudioBuffer about default settings for this implementation. 656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set all values to zero here since the actual settings will be done by 657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // InitPlayout and InitRecording later. 658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordingSampleRate(0); 659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetPlayoutSampleRate(0); 660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordingChannels(0); 661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetPlayoutChannels(0); 662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ActiveAudioLayer 666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 66864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const 669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audioLayer = AudioDeviceModule::kWindowsCoreAudio; 671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Init 676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 67864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::Init() 679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_initialized) 684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playWarning = 0; 689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playError = 0; 690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recWarning = 0; 691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recError = 0; 692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Enumerate all audio rendering and capturing endpoint devices. 694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Note that, some of these will not be able to select by the user. 695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The complete collection is for internal use only. 696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _EnumerateEndpointDevicesAll(eRender); 698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _EnumerateEndpointDevicesAll(eCapture); 699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _initialized = true; 701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Terminate 707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 70964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::Terminate() 710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_initialized) { 715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _initialized = false; 719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _speakerIsInitialized = false; 720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _microphoneIsInitialized = false; 721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = false; 722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording = false; 723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderCollection); 725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrCaptureCollection); 726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceOut); 727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceIn); 728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientOut); 729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientIn); 730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderClient); 731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrCaptureClient); 732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrCaptureVolume); 733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderSimpleVolume); 734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Initialized 740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::Initialized() const 743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_initialized); 745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// InitSpeaker 749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 75164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::InitSpeaker() 752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playing) 757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceOut == NULL) 762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_usingOutputDeviceIndex) 767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 76864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int16_t nDevices = PlayoutDevices(); 769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_outputDeviceIndex > (nDevices - 1)) 770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "current device selection is invalid => unable to initialize"); 772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 77664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t ret(0); 777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceOut); 779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_usingOutputDeviceIndex) 780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Refresh the selected rendering endpoint device using current index 782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetListDevice(eRender, _outputDeviceIndex, &_ptrDeviceOut); 783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ERole role; 787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (_outputDevice == AudioDeviceModule::kDefaultDevice) ? role = eConsole : role = eCommunications; 788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Refresh the selected rendering endpoint device using role 789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetDefaultDevice(eRender, role, &_ptrDeviceOut); 790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != 0 || (_ptrDeviceOut == NULL)) 793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to initialize the rendering enpoint device"); 795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceOut); 796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAudioSessionManager* pManager = NULL; 800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _ptrDeviceOut->Activate(__uuidof(IAudioSessionManager), 801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSCTX_ALL, 802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, 803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void**)&pManager); 804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != 0 || pManager == NULL) 805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to initialize the render manager"); 808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pManager); 809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderSimpleVolume); 813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = pManager->GetSimpleAudioVolume(NULL, FALSE, &_ptrRenderSimpleVolume); 814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != 0 || _ptrRenderSimpleVolume == NULL) 815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to initialize the render simple volume"); 818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pManager); 819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderSimpleVolume); 820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pManager); 823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _speakerIsInitialized = true; 825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// InitMicrophone 831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 83364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::InitMicrophone() 834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recording) 839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceIn == NULL) 844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_usingInputDeviceIndex) 849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 85064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int16_t nDevices = RecordingDevices(); 851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_inputDeviceIndex > (nDevices - 1)) 852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "current device selection is invalid => unable to initialize"); 854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 85864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t ret(0); 859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceIn); 861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_usingInputDeviceIndex) 862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Refresh the selected capture endpoint device using current index 864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetListDevice(eCapture, _inputDeviceIndex, &_ptrDeviceIn); 865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ERole role; 869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (_inputDevice == AudioDeviceModule::kDefaultDevice) ? role = eConsole : role = eCommunications; 870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Refresh the selected capture endpoint device using role 871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetDefaultDevice(eCapture, role, &_ptrDeviceIn); 872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != 0 || (_ptrDeviceIn == NULL)) 875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to initialize the capturing enpoint device"); 877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceIn); 878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _ptrDeviceIn->Activate(__uuidof(IAudioEndpointVolume), 882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSCTX_ALL, 883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, 884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org reinterpret_cast<void **>(&_ptrCaptureVolume)); 885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != 0 || _ptrCaptureVolume == NULL) 886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to initialize the capture volume"); 889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrCaptureVolume); 890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _microphoneIsInitialized = true; 894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerIsInitialized 900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::SpeakerIsInitialized() const 903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_speakerIsInitialized); 906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneIsInitialized 910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::MicrophoneIsInitialized() const 913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_microphoneIsInitialized); 916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerVolumeIsAvailable 920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 92264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SpeakerVolumeIsAvailable(bool& available) 923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceOut == NULL) 928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAudioSessionManager* pManager = NULL; 934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ISimpleAudioVolume* pVolume = NULL; 935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceOut->Activate(__uuidof(IAudioSessionManager), CLSCTX_ALL, NULL, (void**)&pManager); 937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pManager->GetSimpleAudioVolume(NULL, FALSE, &pVolume); 940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float volume(0.0f); 943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pVolume->GetMasterVolume(&volume); 944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pManager); 951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pManager); 958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetSpeakerVolume 964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 96664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetSpeakerVolume(uint32_t volume) 967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_speakerIsInitialized) 973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceOut == NULL) 978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 98364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org if (volume < (uint32_t)MIN_CORE_SPEAKER_VOLUME || 98464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org volume > (uint32_t)MAX_CORE_SPEAKER_VOLUME) 985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // scale input volume to valid range (0.0 to 1.0) 992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const float fLevel = (float)volume/MAX_CORE_SPEAKER_VOLUME; 993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _volumeMutex.Enter(); 994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderSimpleVolume->SetMasterVolume(fLevel,NULL); 995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _volumeMutex.Leave(); 996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerVolume 1007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 100964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SpeakerVolume(uint32_t& volume) const 1010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_speakerIsInitialized) 1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceOut == NULL) 1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float fLevel(0.0f); 1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _volumeMutex.Enter(); 1030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderSimpleVolume->GetMasterVolume(&fLevel); 1031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _volumeMutex.Leave(); 1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // scale input volume range [0.0,1.0] to valid output range 103564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org volume = static_cast<uint32_t> (fLevel*MAX_CORE_SPEAKER_VOLUME); 1036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetWaveOutVolume 1046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 104864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetWaveOutVolume(uint16_t volumeLeft, uint16_t volumeRight) 1049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// WaveOutVolume 1055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 105764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::WaveOutVolume(uint16_t& volumeLeft, uint16_t& volumeRight) const 1058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MaxSpeakerVolume 1064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 1065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// The internal range for Core Audio is 0.0 to 1.0, where 0.0 indicates 1066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// silence and 1.0 indicates full volume (no attenuation). 1067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// We add our (webrtc-internal) own max level to match the Wave API and 1068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// how it is used today in VoE. 1069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 107164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MaxSpeakerVolume(uint32_t& maxVolume) const 1072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_speakerIsInitialized) 1075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 107964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org maxVolume = static_cast<uint32_t> (MAX_CORE_SPEAKER_VOLUME); 1080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MinSpeakerVolume 1086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 108864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MinSpeakerVolume(uint32_t& minVolume) const 1089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_speakerIsInitialized) 1092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 109664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org minVolume = static_cast<uint32_t> (MIN_CORE_SPEAKER_VOLUME); 1097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerVolumeStepSize 1103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 110564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SpeakerVolumeStepSize(uint16_t& stepSize) const 1106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_speakerIsInitialized) 1109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stepSize = CORE_SPEAKER_VOLUME_STEP_SIZE; 1114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerMuteIsAvailable 1120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 112264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SpeakerMuteIsAvailable(bool& available) 1123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceOut == NULL) 1128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAudioEndpointVolume* pVolume = NULL; 1134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Query the speaker system mute state. 1136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceOut->Activate(__uuidof(IAudioEndpointVolume), 1137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSCTX_ALL, NULL, reinterpret_cast<void**>(&pVolume)); 1138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BOOL mute; 1141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pVolume->GetMute(&mute); 1142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 1143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 1144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 1146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetSpeakerMute 1159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 116164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetSpeakerMute(bool enable) 1162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_speakerIsInitialized) 1167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceOut == NULL) 1172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAudioEndpointVolume* pVolume = NULL; 1178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the speaker system mute state. 1180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceOut->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, reinterpret_cast<void**>(&pVolume)); 1181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const BOOL mute(enable); 1184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pVolume->SetMute(mute, NULL); 1185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerMute 1199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 120164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SpeakerMute(bool& enabled) const 1202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_speakerIsInitialized) 1205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceOut == NULL) 1210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAudioEndpointVolume* pVolume = NULL; 1216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Query the speaker system mute state. 1218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceOut->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, reinterpret_cast<void**>(&pVolume)); 1219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BOOL mute; 1222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pVolume->GetMute(&mute); 1223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = (mute == TRUE) ? true : false; 1226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneMuteIsAvailable 1239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 124164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MicrophoneMuteIsAvailable(bool& available) 1242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceIn == NULL) 1247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAudioEndpointVolume* pVolume = NULL; 1253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Query the microphone system mute state. 1255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceIn->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, reinterpret_cast<void**>(&pVolume)); 1256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BOOL mute; 1259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pVolume->GetMute(&mute); 1260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 1261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 1262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 1264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetMicrophoneMute 1276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 127864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetMicrophoneMute(bool enable) 1279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_microphoneIsInitialized) 1282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceIn == NULL) 1287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAudioEndpointVolume* pVolume = NULL; 1293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the microphone system mute state. 1295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceIn->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, reinterpret_cast<void**>(&pVolume)); 1296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const BOOL mute(enable); 1299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pVolume->SetMute(mute, NULL); 1300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneMute 1313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 131564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MicrophoneMute(bool& enabled) const 1316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_microphoneIsInitialized) 1319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAudioEndpointVolume* pVolume = NULL; 1325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Query the microphone system mute state. 1327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceIn->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, reinterpret_cast<void**>(&pVolume)); 1328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BOOL mute; 1331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pVolume->GetMute(&mute); 1332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = (mute == TRUE) ? true : false; 1335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneBoostIsAvailable 1347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 134964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MicrophoneBoostIsAvailable(bool& available) 1350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 1353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetMicrophoneBoost 1358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 136064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetMicrophoneBoost(bool enable) 1361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_microphoneIsInitialized) 1364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneBoost 1373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 137564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MicrophoneBoost(bool& enabled) const 1376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_microphoneIsInitialized) 1379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// StereoRecordingIsAvailable 1388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 139064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::StereoRecordingIsAvailable(bool& available) 1391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 1394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetStereoRecording 1399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 140164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetStereoRecording(bool enable) 1402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (enable) 1407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannelsPrioList[0] = 2; // try stereo first 1409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannelsPrioList[1] = 1; 1410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = 2; 1411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannelsPrioList[0] = 1; // try mono first 1415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannelsPrioList[1] = 2; 1416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = 1; 1417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// StereoRecording 1424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 142664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::StereoRecording(bool& enabled) const 1427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recChannels == 2) 1430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = true; 1431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = false; 1433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// StereoPlayoutIsAvailable 1439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 144164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::StereoPlayoutIsAvailable(bool& available) 1442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 1445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetStereoPlayout 1450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 145264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetStereoPlayout(bool enable) 1453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (enable) 1458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannelsPrioList[0] = 2; // try stereo first 1460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannelsPrioList[1] = 1; 1461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels = 2; 1462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannelsPrioList[0] = 1; // try mono first 1466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannelsPrioList[1] = 2; 1467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels = 1; 1468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// StereoPlayout 1475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 147764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::StereoPlayout(bool& enabled) const 1478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playChannels == 2) 1481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = true; 1482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enabled = false; 1484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetAGC 1490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 149264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetAGC(bool enable) 1493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _AGC = enable; 1496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// AGC 1501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::AGC() const 1504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _AGC; 1507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneVolumeIsAvailable 1511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 151364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MicrophoneVolumeIsAvailable(bool& available) 1514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceIn == NULL) 1519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAudioEndpointVolume* pVolume = NULL; 1525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceIn->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, reinterpret_cast<void**>(&pVolume)); 1527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float volume(0.0f); 1530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pVolume->GetMasterVolumeLevelScalar(&volume); 1531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 1532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 1534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 1536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pVolume); 1543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetMicrophoneVolume 1548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 155064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetMicrophoneVolume(uint32_t volume) 1551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "AudioDeviceWindowsCore::SetMicrophoneVolume(volume=%u)", volume); 1553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_microphoneIsInitialized) 1558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceIn == NULL) 1563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 156864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org if (volume < static_cast<uint32_t>(MIN_CORE_MICROPHONE_VOLUME) || 156964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org volume > static_cast<uint32_t>(MAX_CORE_MICROPHONE_VOLUME)) 1570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // scale input volume to valid range (0.0 to 1.0) 1576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const float fLevel = static_cast<float>(volume)/MAX_CORE_MICROPHONE_VOLUME; 1577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _volumeMutex.Enter(); 1578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrCaptureVolume->SetMasterVolumeLevelScalar(fLevel, NULL); 1579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _volumeMutex.Leave(); 1580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneVolume 1591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 159364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MicrophoneVolume(uint32_t& volume) const 1594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_microphoneIsInitialized) 1599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceIn == NULL) 1604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 1610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float fLevel(0.0f); 1611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org volume = 0; 1612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _volumeMutex.Enter(); 1613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrCaptureVolume->GetMasterVolumeLevelScalar(&fLevel); 1614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _volumeMutex.Leave(); 1615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 1616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // scale input volume range [0.0,1.0] to valid output range 161864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org volume = static_cast<uint32_t> (fLevel*MAX_CORE_MICROPHONE_VOLUME); 1619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 1623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MaxMicrophoneVolume 1629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 1630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// The internal range for Core Audio is 0.0 to 1.0, where 0.0 indicates 1631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// silence and 1.0 indicates full volume (no attenuation). 1632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// We add our (webrtc-internal) own max level to match the Wave API and 1633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// how it is used today in VoE. 1634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 163664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MaxMicrophoneVolume(uint32_t& maxVolume) const 1637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "%s", __FUNCTION__); 1639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_microphoneIsInitialized) 1641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 164564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org maxVolume = static_cast<uint32_t> (MAX_CORE_MICROPHONE_VOLUME); 1646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MinMicrophoneVolume 1652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 165464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MinMicrophoneVolume(uint32_t& minVolume) const 1655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_microphoneIsInitialized) 1658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 166264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org minVolume = static_cast<uint32_t> (MIN_CORE_MICROPHONE_VOLUME); 1663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneVolumeStepSize 1669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 167164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::MicrophoneVolumeStepSize(uint16_t& stepSize) const 1672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_microphoneIsInitialized) 1675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stepSize = CORE_MICROPHONE_VOLUME_STEP_SIZE; 1680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// PlayoutDevices 1686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 168864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint16_t AudioDeviceWindowsCore::PlayoutDevices() 1689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_RefreshDeviceList(eRender) != -1) 1694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_DeviceListCount(eRender)); 1696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetPlayoutDevice I (II) 1703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 170564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetPlayoutDevice(uint16_t index) 1706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playIsInitialized) 1709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get current number of available rendering endpoint devices and refresh the rendering collection. 1714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT nDevices = PlayoutDevices(); 1715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (index < 0 || index > (nDevices-1)) 1717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device index is out of range [0,%u]", (nDevices-1)); 1719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr(S_OK); 1725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrRenderCollection != NULL); 1727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Select an endpoint rendering device given the specified index 1729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceOut); 1730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderCollection->Item( 1731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org index, 1732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &_ptrDeviceOut); 1733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 1734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceOut); 1737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WCHAR szDeviceName[MAX_PATH]; 1741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int bufferLen = sizeof(szDeviceName)/sizeof(szDeviceName)[0]; 1742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint device's friendly-name 1744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_GetDeviceName(_ptrDeviceOut, szDeviceName, bufferLen) == 0) 1745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "friendly name: \"%S\"", szDeviceName); 1747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _usingOutputDeviceIndex = true; 1750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputDeviceIndex = index; 1751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetPlayoutDevice II (II) 1757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 175964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device) 1760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playIsInitialized) 1762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ERole role(eCommunications); 1767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (device == AudioDeviceModule::kDefaultDevice) 1769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role = eConsole; 1771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (device == AudioDeviceModule::kDefaultCommunicationDevice) 1773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role = eCommunications; 1775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Refresh the list of rendering endpoint devices 1780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _RefreshDeviceList(eRender); 1781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr(S_OK); 1783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrEnumerator != NULL); 1785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Select an endpoint rendering device given the specified role 1787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceOut); 1788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrEnumerator->GetDefaultAudioEndpoint( 1789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org eRender, 1790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role, 1791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &_ptrDeviceOut); 1792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 1793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 1795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceOut); 1796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WCHAR szDeviceName[MAX_PATH]; 1800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int bufferLen = sizeof(szDeviceName)/sizeof(szDeviceName)[0]; 1801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint device's friendly-name 1803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_GetDeviceName(_ptrDeviceOut, szDeviceName, bufferLen) == 0) 1804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "friendly name: \"%S\"", szDeviceName); 1806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _usingOutputDeviceIndex = false; 1809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputDevice = device; 1810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// PlayoutDeviceName 1816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 181864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::PlayoutDeviceName( 181964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t index, 1820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char name[kAdmMaxDeviceNameSize], 1821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char guid[kAdmMaxGuidSize]) 1822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool defaultCommunicationDevice(false); 182564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org const int16_t nDevices(PlayoutDevices()); // also updates the list of devices 1826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Special fix for the case when the user selects '-1' as index (<=> Default Communication Device) 182864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org if (index == (uint16_t)(-1)) 1829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org defaultCommunicationDevice = true; 1831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org index = 0; 1832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Default Communication endpoint device will be used"); 1833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((index > (nDevices-1)) || (name == NULL)) 1836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(name, 0, kAdmMaxDeviceNameSize); 1841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (guid != NULL) 1843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(guid, 0, kAdmMaxGuidSize); 1845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 184964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t ret(-1); 1850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WCHAR szDeviceName[MAX_PATH]; 1851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int bufferLen = sizeof(szDeviceName)/sizeof(szDeviceName)[0]; 1852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint device's friendly-name 1854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (defaultCommunicationDevice) 1855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetDefaultDeviceName(eRender, eCommunications, szDeviceName, bufferLen); 1857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetListDeviceName(eRender, index, szDeviceName, bufferLen); 1861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret == 0) 1864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Convert the endpoint device's friendly-name to UTF-8 1866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WideCharToMultiByte(CP_UTF8, 0, szDeviceName, -1, name, kAdmMaxDeviceNameSize, NULL, NULL) == 0) 1867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d", GetLastError()); 1869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint ID string (uniquely identifies the device among all audio endpoint devices) 1873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (defaultCommunicationDevice) 1874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetDefaultDeviceID(eRender, eCommunications, szDeviceName, bufferLen); 1876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetListDeviceID(eRender, index, szDeviceName, bufferLen); 1880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (guid != NULL && ret == 0) 1883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Convert the endpoint device's ID string to UTF-8 1885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WideCharToMultiByte(CP_UTF8, 0, szDeviceName, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) 1886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d", GetLastError()); 1888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ret; 1892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// RecordingDeviceName 1896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 189864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::RecordingDeviceName( 189964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint16_t index, 1900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char name[kAdmMaxDeviceNameSize], 1901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char guid[kAdmMaxGuidSize]) 1902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool defaultCommunicationDevice(false); 190564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org const int16_t nDevices(RecordingDevices()); // also updates the list of devices 1906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Special fix for the case when the user selects '-1' as index (<=> Default Communication Device) 190864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org if (index == (uint16_t)(-1)) 1909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org defaultCommunicationDevice = true; 1911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org index = 0; 1912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Default Communication endpoint device will be used"); 1913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((index > (nDevices-1)) || (name == NULL)) 1916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(name, 0, kAdmMaxDeviceNameSize); 1921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (guid != NULL) 1923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(guid, 0, kAdmMaxGuidSize); 1925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 192964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t ret(-1); 1930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WCHAR szDeviceName[MAX_PATH]; 1931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int bufferLen = sizeof(szDeviceName)/sizeof(szDeviceName)[0]; 1932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint device's friendly-name 1934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (defaultCommunicationDevice) 1935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetDefaultDeviceName(eCapture, eCommunications, szDeviceName, bufferLen); 1937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetListDeviceName(eCapture, index, szDeviceName, bufferLen); 1941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret == 0) 1944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Convert the endpoint device's friendly-name to UTF-8 1946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WideCharToMultiByte(CP_UTF8, 0, szDeviceName, -1, name, kAdmMaxDeviceNameSize, NULL, NULL) == 0) 1947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d", GetLastError()); 1949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint ID string (uniquely identifies the device among all audio endpoint devices) 1953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (defaultCommunicationDevice) 1954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetDefaultDeviceID(eCapture, eCommunications, szDeviceName, bufferLen); 1956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 1958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = _GetListDeviceID(eCapture, index, szDeviceName, bufferLen); 1960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (guid != NULL && ret == 0) 1963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Convert the endpoint device's ID string to UTF-8 1965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WideCharToMultiByte(CP_UTF8, 0, szDeviceName, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) 1966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d", GetLastError()); 1968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ret; 1972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// RecordingDevices 1976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 197864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint16_t AudioDeviceWindowsCore::RecordingDevices() 1979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 1982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_RefreshDeviceList(eCapture) != -1) 1984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_DeviceListCount(eCapture)); 1986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 1989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetRecordingDevice I (II) 1993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 1994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 199564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetRecordingDevice(uint16_t index) 1996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recIsInitialized) 1999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get current number of available capture endpoint devices and refresh the capture collection. 2004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT nDevices = RecordingDevices(); 2005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (index < 0 || index > (nDevices-1)) 2007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device index is out of range [0,%u]", (nDevices-1)); 2009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 2013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr(S_OK); 2015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrCaptureCollection != NULL); 2017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Select an endpoint capture device given the specified index 2019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceIn); 2020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrCaptureCollection->Item( 2021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org index, 2022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &_ptrDeviceIn); 2023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 2024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 2026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceIn); 2027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WCHAR szDeviceName[MAX_PATH]; 2031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int bufferLen = sizeof(szDeviceName)/sizeof(szDeviceName)[0]; 2032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint device's friendly-name 2034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_GetDeviceName(_ptrDeviceIn, szDeviceName, bufferLen) == 0) 2035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "friendly name: \"%S\"", szDeviceName); 2037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _usingInputDeviceIndex = true; 2040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDeviceIndex = index; 2041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetRecordingDevice II (II) 2047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 204964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetRecordingDevice(AudioDeviceModule::WindowsDeviceType device) 2050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recIsInitialized) 2052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ERole role(eCommunications); 2057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (device == AudioDeviceModule::kDefaultDevice) 2059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role = eConsole; 2061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (device == AudioDeviceModule::kDefaultCommunicationDevice) 2063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role = eCommunications; 2065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 2068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Refresh the list of capture endpoint devices 2070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _RefreshDeviceList(eCapture); 2071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr(S_OK); 2073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrEnumerator != NULL); 2075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Select an endpoint capture device given the specified role 2077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceIn); 2078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrEnumerator->GetDefaultAudioEndpoint( 2079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org eCapture, 2080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role, 2081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &_ptrDeviceIn); 2082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 2083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 2085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrDeviceIn); 2086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WCHAR szDeviceName[MAX_PATH]; 2090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int bufferLen = sizeof(szDeviceName)/sizeof(szDeviceName)[0]; 2091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint device's friendly-name 2093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_GetDeviceName(_ptrDeviceIn, szDeviceName, bufferLen) == 0) 2094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "friendly name: \"%S\"", szDeviceName); 2096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _usingInputDeviceIndex = false; 2099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDevice = device; 2100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// PlayoutIsAvailable 2106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 210864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::PlayoutIsAvailable(bool& available) 2109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 2112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Try to initialize the playout side 211464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t res = InitPlayout(); 2115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Cancel effect of initialization 2117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopPlayout(); 2118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (res != -1) 2120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 2122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// RecordingIsAvailable 2129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 213164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::RecordingIsAvailable(bool& available) 2132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = false; 2135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Try to initialize the recording side 213764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t res = InitRecording(); 2138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Cancel effect of initialization 2140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopRecording(); 2141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (res != -1) 2143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org available = true; 2145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// InitPlayout 2152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 215464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::InitPlayout() 2155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 2158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playing) 2160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playIsInitialized) 2165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceOut == NULL) 2170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize the speaker (devices might have been added or removed) 2175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (InitSpeaker() == -1) 2176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "InitSpeaker() failed"); 2178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Ensure that the updated rendering endpoint device is valid 2181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceOut == NULL) 2182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_builtInAecEnabled && _recIsInitialized) 2187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Ensure the correct render device is configured in case 2189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // InitRecording() was called before InitPlayout(). 2190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetDMOProperties() == -1) 2191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 2197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WAVEFORMATEX* pWfxOut = NULL; 219822c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org WAVEFORMATEX Wfx = WAVEFORMATEX(); 2199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WAVEFORMATEX* pWfxClosestMatch = NULL; 2200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Create COM object with IAudioClient interface. 2202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientOut); 2203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceOut->Activate( 2204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __uuidof(IAudioClient), 2205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSCTX_ALL, 2206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, 2207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void**)&_ptrClientOut); 2208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 2209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Retrieve the stream format that the audio engine uses for its internal 2211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // processing (mixing) of shared-mode streams. 2212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->GetMixFormat(&pWfxOut); 2213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SUCCEEDED(hr)) 2214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Audio Engine's current rendering mix format:"); 2216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // format type 2217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wFormatTag : 0x%X (%u)", pWfxOut->wFormatTag, pWfxOut->wFormatTag); 2218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // number of channels (i.e. mono, stereo...) 2219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nChannels : %d", pWfxOut->nChannels); 2220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // sample rate 2221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nSamplesPerSec : %d", pWfxOut->nSamplesPerSec); 2222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // for buffer estimation 2223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nAvgBytesPerSec: %d", pWfxOut->nAvgBytesPerSec); 2224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // block size of data 2225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nBlockAlign : %d", pWfxOut->nBlockAlign); 2226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // number of bits per sample of mono data 2227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wBitsPerSample : %d", pWfxOut->wBitsPerSample); 2228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cbSize : %d", pWfxOut->cbSize); 2229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set wave format 2232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.wFormatTag = WAVE_FORMAT_PCM; 2233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.wBitsPerSample = 16; 2234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.cbSize = 0; 2235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int freqs[] = {48000, 44100, 16000, 96000, 32000, 8000}; 2237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = S_FALSE; 2238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Iterate over frequencies and channels, in order of priority 2240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int freq = 0; freq < sizeof(freqs)/sizeof(freqs[0]); freq++) 2241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int chan = 0; chan < sizeof(_playChannelsPrioList)/sizeof(_playChannelsPrioList[0]); chan++) 2243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nChannels = _playChannelsPrioList[chan]; 2245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nSamplesPerSec = freqs[freq]; 2246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nBlockAlign = Wfx.nChannels * Wfx.wBitsPerSample / 8; 2247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nAvgBytesPerSec = Wfx.nSamplesPerSec * Wfx.nBlockAlign; 2248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If the method succeeds and the audio endpoint device supports the specified stream format, 2249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // it returns S_OK. If the method succeeds and provides a closest match to the specified format, 2250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // it returns S_FALSE. 2251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->IsFormatSupported( 2252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AUDCLNT_SHAREMODE_SHARED, 2253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &Wfx, 2254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pWfxClosestMatch); 2255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr == S_OK) 2256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 2258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nChannels=%d, nSamplesPerSec=%d is not supported", 2262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nChannels, Wfx.nSamplesPerSec); 2263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr == S_OK) 2266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 2267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(andrew): what happens in the event of failure in the above loop? 2270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Is _ptrClientOut->Initialize expected to fail? 2271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Same in InitRecording(). 2272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr == S_OK) 2273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playAudioFrameSize = Wfx.nBlockAlign; 2275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBlockSize = Wfx.nSamplesPerSec/100; 2276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playSampleRate = Wfx.nSamplesPerSec; 2277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _devicePlaySampleRate = Wfx.nSamplesPerSec; // The device itself continues to run at 44.1 kHz. 2278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _devicePlayBlockSize = Wfx.nSamplesPerSec/100; 2279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playChannels = Wfx.nChannels; 2280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "VoE selected this rendering format:"); 2282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wFormatTag : 0x%X (%u)", Wfx.wFormatTag, Wfx.wFormatTag); 2283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nChannels : %d", Wfx.nChannels); 2284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nSamplesPerSec : %d", Wfx.nSamplesPerSec); 2285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nAvgBytesPerSec : %d", Wfx.nAvgBytesPerSec); 2286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nBlockAlign : %d", Wfx.nBlockAlign); 2287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wBitsPerSample : %d", Wfx.wBitsPerSample); 2288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cbSize : %d", Wfx.cbSize); 2289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Additional settings:"); 2290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playAudioFrameSize: %d", _playAudioFrameSize); 2291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playBlockSize : %d", _playBlockSize); 2292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playChannels : %d", _playChannels); 2293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Create a rendering stream. 2296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 2297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // **************************************************************************** 2298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // For a shared-mode stream that uses event-driven buffering, the caller must 2299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // set both hnsPeriodicity and hnsBufferDuration to 0. The Initialize method 2300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // determines how large a buffer to allocate based on the scheduling period 2301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // of the audio engine. Although the client's buffer processing thread is 2302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // event driven, the basic buffer management process, as described previously, 2303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // is unaltered. 2304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Each time the thread awakens, it should call IAudioClient::GetCurrentPadding 2305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // to determine how much data to write to a rendering buffer or read from a capture 2306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // buffer. In contrast to the two buffers that the Initialize method allocates 2307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // for an exclusive-mode stream that uses event-driven buffering, a shared-mode 2308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // stream requires a single buffer. 2309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // **************************************************************************** 2310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 2311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org REFERENCE_TIME hnsBufferDuration = 0; // ask for minimum buffer size (default) 2312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_devicePlaySampleRate == 44100) 2313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Ask for a larger buffer size (30ms) when using 44.1kHz as render rate. 2315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // There seems to be a larger risk of underruns for 44.1 compared 2316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // with the default rate (48kHz). When using default, we set the requested 2317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // buffer duration to 0, which sets the buffer to the minimum size 2318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // required by the engine thread. The actual buffer size can then be 2319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // read by GetBufferSize() and it is 20ms on most machines. 2320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hnsBufferDuration = 30*10000; 2321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->Initialize( 2323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AUDCLNT_SHAREMODE_SHARED, // share Audio Engine with other applications 2324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AUDCLNT_STREAMFLAGS_EVENTCALLBACK, // processing of the audio buffer by the client will be event driven 2325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hnsBufferDuration, // requested buffer capacity as a time value (in 100-nanosecond units) 2326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, // periodicity 2327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &Wfx, // selected wave format 2328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL); // session GUID 2329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 2331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "IAudioClient::Initialize() failed:"); 2333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pWfxClosestMatch != NULL) 2334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "closest mix format: #channels=%d, samples/sec=%d, bits/sample=%d", 2336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pWfxClosestMatch->nChannels, pWfxClosestMatch->nSamplesPerSec, pWfxClosestMatch->wBitsPerSample); 2337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "no format suggested"); 2341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 2344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrAudioBuffer) 2346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update the audio buffer with the selected parameters 2348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetPlayoutSampleRate(_playSampleRate); 234964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org _ptrAudioBuffer->SetPlayoutChannels((uint8_t)_playChannels); 2350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We can enter this state during CoreAudioIsSupported() when no AudioDeviceImplementation 2354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // has been created, hence the AudioDeviceBuffer does not exist. 2355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // It is OK to end up here since we don't initiate any media in CoreAudioIsSupported(). 2356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceBuffer must be attached before streaming can start"); 2357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the actual size of the shared (endpoint buffer). 2360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Typical value is 960 audio frames <=> 20ms @ 48kHz sample rate. 2361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT bufferFrameCount(0); 2362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->GetBufferSize( 2363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &bufferFrameCount); 2364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SUCCEEDED(hr)) 2365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "IAudioClient::GetBufferSize() => %u (<=> %u bytes)", 2367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bufferFrameCount, bufferFrameCount*_playAudioFrameSize); 2368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the event handle that the system signals when an audio buffer is ready 2371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // to be processed by the client. 2372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->SetEventHandle( 2373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRenderSamplesReadyEvent); 2374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 2375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get an IAudioRenderClient interface. 2377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderClient); 2378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->GetService( 2379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __uuidof(IAudioRenderClient), 2380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void**)&_ptrRenderClient); 2381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 2382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Mark playout side as initialized 2384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playIsInitialized = true; 2385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pWfxOut); 2387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pWfxClosestMatch); 2388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "render side is now initialized"); 2390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 2393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 2394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pWfxOut); 2395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pWfxClosestMatch); 2396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientOut); 2397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderClient); 2398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Capture initialization when the built-in AEC DirectX Media Object (DMO) is 2402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// used. Called from InitRecording(), most of which is skipped over. The DMO 2403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// handles device initialization itself. 2404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Reference: http://msdn.microsoft.com/en-us/library/ff819492(v=vs.85).aspx 240564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::InitRecordingDMO() 2406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_builtInAecEnabled); 2408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_dmo != NULL); 2409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetDMOProperties() == -1) 2411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DMO_MEDIA_TYPE mt = {0}; 2416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = MoInitMediaType(&mt, sizeof(WAVEFORMATEX)); 2417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 2418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MoFreeMediaType(&mt); 2420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 2421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mt.majortype = MEDIATYPE_Audio; 2424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mt.subtype = MEDIASUBTYPE_PCM; 2425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mt.formattype = FORMAT_WaveFormatEx; 2426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Supported formats 2428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // nChannels: 1 (in AEC-only mode) 2429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // nSamplesPerSec: 8000, 11025, 16000, 22050 2430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // wBitsPerSample: 16 2431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WAVEFORMATEX* ptrWav = reinterpret_cast<WAVEFORMATEX*>(mt.pbFormat); 2432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ptrWav->wFormatTag = WAVE_FORMAT_PCM; 2433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ptrWav->nChannels = 1; 2434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 16000 is the highest we can support with our resampler. 2435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ptrWav->nSamplesPerSec = 16000; 2436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ptrWav->nAvgBytesPerSec = 32000; 2437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ptrWav->nBlockAlign = 2; 2438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ptrWav->wBitsPerSample = 16; 2439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ptrWav->cbSize = 0; 2440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the VoE format equal to the AEC output format. 2442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recAudioFrameSize = ptrWav->nBlockAlign; 2443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recSampleRate = ptrWav->nSamplesPerSec; 2444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recBlockSize = ptrWav->nSamplesPerSec / 100; 2445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = ptrWav->nChannels; 2446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the DMO output format parameters. 2448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _dmo->SetOutputType(kAecCaptureStreamIndex, &mt, 0); 2449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MoFreeMediaType(&mt); 2450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 2451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 2453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrAudioBuffer) 2457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordingSampleRate(_recSampleRate); 2459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordingChannels(_recChannels); 2460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Refer to InitRecording() for comments. 2464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AudioDeviceBuffer must be attached before streaming can start"); 2466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mediaBuffer = new MediaBufferImpl(_recBlockSize * _recAudioFrameSize); 2469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Optional, but if called, must be after media types are set. 2471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _dmo->AllocateStreamingResources(); 2472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 2473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 2475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recIsInitialized = true; 2479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Capture side is now initialized"); 2481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// InitRecording 2487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 248964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::InitRecording() 2490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 2493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recording) 2495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recIsInitialized) 2500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (QueryPerformanceFrequency(&_perfCounterFreq) == 0) 2505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _perfCounterFactor = 10000000.0 / (double)_perfCounterFreq.QuadPart; 2509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceIn == NULL) 2511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize the microphone (devices might have been added or removed) 2516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (InitMicrophone() == -1) 2517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "InitMicrophone() failed"); 2519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Ensure that the updated capturing endpoint device is valid 2522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrDeviceIn == NULL) 2523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_builtInAecEnabled) 2528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The DMO will configure the capture device. 2530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return InitRecordingDMO(); 2531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 2534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WAVEFORMATEX* pWfxIn = NULL; 253522c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org WAVEFORMATEX Wfx = WAVEFORMATEX(); 2536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WAVEFORMATEX* pWfxClosestMatch = NULL; 2537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Create COM object with IAudioClient interface. 2539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientIn); 2540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrDeviceIn->Activate( 2541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __uuidof(IAudioClient), 2542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSCTX_ALL, 2543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, 2544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void**)&_ptrClientIn); 2545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 2546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Retrieve the stream format that the audio engine uses for its internal 2548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // processing (mixing) of shared-mode streams. 2549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->GetMixFormat(&pWfxIn); 2550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SUCCEEDED(hr)) 2551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Audio Engine's current capturing mix format:"); 2553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // format type 2554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wFormatTag : 0x%X (%u)", pWfxIn->wFormatTag, pWfxIn->wFormatTag); 2555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // number of channels (i.e. mono, stereo...) 2556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nChannels : %d", pWfxIn->nChannels); 2557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // sample rate 2558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nSamplesPerSec : %d", pWfxIn->nSamplesPerSec); 2559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // for buffer estimation 2560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nAvgBytesPerSec: %d", pWfxIn->nAvgBytesPerSec); 2561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // block size of data 2562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nBlockAlign : %d", pWfxIn->nBlockAlign); 2563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // number of bits per sample of mono data 2564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wBitsPerSample : %d", pWfxIn->wBitsPerSample); 2565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cbSize : %d", pWfxIn->cbSize); 2566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set wave format 2569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.wFormatTag = WAVE_FORMAT_PCM; 2570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.wBitsPerSample = 16; 2571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.cbSize = 0; 2572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int freqs[6] = {48000, 44100, 16000, 96000, 32000, 8000}; 2574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = S_FALSE; 2575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Iterate over frequencies and channels, in order of priority 2577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int freq = 0; freq < sizeof(freqs)/sizeof(freqs[0]); freq++) 2578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int chan = 0; chan < sizeof(_recChannelsPrioList)/sizeof(_recChannelsPrioList[0]); chan++) 2580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nChannels = _recChannelsPrioList[chan]; 2582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nSamplesPerSec = freqs[freq]; 2583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nBlockAlign = Wfx.nChannels * Wfx.wBitsPerSample / 8; 2584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nAvgBytesPerSec = Wfx.nSamplesPerSec * Wfx.nBlockAlign; 2585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If the method succeeds and the audio endpoint device supports the specified stream format, 2586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // it returns S_OK. If the method succeeds and provides a closest match to the specified format, 2587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // it returns S_FALSE. 2588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->IsFormatSupported( 2589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AUDCLNT_SHAREMODE_SHARED, 2590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &Wfx, 2591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pWfxClosestMatch); 2592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr == S_OK) 2593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 2595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nChannels=%d, nSamplesPerSec=%d is not supported", 2599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Wfx.nChannels, Wfx.nSamplesPerSec); 2600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr == S_OK) 2603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 2604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr == S_OK) 2607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recAudioFrameSize = Wfx.nBlockAlign; 2609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recSampleRate = Wfx.nSamplesPerSec; 2610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recBlockSize = Wfx.nSamplesPerSec/100; 2611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recChannels = Wfx.nChannels; 2612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "VoE selected this capturing format:"); 2614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wFormatTag : 0x%X (%u)", Wfx.wFormatTag, Wfx.wFormatTag); 2615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nChannels : %d", Wfx.nChannels); 2616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nSamplesPerSec : %d", Wfx.nSamplesPerSec); 2617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nAvgBytesPerSec : %d", Wfx.nAvgBytesPerSec); 2618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nBlockAlign : %d", Wfx.nBlockAlign); 2619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wBitsPerSample : %d", Wfx.wBitsPerSample); 2620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cbSize : %d", Wfx.cbSize); 2621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Additional settings:"); 2622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_recAudioFrameSize: %d", _recAudioFrameSize); 2623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_recBlockSize : %d", _recBlockSize); 2624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_recChannels : %d", _recChannels); 2625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Create a capturing stream. 2628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->Initialize( 2629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AUDCLNT_SHAREMODE_SHARED, // share Audio Engine with other applications 2630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AUDCLNT_STREAMFLAGS_EVENTCALLBACK | // processing of the audio buffer by the client will be event driven 2631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AUDCLNT_STREAMFLAGS_NOPERSIST, // volume and mute settings for an audio session will not persist across system restarts 2632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, // required for event-driven shared mode 2633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, // periodicity 2634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &Wfx, // selected wave format 2635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL); // session GUID 2636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr != S_OK) 2639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "IAudioClient::Initialize() failed:"); 2641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pWfxClosestMatch != NULL) 2642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "closest mix format: #channels=%d, samples/sec=%d, bits/sample=%d", 2644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pWfxClosestMatch->nChannels, pWfxClosestMatch->nSamplesPerSec, pWfxClosestMatch->wBitsPerSample); 2645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "no format suggested"); 2649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 2652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrAudioBuffer) 2654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update the audio buffer with the selected parameters 2656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordingSampleRate(_recSampleRate); 265764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org _ptrAudioBuffer->SetRecordingChannels((uint8_t)_recChannels); 2658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We can enter this state during CoreAudioIsSupported() when no AudioDeviceImplementation 2662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // has been created, hence the AudioDeviceBuffer does not exist. 2663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // It is OK to end up here since we don't initiate any media in CoreAudioIsSupported(). 2664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceBuffer must be attached before streaming can start"); 2665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the actual size of the shared (endpoint buffer). 2668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Typical value is 960 audio frames <=> 20ms @ 48kHz sample rate. 2669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT bufferFrameCount(0); 2670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->GetBufferSize( 2671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &bufferFrameCount); 2672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SUCCEEDED(hr)) 2673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "IAudioClient::GetBufferSize() => %u (<=> %u bytes)", 2675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bufferFrameCount, bufferFrameCount*_recAudioFrameSize); 2676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the event handle that the system signals when an audio buffer is ready 2679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // to be processed by the client. 2680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->SetEventHandle( 2681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hCaptureSamplesReadyEvent); 2682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 2683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get an IAudioCaptureClient interface. 2685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrCaptureClient); 2686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->GetService( 2687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __uuidof(IAudioCaptureClient), 2688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void**)&_ptrCaptureClient); 2689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 2690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Mark capture side as initialized 2692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recIsInitialized = true; 2693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pWfxIn); 2695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pWfxClosestMatch); 2696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "capture side is now initialized"); 2698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 2701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 2702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pWfxIn); 2703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pWfxClosestMatch); 2704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientIn); 2705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrCaptureClient); 2706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// StartRecording 2711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 271364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::StartRecording() 2714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_recIsInitialized) 2717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_hRecThread != NULL) 2722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recording) 2727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped critScoped(&_critSect); 2733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Create thread which will drive the capturing 2735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LPTHREAD_START_ROUTINE lpStartAddress = WSAPICaptureThread; 2736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_builtInAecEnabled) 2737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Redirect to the DMO polling method. 2739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org lpStartAddress = WSAPICaptureThreadPollDMO; 2740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_playing) 2742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The DMO won't provide us captured output data unless we 2744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // give it render data to process. 2745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Playout must be started before recording when using the " 2747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "built-in AEC"); 2748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_hRecThread == NULL); 2753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRecThread = CreateThread(NULL, 2754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 2755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org lpStartAddress, 2756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org this, 2757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 2758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL); 2759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_hRecThread == NULL) 2760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to create the recording thread"); 2763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set thread priority to highest possible 2767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetThreadPriority(_hRecThread, THREAD_PRIORITY_TIME_CRITICAL); 2768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_hGetCaptureVolumeThread == NULL); 2770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hGetCaptureVolumeThread = CreateThread(NULL, 2771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 2772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org GetCaptureVolumeThread, 2773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org this, 2774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 2775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL); 2776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_hGetCaptureVolumeThread == NULL) 2777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to create the volume getter thread"); 2780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_hSetCaptureVolumeThread == NULL); 2784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hSetCaptureVolumeThread = CreateThread(NULL, 2785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 2786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetCaptureVolumeThread, 2787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org this, 2788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 2789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL); 2790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_hSetCaptureVolumeThread == NULL) 2791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to create the volume setter thread"); 2794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } // critScoped 2797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD ret = WaitForSingleObject(_hCaptureStartedEvent, 1000); 2799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != WAIT_OBJECT_0) 2800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "capturing did not start up properly"); 2803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "capture audio stream has now started..."); 2807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _avgCPULoad = 0.0f; 2809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playAcc = 0; 2810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording = true; 2811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// StopRecording 2817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 281964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::StopRecording() 2820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 282164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t err = 0; 2822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_recIsInitialized) 2824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 2829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_hRecThread == NULL) 2831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "no capturing stream is active => close down WASAPI only"); 2834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientIn); 2835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrCaptureClient); 2836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recIsInitialized = false; 2837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording = false; 2838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 2839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Stop the driving thread... 2843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "closing down the webrtc_core_audio_capture_thread..."); 2845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Manual-reset event; it will remain signalled to stop all capture threads. 2846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetEvent(_hShutdownCaptureEvent); 2847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 2849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD ret = WaitForSingleObject(_hRecThread, 2000); 2850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != WAIT_OBJECT_0) 2851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to close down webrtc_core_audio_capture_thread"); 2854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = -1; 2855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "webrtc_core_audio_capture_thread is now closed"); 2860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = WaitForSingleObject(_hGetCaptureVolumeThread, 2000); 2863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != WAIT_OBJECT_0) 2864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the thread did not stop as it should 2866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to close down volume getter thread"); 2868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = -1; 2869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " volume getter thread is now closed"); 2874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret = WaitForSingleObject(_hSetCaptureVolumeThread, 2000); 2877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != WAIT_OBJECT_0) 2878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the thread did not stop as it should 2880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " failed to close down volume setter thread"); 2882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = -1; 2883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 2885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 2887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " volume setter thread is now closed"); 2888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 2890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ResetEvent(_hShutdownCaptureEvent); // Must be manually reset. 2892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Ensure that the thread has released these interfaces properly. 2893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(err == -1 || _ptrClientIn == NULL); 2894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(err == -1 || _ptrCaptureClient == NULL); 2895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recIsInitialized = false; 2897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recording = false; 2898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // These will create thread leaks in the result of an error, 2900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // but we can at least resume the call. 2901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hRecThread); 2902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hRecThread = NULL; 2903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hGetCaptureVolumeThread); 2905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hGetCaptureVolumeThread = NULL; 2906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hSetCaptureVolumeThread); 2908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hSetCaptureVolumeThread = NULL; 2909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_builtInAecEnabled) 2911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_dmo != NULL); 2913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This is necessary. Otherwise the DMO can generate garbage render 2914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // audio even after rendering has stopped. 2915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = _dmo->FreeStreamingResources(); 2916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 2917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 2919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = -1; 2920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Reset the recording delay value. 2924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sndCardRecDelay = 0; 2925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 2927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return err; 2929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// RecordingIsInitialized 2933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::RecordingIsInitialized() const 2936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_recIsInitialized); 2938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Recording 2942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::Recording() const 2945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_recording); 2947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// PlayoutIsInitialized 2951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::PlayoutIsInitialized() const 2954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_playIsInitialized); 2957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 2958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// StartPlayout 2961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 2962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 296364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::StartPlayout() 2964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 2965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_playIsInitialized) 2967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_hPlayThread != NULL) 2972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_playing) 2977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped critScoped(&_critSect); 2983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Create thread which will drive the rendering. 2985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_hPlayThread == NULL); 2986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hPlayThread = CreateThread( 2987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, 2988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 2989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WSAPIRenderThread, 2990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org this, 2991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 2992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL); 2993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_hPlayThread == NULL) 2994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 2995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 2996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to create the playout thread"); 2997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 2998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set thread priority to highest possible. 3001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetThreadPriority(_hPlayThread, THREAD_PRIORITY_TIME_CRITICAL); 3002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } // critScoped 3003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD ret = WaitForSingleObject(_hRenderStartedEvent, 1000); 3005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != WAIT_OBJECT_0) 3006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 3008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "rendering did not start up properly"); 3009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 3010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = true; 3013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 3014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "rendering audio stream has now started..."); 3015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// StopPlayout 3021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 302364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::StopPlayout() 3024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_playIsInitialized) 3027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped critScoped(&_critSect) ; 3033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_hPlayThread == NULL) 3035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 3037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "no rendering stream is active => close down WASAPI only"); 3038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientOut); 3039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderClient); 3040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playIsInitialized = false; 3041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = false; 3042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // stop the driving thread... 3046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 3047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "closing down the webrtc_core_audio_render_thread..."); 3048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetEvent(_hShutdownRenderEvent); 3049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } // critScoped 3050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD ret = WaitForSingleObject(_hPlayThread, 2000); 3052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != WAIT_OBJECT_0) 3053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the thread did not stop as it should 3055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 3056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to close down webrtc_core_audio_render_thread"); 3057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hPlayThread); 3058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hPlayThread = NULL; 3059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playIsInitialized = false; 3060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = false; 3061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 3062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped critScoped(&_critSect); 3066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 3067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "webrtc_core_audio_render_thread is now closed"); 3068d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org 3069d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org // to reset this event manually at each time we finish with it, 3070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // in case that the render thread has exited before StopPlayout(), 3071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // this event might be caught by the new render thread within same VoE instance. 3072d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org ResetEvent(_hShutdownRenderEvent); 3073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientOut); 3075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderClient); 3076d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org 3077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playIsInitialized = false; 3078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playing = false; 3079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CloseHandle(_hPlayThread); 3081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hPlayThread = NULL; 3082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_builtInAecEnabled && _recording) 3084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The DMO won't provide us captured output data unless we 3086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // give it render data to process. 3087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We still permit the playout to shutdown, and trace a warning. 3089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Otherwise, VoE can get into a state which will never permit 3090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // playout to stop properly. 3091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 3092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Recording should be stopped before playout when using the " 3093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "built-in AEC"); 3094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Reset the playout delay value. 3097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sndCardPlayDelay = 0; 3098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } // critScoped 3099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// PlayoutDelay 3105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 310764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::PlayoutDelay(uint16_t& delayMS) const 3108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped critScoped(&_critSect); 311064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org delayMS = static_cast<uint16_t>(_sndCardPlayDelay); 3111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// RecordingDelay 3116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 311864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::RecordingDelay(uint16_t& delayMS) const 3119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped critScoped(&_critSect); 312164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org delayMS = static_cast<uint16_t>(_sndCardRecDelay); 3122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Playing 3127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::Playing() const 3130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (_playing); 3132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetPlayoutBuffer 3135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 313764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::SetPlayoutBuffer(const AudioDeviceModule::BufferType type, uint16_t sizeMS) 3138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 3141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufType = type; 3143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (type == AudioDeviceModule::kFixedBufferSize) 3145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playBufDelayFixed = sizeMS; 3147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// PlayoutBuffer 3154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 315664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::PlayoutBuffer(AudioDeviceModule::BufferType& type, uint16_t& sizeMS) const 3157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped lock(&_critSect); 3159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org type = _playBufType; 3160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (type == AudioDeviceModule::kFixedBufferSize) 3162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sizeMS = _playBufDelayFixed; 3164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 3166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Use same value as for PlayoutDelay 316864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org sizeMS = static_cast<uint16_t>(_sndCardPlayDelay); 3169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// CPULoad 3176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 317864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::CPULoad(uint16_t& load) const 3179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 318164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org load = static_cast<uint16_t> (100*_avgCPULoad); 3182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// PlayoutWarning 3188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::PlayoutWarning() const 3191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ( _playWarning > 0); 3193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// PlayoutError 3197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::PlayoutError() const 3200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ( _playError > 0); 3202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// RecordingWarning 3206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::RecordingWarning() const 3209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ( _recWarning > 0); 3211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// RecordingError 3215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::RecordingError() const 3218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ( _recError > 0); 3220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ClearPlayoutWarning 3224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceWindowsCore::ClearPlayoutWarning() 3227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playWarning = 0; 3229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ClearPlayoutError 3233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceWindowsCore::ClearPlayoutError() 3236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playError = 0; 3238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ClearRecordingWarning 3242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceWindowsCore::ClearRecordingWarning() 3245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recWarning = 0; 3247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ClearRecordingError 3251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceWindowsCore::ClearRecordingError() 3254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recError = 0; 3256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 3259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Private Methods 3260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================ 3261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// [static] WSAPIRenderThread 3264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD WINAPI AudioDeviceWindowsCore::WSAPIRenderThread(LPVOID context) 3267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return reinterpret_cast<AudioDeviceWindowsCore*>(context)-> 3269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DoRenderThread(); 3270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// [static] WSAPICaptureThread 3274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD WINAPI AudioDeviceWindowsCore::WSAPICaptureThread(LPVOID context) 3277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return reinterpret_cast<AudioDeviceWindowsCore*>(context)-> 3279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DoCaptureThread(); 3280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD WINAPI AudioDeviceWindowsCore::WSAPICaptureThreadPollDMO(LPVOID context) 3283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return reinterpret_cast<AudioDeviceWindowsCore*>(context)-> 3285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DoCaptureThreadPollDMO(); 3286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD WINAPI AudioDeviceWindowsCore::GetCaptureVolumeThread(LPVOID context) 3289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return reinterpret_cast<AudioDeviceWindowsCore*>(context)-> 3291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DoGetCaptureVolumeThread(); 3292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD WINAPI AudioDeviceWindowsCore::SetCaptureVolumeThread(LPVOID context) 3295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return reinterpret_cast<AudioDeviceWindowsCore*>(context)-> 3297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DoSetCaptureVolumeThread(); 3298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD AudioDeviceWindowsCore::DoGetCaptureVolumeThread() 3301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HANDLE waitObject = _hShutdownCaptureEvent; 3303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (1) 3305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (AGC()) 3307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 330864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t currentMicLevel = 0; 3309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (MicrophoneVolume(currentMicLevel) == 0) 3310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This doesn't set the system volume, just stores it. 3312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 3313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrAudioBuffer) 3314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetCurrentMicLevel(currentMicLevel); 3316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD waitResult = WaitForSingleObject(waitObject, 3322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org GET_MIC_VOLUME_INTERVAL_MS); 3323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (waitResult) 3324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_OBJECT_0: // _hShutdownCaptureEvent 3326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_TIMEOUT: // timeout notification 3328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: // unexpected error 3330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 3331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " unknown wait termination on get volume thread"); 333222c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org return 1; 3333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD AudioDeviceWindowsCore::DoSetCaptureVolumeThread() 3338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HANDLE waitArray[2] = {_hShutdownCaptureEvent, _hSetCaptureVolumeEvent}; 3340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (1) 3342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD waitResult = WaitForMultipleObjects(2, waitArray, FALSE, INFINITE); 3344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (waitResult) 3345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_OBJECT_0: // _hShutdownCaptureEvent 3347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 3348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_OBJECT_0 + 1: // _hSetCaptureVolumeEvent 3349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: // unexpected error 3351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 3352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " unknown wait termination on set volume thread"); 335322c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org return 1; 3354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 335764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t newMicLevel = _newMicLevel; 3358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetMicrophoneVolume(newMicLevel) == -1) 3361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 3363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org " the required modification of the microphone volume failed"); 3364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// DoRenderThread 3370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD AudioDeviceWindowsCore::DoRenderThread() 3373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool keepPlaying = true; 3376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HANDLE waitArray[2] = {_hShutdownRenderEvent, _hRenderSamplesReadyEvent}; 3377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 3378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HANDLE hMmTask = NULL; 3379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LARGE_INTEGER t1; 3381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LARGE_INTEGER t2; 338264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t time(0); 3383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize COM as MTA in this thread. 3385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ScopedCOMInitializer comInit(ScopedCOMInitializer::kMTA); 3386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!comInit.succeeded()) { 3387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 3388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to initialize COM in render thread"); 338922c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org return 1; 3390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 339222c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org _SetThreadName(0, "webrtc_core_audio_render_thread"); 3393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Use Multimedia Class Scheduler Service (MMCSS) to boost the thread priority. 3395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_winSupportAvrt) 3397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD taskIndex(0); 3399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hMmTask = _PAvSetMmThreadCharacteristicsA("Pro Audio", &taskIndex); 3400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hMmTask) 3401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FALSE == _PAvSetMmThreadPriority(hMmTask, AVRT_PRIORITY_CRITICAL)) 3403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to boost play-thread using MMCSS"); 3405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "render thread is now registered with MMCSS (taskIndex=%d)", taskIndex); 3407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 3409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to enable MMCSS on render thread (err=%d)", GetLastError()); 3411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(GetLastError()); 3412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 3416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3417d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org IAudioClock* clock = NULL; 3418d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org 3419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get size of rendering buffer (length is expressed as the number of audio frames the buffer can hold). 3420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This value is fixed during the rendering session. 3421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT32 bufferLength = 0; 3423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->GetBufferSize(&bufferLength); 3424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 3425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] size of buffer : %u", bufferLength); 3426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get maximum latency for the current stream (will not change for the lifetime of the IAudioClient object). 3428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org REFERENCE_TIME latency; 3430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrClientOut->GetStreamLatency(&latency); 3431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] max stream latency : %u (%3.2f ms)", 3432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (DWORD)latency, (double)(latency/10000.0)); 3433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the length of the periodic interval separating successive processing passes by 3435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the audio engine on the data in the endpoint buffer. 3436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The period between processing passes by the audio engine is fixed for a particular 3438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // audio endpoint device and represents the smallest processing quantum for the audio engine. 3439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This period plus the stream latency between the buffer and endpoint device represents 3440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the minimum possible latency that an audio application can achieve. 3441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Typical value: 100000 <=> 0.01 sec = 10ms. 3442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org REFERENCE_TIME devPeriod = 0; 3444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org REFERENCE_TIME devPeriodMin = 0; 3445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrClientOut->GetDevicePeriod(&devPeriod, &devPeriodMin); 3446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] device period : %u (%3.2f ms)", 3447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (DWORD)devPeriod, (double)(devPeriod/10000.0)); 3448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Derive initial rendering delay. 3450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Example: 10*(960/480) + 15 = 20 + 15 = 35ms 3451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int playout_delay = 10 * (bufferLength / _playBlockSize) + 3453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (int)((latency + devPeriod) / 10000); 3454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sndCardPlayDelay = playout_delay; 3455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _writtenSamples = 0; 3456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 3457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "[REND] initial delay : %u", playout_delay); 3458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org double endpointBufferSizeMS = 10.0 * ((double)bufferLength / (double)_devicePlayBlockSize); 3460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] endpointBufferSizeMS : %3.2f", endpointBufferSizeMS); 3461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Before starting the stream, fill the rendering buffer with silence. 3463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BYTE *pData = NULL; 3465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderClient->GetBuffer(bufferLength, &pData); 3466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 3467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderClient->ReleaseBuffer(bufferLength, AUDCLNT_BUFFERFLAGS_SILENT); 3469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 3470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _writtenSamples += bufferLength; 3472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->GetService(__uuidof(IAudioClock), (void**)&clock); 3474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) { 3475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 3476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to get IAudioClock interface from the IAudioClient"); 3477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Start up the rendering audio stream. 3480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->Start(); 3481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 3482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set event which will ensure that the calling thread modifies the playing state to true. 3486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetEvent(_hRenderStartedEvent); 3488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // >> ------------------ THREAD LOOP ------------------ 3490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (keepPlaying) 3492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Wait for a render notification event or a shutdown event 3494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD waitResult = WaitForMultipleObjects(2, waitArray, FALSE, 500); 3495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (waitResult) 3496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_OBJECT_0 + 0: // _hShutdownRenderEvent 3498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org keepPlaying = false; 3499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_OBJECT_0 + 1: // _hRenderSamplesReadyEvent 3501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_TIMEOUT: // timeout notification 3503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "render event timed out after 0.5 seconds"); 3504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 3505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: // unexpected error 3506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "unknown wait termination on render side"); 3507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 3508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (keepPlaying) 3511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 3513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Sanity check to ensure that essential states are not modified 3515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // during the unlocked period. 3516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrRenderClient == NULL || _ptrClientOut == NULL) 3517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 3520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "output state has been modified during unlocked period"); 3521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 3522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the number of frames of padding (queued up to play) in the endpoint buffer. 3525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT32 padding = 0; 3526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->GetCurrentPadding(&padding); 3527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 3528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Derive the amount of available space in the output buffer 353064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t framesAvailable = bufferLength - padding; 3531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "#avaliable audio frames = %u", framesAvailable); 3532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Do we have 10 ms available in the render buffer? 3534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (framesAvailable < _playBlockSize) 3535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Not enough space in render buffer to store next render packet. 3537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Write n*10ms buffers to the render buffer 354264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org const uint32_t n10msBuffers = (framesAvailable / _playBlockSize); 354364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org for (uint32_t n = 0; n < n10msBuffers; n++) 3544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get pointer (i.e., grab the buffer) to next space in the shared render buffer. 3546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderClient->GetBuffer(_playBlockSize, &pData); 3547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 3548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org QueryPerformanceCounter(&t1); // measure time: START 3550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrAudioBuffer) 3552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Request data to be played out (#bytes = _playBlockSize*_audioFrameSize) 3554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 355564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t nSamples = 3556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->RequestPlayoutData(_playBlockSize); 3557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 3558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3559d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org if (nSamples == -1) 3560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 3563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to read data from render client"); 3564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 3565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Sanity check to ensure that essential states are not modified during the unlocked period 3568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrRenderClient == NULL || _ptrClientOut == NULL) 3569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, "output state has been modified during unlocked period"); 3572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 3573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 357464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org if (nSamples != static_cast<int32_t>(_playBlockSize)) 3575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "nSamples(%d) != _playBlockSize(%d)", nSamples, _playBlockSize); 3577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the actual (stored) data 358064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org nSamples = _ptrAudioBuffer->GetPlayoutData((int8_t*)pData); 3581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org QueryPerformanceCounter(&t2); // measure time: STOP 3584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org time = (int)(t2.QuadPart-t1.QuadPart); 3585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playAcc += time; 3586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD dwFlags(0); 3588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderClient->ReleaseBuffer(_playBlockSize, dwFlags); 3589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // See http://msdn.microsoft.com/en-us/library/dd316605(VS.85).aspx 3590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // for more details regarding AUDCLNT_E_DEVICE_INVALIDATED. 3591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 3592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _writtenSamples += _playBlockSize; 3594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check the current delay on the playout side. 3597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (clock) { 3598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT64 pos = 0; 3599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT64 freq = 1; 3600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org clock->GetPosition(&pos, NULL); 3601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org clock->GetFrequency(&freq); 3602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org playout_delay = ROUND((double(_writtenSamples) / 3603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _devicePlaySampleRate - double(pos) / freq) * 1000.0); 3604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sndCardPlayDelay = playout_delay; 3605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // ------------------ THREAD LOOP ------------------ << 3612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SleepMs(static_cast<DWORD>(endpointBufferSizeMS+0.5)); 3614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientOut->Stop(); 3615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 3617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(clock); 3618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 3620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrClientOut->Stop(); 36221a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org _UnLock(); 3623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 3624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_winSupportAvrt) 3627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (NULL != hMmTask) 3629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _PAvRevertMmThreadCharacteristics(hMmTask); 3631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 36341a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org _Lock(); 36351a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org 3636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (keepPlaying) 3637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 36381a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org if (_ptrClientOut != NULL) 3639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 36401a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org hr = _ptrClientOut->Stop(); 36411a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org if (FAILED(hr)) 36421a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org { 36431a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org _TraceCOMError(hr); 36441a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org } 36451a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org hr = _ptrClientOut->Reset(); 36461a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org if (FAILED(hr)) 36471a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org { 36481a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org _TraceCOMError(hr); 36491a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org } 3650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Trigger callback from module process thread 3652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playError = 1; 3653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "kPlayoutError message posted: rendering thread has ended pre-maturely"); 3654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 3656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_Rendering thread is now terminated properly"); 3658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 36601a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org _UnLock(); 36611a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org 3662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (DWORD)hr; 3663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD AudioDeviceWindowsCore::InitCaptureThreadPriority() 3666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hMmTask = NULL; 3668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 366922c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org _SetThreadName(0, "webrtc_core_audio_capture_thread"); 3670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Use Multimedia Class Scheduler Service (MMCSS) to boost the thread 3672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // priority. 3673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_winSupportAvrt) 3674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD taskIndex(0); 3676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hMmTask = _PAvSetMmThreadCharacteristicsA("Pro Audio", &taskIndex); 3677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_hMmTask) 3678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_PAvSetMmThreadPriority(_hMmTask, AVRT_PRIORITY_CRITICAL)) 3680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 3682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to boost rec-thread using MMCSS"); 3683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 3685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "capture thread is now registered with MMCSS (taskIndex=%d)", 3686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org taskIndex); 3687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 3689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 3691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to enable MMCSS on capture thread (err=%d)", 3692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org GetLastError()); 3693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(GetLastError()); 3694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return S_OK; 3698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceWindowsCore::RevertCaptureThreadPriority() 3701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_winSupportAvrt) 3703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (NULL != _hMmTask) 3705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _PAvRevertMmThreadCharacteristics(_hMmTask); 3707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _hMmTask = NULL; 3711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD AudioDeviceWindowsCore::DoCaptureThreadPollDMO() 3714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_mediaBuffer != NULL); 3716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool keepRecording = true; 3717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize COM as MTA in this thread. 3719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ScopedCOMInitializer comInit(ScopedCOMInitializer::kMTA); 3720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!comInit.succeeded()) { 3721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 3722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to initialize COM in polling DMO thread"); 372322c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org return 1; 3724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = InitCaptureThreadPriority(); 3727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 3728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return hr; 3730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set event which will ensure that the calling thread modifies the 3733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // recording state to true. 3734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetEvent(_hCaptureStartedEvent); 3735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // >> ---------------------------- THREAD LOOP ---------------------------- 3737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (keepRecording) 3738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Poll the DMO every 5 ms. 3740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // (The same interval used in the Wave implementation.) 3741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD waitResult = WaitForSingleObject(_hShutdownCaptureEvent, 5); 3742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (waitResult) 3743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_OBJECT_0: // _hShutdownCaptureEvent 3745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org keepRecording = false; 3746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_TIMEOUT: // timeout notification 3748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: // unexpected error 3750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 3751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Unknown wait termination on capture side"); 3752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = -1; // To signal an error callback. 3753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org keepRecording = false; 3754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (keepRecording) 3758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped critScoped(&_critSect); 3760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD dwStatus = 0; 3762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DMO_OUTPUT_DATA_BUFFER dmoBuffer = {0}; 3764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dmoBuffer.pBuffer = _mediaBuffer; 3765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dmoBuffer.pBuffer->AddRef(); 3766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Poll the DMO for AEC processed capture data. The DMO will 3768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // copy available data to |dmoBuffer|, and should only return 3769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 10 ms frames. The value of |dwStatus| should be ignored. 3770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _dmo->ProcessOutput(0, 1, &dmoBuffer, &dwStatus); 3771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(dmoBuffer.pBuffer); 3772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dwStatus = dmoBuffer.dwStatus; 3773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 3775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 3777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org keepRecording = false; 3778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 3779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ULONG bytesProduced = 0; 3783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BYTE* data; 3784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get a pointer to the data buffer. This should be valid until 3785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the next call to ProcessOutput. 3786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _mediaBuffer->GetBufferAndLength(&data, &bytesProduced); 3787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 3788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 3790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org keepRecording = false; 3791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 3792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(andrew): handle AGC. 3796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (bytesProduced > 0) 3798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int kSamplesProduced = bytesProduced / _recAudioFrameSize; 3800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(andrew): verify that this is always satisfied. It might 3801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // be that ProcessOutput will try to return more than 10 ms if 3802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // we fail to call it frequently enough. 3803d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org assert(kSamplesProduced == static_cast<int>(_recBlockSize)); 380464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org assert(sizeof(BYTE) == sizeof(int8_t)); 3805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetRecordedBuffer( 380664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org reinterpret_cast<int8_t*>(data), 3807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kSamplesProduced); 3808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetVQEData(0, 0, 0); 3809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); // Release lock while making the callback. 3811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->DeliverRecordedData(); 3812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 3813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Reset length to indicate buffer availability. 3816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _mediaBuffer->SetLength(0); 3817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 3818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 3820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org keepRecording = false; 3821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 3822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!(dwStatus & DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE)) 3826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The DMO cannot currently produce more data. This is the 3828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // normal case; otherwise it means the DMO had more than 10 ms 3829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // of data available and ProcessOutput should be called again. 3830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // ---------------------------- THREAD LOOP ---------------------------- << 3835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RevertCaptureThreadPriority(); 3837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 3839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Trigger callback from module process thread 3841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recError = 1; 3842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceUtility, _id, 3843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "kRecordingError message posted: capturing thread has ended " 3844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "prematurely"); 3845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 3847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 3849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Capturing thread is now terminated properly"); 3850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return hr; 3853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 3854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// DoCaptureThread 3858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 3859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDWORD AudioDeviceWindowsCore::DoCaptureThread() 3861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 3862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool keepRecording = true; 3864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HANDLE waitArray[2] = {_hShutdownCaptureEvent, _hCaptureSamplesReadyEvent}; 3865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 3866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LARGE_INTEGER t1; 3868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LARGE_INTEGER t2; 386964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t time(0); 3870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BYTE* syncBuffer = NULL; 3872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT32 syncBufIndex = 0; 3873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _readSamples = 0; 3875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize COM as MTA in this thread. 3877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ScopedCOMInitializer comInit(ScopedCOMInitializer::kMTA); 3878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!comInit.succeeded()) { 3879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 3880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to initialize COM in capture thread"); 388122c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org return 1; 3882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = InitCaptureThreadPriority(); 3885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 3886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return hr; 3888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 3891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get size of capturing buffer (length is expressed as the number of audio frames the buffer can hold). 3893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This value is fixed during the capturing session. 3894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT32 bufferLength = 0; 3896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->GetBufferSize(&bufferLength); 3897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 3898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[CAPT] size of buffer : %u", bufferLength); 3899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Allocate memory for sync buffer. 3901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // It is used for compensation between native 44.1 and internal 44.0 and 3902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // for cases when the capture buffer is larger than 10ms. 3903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const UINT32 syncBufferSize = 2*(bufferLength * _recAudioFrameSize); 3905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org syncBuffer = new BYTE[syncBufferSize]; 3906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (syncBuffer == NULL) 3907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 390822c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org return (DWORD)E_POINTER; 3909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[CAPT] size of sync buffer : %u [bytes]", syncBufferSize); 3911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get maximum latency for the current stream (will not change for the lifetime of the IAudioClient object). 3913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org REFERENCE_TIME latency; 3915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrClientIn->GetStreamLatency(&latency); 3916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[CAPT] max stream latency : %u (%3.2f ms)", 3917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (DWORD)latency, (double)(latency / 10000.0)); 3918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the length of the periodic interval separating successive processing passes by 3920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the audio engine on the data in the endpoint buffer. 3921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org REFERENCE_TIME devPeriod = 0; 3923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org REFERENCE_TIME devPeriodMin = 0; 3924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrClientIn->GetDevicePeriod(&devPeriod, &devPeriodMin); 3925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[CAPT] device period : %u (%3.2f ms)", 3926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (DWORD)devPeriod, (double)(devPeriod / 10000.0)); 3927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org double extraDelayMS = (double)((latency + devPeriod) / 10000.0); 3929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[CAPT] extraDelayMS : %3.2f", extraDelayMS); 3930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org double endpointBufferSizeMS = 10.0 * ((double)bufferLength / (double)_recBlockSize); 3932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[CAPT] endpointBufferSizeMS : %3.2f", endpointBufferSizeMS); 3933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Start up the capturing stream. 3935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->Start(); 3937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 3938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set event which will ensure that the calling thread modifies the recording state to true. 3942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetEvent(_hCaptureStartedEvent); 3944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // >> ---------------------------- THREAD LOOP ---------------------------- 3946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (keepRecording) 3948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Wait for a capture notification event or a shutdown event 3950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD waitResult = WaitForMultipleObjects(2, waitArray, FALSE, 500); 3951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (waitResult) 3952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_OBJECT_0 + 0: // _hShutdownCaptureEvent 3954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org keepRecording = false; 3955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_OBJECT_0 + 1: // _hCaptureSamplesReadyEvent 3957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 3958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case WAIT_TIMEOUT: // timeout notification 3959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "capture event timed out after 0.5 seconds"); 3960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 3961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: // unexpected error 3962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "unknown wait termination on capture side"); 3963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 3964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (keepRecording) 3967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org BYTE *pData = 0; 3969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT32 framesAvailable = 0; 3970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD flags = 0; 3971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT64 recTime = 0; 3972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT64 recPos = 0; 3973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); 3975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Sanity check to ensure that essential states are not modified 3977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // during the unlocked period. 3978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrCaptureClient == NULL || _ptrClientIn == NULL) 3979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 3981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 3982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "input state has been modified during unlocked period"); 3983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 3984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Find out how much capture data is available 3987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrCaptureClient->GetBuffer(&pData, // packet which is ready to be read by used 3989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &framesAvailable, // #frames in the captured packet (can be zero) 3990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &flags, // support flags (check) 3991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &recPos, // device position of first audio frame in data packet 3992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &recTime); // value of performance counter at the time of recording the first audio frame 3993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SUCCEEDED(hr)) 3995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (AUDCLNT_S_BUFFER_EMPTY == hr) 3997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 3998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Buffer was empty => start waiting for a new capture notification event 3999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 4000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 4001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (flags & AUDCLNT_BUFFERFLAGS_SILENT) 4004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Treat all of the data in the packet as silence and ignore the actual data values. 4006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "AUDCLNT_BUFFERFLAGS_SILENT"); 4007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pData = NULL; 4008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(framesAvailable != 0); 4011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pData) 4013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CopyMemory(&syncBuffer[syncBufIndex*_recAudioFrameSize], pData, framesAvailable*_recAudioFrameSize); 4015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 4017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ZeroMemory(&syncBuffer[syncBufIndex*_recAudioFrameSize], framesAvailable*_recAudioFrameSize); 4019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(syncBufferSize >= (syncBufIndex*_recAudioFrameSize)+framesAvailable*_recAudioFrameSize); 4021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Release the capture buffer 4023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 4024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrCaptureClient->ReleaseBuffer(framesAvailable); 4025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 4026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _readSamples += framesAvailable; 4028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org syncBufIndex += framesAvailable; 4029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org QueryPerformanceCounter(&t1); 4031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the current recording and playout delay. 403364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t sndCardRecDelay = (uint32_t) 4034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (((((UINT64)t1.QuadPart * _perfCounterFactor) - recTime) 4035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org / 10000) + (10*syncBufIndex) / _recBlockSize - 10); 403664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t sndCardPlayDelay = 403764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org static_cast<uint32_t>(_sndCardPlayDelay); 4038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sndCardRecDelay = sndCardRecDelay; 4040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (syncBufIndex >= _recBlockSize) 4042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrAudioBuffer) 4044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 404564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org _ptrAudioBuffer->SetRecordedBuffer((const int8_t*)syncBuffer, _recBlockSize); 4046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->SetVQEData(sndCardPlayDelay, 4047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sndCardRecDelay, 40488cfa49594feb82a0c1f91d1a661b22cc43ca44ceandrew@webrtc.org 0); 4049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 405028832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org _ptrAudioBuffer->SetTypingStatus(KeyPressed()); 405128832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org 4052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org QueryPerformanceCounter(&t1); // measure time: START 4053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); // release lock while making the callback 4055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrAudioBuffer->DeliverRecordedData(); 4056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _Lock(); // restore the lock 4057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org QueryPerformanceCounter(&t2); // measure time: STOP 4059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Measure "average CPU load". 4061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Basically what we do here is to measure how many percent of our 10ms period 4062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // is used for encoding and decoding. This value shuld be used as a warning indicator 4063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // only and not seen as an absolute value. Running at ~100% will lead to bad QoS. 4064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org time = (int)(t2.QuadPart - t1.QuadPart); 4065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _avgCPULoad = (float)(_avgCPULoad*.99 + (time + _playAcc) / (double)(_perfCounterFreq.QuadPart)); 4066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _playAcc = 0; 4067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Sanity check to ensure that essential states are not modified during the unlocked period 4069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrCaptureClient == NULL || _ptrClientIn == NULL) 4070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 4072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, "input state has been modified during unlocked period"); 4073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 4074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // store remaining data which was not able to deliver as 10ms segment 4078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MoveMemory(&syncBuffer[0], &syncBuffer[_recBlockSize*_recAudioFrameSize], (syncBufIndex-_recBlockSize)*_recAudioFrameSize); 4079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org syncBufIndex -= _recBlockSize; 4080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sndCardRecDelay -= 10; 4081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_AGC) 4084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 408564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org uint32_t newMicLevel = _ptrAudioBuffer->NewMicLevel(); 4086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (newMicLevel != 0) 4087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The VQE will only deliver non-zero microphone levels when a change is needed. 4089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set this new mic level (received from the observer as return value in the callback). 4090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "AGC change of volume: new=%u", newMicLevel); 4091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We store this outside of the audio buffer to avoid 4092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // having it overwritten by the getter thread. 4093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _newMicLevel = newMicLevel; 4094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetEvent(_hSetCaptureVolumeEvent); 4095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 4099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If GetBuffer returns AUDCLNT_E_BUFFER_ERROR, the thread consuming the audio samples 4101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // must wait for the next processing pass. The client might benefit from keeping a count 4102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // of the failed GetBuffer calls. If GetBuffer returns this error repeatedly, the client 4103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // can start a new processing loop after shutting down the current client by calling 4104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // IAudioClient::Stop, IAudioClient::Reset, and releasing the audio client. 4105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 4106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "IAudioCaptureClient::GetBuffer returned AUDCLNT_E_BUFFER_ERROR, hr = 0x%08X", hr); 4107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org goto Exit; 4108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _UnLock(); 4111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // ---------------------------- THREAD LOOP ---------------------------- << 4115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->Stop(); 4117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 4119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrClientIn->Stop(); 41221a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org _UnLock(); 4123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RevertCaptureThreadPriority(); 4127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 41281a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org _Lock(); 41291a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org 4130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (keepRecording) 4131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_ptrClientIn != NULL) 4133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->Stop(); 4135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrClientIn->Reset(); 4140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Trigger callback from module process thread 4147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _recError = 1; 4148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "kRecordingError message posted: capturing thread has ended pre-maturely"); 4149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 4151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_Capturing thread is now terminated properly"); 4153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrClientIn); 4156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrCaptureClient); 4157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 41581a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org _UnLock(); 41591a67b9cbfec83471989b6075dd534511ce81bf42braveyao@webrtc.org 4160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (syncBuffer) 4161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete [] syncBuffer; 4163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (DWORD)hr; 4166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint32_t AudioDeviceWindowsCore::EnableBuiltInAEC(bool enable) 4169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_recIsInitialized) 4172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 4174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Attempt to set Windows AEC with recording already initialized"); 4175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_dmo == NULL) 4179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 4181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Built-in AEC DMO was not initialized properly at create time"); 4182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _builtInAecEnabled = enable; 4186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioDeviceWindowsCore::BuiltInAECIsEnabled() const 4190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _builtInAecEnabled; 4192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint AudioDeviceWindowsCore::SetDMOProperties() 4195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 4197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_dmo != NULL); 4198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org scoped_refptr<IPropertyStore> ps; 4200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IPropertyStore* ptrPS = NULL; 4202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _dmo->QueryInterface(IID_IPropertyStore, 4203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org reinterpret_cast<void**>(&ptrPS)); 4204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr) || ptrPS == NULL) 4205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ps = ptrPS; 4210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(ptrPS); 4211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the AEC system mode. 4214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SINGLE_CHANNEL_AEC - AEC processing only. 4215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetVtI4Property(ps, 4216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MFPKEY_WMAAECMA_SYSTEM_MODE, 4217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SINGLE_CHANNEL_AEC)) 4218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the AEC source mode. 4223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // VARIANT_TRUE - Source mode (we poll the AEC for captured data). 4224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetBoolProperty(ps, 4225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MFPKEY_WMAAECMA_DMO_SOURCE_MODE, 4226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VARIANT_TRUE) == -1) 4227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Enable the feature mode. 4232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This lets us override all the default processing settings below. 4233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetBoolProperty(ps, 4234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MFPKEY_WMAAECMA_FEATURE_MODE, 4235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VARIANT_TRUE) == -1) 4236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Disable analog AGC (default enabled). 4241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetBoolProperty(ps, 4242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MFPKEY_WMAAECMA_MIC_GAIN_BOUNDER, 4243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VARIANT_FALSE) == -1) 4244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Disable noise suppression (default enabled). 4249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 0 - Disabled, 1 - Enabled 4250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetVtI4Property(ps, 4251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MFPKEY_WMAAECMA_FEATR_NS, 4252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0) == -1) 4253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Relevant parameters to leave at default settings: 4258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // MFPKEY_WMAAECMA_FEATR_AGC - Digital AGC (disabled). 4259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // MFPKEY_WMAAECMA_FEATR_CENTER_CLIP - AEC center clipping (enabled). 4260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // MFPKEY_WMAAECMA_FEATR_ECHO_LENGTH - Filter length (256 ms). 4261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(andrew): investigate decresing the length to 128 ms. 4262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // MFPKEY_WMAAECMA_FEATR_FRAME_SIZE - Frame size (0). 4263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 0 is automatic; defaults to 160 samples (or 10 ms frames at the 4264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // selected 16 kHz) as long as mic array processing is disabled. 4265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // MFPKEY_WMAAECMA_FEATR_NOISE_FILL - Comfort noise (enabled). 4266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // MFPKEY_WMAAECMA_FEATR_VAD - VAD (disabled). 4267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the devices selected by VoE. If using a default device, we need to 4269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // search for the device index. 4270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int inDevIndex = _inputDeviceIndex; 4271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int outDevIndex = _outputDeviceIndex; 4272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_usingInputDeviceIndex) 4273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ERole role = eCommunications; 4275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_inputDevice == AudioDeviceModule::kDefaultDevice) 4276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role = eConsole; 4278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_GetDefaultDeviceIndex(eCapture, role, &inDevIndex) == -1) 4281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_usingOutputDeviceIndex) 4287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ERole role = eCommunications; 4289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_outputDevice == AudioDeviceModule::kDefaultDevice) 4290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role = eConsole; 4292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_GetDefaultDeviceIndex(eRender, role, &outDevIndex) == -1) 4295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD devIndex = static_cast<uint32_t>(outDevIndex << 16) + 4301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static_cast<uint32_t>(0x0000ffff & inDevIndex); 4302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 4303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Capture device index: %d, render device index: %d", 4304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org inDevIndex, outDevIndex); 4305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetVtI4Property(ps, 4306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MFPKEY_WMAAECMA_DEVICE_INDEXES, 4307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org devIndex) == -1) 4308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint AudioDeviceWindowsCore::SetBoolProperty(IPropertyStore* ptrPS, 4316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org REFPROPERTYKEY key, 4317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VARIANT_BOOL value) 4318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PROPVARIANT pv; 4320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PropVariantInit(&pv); 4321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pv.vt = VT_BOOL; 4322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pv.boolVal = value; 4323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = ptrPS->SetValue(key, pv); 4324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PropVariantClear(&pv); 4325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint AudioDeviceWindowsCore::SetVtI4Property(IPropertyStore* ptrPS, 4334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org REFPROPERTYKEY key, 4335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LONG value) 4336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PROPVARIANT pv; 4338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PropVariantInit(&pv); 4339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pv.vt = VT_I4; 4340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pv.lVal = value; 4341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = ptrPS->SetValue(key, pv); 4342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PropVariantClear(&pv); 4343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _RefreshDeviceList 4353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Creates a new list of endpoint rendering or capture devices after 4355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// deleting any previously created (and possibly out-of-date) list of 4356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// such devices. 4357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 435964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_RefreshDeviceList(EDataFlow dir) 4360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 4364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDeviceCollection *pCollection = NULL; 4365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(dir == eRender || dir == eCapture); 4367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrEnumerator != NULL); 4368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Create a fresh list of devices using the specified direction 4370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrEnumerator->EnumAudioEndpoints( 4371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dir, 4372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DEVICE_STATE_ACTIVE, 4373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pCollection); 4374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pCollection); 4378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dir == eRender) 4382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrRenderCollection); 4384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrRenderCollection = pCollection; 4385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 4387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(_ptrCaptureCollection); 4389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _ptrCaptureCollection = pCollection; 4390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _DeviceListCount 4397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Gets a count of the endpoint rendering or capture devices in the 4399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// current list of such devices. 4400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 440264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint16_t AudioDeviceWindowsCore::_DeviceListCount(EDataFlow dir) 4403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 4407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT count = 0; 4408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(eRender == dir || eCapture == dir); 4410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (eRender == dir && NULL != _ptrRenderCollection) 4412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderCollection->GetCount(&count); 4414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (NULL != _ptrCaptureCollection) 4416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrCaptureCollection->GetCount(&count); 4418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 442664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org return static_cast<int16_t> (count); 4427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _GetListDeviceName 4431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Gets the friendly name of an endpoint rendering or capture device 4433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// from the current list of such devices. The caller uses an index 4434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// into the list to identify the device. 4435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Uses: _ptrRenderCollection or _ptrCaptureCollection which is updated 4437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// in _RefreshDeviceList(). 4438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 444064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_GetListDeviceName(EDataFlow dir, int index, LPWSTR szBuffer, int bufferLen) 4441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 4445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDevice *pDevice = NULL; 4446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(dir == eRender || dir == eCapture); 4448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (eRender == dir && NULL != _ptrRenderCollection) 4450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderCollection->Item(index, &pDevice); 4452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (NULL != _ptrCaptureCollection) 4454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrCaptureCollection->Item(index, &pDevice); 4456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pDevice); 4462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 446564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t res = _GetDeviceName(pDevice, szBuffer, bufferLen); 4466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pDevice); 4467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return res; 4468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _GetDefaultDeviceName 4472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Gets the friendly name of an endpoint rendering or capture device 4474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// given a specified device role. 4475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Uses: _ptrEnumerator 4477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 447964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_GetDefaultDeviceName(EDataFlow dir, ERole role, LPWSTR szBuffer, int bufferLen) 4480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 4484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDevice *pDevice = NULL; 4485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(dir == eRender || dir == eCapture); 4487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(role == eConsole || role == eCommunications); 4488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrEnumerator != NULL); 4489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrEnumerator->GetDefaultAudioEndpoint( 4491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dir, 4492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role, 4493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pDevice); 4494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pDevice); 4499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 450264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t res = _GetDeviceName(pDevice, szBuffer, bufferLen); 4503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pDevice); 4504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return res; 4505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _GetListDeviceID 4509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Gets the unique ID string of an endpoint rendering or capture device 4511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// from the current list of such devices. The caller uses an index 4512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// into the list to identify the device. 4513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Uses: _ptrRenderCollection or _ptrCaptureCollection which is updated 4515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// in _RefreshDeviceList(). 4516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 451864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_GetListDeviceID(EDataFlow dir, int index, LPWSTR szBuffer, int bufferLen) 4519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 4523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDevice *pDevice = NULL; 4524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(dir == eRender || dir == eCapture); 4526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (eRender == dir && NULL != _ptrRenderCollection) 4528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrRenderCollection->Item(index, &pDevice); 4530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (NULL != _ptrCaptureCollection) 4532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrCaptureCollection->Item(index, &pDevice); 4534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pDevice); 4540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 454364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t res = _GetDeviceID(pDevice, szBuffer, bufferLen); 4544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pDevice); 4545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return res; 4546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _GetDefaultDeviceID 4550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Gets the uniqe device ID of an endpoint rendering or capture device 4552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// given a specified device role. 4553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 4554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Uses: _ptrEnumerator 4555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 455764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_GetDefaultDeviceID(EDataFlow dir, ERole role, LPWSTR szBuffer, int bufferLen) 4558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 4562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDevice *pDevice = NULL; 4563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(dir == eRender || dir == eCapture); 4565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(role == eConsole || role == eCommunications); 4566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrEnumerator != NULL); 4567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrEnumerator->GetDefaultAudioEndpoint( 4569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dir, 4570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role, 4571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pDevice); 4572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pDevice); 4577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 458064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int32_t res = _GetDeviceID(pDevice, szBuffer, bufferLen); 4581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pDevice); 4582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return res; 4583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 458564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_GetDefaultDeviceIndex(EDataFlow dir, 458664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org ERole role, 458764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int* index) 4588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 4592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WCHAR szDefaultDeviceID[MAX_PATH] = {0}; 4593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WCHAR szDeviceID[MAX_PATH] = {0}; 4594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const size_t kDeviceIDLength = sizeof(szDeviceID)/sizeof(szDeviceID[0]); 4596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(kDeviceIDLength == 4597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sizeof(szDefaultDeviceID) / sizeof(szDefaultDeviceID[0])); 4598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_GetDefaultDeviceID(dir, 4600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role, 4601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org szDefaultDeviceID, 4602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kDeviceIDLength) == -1) 4603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDeviceCollection* collection = _ptrCaptureCollection; 4608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dir == eRender) 4609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org collection = _ptrRenderCollection; 4611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!collection) 4614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 4616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Device collection not valid"); 4617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT count = 0; 4621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = collection->GetCount(&count); 4622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *index = -1; 4629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (UINT i = 0; i < count; i++) 4630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(szDeviceID, 0, sizeof(szDeviceID)); 4632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org scoped_refptr<IMMDevice> device; 4633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDevice* ptrDevice = NULL; 4635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = collection->Item(i, &ptrDevice); 4636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr) || ptrDevice == NULL) 4637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org device = ptrDevice; 4642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(ptrDevice); 4643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_GetDeviceID(device, szDeviceID, kDeviceIDLength) == -1) 4646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (wcsncmp(szDefaultDeviceID, szDeviceID, kDeviceIDLength) == 0) 4651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Found a match. 4653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *index = i; 4654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 4655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (*index == -1) 4660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 4662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Unable to find collection index for default device"); 4663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _GetDeviceName 4671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 467364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_GetDeviceName(IMMDevice* pDevice, 467464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org LPWSTR pszBuffer, 467564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org int bufferLen) 4676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static const WCHAR szDefault[] = L"<Device not available>"; 4680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = E_FAIL; 4682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IPropertyStore *pProps = NULL; 4683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PROPVARIANT varName; 4684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(pszBuffer != NULL); 4686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(bufferLen > 0); 4687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pDevice != NULL) 4689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pDevice->OpenPropertyStore(STGM_READ, &pProps); 4691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 4694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "IMMDevice::OpenPropertyStore failed, hr = 0x%08X", hr); 4695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize container for property value. 4699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PropVariantInit(&varName); 4700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SUCCEEDED(hr)) 4702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint device's friendly-name property. 4704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName); 4705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 4708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "IPropertyStore::GetValue failed, hr = 0x%08X", hr); 4709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((SUCCEEDED(hr)) && (VT_EMPTY == varName.vt)) 4713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = E_FAIL; 4715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 4716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "IPropertyStore::GetValue returned no value, hr = 0x%08X", hr); 4717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((SUCCEEDED(hr)) && (VT_LPWSTR != varName.vt)) 4720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The returned value is not a wide null terminated string. 4722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = E_UNEXPECTED; 4723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 4724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "IPropertyStore::GetValue returned unexpected type, hr = 0x%08X", hr); 4725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SUCCEEDED(hr) && (varName.pwszVal != NULL)) 4728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Copy the valid device name to the provided ouput buffer. 4730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org wcsncpy_s(pszBuffer, bufferLen, varName.pwszVal, _TRUNCATE); 4731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 4733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Failed to find the device name. 4735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org wcsncpy_s(pszBuffer, bufferLen, szDefault, _TRUNCATE); 4736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PropVariantClear(&varName); 4739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pProps); 4740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _GetDeviceID 4746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 474864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_GetDeviceID(IMMDevice* pDevice, LPWSTR pszBuffer, int bufferLen) 4749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static const WCHAR szDefault[] = L"<Device not available>"; 4753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = E_FAIL; 4755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org LPWSTR pwszID = NULL; 4756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(pszBuffer != NULL); 4758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(bufferLen > 0); 4759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pDevice != NULL) 4761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pDevice->GetId(&pwszID); 4763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr == S_OK) 4766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Found the device ID. 4768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org wcsncpy_s(pszBuffer, bufferLen, pwszID, _TRUNCATE); 4769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 4771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Failed to find the device ID. 4773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org wcsncpy_s(pszBuffer, bufferLen, szDefault, _TRUNCATE); 4774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pwszID); 4777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _GetDefaultDevice 4782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 478464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_GetDefaultDevice(EDataFlow dir, ERole role, IMMDevice** ppDevice) 4785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr(S_OK); 4789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrEnumerator != NULL); 4791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrEnumerator->GetDefaultAudioEndpoint( 4793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dir, 4794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org role, 4795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ppDevice); 4796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _GetListDevice 4807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 480964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_GetListDevice(EDataFlow dir, int index, IMMDevice** ppDevice) 4810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr(S_OK); 4812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrEnumerator != NULL); 4814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDeviceCollection *pCollection = NULL; 4816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrEnumerator->EnumAudioEndpoints( 4818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dir, 4819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DEVICE_STATE_ACTIVE, // only active endpoints are OK 4820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pCollection); 4821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pCollection); 4825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pCollection->Item( 4829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org index, 4830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ppDevice); 4831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 4832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 4834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pCollection); 4835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 4836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _EnumerateEndpointDevicesAll 4843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 4844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 484564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioDeviceWindowsCore::_EnumerateEndpointDevicesAll(EDataFlow dataFlow) const 4846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 4847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); 4848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_ptrEnumerator != NULL); 4850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 4852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IMMDeviceCollection *pCollection = NULL; 4853d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org IMMDevice *pEndpoint = NULL; 4854d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org IPropertyStore *pProps = NULL; 4855d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org IAudioEndpointVolume* pEndpointVolume = NULL; 4856d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org LPWSTR pwszID = NULL; 4857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Generate a collection of audio endpoint devices in the system. 4859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get states for *all* endpoint devices. 4860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Output: IMMDeviceCollection interface. 4861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _ptrEnumerator->EnumAudioEndpoints( 4862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dataFlow, // data-flow direction (input parameter) 486353a26ce1a6dc73296fceabb7343f90181a16022ebraveyao@webrtc.org DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED | DEVICE_STATE_UNPLUGGED, 4864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pCollection); // release interface when done 4865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 4867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // use the IMMDeviceCollection interface... 4869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4870d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org UINT count = 0; 4871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Retrieve a count of the devices in the device collection. 4873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pCollection->GetCount(&count); 4874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EXIT_ON_ERROR(hr); 4875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dataFlow == eRender) 4876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#rendering endpoint devices (counting all): %u", count); 4877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (dataFlow == eCapture) 4878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#capturing endpoint devices (counting all): %u", count); 4879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (count == 0) 4881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 4883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Each loop prints the name of an endpoint device. 4886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (ULONG i = 0; i < count; i++) 4887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Endpoint %d:", i); 4889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get pointer to endpoint number i. 4891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Output: IMMDevice interface. 4892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pCollection->Item( 4893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org i, 4894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pEndpoint); 4895531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // use the IMMDevice interface of the specified endpoint device... 4898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint ID string (uniquely identifies the device among all audio endpoint devices) 4900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pEndpoint->GetId(&pwszID); 4901531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "ID string : %S", pwszID); 4903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Retrieve an interface to the device's property store. 4905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Output: IPropertyStore interface. 4906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pEndpoint->OpenPropertyStore( 4907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org STGM_READ, 4908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pProps); 4909531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // use the IPropertyStore interface... 4912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PROPVARIANT varName; 4914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize container for property value. 4915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PropVariantInit(&varName); 4916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint's friendly-name property. 4918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Example: "Speakers (Realtek High Definition Audio)" 4919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pProps->GetValue( 4920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PKEY_Device_FriendlyName, 4921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &varName); 4922531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "friendly name: \"%S\"", varName.pwszVal); 4924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the endpoint's current device state 4926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD dwState; 4927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pEndpoint->GetState(&dwState); 4928531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dwState & DEVICE_STATE_ACTIVE) 4930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "state (0x%x) : *ACTIVE*", dwState); 4931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dwState & DEVICE_STATE_DISABLED) 4932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "state (0x%x) : DISABLED", dwState); 4933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dwState & DEVICE_STATE_NOTPRESENT) 4934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "state (0x%x) : NOTPRESENT", dwState); 4935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dwState & DEVICE_STATE_UNPLUGGED) 4936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "state (0x%x) : UNPLUGGED", dwState); 4937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check the hardware volume capabilities. 4939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DWORD dwHwSupportMask = 0; 4940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pEndpoint->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, 4941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, (void**)&pEndpointVolume); 4942531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pEndpointVolume->QueryHardwareSupport(&dwHwSupportMask); 4944531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dwHwSupportMask & ENDPOINT_HARDWARE_SUPPORT_VOLUME) 4946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The audio endpoint device supports a hardware volume control 4947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "hwmask (0x%x) : HARDWARE_SUPPORT_VOLUME", dwHwSupportMask); 4948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dwHwSupportMask & ENDPOINT_HARDWARE_SUPPORT_MUTE) 4949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The audio endpoint device supports a hardware mute control 4950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "hwmask (0x%x) : HARDWARE_SUPPORT_MUTE", dwHwSupportMask); 4951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dwHwSupportMask & ENDPOINT_HARDWARE_SUPPORT_METER) 4952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The audio endpoint device supports a hardware peak meter 4953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "hwmask (0x%x) : HARDWARE_SUPPORT_METER", dwHwSupportMask); 4954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check the channel count (#channels in the audio stream that enters or leaves the audio endpoint device) 4956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT nChannelCount(0); 4957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pEndpointVolume->GetChannelCount( 4958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &nChannelCount); 4959531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#channels : %u", nChannelCount); 4961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dwHwSupportMask & ENDPOINT_HARDWARE_SUPPORT_VOLUME) 4963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 4964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the volume range. 4965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float fLevelMinDB(0.0); 4966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float fLevelMaxDB(0.0); 4967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float fVolumeIncrementDB(0.0); 4968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pEndpointVolume->GetVolumeRange( 4969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &fLevelMinDB, 4970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &fLevelMaxDB, 4971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &fVolumeIncrementDB); 4972531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "volume range : %4.2f (min), %4.2f (max), %4.2f (inc) [dB]", 4974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fLevelMinDB, fLevelMaxDB, fVolumeIncrementDB); 4975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The volume range from vmin = fLevelMinDB to vmax = fLevelMaxDB is divided 4977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // into n uniform intervals of size vinc = fVolumeIncrementDB, where 4978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // n = (vmax ?vmin) / vinc. 4979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The values vmin, vmax, and vinc are measured in decibels. The client can set 4980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the volume level to one of n + 1 discrete values in the range from vmin to vmax. 4981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int n = (int)((fLevelMaxDB-fLevelMinDB)/fVolumeIncrementDB); 4982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#intervals : %d", n); 4983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get information about the current step in the volume range. 4985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This method represents the volume level of the audio stream that enters or leaves 4986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the audio endpoint device as an index or "step" in a range of discrete volume levels. 4987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Output value nStepCount is the number of steps in the range. Output value nStep 4988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // is the step index of the current volume level. If the number of steps is n = nStepCount, 4989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // then step index nStep can assume values from 0 (minimum volume) to n ?1 (maximum volume). 4990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT nStep(0); 4991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UINT nStepCount(0); 4992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = pEndpointVolume->GetVolumeStepInfo( 4993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &nStep, 4994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &nStepCount); 4995531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org CONTINUE_ON_ERROR(hr); 4996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "volume steps : %d (nStep), %d (nStepCount)", nStep, nStepCount); 4997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4998531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.orgNext: 4999531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org if (FAILED(hr)) { 5000531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 5001531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org "Error when logging device information"); 5002531a99b24da5e3cc299a1012a65fc6002f89bf13braveyao@webrtc.org } 5003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pwszID); 5004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pwszID = NULL; 5005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PropVariantClear(&varName); 5006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pProps); 5007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pEndpoint); 5008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pEndpointVolume); 5009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pCollection); 5011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 5012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgExit: 5014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _TraceCOMError(hr); 5015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CoTaskMemFree(pwszID); 5016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pwszID = NULL; 5017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pCollection); 5018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pEndpoint); 5019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pEndpointVolume); 5020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SAFE_RELEASE(pProps); 5021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 5022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 5023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 5025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _TraceCOMError 5026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 5027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceWindowsCore::_TraceCOMError(HRESULT hr) const 5029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 5030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org TCHAR buf[MAXERRORLENGTH]; 5031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org TCHAR errorText[MAXERRORLENGTH]; 5032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | 5034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org FORMAT_MESSAGE_IGNORE_INSERTS; 5035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const DWORD dwLangID = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); 5036d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org 5037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Gets the system's human readable message string for this HRESULT. 5038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // All error message in English by default. 5039d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org DWORD messageLength = ::FormatMessageW(dwFlags, 5040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 5041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr, 5042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dwLangID, 5043d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org errorText, 5044d6f6ff0da2180d5964e733ba8205c1a3353872c4henrika@webrtc.org MAXERRORLENGTH, 5045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL); 5046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(messageLength <= MAXERRORLENGTH); 5048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Trims tailing white space (FormatMessage() leaves a trailing cr-lf.). 5050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (; messageLength && ::isspace(errorText[messageLength - 1]); 5051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org --messageLength) 5052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 5053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org errorText[messageLength - 1] = '\0'; 5054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 5057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Core Audio method failed (hr=0x%x)", hr); 5058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: ")); 5059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StringCchCat(buf, MAXERRORLENGTH, errorText); 5060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "%s", WideToUTF8(buf)); 5061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 5062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 5064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// _SetThreadName 5065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 5066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioDeviceWindowsCore::_SetThreadName(DWORD dwThreadID, LPCSTR szThreadName) 5068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 5069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // See http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx for details on the code 5070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // in this function. Name of article is "Setting a Thread Name (Unmanaged)". 5071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org THREADNAME_INFO info; 5073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org info.dwType = 0x1000; 5074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org info.szName = szThreadName; 5075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org info.dwThreadID = dwThreadID; 5076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org info.dwFlags = 0; 5077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __try 5079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 5080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR *)&info ); 5081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org __except (EXCEPTION_CONTINUE_EXECUTION) 5083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 5084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 5086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 5088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// WideToUTF8 5089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ---------------------------------------------------------------------------- 5090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgchar* AudioDeviceWindowsCore::WideToUTF8(const TCHAR* src) const { 5092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef UNICODE 5093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const size_t kStrLen = sizeof(_str); 5094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(_str, 0, kStrLen); 5095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get required size (in bytes) to be able to complete the conversion. 5096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int required_size = WideCharToMultiByte(CP_UTF8, 0, src, -1, _str, 0, 0, 0); 5097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (required_size <= kStrLen) 5098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 5099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Process the entire input string, including the terminating null char. 5100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WideCharToMultiByte(CP_UTF8, 0, src, -1, _str, kStrLen, 0, 0) == 0) 5101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(_str, 0, kStrLen); 5102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _str; 5104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#else 5105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return const_cast<char*>(src); 5106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 5107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 5108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 510928832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org 511028832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.orgbool AudioDeviceWindowsCore::KeyPressed() const{ 511128832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org 511228832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org int key_down = 0; 511328832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org for (int key = VK_SPACE; key < VK_NUMLOCK; key++) { 511428832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org short res = GetAsyncKeyState(key); 511528832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org key_down |= res & 0x1; // Get the LSB 511628832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org } 511728832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org return (key_down > 0); 511828832e1965ca0c22ca6a26bbd3387db4db640bedniklas.enbom@webrtc.org} 5119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace webrtc 5120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif // WEBRTC_WINDOWS_CORE_AUDIO_BUILD 5122