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.

485 lines
19 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: MixLine.cpp
  6. * Content: Class for managing the mixerLine API.
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 11/30/99 rodtoll Created based on source from dsound
  12. * 01/24/2000 rodtoll Mirroring changes from dsound bug #128264
  13. *
  14. ***************************************************************************/
  15. #include "dxvutilspch.h"
  16. #undef DPF_SUBCOMP
  17. #define DPF_SUBCOMP DN_SUBCOMP_VOICE
  18. #define DVF_MIXERLINE_PROCEDURE_DEBUG_LEVEL DVF_INFOLEVEL
  19. #define DPFLVL_INFO 5
  20. #define DPF_MIXER DPFX
  21. #undef DPF_MODNAME
  22. #define DPF_MODNAME "CMixerLine::CMixerLine"
  23. CMixerLine::CMixerLine(
  24. ): m_fAcquiredVolCtrl(FALSE),
  25. m_pmxMuxFlags(NULL),
  26. m_dwRangeMin(0),
  27. m_dwRangeSize(0xFFFF),
  28. m_uWaveDeviceId(0),
  29. m_pfMicValue(NULL)
  30. {
  31. ZeroMemory( &m_mxcdMasterVol, sizeof( MIXERCONTROLDETAILS ) );
  32. ZeroMemory( &m_mxcdMasterMute, sizeof( MIXERCONTROLDETAILS ) );
  33. ZeroMemory( &m_mxcdMasterMux, sizeof( MIXERCONTROLDETAILS ) );
  34. ZeroMemory( &m_mxcdMicVol, sizeof( MIXERCONTROLDETAILS ) );
  35. ZeroMemory( &m_mxcdMicMute, sizeof( MIXERCONTROLDETAILS ) );
  36. ZeroMemory( &m_mxVolume, sizeof( MIXERCONTROLDETAILS_UNSIGNED ) );
  37. ZeroMemory( &m_mxMute, sizeof( MIXERCONTROLDETAILS_BOOLEAN ) );
  38. }
  39. #undef DPF_MODNAME
  40. #define DPF_MODNAME "CMixerLine::~CMixerLine"
  41. CMixerLine::~CMixerLine()
  42. {
  43. if( m_pmxMuxFlags != NULL )
  44. {
  45. delete [] m_pmxMuxFlags;
  46. }
  47. }
  48. #undef DPF_MODNAME
  49. #define DPF_MODNAME "CMixerLine::Initialize"
  50. HRESULT CMixerLine::Initialize( UINT uiDeviceID )
  51. {
  52. if( m_fAcquiredVolCtrl )
  53. {
  54. DPFX(DPFPREP, DVF_ERRORLEVEL, "Initialize has not been called" );
  55. return DVERR_INITIALIZED;
  56. }
  57. m_uWaveDeviceId = uiDeviceID;
  58. // Set up the master waveIn destination mixer line
  59. MIXERLINE mxMastLine;
  60. ZeroMemory(&mxMastLine, sizeof mxMastLine);
  61. mxMastLine.cbStruct = sizeof mxMastLine;
  62. mxMastLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
  63. // Set up the microphone source line
  64. MIXERLINE mxMicLine;
  65. ZeroMemory(&mxMicLine, sizeof mxMicLine);
  66. // Set up the mixer-line control structure
  67. MIXERCONTROL mxCtrl;
  68. ZeroMemory(&mxCtrl, sizeof mxCtrl);
  69. mxCtrl.cbStruct = sizeof mxCtrl;
  70. // Set up the 1-element array of controls
  71. MIXERLINECONTROLS mxLineCtrls;
  72. ZeroMemory(&mxLineCtrls, sizeof mxLineCtrls);
  73. mxLineCtrls.cbStruct = sizeof mxLineCtrls;
  74. mxLineCtrls.cControls = 1;
  75. mxLineCtrls.cbmxctrl = sizeof mxCtrl;
  76. mxLineCtrls.pamxctrl = &mxCtrl;
  77. // Set up the control details structures
  78. m_mxcdMasterVol.cbDetails = sizeof m_mxVolume;
  79. m_mxcdMasterVol.paDetails = &m_mxVolume;
  80. m_mxcdMasterVol.cChannels = 1;
  81. m_mxcdMasterMute.cbDetails = sizeof m_mxMute;
  82. m_mxcdMasterMute.paDetails = &m_mxMute;
  83. m_mxcdMasterMute.cChannels = 1;
  84. m_mxcdMicVol.cbDetails = sizeof m_mxVolume;
  85. m_mxcdMicVol.paDetails = &m_mxVolume;
  86. m_mxcdMicVol.cChannels = 1;
  87. m_mxcdMicMute.cbDetails = sizeof m_mxMute;
  88. m_mxcdMicMute.paDetails = &m_mxMute;
  89. m_mxcdMicMute.cChannels = 1;
  90. // We use the waveIn device ID instead of a "real" mixer device below
  91. HMIXEROBJ hMixObj;
  92. MMRESULT mmr = mixerGetID((HMIXEROBJ) ((UINT_PTR)m_uWaveDeviceId), (LPUINT)&hMixObj, MIXER_OBJECTF_WAVEIN);
  93. if (MMSYSERR_NOERROR == mmr)
  94. {
  95. DPF_MIXER(DPFPREP, DPFLVL_INFO, "mixerGetID failed.");
  96. }
  97. // Find the master recording destination line
  98. mmr = mixerGetLineInfo(hMixObj, &mxMastLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
  99. if (mmr == MMSYSERR_NOERROR)
  100. {
  101. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Found the master recording mixer line");
  102. // Look for a volume fader control on the master line
  103. mxLineCtrls.dwLineID = mxMastLine.dwLineID;
  104. mxLineCtrls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
  105. mmr = mixerGetLineControls(hMixObj, &mxLineCtrls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
  106. if (mmr == MMSYSERR_NOERROR)
  107. {
  108. // Found it - use the cbStruct field to flag success
  109. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Found a volume fader on the master line");
  110. m_mxcdMasterVol.cbStruct = sizeof m_mxcdMasterVol;
  111. m_mxcdMasterVol.dwControlID = mxCtrl.dwControlID;
  112. m_dwRangeMin = mxCtrl.Bounds.dwMinimum;
  113. m_dwRangeSize = mxCtrl.Bounds.dwMaximum - mxCtrl.Bounds.dwMinimum;
  114. mmr = mixerGetControlDetails(hMixObj, &m_mxcdMasterVol, MIXER_GETCONTROLDETAILSF_VALUE);
  115. }
  116. if (mmr != MMSYSERR_NOERROR)
  117. m_mxcdMasterVol.cbStruct = 0;
  118. // Look for a mute control on the master line
  119. mxLineCtrls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
  120. mmr = mixerGetLineControls(hMixObj, &mxLineCtrls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
  121. if (mmr == MMSYSERR_NOERROR)
  122. {
  123. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Found a mute control on the master line");
  124. m_mxcdMasterMute.cbStruct = sizeof m_mxcdMasterMute;
  125. m_mxcdMasterMute.dwControlID = mxCtrl.dwControlID;
  126. mmr = mixerGetControlDetails(hMixObj, &m_mxcdMasterMute, MIXER_GETCONTROLDETAILSF_VALUE);
  127. }
  128. if (mmr != MMSYSERR_NOERROR)
  129. m_mxcdMasterMute.cbStruct = 0;
  130. // Look for the microphone source line
  131. mxMicLine.cbStruct = sizeof mxMicLine;
  132. mxMicLine.dwDestination = mxMastLine.dwDestination;
  133. for (UINT i=0; i < mxMastLine.cConnections; ++i)
  134. {
  135. mxMicLine.dwSource = i;
  136. // Note: for some mysterious reason, I had to remove MIXER_OBJECTF_WAVEIN
  137. // from this call to mixerGetLineInfo() to make it work.
  138. mmr = mixerGetLineInfo(hMixObj, &mxMicLine, MIXER_GETLINEINFOF_SOURCE);
  139. if (mmr != MMSYSERR_NOERROR || mxMicLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
  140. break;
  141. }
  142. if (mxMicLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
  143. {
  144. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Found a microphone mixer line");
  145. // Look for a volume fader control on the mic line
  146. mxLineCtrls.dwLineID = mxMicLine.dwLineID;
  147. mxLineCtrls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
  148. mmr = mixerGetLineControls(hMixObj, &mxLineCtrls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
  149. if (mmr == MMSYSERR_NOERROR)
  150. {
  151. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Found a volume fader on the mic line");
  152. m_mxcdMicVol.cbStruct = sizeof m_mxcdMicVol;
  153. m_mxcdMicVol.dwControlID = mxCtrl.dwControlID;
  154. m_dwRangeMin = mxCtrl.Bounds.dwMinimum;
  155. m_dwRangeSize = mxCtrl.Bounds.dwMaximum - mxCtrl.Bounds.dwMinimum;
  156. mmr = mixerGetControlDetails(hMixObj, &m_mxcdMicVol, MIXER_GETCONTROLDETAILSF_VALUE);
  157. }
  158. if (mmr != MMSYSERR_NOERROR)
  159. m_mxcdMicVol.cbStruct = 0;
  160. // Look for a mute control on the mic line
  161. mxLineCtrls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
  162. mmr = mixerGetLineControls(hMixObj, &mxLineCtrls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
  163. if (mmr == MMSYSERR_NOERROR)
  164. {
  165. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Found a mute control on the mic line");
  166. m_mxcdMicMute.cbStruct = sizeof m_mxcdMicMute;
  167. m_mxcdMicMute.dwControlID = mxCtrl.dwControlID;
  168. mmr = mixerGetControlDetails(hMixObj, &m_mxcdMicMute, MIXER_GETCONTROLDETAILSF_VALUE);
  169. }
  170. if (mmr != MMSYSERR_NOERROR)
  171. m_mxcdMicMute.cbStruct = 0;
  172. // Look for a MUX or MIXER control on the master line
  173. mxLineCtrls.dwLineID = mxMastLine.dwLineID;
  174. mxLineCtrls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;
  175. m_fMasterMuxIsMux = TRUE;
  176. mmr = mixerGetLineControls(hMixObj, &mxLineCtrls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
  177. if (mmr != MMSYSERR_NOERROR)
  178. {
  179. mxLineCtrls.dwControlType = MIXERCONTROL_CONTROLTYPE_MIXER;
  180. m_fMasterMuxIsMux = FALSE;
  181. mmr = mixerGetLineControls(hMixObj, &mxLineCtrls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
  182. }
  183. if (mmr == MMSYSERR_NOERROR)
  184. {
  185. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Found an item list control on the master line");
  186. m_mxcdMasterMux.cbStruct = sizeof m_mxcdMasterMux;
  187. m_mxcdMasterMux.dwControlID = mxCtrl.dwControlID;
  188. m_mxcdMasterMux.cMultipleItems = mxCtrl.cMultipleItems;
  189. // We save the cChannels value, because some evil VxD drivers (read: Aureal
  190. // Vortex) will set it to 0 in the call to mixerGetControlDetails() below
  191. int nChannels = (mxCtrl.fdwControl & MIXERCONTROL_CONTROLF_UNIFORM) ? 1 : mxMastLine.cChannels;
  192. m_mxcdMasterMux.cChannels = nChannels;
  193. // Get the MUX or MIXER list items
  194. m_mxcdMasterMux.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT);
  195. MIXERCONTROLDETAILS_LISTTEXT *pList = new MIXERCONTROLDETAILS_LISTTEXT [ m_mxcdMasterMux.cbDetails * m_mxcdMasterMux.cChannels * mxCtrl.cMultipleItems ];
  196. if (pList != NULL)
  197. {
  198. m_mxcdMasterMux.paDetails = pList;
  199. mmr = mixerGetControlDetails(hMixObj, &m_mxcdMasterMux, MIXER_GETCONTROLDETAILSF_LISTTEXT);
  200. if (mmr == MMSYSERR_NOERROR)
  201. {
  202. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Got the list controls's LISTTEXT details");
  203. // Get the MUX or MIXER list values
  204. m_mxcdMasterMux.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
  205. m_mxcdMasterMux.cChannels = nChannels;
  206. m_pmxMuxFlags = new MIXERCONTROLDETAILS_BOOLEAN [ m_mxcdMasterMux.cbDetails * m_mxcdMasterMux.cChannels * mxCtrl.cMultipleItems ];
  207. if (m_pmxMuxFlags != NULL)
  208. {
  209. m_mxcdMasterMux.paDetails = m_pmxMuxFlags;
  210. mmr = mixerGetControlDetails(hMixObj, &m_mxcdMasterMux, MIXER_GETCONTROLDETAILSF_VALUE);
  211. if (mmr == MMSYSERR_NOERROR) // Enable the item corresponding to the mic line
  212. {
  213. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Got the list controls's VALUE details");
  214. for (UINT i=0; i < mxCtrl.cMultipleItems; ++i)
  215. {
  216. if (pList[i].dwParam1 == mxMicLine.dwLineID)
  217. m_pfMicValue = &m_pmxMuxFlags[i].fValue;
  218. else if (mxLineCtrls.dwControlType == MIXERCONTROL_CONTROLTYPE_MUX)
  219. m_pmxMuxFlags[i].fValue = FALSE;
  220. DPF_MIXER(DPFPREP, DPFLVL_INFO, "Set list item %d to %d", i, pList[i].dwParam1 == mxMicLine.dwLineID);
  221. }
  222. }
  223. }
  224. }
  225. delete[] pList;
  226. pList = NULL;
  227. }
  228. if (!m_pmxMuxFlags || !m_pfMicValue || mmr != MMSYSERR_NOERROR)
  229. m_mxcdMasterMux.cbStruct = 0;
  230. }
  231. }
  232. }
  233. // To be able to control the recording level, we minimally require
  234. // a volume fader on the master line or one on the microphone line:
  235. m_fAcquiredVolCtrl = m_mxcdMasterVol.cbStruct || m_mxcdMicVol.cbStruct;
  236. HRESULT hr = m_fAcquiredVolCtrl ? DS_OK : DSERR_CONTROLUNAVAIL;
  237. return hr;
  238. }
  239. #undef DPF_MODNAME
  240. #define DPF_MODNAME "CMixerLine::SetMicrophoneVolume"
  241. HRESULT CMixerLine::SetMicrophoneVolume( LONG lMicrophoneVolume )
  242. {
  243. if( !m_fAcquiredVolCtrl )
  244. {
  245. DPFX(DPFPREP, DVF_ERRORLEVEL, "Initialize has not been called" );
  246. return DVERR_NOTINITIALIZED;
  247. }
  248. MMRESULT mmr = MMSYSERR_NOTSUPPORTED; // Default return code
  249. // Set the microphone recording level control if available
  250. if (m_mxcdMicVol.cbStruct)
  251. {
  252. // Convert the DSBVOLUME level to an amplification factor from 0 to 0xFFFF
  253. m_mxVolume.dwValue = DBToAmpFactor(lMicrophoneVolume);
  254. // Adjust range if necessary
  255. if (m_dwRangeMin != 0 || m_dwRangeSize != 0xFFFF)
  256. m_mxVolume.dwValue = DWORD(m_dwRangeMin + m_dwRangeSize*double(m_mxVolume.dwValue)/0xFFFF);
  257. mmr = mixerSetControlDetails((HMIXEROBJ)((UINT_PTR)m_uWaveDeviceId),
  258. &m_mxcdMicVol, MIXER_OBJECTF_WAVEIN | MIXER_GETCONTROLDETAILSF_VALUE);
  259. }
  260. HRESULT hr = MMRESULTtoHRESULT(mmr);
  261. return hr;
  262. }
  263. #undef DPF_MODNAME
  264. #define DPF_MODNAME "CMixerLine::GetMicrophoneVolume"
  265. HRESULT CMixerLine::GetMicrophoneVolume( LPLONG plMicrophoneVolume )
  266. {
  267. if( !m_fAcquiredVolCtrl )
  268. {
  269. DPFX(DPFPREP, DVF_ERRORLEVEL, "Initialize has not been called" );
  270. return DVERR_NOTINITIALIZED;
  271. }
  272. MMRESULT mmr = MMSYSERR_NOTSUPPORTED; // Default return code
  273. DNASSERT(plMicrophoneVolume != NULL);
  274. // Get the microphone recording level if available
  275. if (m_mxcdMicVol.cbStruct != 0)
  276. {
  277. mmr = mixerGetControlDetails( (HMIXEROBJ)((UINT_PTR)m_uWaveDeviceId),
  278. &m_mxcdMicVol, MIXER_OBJECTF_WAVEIN | MIXER_GETCONTROLDETAILSF_VALUE);
  279. if (mmr == MMSYSERR_NOERROR)
  280. {
  281. DNASSERT(m_mxVolume.dwValue >= m_dwRangeMin && m_mxVolume.dwValue <= m_dwRangeMin + m_dwRangeSize);
  282. // Adjust range if necessary
  283. if (m_dwRangeMin != 0 || m_dwRangeSize != 0xFFFF)
  284. m_mxVolume.dwValue = DWORD(double(m_mxVolume.dwValue-m_dwRangeMin) / m_dwRangeSize * 0xFFFF);
  285. // Convert the amplification factor to a DSBVOLUME level
  286. *plMicrophoneVolume = AmpFactorToDB(m_mxVolume.dwValue);
  287. }
  288. }
  289. HRESULT hr = MMRESULTtoHRESULT(mmr);
  290. return hr;
  291. }
  292. #undef DPF_MODNAME
  293. #define DPF_MODNAME "CMixerLine::SetMasterRecordVolume"
  294. HRESULT CMixerLine::SetMasterRecordVolume( LONG lRecordVolume )
  295. {
  296. if( !m_fAcquiredVolCtrl )
  297. {
  298. DPFX(DPFPREP, DVF_ERRORLEVEL, "Initialize has not been called" );
  299. return DVERR_NOTINITIALIZED;
  300. }
  301. MMRESULT mmr = MMSYSERR_NOTSUPPORTED; // Default return code
  302. // Set the master recording level control if available
  303. if (m_mxcdMasterVol.cbStruct)
  304. {
  305. // Convert the DSBVOLUME level to an amplification factor from 0 to 0xFFFF
  306. m_mxVolume.dwValue = DBToAmpFactor(lRecordVolume);
  307. // Adjust range if necessary
  308. if (m_dwRangeMin != 0 || m_dwRangeSize != 0xFFFF)
  309. m_mxVolume.dwValue = DWORD(m_dwRangeMin + m_dwRangeSize*double(m_mxVolume.dwValue)/0xFFFF);
  310. mmr = mixerSetControlDetails((HMIXEROBJ)((UINT_PTR)m_uWaveDeviceId),
  311. &m_mxcdMasterVol, MIXER_OBJECTF_WAVEIN | MIXER_GETCONTROLDETAILSF_VALUE);
  312. }
  313. HRESULT hr = MMRESULTtoHRESULT(mmr);
  314. return hr;
  315. }
  316. #undef DPF_MODNAME
  317. #define DPF_MODNAME "CMixerLine::GetMasterRecordVolume"
  318. HRESULT CMixerLine::GetMasterRecordVolume( LPLONG plRecordVolume )
  319. {
  320. if( !m_fAcquiredVolCtrl )
  321. {
  322. DPFX(DPFPREP, DVF_ERRORLEVEL, "Initialize has not been called" );
  323. return DVERR_NOTINITIALIZED;
  324. }
  325. DNASSERT(plRecordVolume != NULL);
  326. MMRESULT mmr = MMSYSERR_NOTSUPPORTED; // Default return code
  327. // Get the master recording level if available
  328. if (m_mxcdMasterVol.cbStruct != 0)
  329. {
  330. mmr = mixerGetControlDetails((HMIXEROBJ)((UINT_PTR)m_uWaveDeviceId),
  331. &m_mxcdMasterVol, MIXER_OBJECTF_WAVEIN | MIXER_GETCONTROLDETAILSF_VALUE);
  332. if (mmr == MMSYSERR_NOERROR)
  333. {
  334. DNASSERT(m_mxVolume.dwValue >= m_dwRangeMin && m_mxVolume.dwValue <= m_dwRangeMin + m_dwRangeSize);
  335. // Adjust range if necessary
  336. if (m_dwRangeMin != 0 || m_dwRangeSize != 0xFFFF)
  337. m_mxVolume.dwValue = DWORD(double(m_mxVolume.dwValue-m_dwRangeMin) / m_dwRangeSize * 0xFFFF);
  338. // Convert the amplification factor to a DSBVOLUME level
  339. *plRecordVolume = AmpFactorToDB(m_mxVolume.dwValue);
  340. }
  341. }
  342. HRESULT hr = MMRESULTtoHRESULT(mmr);
  343. return hr;
  344. }
  345. #undef DPF_MODNAME
  346. #define DPF_MODNAME "CMixerLine::SelectMicrophone"
  347. HRESULT CMixerLine::EnableMicrophone( BOOL fEnable )
  348. {
  349. if( !m_fAcquiredVolCtrl )
  350. {
  351. DPFX(DPFPREP, DVF_ERRORLEVEL, "Initialize has not been called" );
  352. return DVERR_NOTINITIALIZED;
  353. }
  354. HMIXEROBJ hMixObj = (HMIXEROBJ)((UINT_PTR)m_uWaveDeviceId);
  355. MMRESULT mmr = MMSYSERR_NOERROR;
  356. HRESULT hr;
  357. // Check for presence of microphone controls
  358. if (!m_mxcdMasterMux.cbStruct && !m_mxcdMasterMute.cbStruct && !m_mxcdMicMute.cbStruct)
  359. {
  360. // We cannot do anything to enable the microphone line
  361. hr = DSERR_UNSUPPORTED;
  362. }
  363. else
  364. {
  365. // Select the mic on the Mux control, if available
  366. //
  367. if (m_mxcdMasterMux.cbStruct && !(m_fMasterMuxIsMux && !fEnable))
  368. {
  369. *m_pfMicValue = fEnable;
  370. mmr = mixerSetControlDetails(hMixObj, &m_mxcdMasterMux, MIXER_OBJECTF_WAVEIN | MIXER_GETCONTROLDETAILSF_VALUE);
  371. }
  372. // Mute/unmute the lines, if mute controls are available
  373. m_mxMute.fValue = !fEnable;
  374. if (m_mxcdMasterMute.cbStruct && mmr == MMSYSERR_NOERROR)
  375. mmr = mixerSetControlDetails(hMixObj, &m_mxcdMasterMute, MIXER_OBJECTF_WAVEIN | MIXER_GETCONTROLDETAILSF_VALUE);
  376. if (m_mxcdMicMute.cbStruct && mmr == MMSYSERR_NOERROR)
  377. mmr = mixerSetControlDetails(hMixObj, &m_mxcdMicMute, MIXER_OBJECTF_WAVEIN | MIXER_GETCONTROLDETAILSF_VALUE);
  378. hr = MMRESULTtoHRESULT(mmr);
  379. }
  380. return hr;
  381. }
  382. #undef DPF_MODNAME
  383. #define DPF_MODNAME "CMixerLine::MMRESULTtoHRESULT"
  384. HRESULT CMixerLine::MMRESULTtoHRESULT( MMRESULT mmr )
  385. {
  386. HRESULT hr;
  387. switch(mmr)
  388. {
  389. case MMSYSERR_NOERROR:
  390. hr = DS_OK;
  391. break;
  392. case MMSYSERR_BADDEVICEID:
  393. case MMSYSERR_NODRIVER:
  394. hr = DSERR_NODRIVER;
  395. break;
  396. case MMSYSERR_ALLOCATED:
  397. hr = DSERR_ALLOCATED;
  398. break;
  399. case MMSYSERR_NOMEM:
  400. hr = DSERR_OUTOFMEMORY;
  401. break;
  402. case MMSYSERR_NOTSUPPORTED:
  403. hr = DSERR_UNSUPPORTED;
  404. break;
  405. case WAVERR_BADFORMAT:
  406. hr = DSERR_BADFORMAT;
  407. break;
  408. default:
  409. hr = DSERR_GENERIC;
  410. break;
  411. }
  412. return hr;
  413. }