Source code of Windows XP (NT5)
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.

286 lines
9.6 KiB

  1. /****************************************************************************
  2. *
  3. * waveout.c
  4. *
  5. * WDM Audio support for Wave Output devices
  6. *
  7. * Copyright (C) Microsoft Corporation, 1997 - 1999 All Rights Reserved.
  8. *
  9. * History
  10. * 5-12-97 - Noel Cross (NoelC)
  11. *
  12. ***************************************************************************/
  13. #include "wdmdrv.h"
  14. /****************************************************************************
  15. This function conforms to the standard Wave output driver message proc
  16. (wodMessage), which is documented in mmddk.h.
  17. ****************************************************************************/
  18. DWORD FAR PASCAL _loadds wodMessage
  19. (
  20. UINT id,
  21. UINT msg,
  22. DWORD_PTR dwUser,
  23. DWORD_PTR dwParam1,
  24. DWORD_PTR dwParam2
  25. )
  26. {
  27. LPDEVICEINFO pOutClient;
  28. LPDEVICEINFO pDeviceInfo;
  29. LPWAVEHDR lpWaveHdr;
  30. MMRESULT mmr;
  31. switch (msg) {
  32. case WODM_INIT:
  33. DPF(DL_TRACE|FA_WAVE, ("WODM_INIT") );
  34. return(wdmaudAddRemoveDevNode(WaveOutDevice, (LPCWSTR)dwParam2, TRUE));
  35. case DRVM_EXIT:
  36. DPF(DL_TRACE|FA_WAVE, ("DRVM_EXIT: WaveOut") );
  37. return(wdmaudAddRemoveDevNode(WaveOutDevice, (LPCWSTR)dwParam2, FALSE));
  38. case WODM_GETNUMDEVS:
  39. DPF(DL_TRACE|FA_WAVE, ("WODM_GETNUMDEVS") );
  40. return wdmaudGetNumDevs(WaveOutDevice, (LPCWSTR)dwParam1);
  41. case WODM_GETDEVCAPS:
  42. DPF(DL_TRACE|FA_WAVE, ("WODM_GETDEVCAPS") );
  43. if (pDeviceInfo = GlobalAllocDeviceInfo((LPCWSTR)dwParam2))
  44. {
  45. pDeviceInfo->DeviceType = WaveOutDevice;
  46. pDeviceInfo->DeviceNumber = id;
  47. mmr = wdmaudGetDevCaps(pDeviceInfo, (MDEVICECAPSEX FAR*)dwParam1);
  48. GlobalFreeDeviceInfo(pDeviceInfo);
  49. return mmr;
  50. } else {
  51. MMRRETURN( MMSYSERR_NOMEM );
  52. }
  53. case WODM_PREFERRED:
  54. DPF(DL_TRACE|FA_WAVE, ("WODM_PREFERRED: %d", id) );
  55. return wdmaudSetPreferredDevice(
  56. WaveOutDevice,
  57. id,
  58. dwParam1,
  59. dwParam2);
  60. case WODM_OPEN:
  61. {
  62. LPWAVEOPENDESC pwod = (LPWAVEOPENDESC)dwParam1;
  63. DPF(DL_TRACE|FA_WAVE, ("WODM_OPEN") );
  64. if (pDeviceInfo = GlobalAllocDeviceInfo((LPCWSTR)pwod->dnDevNode))
  65. {
  66. pDeviceInfo->DeviceType = WaveOutDevice;
  67. pDeviceInfo->DeviceNumber = id;
  68. #ifdef UNDER_NT
  69. pDeviceInfo->DeviceHandle = (HANDLE32)pwod->hWave;
  70. #else
  71. pDeviceInfo->DeviceHandle = (HANDLE32)MAKELONG(pwod->hWave,0);
  72. #endif
  73. mmr = waveOpen(pDeviceInfo, dwUser, pwod, (DWORD)dwParam2);
  74. GlobalFreeDeviceInfo(pDeviceInfo);
  75. return mmr;
  76. } else {
  77. MMRRETURN( MMSYSERR_NOMEM );
  78. }
  79. }
  80. case WODM_CLOSE:
  81. DPF(DL_TRACE|FA_WAVE, ("WODM_CLOSE") );
  82. pOutClient = (LPDEVICEINFO)dwUser;
  83. if( ((mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
  84. ((mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR) )
  85. {
  86. MMRRETURN( mmr );
  87. }
  88. mmr = wdmaudCloseDev( pOutClient );
  89. if (MMSYSERR_NOERROR == mmr)
  90. {
  91. waveCallback(pOutClient, WOM_CLOSE, 0L);
  92. ISVALIDDEVICEINFO(pOutClient);
  93. ISVALIDDEVICESTATE(pOutClient->DeviceState,FALSE);
  94. waveCleanUp(pOutClient);
  95. }
  96. return mmr;
  97. case WODM_WRITE:
  98. DPF(DL_TRACE|FA_WAVE, ("WODM_WRITE") );
  99. lpWaveHdr = (LPWAVEHDR)dwParam1;
  100. pOutClient = (LPDEVICEINFO)dwUser;
  101. //
  102. // Sanity check the parameters and fail bad data!
  103. //
  104. if( ( (mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
  105. ( (mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR ) ||
  106. ( (mmr=IsValidWaveHeader(lpWaveHdr)) != MMSYSERR_NOERROR ) )
  107. {
  108. MMRRETURN( mmr );
  109. }
  110. // check if it's been prepared
  111. DPFASSERT(lpWaveHdr->dwFlags & WHDR_PREPARED);
  112. if (!(lpWaveHdr->dwFlags & WHDR_PREPARED))
  113. MMRRETURN( WAVERR_UNPREPARED );
  114. // if it is already in our Q, then we cannot do this
  115. DPFASSERT(!(lpWaveHdr->dwFlags & WHDR_INQUEUE));
  116. if ( lpWaveHdr->dwFlags & WHDR_INQUEUE )
  117. MMRRETURN( WAVERR_STILLPLAYING );
  118. //
  119. // Put the request at the end of our queue.
  120. //
  121. return waveWrite(pOutClient, lpWaveHdr);
  122. case WODM_PAUSE:
  123. DPF(DL_TRACE|FA_WAVE, ("WODM_PAUSE") );
  124. pOutClient = (LPDEVICEINFO)dwUser;
  125. return wdmaudSetDeviceState(pOutClient,
  126. IOCTL_WDMAUD_WAVE_OUT_PAUSE);
  127. case WODM_RESTART:
  128. DPF(DL_TRACE|FA_WAVE, ("WODM_RESTART") );
  129. pOutClient = (LPDEVICEINFO)dwUser;
  130. return wdmaudSetDeviceState(pOutClient,
  131. IOCTL_WDMAUD_WAVE_OUT_PLAY);
  132. case WODM_RESET:
  133. DPF(DL_TRACE|FA_WAVE, ("WODM_RESET") );
  134. pOutClient = (LPDEVICEINFO)dwUser;
  135. return wdmaudSetDeviceState(pOutClient,
  136. IOCTL_WDMAUD_WAVE_OUT_RESET);
  137. case WODM_BREAKLOOP:
  138. DPF(DL_TRACE|FA_WAVE, ("WODM_BREAKLOOP") );
  139. pOutClient = (LPDEVICEINFO)dwUser;
  140. return wdmaudSetDeviceState(pOutClient,
  141. IOCTL_WDMAUD_WAVE_OUT_BREAKLOOP);
  142. case WODM_GETPOS:
  143. DPF(DL_TRACE|FA_WAVE, ("WODM_GETPOS") );
  144. pOutClient = (LPDEVICEINFO)dwUser;
  145. if( ((mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
  146. ((mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR ) )
  147. {
  148. MMRRETURN( mmr );
  149. }
  150. mmr = wdmaudGetPos(pOutClient,
  151. (LPMMTIME)dwParam1,
  152. (DWORD)dwParam2,
  153. WaveOutDevice);
  154. DPF(DL_TRACE|FA_WAVE, ("GetPos: returned %lu", ((LPMMTIME)(dwParam1))->u.ms));
  155. return mmr;
  156. case WODM_SETVOLUME:
  157. DPF(DL_TRACE|FA_WAVE, ("WODM_SETVOLUME") );
  158. pOutClient = GlobalAllocDeviceInfo((LPWSTR)dwParam2);
  159. if (NULL == pOutClient)
  160. {
  161. MMRRETURN( MMSYSERR_NOMEM );
  162. }
  163. pOutClient->DeviceType = WaveOutDevice;
  164. pOutClient->DeviceNumber = id;
  165. pOutClient->OpenDone = 0;
  166. PRESETERROR(pOutClient);
  167. mmr = wdmaudIoControl(pOutClient,
  168. sizeof(DWORD),
  169. (LPBYTE)&dwParam1,
  170. IOCTL_WDMAUD_WAVE_OUT_SET_VOLUME);
  171. POSTEXTRACTERROR(mmr,pOutClient);
  172. GlobalFreeDeviceInfo(pOutClient);
  173. return mmr;
  174. case WODM_GETVOLUME:
  175. DPF(DL_TRACE|FA_WAVE, ("WODM_GETVOLUME") );
  176. pOutClient = GlobalAllocDeviceInfo((LPWSTR)dwParam2);
  177. if (pOutClient)
  178. {
  179. LPDWORD pVolume;
  180. pVolume = (LPDWORD) GlobalAllocPtr( GPTR, sizeof(DWORD));
  181. if (pVolume)
  182. {
  183. pOutClient->DeviceType = WaveOutDevice;
  184. pOutClient->DeviceNumber = id;
  185. pOutClient->OpenDone = 0;
  186. mmr = wdmaudIoControl(pOutClient,
  187. sizeof(DWORD),
  188. (LPBYTE)pVolume,
  189. IOCTL_WDMAUD_WAVE_OUT_GET_VOLUME);
  190. //
  191. // Only write back information on success.
  192. //
  193. if( MMSYSERR_NOERROR == mmr )
  194. *((DWORD FAR *) dwParam1) = *pVolume;
  195. GlobalFreePtr(pVolume);
  196. } else {
  197. mmr = MMSYSERR_NOMEM;
  198. }
  199. GlobalFreeDeviceInfo(pOutClient);
  200. } else {
  201. mmr = MMSYSERR_NOMEM;
  202. }
  203. MMRRETURN( mmr );
  204. #ifdef UNDER_NT
  205. case WODM_PREPARE:
  206. DPF(DL_TRACE|FA_WAVE, ("WODM_PREPARE") );
  207. pOutClient = (LPDEVICEINFO)dwUser;
  208. if( ((mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
  209. ((mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR ) )
  210. {
  211. MMRRETURN( mmr );
  212. }
  213. return wdmaudPrepareWaveHeader(pOutClient, (LPWAVEHDR)dwParam1);
  214. case WODM_UNPREPARE:
  215. DPF(DL_TRACE|FA_WAVE, ("WODM_UNPREPARE") );
  216. pOutClient = (LPDEVICEINFO)dwUser;
  217. if( ((mmr=IsValidDeviceInfo(pOutClient)) != MMSYSERR_NOERROR ) ||
  218. ((mmr=IsValidDeviceState(pOutClient->DeviceState,FALSE)) != MMSYSERR_NOERROR ) )
  219. {
  220. MMRRETURN( mmr );
  221. }
  222. return wdmaudUnprepareWaveHeader(pOutClient, (LPWAVEHDR)dwParam1);
  223. #endif
  224. case WODM_GETPITCH:
  225. case WODM_SETPITCH:
  226. case WODM_GETPLAYBACKRATE:
  227. case WODM_SETPLAYBACKRATE:
  228. MMRRETURN( MMSYSERR_NOTSUPPORTED );
  229. default:
  230. MMRRETURN( MMSYSERR_NOTSUPPORTED );
  231. }
  232. //
  233. // Should not get here
  234. //
  235. DPFASSERT(0);
  236. MMRRETURN( MMSYSERR_NOTSUPPORTED );
  237. }