Leaked source code of windows server 2003
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.

716 lines
19 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // wavmixer.c - wav mixer functions
  24. ////
  25. #include "winlocal.h"
  26. #include <mmsystem.h>
  27. #include "wavmixer.h"
  28. #include "calc.h"
  29. #include "mem.h"
  30. #include "trace.h"
  31. ////
  32. // private definitions
  33. ////
  34. // wavmixer control struct
  35. //
  36. typedef struct WAVMIXER
  37. {
  38. DWORD dwVersion;
  39. HINSTANCE hInst;
  40. HTASK hTask;
  41. HMIXER hMixer;
  42. UINT nLastError;
  43. DWORD dwFlags;
  44. } WAVMIXER, FAR *LPWAVMIXER;
  45. #define VOLUME_MINLEVEL 0
  46. #define VOLUME_MAXLEVEL 100
  47. #define VOLUME_POSITIONS (VOLUME_MAXLEVEL - VOLUME_MINLEVEL)
  48. #define WAVMIXER_SUPPORTSVOLUME 0x00000001
  49. #define WAVMIXER_GETVOLUME 0x00000002
  50. #define WAVMIXER_SETVOLUME 0x00000004
  51. #define LEVEL_MINLEVEL 0
  52. #define LEVEL_MAXLEVEL 100
  53. #define LEVEL_POSITIONS (LEVEL_MAXLEVEL - LEVEL_MINLEVEL)
  54. #define WAVMIXER_SUPPORTSLEVEL 0x00000001
  55. #define WAVMIXER_GETLEVEL 0x00000002
  56. // helper functions
  57. //
  58. static int WINAPI WavMixerVolume(HWAVMIXER hWavMixer, LPINT lpnLevel, DWORD dwFlags);
  59. static int WINAPI WavMixerLevel(HWAVMIXER hWavMixer, LPINT lpnLevel, DWORD dwFlags);
  60. static LPWAVMIXER WavMixerGetPtr(HWAVMIXER hWavMixer);
  61. static HWAVMIXER WavMixerGetHandle(LPWAVMIXER lpWavMixer);
  62. ////
  63. // public functions
  64. ////
  65. // WavMixerInit - initialize wav mixer device
  66. // <dwVersion> (i) must be WAVMIXER_VERSION
  67. // <hInst> (i) instance handle of calling module
  68. // <lParam> (i) device id or handle, as specified by <dwFlags>
  69. // <dwReserved1> (i) reserved; must be 0;
  70. // <dwReserved2> (i) reserved; must be 0;
  71. // <dwFlags> (i) control flags
  72. // WAVMIXER_HWAVEIN <lParam> contains an HWAVEIN
  73. // WAVMIXER_HWAVEOUT <lParam> contains an HWAVEOUT
  74. // WAVMIXER_WAVEIN <lParam> contains a wav input device id
  75. // WAVMIXER_WAVEOUT <lParam> contains a wav output device id
  76. // return handle (NULL if error)
  77. //
  78. HWAVMIXER WINAPI WavMixerInit(DWORD dwVersion, HINSTANCE hInst,
  79. LPARAM lParam, DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags)
  80. {
  81. BOOL fSuccess = TRUE;
  82. LPWAVMIXER lpWavMixer = NULL;
  83. if (dwVersion != WAVMIXER_VERSION)
  84. fSuccess = TraceFALSE(NULL);
  85. else if (hInst == NULL)
  86. fSuccess = TraceFALSE(NULL);
  87. else if ((lpWavMixer = (LPWAVMIXER) MemAlloc(NULL, sizeof(WAVMIXER), 0)) == NULL)
  88. fSuccess = TraceFALSE(NULL);
  89. else
  90. {
  91. UINT uMxId = (UINT) lParam;
  92. DWORD fdwOpen = 0;
  93. UINT nLastError;
  94. lpWavMixer->dwVersion = dwVersion;
  95. lpWavMixer->hInst = hInst;
  96. lpWavMixer->hTask = GetCurrentTask();
  97. lpWavMixer->hMixer = NULL;
  98. lpWavMixer->nLastError = 0;
  99. lpWavMixer->dwFlags = dwFlags;
  100. if (dwFlags & WAVMIXER_HWAVEIN)
  101. fdwOpen |= MIXER_OBJECTF_HWAVEIN;
  102. if (dwFlags & WAVMIXER_HWAVEOUT)
  103. fdwOpen |= MIXER_OBJECTF_HWAVEOUT;
  104. if (dwFlags & WAVMIXER_WAVEIN)
  105. fdwOpen |= MIXER_OBJECTF_WAVEIN;
  106. if (dwFlags & WAVMIXER_WAVEOUT)
  107. fdwOpen |= MIXER_OBJECTF_WAVEOUT;
  108. // open the mixer device
  109. //
  110. if ((nLastError = mixerOpen(&lpWavMixer->hMixer, uMxId, 0L, 0L, fdwOpen)) != MMSYSERR_NOERROR)
  111. {
  112. fSuccess = TraceFALSE(NULL);
  113. TracePrintf_1(NULL, 5,
  114. TEXT("mixerOpen failed (%u)\n"),
  115. (unsigned) nLastError);
  116. }
  117. }
  118. if (!fSuccess)
  119. {
  120. WavMixerTerm(WavMixerGetHandle(lpWavMixer));
  121. lpWavMixer = NULL;
  122. }
  123. return fSuccess ? WavMixerGetHandle(lpWavMixer) : NULL;
  124. }
  125. // WavMixerTerm - shut down wave mixer device
  126. // <hWavMixer> (i) handle returned from WavMixerInit
  127. // return 0 if success
  128. //
  129. int WINAPI WavMixerTerm(HWAVMIXER hWavMixer)
  130. {
  131. BOOL fSuccess = TRUE;
  132. LPWAVMIXER lpWavMixer;
  133. if ((lpWavMixer = WavMixerGetPtr(hWavMixer)) == NULL)
  134. fSuccess = TraceFALSE(NULL);
  135. else
  136. {
  137. if (lpWavMixer->hMixer != NULL)
  138. {
  139. UINT nLastError;
  140. if ((nLastError = mixerClose(lpWavMixer->hMixer)) != MMSYSERR_NOERROR)
  141. {
  142. fSuccess = TraceFALSE(NULL);
  143. TracePrintf_1(NULL, 5,
  144. TEXT("mixerClose failed (%u)\n"),
  145. (unsigned) nLastError);
  146. }
  147. else
  148. lpWavMixer->hMixer = NULL;
  149. }
  150. if ((lpWavMixer = MemFree(NULL, lpWavMixer)) != NULL)
  151. fSuccess = TraceFALSE(NULL);
  152. }
  153. return fSuccess ? 0 : -1;
  154. }
  155. // WavMixerSupportsVolume - return TRUE if device supports volume control
  156. // <hWavMixer> (i) handle returned from WavMixerInit
  157. // <dwFlags> (i) control flags
  158. // 0 reserved; must be zero
  159. // return TRUE if device supports volume control
  160. //
  161. BOOL WINAPI WavMixerSupportsVolume(HWAVMIXER hWavMixer, DWORD dwFlags)
  162. {
  163. if (WavMixerVolume(hWavMixer, NULL, WAVMIXER_SUPPORTSVOLUME) != 0)
  164. return FALSE;
  165. else
  166. return TRUE;
  167. }
  168. // WavMixerGetVolume - get current volume level
  169. // <hWavMixer> (i) handle returned from WavMixerInit
  170. // <dwFlags> (i) control flags
  171. // 0 reserved; must be zero
  172. // return volume level (0 minimum through 100 maximum, -1 if error)
  173. //
  174. int WINAPI WavMixerGetVolume(HWAVMIXER hWavMixer, DWORD dwFlags)
  175. {
  176. BOOL fSuccess = TRUE;
  177. int nLevel;
  178. if (WavMixerVolume(hWavMixer, &nLevel, WAVMIXER_GETVOLUME) != 0)
  179. fSuccess = TraceFALSE(NULL);
  180. return fSuccess ? nLevel : -1;
  181. }
  182. // WavMixerSetVolume - set current volume level
  183. // <hWavMixer> (i) handle returned from WavMixerInit
  184. // <nLevel> (i) volume level
  185. // 0 minimum volume
  186. // 100 maximum volume
  187. // <dwFlags> (i) control flags
  188. // 0 reserved; must be zero
  189. // return new volume level (0 minimum through 100 maximum, -1 if error)
  190. //
  191. int WINAPI WavMixerSetVolume(HWAVMIXER hWavMixer, int nLevel, DWORD dwFlags)
  192. {
  193. BOOL fSuccess = TRUE;
  194. if (WavMixerVolume(hWavMixer, &nLevel, WAVMIXER_SETVOLUME) != 0)
  195. fSuccess = TraceFALSE(NULL);
  196. return fSuccess ? nLevel : -1;
  197. }
  198. static int WINAPI WavMixerVolume(HWAVMIXER hWavMixer, LPINT lpnLevel, DWORD dwFlags)
  199. {
  200. BOOL fSuccess = TRUE;
  201. LPWAVMIXER lpWavMixer;
  202. LPMIXERCONTROL lpmxc = NULL;
  203. //
  204. // We have to initialize local variable
  205. //
  206. UINT nLastError;
  207. MIXERLINE mxlDst;
  208. MIXERLINE mxlSrc;
  209. BOOL fWaveIn = FALSE;
  210. if ((lpWavMixer = WavMixerGetPtr(hWavMixer)) == NULL)
  211. fSuccess = TraceFALSE(NULL);
  212. else if ((lpmxc = (LPMIXERCONTROL) MemAlloc(NULL, sizeof(MIXERCONTROL), 0)) == NULL)
  213. fSuccess = TraceFALSE(NULL);
  214. // get info for the destination line
  215. //
  216. if (fSuccess)
  217. {
  218. if ((lpWavMixer->dwFlags & WAVMIXER_WAVEIN) ||
  219. (lpWavMixer->dwFlags & WAVMIXER_HWAVEIN))
  220. fWaveIn = TRUE;
  221. mxlDst.cbStruct = sizeof(mxlDst);
  222. mxlDst.dwComponentType = fWaveIn ?
  223. MIXERLINE_COMPONENTTYPE_DST_WAVEIN :
  224. MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
  225. if ((nLastError = mixerGetLineInfo((HMIXEROBJ) lpWavMixer->hMixer, &mxlDst,
  226. MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE)) != MMSYSERR_NOERROR)
  227. {
  228. fSuccess = TraceFALSE(NULL);
  229. TracePrintf_1(NULL, 5,
  230. TEXT("mixerGetLineInfo failed (%u)\n"),
  231. (unsigned) nLastError);
  232. }
  233. }
  234. // find appropriate source line connected to this destination line
  235. //
  236. if (fSuccess)
  237. {
  238. DWORD dwSource;
  239. for (dwSource = 0; fSuccess && dwSource < mxlDst.cConnections; ++dwSource)
  240. {
  241. mxlSrc.cbStruct = sizeof(mxlSrc);
  242. mxlSrc.dwSource = dwSource;
  243. mxlSrc.dwDestination = mxlDst.dwDestination;
  244. if ((nLastError = mixerGetLineInfo((HMIXEROBJ) lpWavMixer->hMixer, &mxlSrc,
  245. MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE)) != MMSYSERR_NOERROR)
  246. {
  247. fSuccess = TraceFALSE(NULL);
  248. TracePrintf_1(NULL, 5,
  249. TEXT("mixerGetLineInfo failed (%u)\n"),
  250. (unsigned) nLastError);
  251. }
  252. else if (mxlSrc.dwComponentType == (DWORD) (fWaveIn ?
  253. MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE :
  254. MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT))
  255. {
  256. // source line found
  257. //
  258. break;
  259. }
  260. }
  261. if (dwSource == mxlDst.cConnections)
  262. {
  263. // unable to find source line
  264. //
  265. fSuccess = TraceFALSE(NULL);
  266. }
  267. }
  268. // find volume control, if any, of the appropriate line
  269. //
  270. if (fSuccess)
  271. {
  272. MIXERLINECONTROLS mxlc;
  273. mxlc.cbStruct = sizeof(mxlc);
  274. mxlc.dwLineID = (fWaveIn ? mxlSrc.dwLineID : mxlDst.dwLineID);
  275. mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
  276. mxlc.cControls = 1;
  277. mxlc.cbmxctrl = sizeof(MIXERCONTROL);
  278. mxlc.pamxctrl = lpmxc;
  279. if ((nLastError = mixerGetLineControls((HMIXEROBJ) lpWavMixer->hMixer, &mxlc,
  280. MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE)) != MMSYSERR_NOERROR)
  281. {
  282. fSuccess = TraceFALSE(NULL);
  283. TracePrintf_1(NULL, 5,
  284. TEXT("mixerGetLineControls failed (%u)\n"),
  285. (unsigned) nLastError);
  286. }
  287. }
  288. // get and/or set current volume level
  289. //
  290. if (fSuccess &&
  291. ((dwFlags & WAVMIXER_GETVOLUME) || (dwFlags & WAVMIXER_SETVOLUME)))
  292. {
  293. LPMIXERCONTROLDETAILS_UNSIGNED lpmxcdu = NULL;
  294. MIXERCONTROLDETAILS mxcd;
  295. DWORD cChannels = mxlSrc.cChannels;
  296. DWORD dwVolume;
  297. int nLevel;
  298. if (lpmxc->fdwControl & MIXERCONTROL_CONTROLF_UNIFORM)
  299. cChannels = 1;
  300. if ((lpmxcdu = (LPMIXERCONTROLDETAILS_UNSIGNED) MemAlloc(NULL,
  301. cChannels * sizeof(MIXERCONTROLDETAILS_UNSIGNED), 0)) == NULL)
  302. {
  303. fSuccess = TraceFALSE(NULL);
  304. }
  305. else
  306. {
  307. mxcd.cbStruct = sizeof(mxcd);
  308. mxcd.dwControlID = lpmxc->dwControlID;
  309. mxcd.cChannels = cChannels;
  310. mxcd.hwndOwner = (HWND) NULL;
  311. mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
  312. mxcd.paDetails = (LPVOID) lpmxcdu;
  313. if ((nLastError = mixerGetControlDetails((HMIXEROBJ) lpWavMixer->hMixer, &mxcd,
  314. MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE)) != MMSYSERR_NOERROR)
  315. {
  316. fSuccess = TraceFALSE(NULL);
  317. TracePrintf_1(NULL, 5,
  318. TEXT("mixerGetControlDetails failed (%u)\n"),
  319. (unsigned) nLastError);
  320. }
  321. else
  322. dwVolume = lpmxcdu[0].dwValue;
  323. }
  324. if (fSuccess && (dwFlags & WAVMIXER_SETVOLUME))
  325. {
  326. if (lpnLevel != NULL)
  327. nLevel = *lpnLevel;
  328. // convert signed level (0 - 100) to unsigned volume (0 - 65535)
  329. //
  330. dwVolume = nLevel * (0xFFFF / VOLUME_POSITIONS);
  331. lpmxcdu[0].dwValue = lpmxcdu[cChannels - 1].dwValue = dwVolume;
  332. TracePrintf_2(NULL, 5,
  333. TEXT("WavMixerSetVolume() = %d, 0x%08lX\n"),
  334. (int) nLevel,
  335. (unsigned long) dwVolume);
  336. if ((nLastError = mixerSetControlDetails((HMIXEROBJ) lpWavMixer->hMixer, &mxcd,
  337. MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE)) != MMSYSERR_NOERROR)
  338. {
  339. fSuccess = TraceFALSE(NULL);
  340. TracePrintf_1(NULL, 5,
  341. TEXT("mixerSetControlDetails failed (%u)\n"),
  342. (unsigned) nLastError);
  343. }
  344. #if 1
  345. // save new volume to pass back
  346. //
  347. else if ((nLastError = mixerGetControlDetails((HMIXEROBJ) lpWavMixer->hMixer, &mxcd,
  348. MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE)) != MMSYSERR_NOERROR)
  349. {
  350. fSuccess = TraceFALSE(NULL);
  351. TracePrintf_1(NULL, 5,
  352. TEXT("mixerGetControlDetails failed (%u)\n"),
  353. (unsigned) nLastError);
  354. }
  355. else
  356. dwVolume = lpmxcdu[0].dwValue;
  357. #endif
  358. }
  359. if (fSuccess &&
  360. #if 1
  361. ((dwFlags & WAVMIXER_GETVOLUME) || (dwFlags & WAVMIXER_SETVOLUME)))
  362. #else
  363. (dwFlags & WAVMIXER_GETVOLUME))
  364. #endif
  365. {
  366. // convert unsigned volume (0 - 65535) to signed level (0 - 100)
  367. //
  368. nLevel = LOWORD(dwVolume) / (0xFFFF / VOLUME_POSITIONS);
  369. if (lpnLevel != NULL)
  370. *lpnLevel = nLevel;
  371. TracePrintf_2(NULL, 5,
  372. TEXT("WavMixerGetVolume() = %d, 0x%08lX\n"),
  373. (int) nLevel,
  374. (unsigned long) dwVolume);
  375. }
  376. if (lpmxcdu != NULL && (lpmxcdu = MemFree(NULL, lpmxcdu)) != NULL)
  377. fSuccess = TraceFALSE(NULL);
  378. }
  379. // clean up
  380. //
  381. if (lpmxc != NULL && (lpmxc = MemFree(NULL, lpmxc)) != NULL)
  382. fSuccess = TraceFALSE(NULL);
  383. if (hWavMixer != NULL && lpWavMixer != NULL)
  384. lpWavMixer->nLastError = nLastError;
  385. return fSuccess ? 0 : -1;
  386. }
  387. // WavMixerSupportsLevel - return TRUE if device supports peak meter level
  388. // <hWavMixer> (i) handle returned from WavMixerInit
  389. // <dwFlags> (i) control flags
  390. // 0 reserved; must be zero
  391. // return TRUE if device supports peak meter level
  392. //
  393. BOOL WINAPI WavMixerSupportsLevel(HWAVMIXER hWavMixer, DWORD dwFlags)
  394. {
  395. if (WavMixerLevel(hWavMixer, NULL, WAVMIXER_SUPPORTSLEVEL) != 0)
  396. return FALSE;
  397. else
  398. return TRUE;
  399. }
  400. // WavMixerGetLevel - get current peak meter level
  401. // <hWavMixer> (i) handle returned from WavMixerInit
  402. // <dwFlags> (i) control flags
  403. // 0 reserved; must be zero
  404. // return peak meter level (0 minimum through 100 maximum, -1 if error)
  405. //
  406. int WINAPI WavMixerGetLevel(HWAVMIXER hWavMixer, DWORD dwFlags)
  407. {
  408. BOOL fSuccess = TRUE;
  409. int nLevel;
  410. if (WavMixerLevel(hWavMixer, &nLevel, WAVMIXER_GETLEVEL) != 0)
  411. fSuccess = TraceFALSE(NULL);
  412. return fSuccess ? nLevel : -1;
  413. }
  414. static int WINAPI WavMixerLevel(HWAVMIXER hWavMixer, LPINT lpnLevel, DWORD dwFlags)
  415. {
  416. BOOL fSuccess = TRUE;
  417. LPWAVMIXER lpWavMixer;
  418. LPMIXERCONTROL lpmxc = NULL;
  419. //
  420. // Initialize local variable
  421. //
  422. UINT nLastError = 0;
  423. MIXERLINE mxlDst;
  424. MIXERLINE mxlSrc;
  425. BOOL fWaveIn = FALSE;
  426. if ((lpWavMixer = WavMixerGetPtr(hWavMixer)) == NULL)
  427. fSuccess = TraceFALSE(NULL);
  428. else if ((lpmxc = (LPMIXERCONTROL) MemAlloc(NULL, sizeof(MIXERCONTROL), 0)) == NULL)
  429. fSuccess = TraceFALSE(NULL);
  430. // get info for the destination line
  431. //
  432. if (fSuccess)
  433. {
  434. if ((lpWavMixer->dwFlags & WAVMIXER_WAVEIN) ||
  435. (lpWavMixer->dwFlags & WAVMIXER_HWAVEIN))
  436. fWaveIn = TRUE;
  437. mxlDst.cbStruct = sizeof(mxlDst);
  438. mxlDst.dwComponentType = fWaveIn ?
  439. MIXERLINE_COMPONENTTYPE_DST_WAVEIN :
  440. MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
  441. if ((nLastError = mixerGetLineInfo((HMIXEROBJ) lpWavMixer->hMixer, &mxlDst,
  442. MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE)) != MMSYSERR_NOERROR)
  443. {
  444. fSuccess = TraceFALSE(NULL);
  445. TracePrintf_1(NULL, 5,
  446. TEXT("mixerGetLineInfo failed (%u)\n"),
  447. (unsigned) nLastError);
  448. }
  449. }
  450. // find appropriate source line connected to this destination line
  451. //
  452. if (fSuccess)
  453. {
  454. DWORD dwSource;
  455. for (dwSource = 0; fSuccess && dwSource < mxlDst.cConnections; ++dwSource)
  456. {
  457. mxlSrc.cbStruct = sizeof(mxlSrc);
  458. mxlSrc.dwSource = dwSource;
  459. mxlSrc.dwDestination = mxlDst.dwDestination;
  460. if ((nLastError = mixerGetLineInfo((HMIXEROBJ) lpWavMixer->hMixer, &mxlSrc,
  461. MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE)) != MMSYSERR_NOERROR)
  462. {
  463. fSuccess = TraceFALSE(NULL);
  464. TracePrintf_1(NULL, 5,
  465. TEXT("mixerGetLineInfo failed (%u)\n"),
  466. (unsigned) nLastError);
  467. }
  468. else if (mxlSrc.dwComponentType == (DWORD) (fWaveIn ?
  469. MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE :
  470. MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT))
  471. {
  472. // source line found
  473. //
  474. break;
  475. }
  476. }
  477. if (dwSource == mxlDst.cConnections)
  478. {
  479. // unable to find source line
  480. //
  481. fSuccess = TraceFALSE(NULL);
  482. }
  483. }
  484. // find peak meter control, if any, of the appropriate line
  485. //
  486. if (fSuccess)
  487. {
  488. MIXERLINECONTROLS mxlc;
  489. mxlc.cbStruct = sizeof(mxlc);
  490. mxlc.dwLineID = (fWaveIn ? mxlDst.dwLineID : mxlSrc.dwLineID);
  491. mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER;
  492. mxlc.cControls = 1;
  493. mxlc.cbmxctrl = sizeof(MIXERCONTROL);
  494. mxlc.pamxctrl = lpmxc;
  495. if ((nLastError = mixerGetLineControls((HMIXEROBJ) lpWavMixer->hMixer, &mxlc,
  496. MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE)) != MMSYSERR_NOERROR)
  497. {
  498. fSuccess = TraceFALSE(NULL);
  499. TracePrintf_1(NULL, 5,
  500. TEXT("mixerGetLineControls failed (%u)\n"),
  501. (unsigned) nLastError);
  502. }
  503. }
  504. // get current peak meter level
  505. //
  506. if (fSuccess && (dwFlags & WAVMIXER_GETLEVEL))
  507. {
  508. LPMIXERCONTROLDETAILS_SIGNED lpmxcds = NULL;
  509. MIXERCONTROLDETAILS mxcd;
  510. DWORD cChannels = mxlDst.cChannels;
  511. DWORD dwLevel;
  512. int nLevel;
  513. if (lpmxc->fdwControl & MIXERCONTROL_CONTROLF_UNIFORM)
  514. cChannels = 1;
  515. if ((lpmxcds = (LPMIXERCONTROLDETAILS_SIGNED) MemAlloc(NULL,
  516. cChannels * sizeof(MIXERCONTROLDETAILS_SIGNED), 0)) == NULL)
  517. {
  518. fSuccess = TraceFALSE(NULL);
  519. }
  520. else
  521. {
  522. mxcd.cbStruct = sizeof(mxcd);
  523. mxcd.dwControlID = lpmxc->dwControlID;
  524. mxcd.cChannels = cChannels;
  525. mxcd.hwndOwner = (HWND) NULL;
  526. mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_SIGNED);
  527. mxcd.paDetails = (LPVOID) lpmxcds;
  528. if ((nLastError = mixerGetControlDetails((HMIXEROBJ) lpWavMixer->hMixer, &mxcd,
  529. MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE)) != MMSYSERR_NOERROR)
  530. {
  531. fSuccess = TraceFALSE(NULL);
  532. TracePrintf_1(NULL, 5,
  533. TEXT("mixerGetControlDetails failed (%u)\n"),
  534. (unsigned) nLastError);
  535. }
  536. else
  537. {
  538. // convert signed level to unsigned level
  539. //
  540. dwLevel = lpmxcds[0].lValue - 0; // lpmxc->Bounds.lMinimum;
  541. dwLevel *= 2;
  542. }
  543. }
  544. // convert unsigned level (0 - 65535) to signed level (0 - 100)
  545. //
  546. nLevel = LOWORD(dwLevel) / (0xFFFF / LEVEL_POSITIONS);
  547. if (lpnLevel != NULL)
  548. *lpnLevel = nLevel;
  549. //
  550. // We have to verify lpmxcds pointer
  551. //
  552. TracePrintf_3(NULL, 5,
  553. TEXT("WavMixerGetLevel() = %d, %ld, 0x%08lX\n"),
  554. (int) nLevel,
  555. lpmxcds ? lpmxcds[0].lValue : 0,
  556. (unsigned long) dwLevel);
  557. if (lpmxcds != NULL && (lpmxcds = MemFree(NULL, lpmxcds)) != NULL)
  558. fSuccess = TraceFALSE(NULL);
  559. }
  560. // clean up
  561. //
  562. if (lpmxc != NULL && (lpmxc = MemFree(NULL, lpmxc)) != NULL)
  563. fSuccess = TraceFALSE(NULL);
  564. if (hWavMixer != NULL && lpWavMixer != NULL)
  565. lpWavMixer->nLastError = nLastError;
  566. return fSuccess ? 0 : -1;
  567. }
  568. ////
  569. // helper functions
  570. ////
  571. // WavMixerGetPtr - verify that wavmixer handle is valid,
  572. // <hWavMixer> (i) handle returned from WavMixerInit
  573. // return corresponding wavmixer pointer (NULL if error)
  574. //
  575. static LPWAVMIXER WavMixerGetPtr(HWAVMIXER hWavMixer)
  576. {
  577. BOOL fSuccess = TRUE;
  578. LPWAVMIXER lpWavMixer;
  579. if ((lpWavMixer = (LPWAVMIXER) hWavMixer) == NULL)
  580. fSuccess = TraceFALSE(NULL);
  581. else if (IsBadWritePtr(lpWavMixer, sizeof(WAVMIXER)))
  582. fSuccess = TraceFALSE(NULL);
  583. #ifdef CHECKTASK
  584. // make sure current task owns the wavmixer handle
  585. //
  586. else if (lpWavMixer->hTask != GetCurrentTask())
  587. fSuccess = TraceFALSE(NULL);
  588. #endif
  589. return fSuccess ? lpWavMixer : NULL;
  590. }
  591. // WavMixerGetHandle - verify that wavmixer pointer is valid,
  592. // <lpWavMixer> (i) pointer to WAVMIXER struct
  593. // return corresponding wavmixer handle (NULL if error)
  594. //
  595. static HWAVMIXER WavMixerGetHandle(LPWAVMIXER lpWavMixer)
  596. {
  597. BOOL fSuccess = TRUE;
  598. //
  599. // we have to initialize local variable
  600. //
  601. HWAVMIXER hWavMixer = NULL;
  602. if ((hWavMixer = (HWAVMIXER) lpWavMixer) == NULL)
  603. fSuccess = TraceFALSE(NULL);
  604. return fSuccess ? hWavMixer : NULL;
  605. }