Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
5.5 KiB

  1. //
  2. // NOTE: Source has a bunch of windows SDK headers checked in to the dx9sdk directory.
  3. // This file is here to isolate dependencies on the newer version of the windows SDK
  4. // NOTE: This code only applies to VISTA and greater
  5. #include <windows.h>
  6. #include <mmdeviceapi.h>
  7. #include <audiopolicy.h>
  8. #include <endpointvolume.h>
  9. #define SAFE_RELEASE(punk) \
  10. if ((punk) != NULL) \
  11. { (punk)->Release(); (punk) = NULL; }
  12. extern unsigned int g_nDeviceStamp;
  13. class CMMNotificationClient : public IMMNotificationClient
  14. {
  15. LONG _cRef;
  16. IMMDeviceEnumerator *_pEnumerator;
  17. public:
  18. CMMNotificationClient() :
  19. _cRef(1),
  20. _pEnumerator(NULL)
  21. {
  22. }
  23. ~CMMNotificationClient()
  24. {
  25. SAFE_RELEASE(_pEnumerator)
  26. }
  27. // IUnknown methods -- AddRef, Release, and QueryInterface
  28. ULONG STDMETHODCALLTYPE AddRef()
  29. {
  30. return InterlockedIncrement(&_cRef);
  31. }
  32. ULONG STDMETHODCALLTYPE Release()
  33. {
  34. ULONG ulRef = InterlockedDecrement(&_cRef);
  35. if (0 == ulRef)
  36. {
  37. delete this;
  38. }
  39. return ulRef;
  40. }
  41. HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, VOID **ppvInterface)
  42. {
  43. if (IID_IUnknown == riid)
  44. {
  45. AddRef();
  46. *ppvInterface = (IUnknown*)this;
  47. }
  48. else if (__uuidof(IMMNotificationClient) == riid)
  49. {
  50. AddRef();
  51. *ppvInterface = (IMMNotificationClient*)this;
  52. }
  53. else
  54. {
  55. *ppvInterface = NULL;
  56. return E_NOINTERFACE;
  57. }
  58. return S_OK;
  59. }
  60. // Callback methods for device-event notifications.
  61. HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged( EDataFlow flow, ERole /*role*/, LPCWSTR /*pwstrDeviceId*/ )
  62. {
  63. if ( flow == eRender )
  64. {
  65. g_nDeviceStamp++;
  66. }
  67. return S_OK;
  68. }
  69. HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR /*pwstrDeviceId*/) { return S_OK; };
  70. HRESULT STDMETHODCALLTYPE OnDeviceRemoved( LPCWSTR /*pwstrDeviceId*/ ) { return S_OK; }
  71. HRESULT STDMETHODCALLTYPE OnDeviceStateChanged( LPCWSTR /*pwstrDeviceId*/, DWORD /*dwNewState*/ ) { return S_OK; }
  72. HRESULT STDMETHODCALLTYPE OnPropertyValueChanged( LPCWSTR /*pwstrDeviceId*/, const PROPERTYKEY /*key*/ ) { return S_OK; }
  73. };
  74. CMMNotificationClient *g_pNotify = NULL;
  75. HRESULT SetupWindowsMixerPreferences( bool bDuckingOptOut = true )
  76. {
  77. HRESULT hr = S_OK;
  78. IMMDeviceEnumerator* pDeviceEnumerator = NULL;
  79. IMMDevice* pEndpoint = NULL;
  80. IAudioSessionManager2* pSessionManager2 = NULL;
  81. IAudioSessionControl* pSessionControl = NULL;
  82. IAudioSessionControl2* pSessionControl2 = NULL;
  83. // Start with the default endpoint.
  84. hr = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDeviceEnumerator) );
  85. if (SUCCEEDED(hr))
  86. {
  87. hr = pDeviceEnumerator->GetDefaultAudioEndpoint( eRender, eConsole, &pEndpoint);
  88. g_pNotify = new CMMNotificationClient;
  89. pDeviceEnumerator->RegisterEndpointNotificationCallback( g_pNotify );
  90. pDeviceEnumerator->Release();
  91. pDeviceEnumerator = NULL;
  92. }
  93. // Activate session manager.
  94. if (SUCCEEDED(hr))
  95. {
  96. hr = pEndpoint->Activate(__uuidof(IAudioSessionManager2), CLSCTX_INPROC_SERVER, NULL, reinterpret_cast<void **>(&pSessionManager2) );
  97. pEndpoint->Release();
  98. pEndpoint = NULL;
  99. }
  100. if (SUCCEEDED(hr))
  101. {
  102. hr = pSessionManager2->GetAudioSessionControl(NULL, 0, &pSessionControl);
  103. // enable this code to force some default master volume for this game.
  104. // NOTE: This will have the side effect of not remembering any setting the user made in the wiundows mixer
  105. #if 0
  106. ISimpleAudioVolume *pSimpleVolume = NULL;
  107. hr = pSessionManager2->GetSimpleAudioVolume( NULL, FALSE, &pSimpleVolume );
  108. if ( SUCCEEDED(hr) )
  109. {
  110. pSimpleVolume->SetMasterVolume( flMasterVolume, NULL );
  111. pSimpleVolume->Release();
  112. }
  113. #endif
  114. pSessionManager2->Release();
  115. pSessionManager2 = NULL;
  116. }
  117. if (SUCCEEDED(hr))
  118. {
  119. hr = pSessionControl->QueryInterface( __uuidof(IAudioSessionControl2), (void**)&pSessionControl2 );
  120. pSessionControl->Release();
  121. pSessionControl = NULL;
  122. }
  123. // Sync the ducking state with the specified preference.
  124. if (SUCCEEDED(hr))
  125. {
  126. if (bDuckingOptOut)
  127. {
  128. hr = pSessionControl2->SetDuckingPreference(TRUE);
  129. }
  130. else
  131. {
  132. hr = pSessionControl2->SetDuckingPreference(FALSE);
  133. }
  134. pSessionControl2->Release();
  135. pSessionControl2 = NULL;
  136. }
  137. return hr;
  138. }
  139. bool GetWindowsDefaultAudioDevice( wchar_t *pDeviceNameOut, size_t nDeviceBufSize )
  140. {
  141. IMMDeviceEnumerator* pDeviceEnumerator = NULL;
  142. IMMDevice* pEndpoint = NULL;
  143. bool bRet = false;
  144. // Get the default audio endpoint from the multimedia API (more reliable than XAudio2 for example because it updates with dynamic changes to the default device)
  145. HRESULT hr = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDeviceEnumerator) );
  146. if (SUCCEEDED(hr))
  147. {
  148. HRESULT hrEndPointDevice = pDeviceEnumerator->GetDefaultAudioEndpoint( eRender, eConsole, &pEndpoint );
  149. if (SUCCEEDED(hrEndPointDevice))
  150. {
  151. // now query the endpoint device for its Id
  152. LPWSTR deviceOut;
  153. if ( S_OK == pEndpoint->GetId( &deviceOut ) )
  154. {
  155. // got a valid Id, return true to the caller and save it
  156. wcsncpy_s( pDeviceNameOut, nDeviceBufSize/sizeof(wchar_t), deviceOut, _TRUNCATE );
  157. bRet = true;
  158. // GetId allocates memory when successful, we have to free it
  159. CoTaskMemFree( deviceOut );
  160. }
  161. pEndpoint->Release();
  162. }
  163. pDeviceEnumerator->Release();
  164. }
  165. return bRet;
  166. }
  167. class CInitializeCOM
  168. {
  169. public:
  170. CInitializeCOM()
  171. {
  172. CoInitializeEx(0, COINIT_MULTITHREADED);
  173. }
  174. ~CInitializeCOM()
  175. {
  176. CoUninitialize();
  177. }
  178. };
  179. void InitCOM()
  180. {
  181. static CInitializeCOM initializer;
  182. }
  183. void ShutdownCOM()
  184. {
  185. }