volumekeeper.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include "stdafx.h"
  2. #include "SpBase.h"
  3. #include "volumekeeper.h"
  4. #include <audioclient.h>
  5. #include <MMDeviceApi.h>
  6. #include <AudioEngineEndPoint.h>
  7. #include <DeviceTopology.h>
  8. #include <EndpointVolume.h>
  9. #include <functiondiscoverykeys.h>
  10. #define EXIT_ON_ERROR(x) if (FAILED(x)) {goto Exit;}
  11. #define RETURN_ERROR(x) FAILED(x)?false:true
  12. class volume_keeper_t : public IAudioEndpointVolumeCallback
  13. {
  14. //float fLevelMinDB;
  15. //float fLevelMaxDB;
  16. //float fLevelIncDB;
  17. char m_dev_key[260];
  18. int m_in_dev;
  19. ULONG m_lRef;
  20. public:
  21. IAudioEndpointVolume *m_pAudioEndpointVolume;
  22. GUID m_guidContext;
  23. float m_kept_value;
  24. volume_keeper_t(const char *dev_key, int in_dev, int kept_value) : m_lRef(1), m_kept_value(kept_value/100.0f), m_pAudioEndpointVolume(NULL), m_in_dev(in_dev)
  25. {
  26. strcpy(m_dev_key, dev_key);
  27. }
  28. HRESULT Init()
  29. {
  30. IMMDeviceEnumerator *pEnumerator = NULL;
  31. IMMDeviceCollection *pDeviceCollection = NULL;
  32. HRESULT hr;
  33. hr = CoCreateGuid(&m_guidContext);
  34. EXIT_ON_ERROR(hr);
  35. hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
  36. EXIT_ON_ERROR(hr);
  37. hr = pEnumerator->EnumAudioEndpoints(m_in_dev ? eCapture : eRender, DEVICE_STATE_ACTIVE, &pDeviceCollection);
  38. EXIT_ON_ERROR(hr);
  39. UINT nCount = 0;
  40. hr = pDeviceCollection->GetCount(&nCount);
  41. EXIT_ON_ERROR(hr);
  42. for (UINT i = 0; i < nCount; ++i) {
  43. IMMDevice *pDevice = NULL;
  44. hr = pDeviceCollection->Item(i, &pDevice);
  45. if (SUCCEEDED(hr)) {
  46. char name[260];
  47. IPropertyStore *pPS = NULL;
  48. PROPVARIANT value;
  49. PropVariantInit(&value);
  50. pDevice->OpenPropertyStore(STGM_READ, &pPS);
  51. pPS->GetValue(PKEY_Device_FriendlyName, &value);
  52. WideCharToMultiByte(CP_ACP, 0, value.pwszVal, -1, name, sizeof(name)-1, 0, 0);
  53. PropVariantClear(&value);
  54. pPS->Release();
  55. if (strstr(name, m_dev_key)) {
  56. hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (void**)&m_pAudioEndpointVolume);
  57. if (SUCCEEDED(hr)) {
  58. hr = m_pAudioEndpointVolume->RegisterControlChangeNotify(this);
  59. m_pAudioEndpointVolume->SetMasterVolumeLevelScalar(m_kept_value, &m_guidContext);
  60. }
  61. pDevice->Release();
  62. break;
  63. } else {
  64. pDevice->Release();
  65. }
  66. } else {
  67. break;
  68. }
  69. }
  70. Exit:
  71. if (pDeviceCollection) {
  72. pDeviceCollection->Release();
  73. }
  74. if (pEnumerator) {
  75. pEnumerator->Release();
  76. }
  77. return hr;
  78. }
  79. void Term()
  80. {
  81. if (m_pAudioEndpointVolume) {
  82. m_pAudioEndpointVolume->UnregisterControlChangeNotify(this);
  83. m_pAudioEndpointVolume->Release();
  84. }
  85. }
  86. void ChangeValue(int nValue)
  87. {
  88. m_kept_value=nValue/100.f;
  89. }
  90. ULONG STDMETHODCALLTYPE AddRef()
  91. {
  92. return InterlockedIncrement(&m_lRef);
  93. }
  94. ULONG STDMETHODCALLTYPE Release()
  95. {
  96. ULONG ulRef = InterlockedDecrement(&m_lRef);
  97. if (0 == ulRef) {
  98. delete this;
  99. }
  100. return ulRef;
  101. }
  102. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface)
  103. {
  104. if (IID_IUnknown == riid) {
  105. AddRef();
  106. *ppvInterface = (IUnknown*)this;
  107. } else if (__uuidof(IAudioEndpointVolumeCallback) == riid) {
  108. AddRef();
  109. *ppvInterface = (IAudioEndpointVolumeCallback*)this;
  110. } else {
  111. *ppvInterface = NULL;
  112. return E_NOINTERFACE;
  113. }
  114. return S_OK;
  115. }
  116. // Callback method for endpoint-volume-change notifications.
  117. HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify)
  118. {
  119. if (pNotify == NULL) {
  120. return E_INVALIDARG;
  121. }
  122. if (pNotify->guidEventContext != m_guidContext) {
  123. //Dbg("volume notify calblack!");
  124. if (pNotify->fMasterVolume != m_kept_value) {
  125. //Dbg("volumechange notify, pNotify->fMasterVolume:%f", pNotify->fMasterVolume);
  126. m_pAudioEndpointVolume->SetMasterVolumeLevelScalar(m_kept_value, &m_guidContext);
  127. }
  128. }
  129. return S_OK;
  130. }
  131. };
  132. void *volume_keeper_create(const char *dev_key_name, int in_dev, int kept_value)
  133. {
  134. if (!dev_key_name)
  135. return NULL;
  136. if (kept_value < 0 || kept_value > 100)
  137. return NULL;
  138. volume_keeper_t *inst = new volume_keeper_t(dev_key_name, in_dev, kept_value);
  139. if (SUCCEEDED(inst->Init()))
  140. {
  141. return inst;
  142. }
  143. else
  144. {
  145. inst->Release();
  146. }
  147. return NULL;
  148. }
  149. void volume_keeper_destroy(void *inst)
  150. {
  151. volume_keeper_t *keeper = (volume_keeper_t*)inst;
  152. keeper->Term();
  153. keeper->Release();
  154. }
  155. void volume_keeper_change(void *inst,int change_value)
  156. {
  157. volume_keeper_t *keeper = (volume_keeper_t*)inst;
  158. float fCurValue = 0.0;
  159. keeper->m_kept_value =(change_value/100.0f);
  160. if (keeper->m_kept_value>1)
  161. {
  162. keeper->m_kept_value = 1;
  163. }
  164. else if (keeper->m_kept_value<0)
  165. {
  166. keeper->m_kept_value = 0;
  167. }
  168. keeper->m_pAudioEndpointVolume->SetMasterVolumeLevelScalar(keeper->m_kept_value,&keeper->m_guidContext);
  169. }
  170. bool get_audiodevice_volumn(void *inst,int*nvalue)
  171. {
  172. volume_keeper_t *keeper = (volume_keeper_t*)inst;
  173. float fValue = 0.0;
  174. keeper->m_pAudioEndpointVolume->GetMasterVolumeLevelScalar(&fValue);
  175. *nvalue = fValue*100;
  176. return true;
  177. }