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.

179 lines
4.6 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. class CMMNotificationClient : public IMMNotificationClient
  13. {
  14. LONG _cRef;
  15. IMMDeviceEnumerator *_pEnumerator;
  16. public:
  17. CMMNotificationClient() :
  18. _cRef(1),
  19. _pEnumerator(NULL)
  20. {
  21. }
  22. ~CMMNotificationClient()
  23. {
  24. SAFE_RELEASE(_pEnumerator)
  25. }
  26. // IUnknown methods -- AddRef, Release, and QueryInterface
  27. ULONG STDMETHODCALLTYPE AddRef()
  28. {
  29. return InterlockedIncrement(&_cRef);
  30. }
  31. ULONG STDMETHODCALLTYPE Release()
  32. {
  33. ULONG ulRef = InterlockedDecrement(&_cRef);
  34. if (0 == ulRef)
  35. {
  36. delete this;
  37. }
  38. return ulRef;
  39. }
  40. HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, VOID **ppvInterface)
  41. {
  42. if (IID_IUnknown == riid)
  43. {
  44. AddRef();
  45. *ppvInterface = (IUnknown*)this;
  46. }
  47. else if (__uuidof(IMMNotificationClient) == riid)
  48. {
  49. AddRef();
  50. *ppvInterface = (IMMNotificationClient*)this;
  51. }
  52. else
  53. {
  54. *ppvInterface = NULL;
  55. return E_NOINTERFACE;
  56. }
  57. return S_OK;
  58. }
  59. // Callback methods for device-event notifications.
  60. HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged( EDataFlow flow, ERole /*role*/, LPCWSTR /*pwstrDeviceId*/ )
  61. {
  62. return S_OK;
  63. }
  64. HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR /*pwstrDeviceId*/) { return S_OK; };
  65. HRESULT STDMETHODCALLTYPE OnDeviceRemoved( LPCWSTR /*pwstrDeviceId*/ ) { return S_OK; }
  66. HRESULT STDMETHODCALLTYPE OnDeviceStateChanged( LPCWSTR /*pwstrDeviceId*/, DWORD /*dwNewState*/ ) { return S_OK; }
  67. HRESULT STDMETHODCALLTYPE OnPropertyValueChanged( LPCWSTR /*pwstrDeviceId*/, const PROPERTYKEY /*key*/ ) { return S_OK; }
  68. };
  69. extern CMMNotificationClient *g_pNotify;
  70. HRESULT SetupWindowsMixerPreferences( float flMasterVolume = 1.0f, bool bDuckingOptOut = true )
  71. {
  72. HRESULT hr = S_OK;
  73. IMMDeviceEnumerator* pDeviceEnumerator = NULL;
  74. IMMDevice* pEndpoint = NULL;
  75. IAudioSessionManager2* pSessionManager2 = NULL;
  76. IAudioSessionControl* pSessionControl = NULL;
  77. IAudioSessionControl2* pSessionControl2 = NULL;
  78. // Start with the default endpoint.
  79. hr = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDeviceEnumerator) );
  80. if ( SUCCEEDED( hr ) )
  81. {
  82. hr = pDeviceEnumerator->GetDefaultAudioEndpoint( eRender, eConsole, &pEndpoint);
  83. g_pNotify = new CMMNotificationClient;
  84. pDeviceEnumerator->RegisterEndpointNotificationCallback( g_pNotify );
  85. pDeviceEnumerator->Release();
  86. pDeviceEnumerator = NULL;
  87. }
  88. // Activate session manager.
  89. if (SUCCEEDED(hr))
  90. {
  91. hr = pEndpoint->Activate(__uuidof(IAudioSessionManager2), CLSCTX_INPROC_SERVER, NULL, reinterpret_cast<void **>(&pSessionManager2) );
  92. if ( !SUCCEEDED( hr ) )
  93. {
  94. // probably on vista, get the regular session manager
  95. IAudioSessionManager *pSessionManager = NULL;
  96. HRESULT hrVista = pEndpoint->Activate(__uuidof(IAudioSessionManager), CLSCTX_INPROC_SERVER, NULL, reinterpret_cast<void **>(&pSessionManager) );
  97. if ( SUCCEEDED( hrVista ) )
  98. {
  99. ISimpleAudioVolume *pSimpleVolume = NULL;
  100. HRESULT hrVolume = pSessionManager->GetSimpleAudioVolume( NULL, 0, &pSimpleVolume );
  101. if ( SUCCEEDED( hrVolume ) )
  102. {
  103. pSimpleVolume->SetMasterVolume( flMasterVolume, NULL );
  104. pSimpleVolume->Release();
  105. }
  106. pSessionManager->Release();
  107. pSessionManager = NULL;
  108. }
  109. }
  110. pEndpoint->Release();
  111. pEndpoint = NULL;
  112. }
  113. if ( SUCCEEDED( hr ) )
  114. {
  115. hr = pSessionManager2->GetAudioSessionControl(NULL, 0, &pSessionControl);
  116. if ( SUCCEEDED( hr ) )
  117. {
  118. ISimpleAudioVolume *pSimpleVolume = NULL;
  119. HRESULT hrVolume = pSessionManager2->GetSimpleAudioVolume( NULL, FALSE, &pSimpleVolume );
  120. if ( SUCCEEDED( hrVolume ) )
  121. {
  122. pSimpleVolume->SetMasterVolume( flMasterVolume, NULL );
  123. pSimpleVolume->Release();
  124. }
  125. }
  126. pSessionManager2->Release();
  127. pSessionManager2 = NULL;
  128. }
  129. if ( SUCCEEDED( hr ) )
  130. {
  131. hr = pSessionControl->QueryInterface( __uuidof(IAudioSessionControl2), (void**)&pSessionControl2 );
  132. pSessionControl->Release();
  133. pSessionControl = NULL;
  134. }
  135. // Sync the ducking state with the specified preference.
  136. if ( SUCCEEDED( hr ) )
  137. {
  138. if (bDuckingOptOut)
  139. {
  140. hr = pSessionControl2->SetDuckingPreference(TRUE);
  141. }
  142. else
  143. {
  144. hr = pSessionControl2->SetDuckingPreference(FALSE);
  145. }
  146. pSessionControl2->Release();
  147. pSessionControl2 = NULL;
  148. }
  149. return hr;
  150. }