home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / dsstream / notify.c < prev    next >
C/C++ Source or Header  |  1997-07-14  |  8KB  |  239 lines

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