wavemain.cpp
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:19k
源码类别:

Windows CE

开发平台:

Windows_Unix

  1. // -----------------------------------------------------------------------------
  2. //
  3. //      THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. //      ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  5. //      THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  6. //      PARTICULAR PURPOSE.
  7. //      Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.
  8. //
  9. // -----------------------------------------------------------------------------
  10. #include "wavemain.h"
  11. #ifdef DEBUG
  12. DBGPARAM dpCurSettings = {
  13.     TEXT("WaveDriver"), {
  14.          TEXT("Test")           //  0
  15.         ,TEXT("Params")         //  1
  16.         ,TEXT("Verbose")        //  2
  17.         ,TEXT("Interrupt")      //  3
  18.         ,TEXT("WODM")           //  4
  19.         ,TEXT("WIDM")           //  5
  20.         ,TEXT("PDD")            //  6
  21.         ,TEXT("MDD")            //  7
  22.         ,TEXT("Regs")           //  8
  23.         ,TEXT("Misc")           //  9
  24.         ,TEXT("Init")           // 10
  25.         ,TEXT("IOcontrol")      // 11
  26.         ,TEXT("Alloc")          // 12
  27.         ,TEXT("Function")       // 13
  28.         ,TEXT("Warning")        // 14
  29.         ,TEXT("Error")          // 15
  30.     }
  31.     ,
  32.         (1 << 15)   // Errors
  33.     |   (1 << 14)   // Warnings
  34. };
  35. #endif
  36. BOOL CALLBACK DllMain(HANDLE hDLL,
  37.                       DWORD dwReason,
  38.                       LPVOID lpvReserved)
  39. {
  40.     if ( dwReason==DLL_PROCESS_ATTACH )
  41.     {
  42.         DEBUGREGISTER((HMODULE)hDLL);
  43.     }
  44.     return TRUE;
  45. }
  46. // -----------------------------------------------------------------------------
  47. //
  48. // @doc     WDEV_EXT
  49. //
  50. // @topic   WAV Device Interface | Implements the WAVEDEV.DLL device
  51. //          interface. These functions are required for the device to
  52. //          be loaded by DEVICE.EXE.
  53. //
  54. // @xref                          <nl>
  55. //          <f WAV_Init>,         <nl>
  56. //          <f WAV_Deinit>,       <nl>
  57. //          <f WAV_Open>,         <nl>
  58. //          <f WAV_Close>,        <nl>
  59. //          <f WAV_Read>,         <nl>
  60. //          <f WAV_Write>,        <nl>
  61. //          <f WAV_Seek>,         <nl>
  62. //          <f WAV_PowerUp>,      <nl>
  63. //          <f WAV_PowerDown>,    <nl>
  64. //          <f WAV_IOControl>     <nl>
  65. //
  66. // -----------------------------------------------------------------------------
  67. //
  68. // @doc     WDEV_EXT
  69. //
  70. // @topic   Designing a Waveform Audio Driver |
  71. //          A waveform audio driver is responsible for processing messages
  72. //          from the Wave API Manager (WAVEAPI.DLL) to playback and record
  73. //          waveform audio. Waveform audio drivers are implemented as
  74. //          dynamic link libraries that are loaded by DEVICE.EXE The
  75. //          default waveform audio driver is named WAVEDEV.DLL (see figure).
  76. //          The messages passed to the audio driver are similar to those
  77. //          passed to a user-mode Windows NT audio driver (such as mmdrv.dll).
  78. //
  79. //          <bmp blk1_bmp>
  80. //
  81. //          Like all device drivers loaded by DEVICE.EXE, the waveform
  82. //          audio driver must export the standard device functions,
  83. //          XXX_Init, XXX_Deinit, XXX_IoControl, etc (see
  84. //          <t WAV Device Interface>). The Waveform Audio Drivers
  85. //          have a device prefix of "WAV".
  86. //
  87. //          Driver loading and unloading is handled by DEVICE.EXE and
  88. //          WAVEAPI.DLL. Calls are made to <f WAV_Init> and <f WAV_Deinit>.
  89. //          When the driver is opened by WAVEAPI.DLL calls are made to
  90. //          <f WAV_Open> and <f WAV_Close>.  On system power up and power down
  91. //          calls are made to <f WAV_PowerUp> and <f WAV_PowerDown>. All
  92. //          other communication between WAVEAPI.DLL and WAVEDEV.DLL is
  93. //          done by calls to <f WAV_IOControl>. The other WAV_xxx functions
  94. //          are not used.
  95. //
  96. // @xref                                          <nl>
  97. //          <t Designing a Waveform Audio PDD>    <nl>
  98. //          <t WAV Device Interface>              <nl>
  99. //          <t Wave Input Driver Messages>        <nl>
  100. //          <t Wave Output Driver Messages>       <nl>
  101. //
  102. // -----------------------------------------------------------------------------
  103. // -----------------------------------------------------------------------------
  104. //
  105. //  @doc    WDEV_EXT
  106. //
  107. //  @func   PVOID | WAV_Init | Device initialization routine
  108. //
  109. //  @parm   DWORD | dwInfo | info passed to RegisterDevice
  110. //
  111. //  @rdesc  Returns a DWORD which will be passed to Open & Deinit or NULL if
  112. //          unable to initialize the device.
  113. //
  114. // -----------------------------------------------------------------------------
  115. DWORD WAV_Init(DWORD Index)
  116. {
  117.     return (DWORD)HardwareContext::CreateHWContext(Index);
  118. }
  119. // -----------------------------------------------------------------------------
  120. //
  121. //  @doc    WDEV_EXT
  122. //
  123. //  @func   PVOID | WAV_Deinit | Device deinitialization routine
  124. //
  125. //  @parm   DWORD | dwData | value returned from WAV_Init call
  126. //
  127. //  @rdesc  Returns TRUE for success, FALSE for failure.
  128. //
  129. // -----------------------------------------------------------------------------
  130. BOOL WAV_Deinit(DWORD dwData)
  131. {
  132.     return g_pHWContext->Deinit();
  133. }
  134. // -----------------------------------------------------------------------------
  135. //
  136. //  @doc    WDEV_EXT
  137. //
  138. //  @func   PVOID | WAV_Open    | Device open routine
  139. //
  140. //  @parm   DWORD | dwData      | Value returned from WAV_Init call (ignored)
  141. //
  142. //  @parm   DWORD | dwAccess    | Requested access (combination of GENERIC_READ
  143. //                                and GENERIC_WRITE) (ignored)
  144. //
  145. //  @parm   DWORD | dwShareMode | Requested share mode (combination of
  146. //                                FILE_SHARE_READ and FILE_SHARE_WRITE) (ignored)
  147. //
  148. //  @rdesc  Returns a DWORD which will be passed to Read, Write, etc or NULL if
  149. //          unable to open device.
  150. //
  151. // -----------------------------------------------------------------------------
  152. DWORD WAV_Open( DWORD dwData,
  153.               DWORD dwAccess,
  154.               DWORD dwShareMode)
  155. {
  156.     return 4;
  157. }
  158. // -----------------------------------------------------------------------------
  159. //
  160. //  @doc    WDEV_EXT
  161. //
  162. //  @func   BOOL | WAV_Close | Device close routine
  163. //
  164. //  @parm   DWORD | dwOpenData | Value returned from WAV_Open call
  165. //
  166. //  @rdesc  Returns TRUE for success, FALSE for failure
  167. //
  168. // -----------------------------------------------------------------------------
  169. BOOL WAV_Close(DWORD dwData)
  170. {
  171.     return TRUE;
  172. }
  173. // -----------------------------------------------------------------------------
  174. //
  175. //  @doc    WDEV_EXT
  176. //
  177. //  @func   DWORD | WAV_Read | Device read routine
  178. //
  179. //  @parm   DWORD | dwOpenData | Value returned from WAV_Open call (ignored)
  180. //
  181. //  @parm   LPVOID | pBuf | Buffer to receive data (ignored)
  182. //
  183. //  @parm   DWORD | len | Maximum length to read (ignored)
  184. //
  185. //  @rdesc  Returns 0 always. WAV_Read should never get called and does
  186. //          nothing. Required DEVICE.EXE function, but all data communication
  187. //          is handled by <f WAV_IOControl>.
  188. //
  189. // -----------------------------------------------------------------------------
  190. DWORD WAV_Read(DWORD dwData,
  191.                LPVOID pBuf,
  192.                DWORD Len)
  193. {
  194.     // Return length read
  195.     return 0;
  196. }
  197. // -----------------------------------------------------------------------------
  198. //
  199. //  @doc    WDEV_EXT
  200. //
  201. //  @func   DWORD | WAV_Write | Device write routine
  202. //
  203. //  @parm   DWORD | dwOpenData | Value returned from WAV_Open call (ignored)
  204. //
  205. //  @parm   LPCVOID | pBuf | Buffer containing data (ignored)
  206. //
  207. //  @parm   DWORD | len | Maximum length to write (ignored)
  208. //
  209. //  @rdesc  Returns 0 always. WAV_Write should never get called and does
  210. //          nothing. Required DEVICE.EXE function, but all data communication
  211. //          is handled by <f WAV_IOControl>.
  212. //
  213. // -----------------------------------------------------------------------------
  214. DWORD WAV_Write(DWORD dwData,
  215.                 LPCVOID pBuf,
  216.                 DWORD Len)
  217. {
  218.     // return number of bytes written (or -1 for error)
  219.     return 0;
  220. }
  221. // -----------------------------------------------------------------------------
  222. //
  223. //  @doc    WDEV_EXT
  224. //
  225. //  @func   DWORD | WAV_Seek | Device seek routine
  226. //
  227. //  @parm   DWORD | dwOpenData | Value returned from WAV_Open call (ignored)
  228. //
  229. //  @parm   long | pos | Position to seek to (relative to type) (ignored)
  230. //
  231. //  @parm   DWORD | type | FILE_BEGIN, FILE_CURRENT, or FILE_END (ignored)
  232. //
  233. //  @rdesc  Returns -1 always. WAV_Seek should never get called and does
  234. //          nothing. Required DEVICE.EXE function, but all data communication
  235. //          is handled by <f WAV_IOControl>.
  236. //
  237. // -----------------------------------------------------------------------------
  238. DWORD WAV_Seek(DWORD dwData,
  239.                long pos,
  240.                DWORD type)
  241. {
  242.     // return an error
  243.     return (DWORD)-1;
  244. }
  245. // -----------------------------------------------------------------------------
  246. //
  247. //  @doc    WDEV_EXT
  248. //
  249. //  @func   void | WAV_PowerUp | Device powerup routine
  250. //
  251. //  @comm   Called to restore device from suspend mode.  Cannot call any
  252. //          routines aside from those in the dll in this call.
  253. //
  254. // -----------------------------------------------------------------------------
  255. VOID WAV_PowerUp(VOID)
  256. {
  257.     g_pHWContext->PowerUp();
  258.     return;
  259. }
  260. // -----------------------------------------------------------------------------
  261. //
  262. //  @doc    WDEV_EXT
  263. //
  264. //  @func   void | WAV_PowerDown | Device powerdown routine
  265. //
  266. //  @comm   Called to suspend device.  Cannot call any routines aside from
  267. //          those in the dll in this call.
  268. //
  269. // -----------------------------------------------------------------------------
  270. VOID WAV_PowerDown(VOID)
  271. {
  272.     g_pHWContext->PowerDown();
  273.     return;
  274. }
  275. BOOL HandleWaveMessage(PMMDRV_MESSAGE_PARAMS pParams, DWORD *pdwResult)
  276. {
  277.     //  set the error code to be no error first
  278.     SetLastError(MMSYSERR_NOERROR);
  279.     UINT uMsg = pParams->uMsg;
  280.     UINT uDeviceId = pParams->uDeviceId;
  281.     DWORD dwParam1 = pParams->dwParam1;
  282.     DWORD dwParam2 = pParams->dwParam2;
  283.     DWORD dwUser   = pParams->dwUser;
  284.     StreamContext *pStreamContext = (StreamContext *)dwUser;
  285.     DWORD dwRet;
  286.     g_pHWContext->Lock();
  287.     switch (uMsg)
  288.     {
  289.     case WODM_GETNUMDEVS:
  290.         {
  291.             dwRet = g_pHWContext->GetNumOutputDevices();
  292.             break;
  293.         }
  294.     case WIDM_GETNUMDEVS:
  295.         {
  296.             dwRet = g_pHWContext->GetNumInputDevices();
  297.             break;
  298.         }
  299.     case WODM_GETDEVCAPS:
  300.         {
  301.             DeviceContext *pDeviceContext;
  302.             UINT NumDevs = g_pHWContext->GetNumOutputDevices();
  303.             if (pStreamContext)
  304.             {
  305.                 pDeviceContext=pStreamContext->GetDeviceContext();
  306.             }
  307.             else
  308.             {
  309.                 pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId);
  310.             }
  311.             dwRet = pDeviceContext->GetDevCaps((PVOID)dwParam1,dwParam2);
  312.             break;
  313.         }
  314.     case WIDM_GETDEVCAPS:
  315.         {
  316.             DeviceContext *pDeviceContext;
  317.             UINT NumDevs = g_pHWContext->GetNumInputDevices();
  318.             if (pStreamContext)
  319.             {
  320.                 pDeviceContext=pStreamContext->GetDeviceContext();
  321.             }
  322.             else
  323.             {
  324.                 pDeviceContext = g_pHWContext->GetInputDeviceContext(uDeviceId);
  325.             }
  326.             dwRet = pDeviceContext->GetDevCaps((PVOID)dwParam1,dwParam2);
  327.             break;
  328.         }
  329.     case WODM_GETEXTDEVCAPS:
  330.         {
  331.             DeviceContext *pDeviceContext;
  332.             UINT NumDevs = g_pHWContext->GetNumOutputDevices();
  333.             if (pStreamContext)
  334.             {
  335.                 pDeviceContext=pStreamContext->GetDeviceContext();
  336.             }
  337.             else
  338.             {
  339.                 pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId);
  340.             }
  341.             dwRet = pDeviceContext->GetExtDevCaps((PVOID)dwParam1,dwParam2);
  342.             break;
  343.         }
  344.     case WODM_OPEN:
  345.         {
  346.             // DEBUGMSG(1, (TEXT("WODM_OPENrn"));
  347.             DeviceContext *pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId);
  348.             dwRet = pDeviceContext->OpenStream((LPWAVEOPENDESC)dwParam1, dwParam2, (StreamContext **)dwUser);
  349.             break;
  350.         }
  351.     case WIDM_OPEN:
  352.         {
  353.             // DEBUGMSG(1, (TEXT("WIDM_OPENrn"));
  354.             DeviceContext *pDeviceContext = g_pHWContext->GetInputDeviceContext(uDeviceId);
  355.             dwRet = pDeviceContext->OpenStream((LPWAVEOPENDESC)dwParam1, dwParam2, (StreamContext **)dwUser);
  356.             break;
  357.         }
  358.     case WODM_CLOSE:
  359.     case WIDM_CLOSE:
  360.         {
  361.             // DEBUGMSG(1, (TEXT("WIDM_CLOSE/WODM_CLOSErn"));
  362.             dwRet = pStreamContext->Close();
  363.             // Release stream context here, rather than inside StreamContext::Close, so that if someone
  364.             // (like CMidiStream) has subclassed Close there's no chance that the object will get released
  365.             // out from under them.
  366.             if (dwRet==MMSYSERR_NOERROR)
  367.             {
  368.                 pStreamContext->Release();
  369.             }
  370.             break;
  371.         }
  372.     case WODM_RESTART:
  373.     case WIDM_START:
  374.         {
  375.             dwRet = pStreamContext->Run();
  376.             break;
  377.         }
  378.     case WODM_PAUSE:
  379.     case WIDM_STOP:
  380.         {
  381.             dwRet = pStreamContext->Stop();
  382.             break;
  383.         }
  384.     case WODM_GETPOS:
  385.     case WIDM_GETPOS:
  386.         {
  387.             dwRet = pStreamContext->GetPos((PMMTIME)dwParam1);
  388.             break;
  389.         }
  390.     case WODM_RESET:
  391.     case WIDM_RESET:
  392.         {
  393.             dwRet = pStreamContext->Reset();
  394.             break;
  395.         }
  396.     case WODM_WRITE:
  397.     case WIDM_ADDBUFFER:
  398.         {
  399.             // DEBUGMSG(1, (TEXT("WODM_WRITE/WIDM_ADDBUFFER, Buffer=0x%xrn"),dwParam1);
  400.             dwRet = pStreamContext->QueueBuffer((LPWAVEHDR)dwParam1);
  401.             break;
  402.         }
  403.     case WODM_GETVOLUME:
  404.         {
  405.             PULONG pdwGain = (PULONG)dwParam1;
  406.             UINT NumDevs = g_pHWContext->GetNumOutputDevices();
  407.             if (pStreamContext)
  408.             {
  409.                 *pdwGain = pStreamContext->GetGain();
  410.             }
  411.             else
  412.             {
  413.                 DeviceContext *pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId);
  414.                 *pdwGain = pDeviceContext->GetGain();
  415.             }
  416.             dwRet = MMSYSERR_NOERROR;
  417.             break;
  418.         }
  419.     case WODM_SETVOLUME:
  420.         {
  421.             UINT NumDevs = g_pHWContext->GetNumOutputDevices();
  422.             LONG dwGain = dwParam1;
  423.             if (pStreamContext)
  424.             {
  425.                 dwRet = pStreamContext->SetGain(dwGain);
  426.             }
  427.             else
  428.             {
  429.                 DeviceContext *pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId);
  430.                 dwRet = pDeviceContext->SetGain(dwGain);
  431.             }
  432.             break;
  433.         }
  434.     case WODM_BREAKLOOP:
  435.         {
  436.             dwRet = pStreamContext->BreakLoop();
  437.             break;
  438.         }
  439.     case WODM_SETPLAYBACKRATE:
  440.         {
  441.             WaveStreamContext *pWaveStream = (WaveStreamContext *)dwUser;
  442.             dwRet = pWaveStream->SetRate(dwParam1);
  443.             break;
  444.         }
  445.     case WODM_GETPLAYBACKRATE:
  446.         {
  447.             WaveStreamContext *pWaveStream = (WaveStreamContext *)dwUser;
  448.             dwRet = pWaveStream->GetRate((DWORD *)dwParam1);
  449.             break;
  450.         }
  451.     case MM_WOM_SETSECONDARYGAINCLASS:
  452.         {
  453.             dwRet = pStreamContext->SetSecondaryGainClass(dwParam1);
  454.             break;
  455.         }
  456.     case MM_WOM_SETSECONDARYGAINLIMIT:
  457.         {
  458.             DeviceContext *pDeviceContext;
  459.             if (pStreamContext)
  460.             {
  461.                 pDeviceContext = pStreamContext->GetDeviceContext();
  462.             }
  463.             else
  464.             {
  465.                 pDeviceContext = g_pHWContext->GetOutputDeviceContext(uDeviceId);
  466.             }
  467.             dwRet = pDeviceContext->SetSecondaryGainLimit(dwParam1,dwParam2);
  468.             break;
  469.         }
  470. /*
  471.     case MM_WOM_FORCESPEAKER:
  472.         {
  473.             if (pStreamContext)
  474.             {
  475.                 dwRet = pStreamContext->ForceSpeaker((BOOL)dwParam1);
  476.             }
  477.             else
  478.             {
  479.                 dwRet = g_pHWContext->ForceSpeaker((BOOL)dwParam1);
  480.             }
  481.             break;
  482.         }
  483. */
  484.     case MM_MOM_MIDIMESSAGE:
  485.         {
  486.             CMidiStream *pMidiStream = (CMidiStream *)dwUser;
  487.             dwRet = pMidiStream->MidiMessage(dwParam1);
  488.             break;
  489.         }
  490.     case WODM_GETPITCH:
  491.     case WODM_SETPITCH:
  492.     case WODM_PREPARE:
  493.     case WODM_UNPREPARE:
  494.     case WIDM_PREPARE:
  495.     case WIDM_UNPREPARE:
  496.         default:
  497.         dwRet  = MMSYSERR_NOTSUPPORTED;
  498.     }
  499.     g_pHWContext->Unlock();
  500.     // Pass the return code back via pBufOut
  501.     if (pdwResult)
  502.     {
  503.         *pdwResult = dwRet;
  504.     }
  505.     return TRUE;
  506. }
  507. // -----------------------------------------------------------------------------
  508. //
  509. //  @doc    WDEV_EXT
  510. //
  511. //  @func   BOOL | WAV_IOControl | Device IO control routine
  512. //
  513. //  @parm   DWORD | dwOpenData | Value returned from WAV_Open call
  514. //
  515. //  @parm   DWORD | dwCode |
  516. //          IO control code for the function to be performed. WAV_IOControl only
  517. //          supports one IOCTL value (IOCTL_WAV_MESSAGE)
  518. //
  519. //  @parm   PBYTE | pBufIn |
  520. //          Pointer to the input parameter structure (<t MMDRV_MESSAGE_PARAMS>).
  521. //
  522. //  @parm   DWORD | dwLenIn |
  523. //          Size in bytes of input parameter structure (sizeof(<t MMDRV_MESSAGE_PARAMS>)).
  524. //
  525. //  @parm   PBYTE | pBufOut | Pointer to the return value (DWORD).
  526. //
  527. //  @parm   DWORD | dwLenOut | Size of the return value variable (sizeof(DWORD)).
  528. //
  529. //  @parm   PDWORD | pdwActualOut | Unused
  530. //
  531. //  @rdesc  Returns TRUE for success, FALSE for failure
  532. //
  533. //  @xref   <t Wave Input Driver Messages> (WIDM_XXX) <nl>
  534. //          <t Wave Output Driver Messages> (WODM_XXX)
  535. //
  536. // -----------------------------------------------------------------------------
  537. BOOL WAV_IOControl(DWORD  dwOpenData,
  538.                    DWORD  dwCode,
  539.                    PBYTE  pBufIn,
  540.                    DWORD  dwLenIn,
  541.                    PBYTE  pBufOut,
  542.                    DWORD  dwLenOut,
  543.                    PDWORD pdwActualOut)
  544. {
  545.     _try
  546.     {
  547.         switch (dwCode)
  548.         {
  549.         case IOCTL_WAV_MESSAGE:
  550.             return HandleWaveMessage((PMMDRV_MESSAGE_PARAMS)pBufIn, (DWORD *)pBufOut);
  551.         default:
  552.             return g_pHWContext->IOControl(dwOpenData, dwCode, pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut);
  553.         }
  554.     }
  555.     _except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  556.     {
  557.         RETAILMSG(1, (TEXT("EXCEPTION IN WAV_IOControl!!!!rn")));
  558.         SetLastError(E_FAIL);
  559.     }
  560.     return FALSE;
  561. }