main.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <portaudio.h>
  4. #include <md5.h>
  5. //#include <pa_debugprint.h>
  6. #include <locale.h>
  7. #include <WinSock2.h>
  8. #define WIN32_LEAN_AND_MEAN
  9. #include <windows.h>
  10. #include "../libaudioframework/audioframework.h"
  11. #include "../libvideoframework/videoframework.h"
  12. #include <MMDeviceApi.h>
  13. #include <AudioEngineEndPoint.h>
  14. #include <DeviceTopology.h>
  15. #include <EndpointVolume.h>
  16. #include <functiondiscoverykeys.h>
  17. #ifndef MAX_STR_LEN
  18. #define MAX_STR_LEN 512
  19. #endif // !MAX_STR_LEN
  20. static int audio_translate_id(int in_direction, int idx)
  21. {
  22. int i, n, ii;
  23. //audio_log_set_func(NULL);
  24. n = Pa_GetDeviceCount();
  25. for (i = 0, ii = 0; i < n; ++i) {
  26. const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
  27. if (in_direction) {
  28. if (info->maxInputChannels) {
  29. if (ii == idx) {
  30. //audio_log_set_func(__audio_log_func);
  31. return i;
  32. }
  33. ii++;
  34. }
  35. } else {
  36. if (info->maxOutputChannels) {
  37. if (ii == idx) {
  38. //audio_log_set_func(__audio_log_func);
  39. return i;
  40. }
  41. ii++;
  42. }
  43. }
  44. }
  45. //audio_log_set_func(__audio_log_func);
  46. return -1;
  47. }
  48. int audio_get_dev_count(int *in_cnt, int *out_cnt)
  49. {
  50. int i;
  51. int icnt = 0, ocnt = 0;
  52. int cnt = Pa_GetDeviceCount();
  53. printf("Pa_GetDeviceCount get device count is %d.\n", cnt);
  54. for (i = 0; i < cnt; ++i) {
  55. const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
  56. if (info->maxInputChannels)
  57. icnt ++;
  58. if (info->maxOutputChannels)
  59. ocnt ++;
  60. }
  61. if (in_cnt)
  62. *in_cnt = icnt;
  63. if (out_cnt)
  64. *out_cnt = ocnt;
  65. return 0;
  66. }
  67. static char *audio_get_dev_name(char *buf, BOOL in_direction, int idx)
  68. {
  69. int cnt = Pa_GetDeviceCount();
  70. int ii, i;
  71. for (i = 0, ii = 0; i < cnt; ++i) {
  72. const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
  73. if (in_direction) {
  74. if (info->maxInputChannels) {
  75. if (idx == ii) {
  76. strcpy(buf, info->name);
  77. return buf;
  78. }
  79. ii++;
  80. }
  81. } else {
  82. if (info->maxOutputChannels) {
  83. if (idx == ii) {
  84. strcpy(buf, info->name);
  85. return buf;
  86. }
  87. ii++;
  88. }
  89. }
  90. }
  91. return NULL;
  92. }
  93. static void show_audio_dev()
  94. {
  95. int icnt, ocnt;
  96. int rc = audio_get_dev_count(&icnt, &ocnt);
  97. if (rc == 0) {
  98. int i;
  99. char tmp[128];
  100. printf("audio input devices(%d):\n", icnt);
  101. for (i = 0; i < icnt; ++i) {
  102. audio_get_dev_name(tmp, TRUE, i);
  103. printf("%d = %s\n", i, tmp);
  104. }
  105. printf("audio output devices(%d):\n", ocnt);
  106. for (i = 0; i < ocnt; ++i) {
  107. audio_get_dev_name(tmp, FALSE, i);
  108. printf("%d = %s\n", i, tmp);
  109. }
  110. printf("\n");
  111. }
  112. }
  113. typedef struct tagAUDIO_DEVICE_INFO
  114. {
  115. char szDeviceName[MAX_STR_LEN];
  116. char szDeviceID[MAX_STR_LEN];
  117. } AUDIO_DEVICE_INFO, *PAUDIO_DEVICE_INFO;
  118. static HRESULT GetDeviceNum(EDataFlow eDataFlow, UINT *uDevCount)
  119. {
  120. IMMDeviceEnumerator *pEnumerator = NULL;
  121. IMMDeviceCollection *pEndpoints = NULL;
  122. HRESULT hr;
  123. hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&pEnumerator);
  124. if (FAILED(hr))
  125. goto on_error;
  126. hr = pEnumerator->lpVtbl->EnumAudioEndpoints(pEnumerator, eDataFlow, DEVICE_STATE_ACTIVE, (void**)&pEndpoints);
  127. if (FAILED(hr))
  128. goto on_error;
  129. hr = pEndpoints->lpVtbl->GetCount(pEndpoints, uDevCount);
  130. if (FAILED(hr))
  131. goto on_error;
  132. on_error:
  133. if (pEndpoints)
  134. pEndpoints->lpVtbl->Release(pEndpoints);
  135. if (pEnumerator)
  136. pEnumerator->lpVtbl->Release(pEnumerator);
  137. return hr;
  138. }
  139. static HRESULT EnumDevice(EDataFlow eDataFlow, UINT uNumElements, AUDIO_DEVICE_INFO *pDevicInfo)
  140. {
  141. IMMDeviceEnumerator *pEnumerator = NULL;
  142. IMMDeviceCollection *pEndpoints = NULL;
  143. HRESULT hr;
  144. UINT uCount;
  145. UINT uIdx;
  146. hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&pEnumerator);
  147. if (FAILED(hr))
  148. goto on_error;
  149. hr = pEnumerator->lpVtbl->EnumAudioEndpoints(pEnumerator, eDataFlow, DEVICE_STATE_ACTIVE, (void**)&pEndpoints);
  150. if (FAILED(hr))
  151. goto on_error;
  152. hr = pEndpoints->lpVtbl->GetCount(pEndpoints, &uCount);
  153. if (FAILED(hr))
  154. goto on_error;
  155. ZeroMemory(pDevicInfo, sizeof(AUDIO_DEVICE_INFO)*uNumElements);
  156. for (uIdx = 0; uIdx < uCount && uIdx < uNumElements; ++uIdx) {
  157. IMMDevice *pDevice = NULL;
  158. IPropertyStore *pPS = NULL;
  159. WCHAR* pszDeviceId = NULL;
  160. PROPVARIANT value;
  161. PropVariantInit(&value);
  162. pEndpoints->lpVtbl->Item(pEndpoints, uIdx, &pDevice);
  163. pDevice->lpVtbl->GetId(pDevice, &pszDeviceId);
  164. pDevice->lpVtbl->OpenPropertyStore(pDevice, STGM_READ, &pPS);
  165. pPS->lpVtbl->GetValue(pPS, &PKEY_Device_FriendlyName, &value);
  166. WideCharToMultiByte(CP_ACP, 0, pszDeviceId, -1, pDevicInfo[uIdx].szDeviceID, MAX_STR_LEN-1, NULL, NULL);
  167. WideCharToMultiByte(CP_ACP, 0, value.pwszVal, -1, pDevicInfo[uIdx].szDeviceName, MAX_STR_LEN-1, NULL, NULL);
  168. PropVariantClear(&value);
  169. CoTaskMemFree(pszDeviceId);
  170. pPS->lpVtbl->Release(pPS);
  171. pDevice->lpVtbl->Release(pDevice);
  172. }
  173. on_error:
  174. if (pEndpoints)
  175. pEndpoints->lpVtbl->Release(pEndpoints);
  176. if (pEnumerator)
  177. pEnumerator->lpVtbl->Release(pEnumerator);
  178. return hr;
  179. }
  180. static int get_device_index(int indev, const char *key)
  181. {
  182. EDataFlow df = indev ? eCapture : eRender;
  183. UINT i;
  184. UINT n;
  185. AUDIO_DEVICE_INFO *pInfo = NULL;
  186. GetDeviceNum(df, &n);
  187. pInfo = malloc(sizeof(AUDIO_DEVICE_INFO) * n);
  188. EnumDevice(df, n, pInfo);
  189. for (i = 0; i < n; ++i) {
  190. if (strstr(pInfo[i].szDeviceName, key)) {
  191. free(pInfo);
  192. return i;
  193. }
  194. }
  195. free(pInfo);
  196. return -1;
  197. }
  198. static void show_audio_dev2()
  199. {
  200. UINT i;
  201. UINT n;
  202. AUDIO_DEVICE_INFO *pInfo = NULL;
  203. GetDeviceNum(eCapture, &n);
  204. pInfo = malloc(sizeof(AUDIO_DEVICE_INFO) * n);
  205. EnumDevice(eCapture, n, pInfo);
  206. printf("audio input devices -- win7 (%d):\n", n);
  207. for (i = 0; i < n; ++i) {
  208. printf("%d = %s\n", i, pInfo[i].szDeviceName);
  209. }
  210. free(pInfo);
  211. GetDeviceNum(eRender, &n);
  212. pInfo = malloc(sizeof(AUDIO_DEVICE_INFO) * n);
  213. EnumDevice(eRender, n, pInfo);
  214. printf("audio output devices -- win7 (%d):\n", n);
  215. for (i = 0; i < n; ++i) {
  216. printf("%d = %s\n", i, pInfo[i].szDeviceName);
  217. }
  218. free(pInfo);
  219. }
  220. static int Bin2Str(unsigned char *x, int xlen, char *str, int str_size)
  221. {
  222. static const char *hex2char = "0123456789ABCDEF";
  223. int i, k = 0;
  224. if (str_size <= xlen * 2)
  225. return -1;
  226. for (i = 0; i < xlen; ++i) {
  227. int h = x[i] >> 4;
  228. int l = x[i] & 0xf;
  229. str[k++] = hex2char[h];
  230. str[k++] = hex2char[l];
  231. }
  232. str[k] = 0;
  233. return k;
  234. }
  235. static void show_video_dev()
  236. {
  237. int i, n;
  238. n = videocap_get_device_count();
  239. printf("video devices(%d):\n", n);
  240. for (i = 0; i < n; ++i) {
  241. WCHAR tmp[256];
  242. char t[256];
  243. videocap_get_device_name(i, tmp, ARRAYSIZE(tmp));
  244. WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
  245. printf("%d = %s;", i, t);
  246. videocap_get_device_path(i, tmp, ARRAYSIZE(tmp));
  247. WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
  248. {
  249. unsigned char x[MD5_DIGESTSIZE];
  250. md5_ctx_t ctx;
  251. md5_init(&ctx);
  252. md5(x, t, strlen(t));
  253. Bin2Str(x, sizeof(x), t, sizeof(t));
  254. }
  255. printf("%s\n", t);
  256. }
  257. printf("\n");
  258. }
  259. static void __dummy_log_callback(const char *log)
  260. {
  261. }
  262. static int app_init()
  263. {
  264. HRESULT hret = CoInitialize(NULL);
  265. Pa_Initialize();
  266. //PaUtil_SetDebugPrintFunction(&__dummy_log_callback);
  267. audioframework_init();
  268. videoframework_init();
  269. return 0;
  270. }
  271. static void app_term()
  272. {
  273. videoframework_term();
  274. audioframework_term();
  275. CoUninitialize();
  276. Pa_Terminate();
  277. }
  278. int main()
  279. {
  280. printf("%s\n", setlocale(LC_ALL, "chs"));
  281. {
  282. HMODULE hModule = GetModuleHandleA("MSVCR100.dll");
  283. if (hModule) {
  284. typedef char* (*f_setlocale)(int, const char*);
  285. f_setlocale f = (f_setlocale)GetProcAddress(hModule, "setlocale");
  286. (*f)(LC_ALL, "chs");
  287. }
  288. }
  289. if (app_init() != 0) {
  290. printf("app init failed!\n");
  291. return -1;
  292. }
  293. show_audio_dev();
  294. show_video_dev();
  295. //MessageBoxA(0,0,0,0);
  296. //show_audio_dev2();
  297. //getchar();
  298. app_term();
  299. return 0;
  300. }