NOTIFY.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:8k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // ===============================================================
  2. // notify.c
  3. // ===============================================================
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <mmsystem.h>
  7. #include <dsound.h>
  8. #include "dsstream.h"
  9. // externs 
  10. extern LPDIRECTSOUNDBUFFER lpDSBStreamBuffer;
  11. extern LPDIRECTSOUNDNOTIFY lpDirectSoundNotify;
  12. extern WAVEINFOCA wiWave;
  13. extern HWND  hWndMain;
  14.  
  15. // function prototypes
  16. void UpdateProgressBar(void);
  17. // ===============================================================
  18. // HandleNotifications
  19. // Deals with the notification events.
  20. // Two events have been defined in SetNotifications().
  21. // The first (index 0) handles position notifications, triggered
  22. // after wiWave.dwNotifySize bytes and the second event deals with
  23. // the stop notification.
  24. // Initally, the entire buffer is filled with the FillDataBuffer()
  25. // call, when the user asks the stream to play. With each subsequent
  26. // notification, handled by this function, the rest of the file 
  27. // is read into the buffer.
  28. // ===============================================================
  29. DWORD HandleNotifications(LPVOID lpvoid)
  30. {
  31. DWORD hr = DS_OK;
  32. #ifdef DEBUG
  33. DWORD dwPlayPos, dwWritePos;
  34. #endif
  35. DWORD hRet = 0;
  36. while((hRet = WaitForMultipleObjects(2, hNotifyEvent, FALSE, INFINITE))!= WAIT_FAILED)
  37. {
  38. if (wiWave.bDonePlaying == TRUE)
  39. {
  40. DPF(0, "Posting stop message");
  41. UpdateProgressBar();
  42. SendMessage( hWndMain, WM_DSSTREAM_DONE, (WPARAM)0, (LPARAM)0 );
  43. break; //quit while loop.
  44. }
  45. // Deal with the event that got signalled.
  46. switch(hRet-WAIT_OBJECT_0)
  47. {
  48. case 0:
  49. { // A play notification has been received.
  50. LPBYTE lpWrite1;
  51. DWORD dwWrite1;
  52. UINT cbActual = 0;
  53. // update the progress slider and wiWave.dwProgress.
  54. UpdateProgressBar();
  55. // If the entire file has been read into the buffer, bFoundEnd will be TRUE.
  56. if (!wiWave.bFoundEnd)
  57. { // read in more of the file.
  58. DPF(0, "Received a notify event with FoundEnd = FALSE. NR = %lu", wiWave.dwNextWriteOffset );
  59. #ifdef DEBUG
  60. hr = lpDSBStreamBuffer->lpVtbl->GetCurrentPosition(lpDSBStreamBuffer, &dwPlayPos, &dwWritePos);
  61. DPF(1, "dwPlayPos = %lu and dwWritePos = %lu", dwPlayPos, dwWritePos);
  62. #endif
  63. // Lock the buffer.
  64. hr = lpDSBStreamBuffer->lpVtbl->Lock(lpDSBStreamBuffer, 
  65. wiWave.dwNextWriteOffset, 
  66. wiWave.dwNotifySize, 
  67. &lpWrite1, &dwWrite1,
  68. NULL, NULL, 0);
  69. if (hr != DS_OK)
  70. {
  71. DPF(0, "couldn't lock buffer with hr = %lu", hr);
  72. return hr;
  73. }
  74. if (dwWrite1 < wiWave.dwNotifySize)
  75. {
  76. DPF(0, "Lock returned number of bytes and requested size differ");
  77. }
  78. // now read the file. 
  79. hr = WaveReadFile(wiWave.hmmio, dwWrite1, lpWrite1, &wiWave.mmck, &cbActual);
  80. // if cbActual is less than the amount asked for, we may have
  81. // reached end of file. If we are looping, we will simply read the 
  82. // file in again until we have written dwWrite1 bytes into the buffer.
  83. // If not looping we fill with silence.
  84. if ((DWORD)cbActual < dwWrite1)
  85. {
  86. DPF(3, "ReadFile read less than what we asked for. less by %lu", dwWrite1-(DWORD)cbActual);
  87. if (!wiWave.bLoopFile)
  88. {
  89. wiWave.bFoundEnd = TRUE;
  90. // fill up the rest of the buffer with silence.
  91. DPF(0, "Filling in silence");
  92. FillMemory( lpWrite1+cbActual, (UINT)dwWrite1-cbActual, 
  93. (BYTE)(wiWave.pwfx->wBitsPerSample == 8 ? 128 : 0));
  94. }
  95. else
  96. { // we're looping. Read in the file again.
  97. int nChkErr = 0;
  98. UINT cbWritten = cbActual; // from previous call above.
  99. DPF(0, "Looping so read in file again");
  100. while (cbWritten < (UINT)dwWrite1) // write only one notification worth.
  101. { // this will keep reading in until the buffer is full. For very short files.
  102. nChkErr = WaveStartDataRead( &wiWave.hmmio, &wiWave.mmck, &wiWave.mmckInRIFF );
  103. ASSERT(nChkErr == 0); // we've already this before so shouldn't fail.
  104. nChkErr = WaveReadFile(wiWave.hmmio, (UINT)dwWrite1-cbWritten, 
  105. lpWrite1 + cbWritten, &wiWave.mmck, &cbActual);
  106. ASSERT(nChkErr == 0); // we've already this before so shouldn't fail.
  107. cbWritten += cbActual;
  108. } // while
  109. ASSERT(wiWave.bFoundEnd == FALSE);
  110. }// if or not looping
  111. }
  112. //unlock now
  113. hr = lpDSBStreamBuffer->lpVtbl->Unlock(lpDSBStreamBuffer, (LPVOID)lpWrite1, dwWrite1,  NULL, 0 );
  114. // setup the nextwrite offset.
  115. wiWave.dwNextWriteOffset += dwWrite1;
  116. if (wiWave.dwNextWriteOffset >= wiWave.dwBufferSize)
  117. wiWave.dwNextWriteOffset -= wiWave.dwBufferSize;
  118. }// if !bFoundEnd.
  119. else
  120. {
  121. // We have read in the whole file. We will keep filling in silence
  122. // in the buffer to allow the remaining sound bytes filled earlier 
  123. // to be played. 
  124. DPF(1, "Received a notify event and bFoundEnd = TRUE");
  125. ASSERT(wiWave.bLoopFile == FALSE);
  126. #ifdef DEBUG
  127. // if we've read all the file and we're not looping, 
  128. hr = lpDSBStreamBuffer->lpVtbl->GetCurrentPosition(lpDSBStreamBuffer, &dwPlayPos, &dwWritePos);
  129. DPF(1, "dwPlayPos = %lu and dwWritePos = %lu", dwPlayPos, dwWritePos);
  130. #endif
  131. // Allow the rest of the bytes to be played and fill here
  132. // with silence. The next notification will quit the while loop.
  133. hr = lpDSBStreamBuffer->lpVtbl->Lock(lpDSBStreamBuffer, 
  134. wiWave.dwNextWriteOffset, 
  135. wiWave.dwNotifySize, 
  136. &lpWrite1, &dwWrite1,
  137. NULL, NULL, 0);
  138. DPF(0, "Filling in silence");
  139. FillMemory(lpWrite1, dwWrite1,(BYTE)(wiWave.pwfx->wBitsPerSample == 8 ? 128 : 0));
  140. hr = lpDSBStreamBuffer->lpVtbl->Unlock(lpDSBStreamBuffer, (LPVOID)lpWrite1, dwWrite1,  NULL, 0 );
  141. // We don't want to cut off the sound before it's done playing.
  142. // If doneplaying is set, the next notification event will post a stop message.
  143. if (wiWave.mmckInRIFF.cksize > wiWave.dwNotifySize &&
  144. wiWave.dwProgress >= wiWave.mmckInRIFF.cksize - wiWave.dwNotifySize)
  145. {
  146. wiWave.bDonePlaying = TRUE;
  147. }
  148. else // for short files.
  149. if (wiWave.dwProgress >= wiWave.mmckInRIFF.cksize)
  150. wiWave.bDonePlaying = TRUE;
  151. }// else
  152. }
  153. break;
  154. case 1:
  155. { // A stop notification has been received.
  156. DPF(0, "Received the stop event");
  157. // update ui.
  158. //UpdateProgressBar();
  159. #ifdef DEBUG
  160. hr = lpDSBStreamBuffer->lpVtbl->GetCurrentPosition(lpDSBStreamBuffer, &dwPlayPos, &dwWritePos);
  161. DPF(1, "dwPlayPos = %lu and dwWritePos = %lu", dwPlayPos, dwWritePos);
  162. #endif
  163. // Set bDonePlaying to True. 
  164. wiWave.bDonePlaying = TRUE;
  165. // call stop.
  166. if (lpDSBStreamBuffer)
  167. {
  168. hr = lpDSBStreamBuffer->lpVtbl->Stop(lpDSBStreamBuffer);
  169. ASSERT(hr == DS_OK); // why would this fail in tis app?
  170. }
  171. CloseHandle(hNotifyEvent[0]);
  172. CloseHandle(hNotifyEvent[1]);
  173. hNotifyEvent[0] = hNotifyEvent[1] = (HANDLE)NULL;
  174. break;
  175. }
  176. default:
  177. ASSERT(FALSE); // we should never fall in here.
  178. break;
  179. }// end switch
  180. } // while
  181. //UpdateProgressBar();
  182. DPF(0, "Exiting thread");
  183. return TRUE;
  184. } //handlenotifications()
  185. // ===========================================================
  186. // UpdateProgressBar
  187. // Gets the current play position and updates the progress
  188. // bar accordingly.
  189. // ===========================================================
  190. void UpdateProgressBar(void)
  191. {
  192. DWORD dwPlayPos, dwWritePos;
  193. int hr = 0; 
  194. DWORD dwPlayed = 0;
  195. hr = lpDSBStreamBuffer->lpVtbl->GetCurrentPosition(lpDSBStreamBuffer, &dwPlayPos, &dwWritePos);
  196. if (hr != DS_OK)
  197. {
  198. DPF(0, "getCurrentPos returned failure");
  199. }
  200. DPF(1, "CurrentPos = %lu and LastPos = %lu", dwPlayPos, wiWave.dwLastPos);
  201. if (dwPlayPos < wiWave.dwLastPos)
  202. {
  203. dwPlayed = wiWave.dwBufferSize - wiWave.dwLastPos + dwPlayPos;
  204. }
  205. else
  206. {
  207. dwPlayed = dwPlayPos - wiWave.dwLastPos;
  208. }
  209. wiWave.dwProgress += dwPlayed;
  210. wiWave.dwLastPos = dwPlayPos;
  211. DPF(1, "wiWave.dwProgress =  %lu", wiWave.dwProgress);
  212. DPF(1, "Posting %lu", wiWave.dwProgress); 
  213. PostMessage( hWndMain, WM_DSSTREAM_PROGRESS, 0L, wiWave.dwProgress );
  214. }