home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / midimon / circbuf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  5.0 KB  |  176 lines

  1. /**************************************************************************
  2.  *
  3.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6.  *  PURPOSE.
  7.  *
  8.  *  Copyright (C) 1993 - 1997  Microsoft Corporation.  All Rights Reserved.
  9.  * 
  10.  **************************************************************************/
  11.  
  12. /*
  13.  * circbuf.c - Routines to manage the circular MIDI input buffer.
  14.  *      This buffer is filled by the low-level callback function and
  15.  *      emptied by the application.  Since this buffer is accessed
  16.  *      by a low-level callback, memory for it must be allocated
  17.  *      exactly as shown in AllocCircularBuffer().
  18.  */
  19.  
  20. #include <windows.h>
  21. #include "midimon.h"
  22. #include "circbuf.h"
  23.  
  24. /*
  25.  * AllocCircularBuffer -    Allocates memory for a CIRCULARBUFFER structure 
  26.  * and a buffer of the specified size.  Each memory block is allocated 
  27.  * with GlobalAlloc() using GMEM_SHARE and GMEM_MOVEABLE flags, locked 
  28.  * with GlobalLock(), and page-locked with GlobalPageLock().
  29.  *
  30.  * Params:  dwSize - The size of the buffer, in events.
  31.  *
  32.  * Return:  A pointer to a CIRCULARBUFFER structure identifying the 
  33.  *      allocated display buffer.  NULL if the buffer could not be allocated.
  34.  */
  35. LPCIRCULARBUFFER AllocCircularBuffer(DWORD dwSize)
  36. {
  37.     HANDLE hMem;
  38.     LPCIRCULARBUFFER lpBuf;
  39.     LPEVENT lpMem;
  40.     
  41.     /* Allocate and lock a CIRCULARBUFFER structure.
  42.      */
  43.     hMem = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE,
  44.                        (DWORD)sizeof(CIRCULARBUFFER));
  45.     if(hMem == NULL)
  46.         return NULL;
  47.  
  48.     lpBuf = (LPCIRCULARBUFFER)GlobalLock(hMem);
  49.     if(lpBuf == NULL)
  50.     {
  51.         GlobalFree(hMem);
  52.         return NULL;
  53.     }
  54.     
  55.     /* Page lock the memory.  Global memory blocks accessed by
  56.      * low-level callback functions must be page locked.
  57.      */
  58. #ifndef _WIN32
  59.     GlobalSmartPageLock((HGLOBAL)HIWORD(lpBuf));
  60. #endif
  61.  
  62.     /* Save the memory handle.
  63.      */
  64.     lpBuf->hSelf = hMem;
  65.     
  66.     /* Allocate and lock memory for the actual buffer.
  67.      */
  68.     hMem = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, dwSize * sizeof(EVENT));
  69.     if(hMem == NULL)
  70.     {
  71. #ifndef _WIN32
  72.         GlobalSmartPageUnlock((HGLOBAL)HIWORD(lpBuf));
  73. #endif
  74.         GlobalUnlock(lpBuf->hSelf);
  75.         GlobalFree(lpBuf->hSelf);
  76.         return NULL;
  77.     }
  78.     
  79.     lpMem = (LPEVENT)GlobalLock(hMem);
  80.     if(lpMem == NULL)
  81.     {
  82.         GlobalFree(hMem);
  83. #ifndef _WIN32
  84.         GlobalSmartPageUnlock((HGLOBAL)HIWORD(lpBuf));
  85. #endif
  86.         GlobalUnlock(lpBuf->hSelf);
  87.         GlobalFree(lpBuf->hSelf);
  88.         return NULL;
  89.     }
  90.     
  91.     /* Page lock the memory.  Global memory blocks accessed by
  92.      * low-level callback functions must be page locked.
  93.      */
  94. #ifndef _WIN32
  95.     GlobalSmartPageLock((HGLOBAL)HIWORD(lpMem));
  96. #endif
  97.     
  98.     /* Set up the CIRCULARBUFFER structure.
  99.      */
  100.     lpBuf->hBuffer = hMem;
  101.     lpBuf->wError = 0;
  102.     lpBuf->dwSize = dwSize;
  103.     lpBuf->dwCount = 0L;
  104.     lpBuf->lpStart = lpMem;
  105.     lpBuf->lpEnd = lpMem + dwSize;
  106.     lpBuf->lpTail = lpMem;
  107.     lpBuf->lpHead = lpMem;
  108.         
  109.     return lpBuf;
  110. }
  111.  
  112. /* FreeCircularBuffer - Frees the memory for the given CIRCULARBUFFER 
  113.  * structure and the memory for the buffer it references.
  114.  *
  115.  * Params:  lpBuf - Points to the CIRCULARBUFFER to be freed.
  116.  *
  117.  * Return:  void
  118.  */
  119. void FreeCircularBuffer(LPCIRCULARBUFFER lpBuf)
  120. {
  121.     HANDLE hMem;
  122.     
  123.     /* Free the buffer itself.
  124.      */
  125. #ifndef _WIN32
  126.     GlobalSmartPageUnlock((HGLOBAL)HIWORD(lpBuf->lpStart));
  127. #endif
  128.     GlobalUnlock(lpBuf->hBuffer);
  129.     GlobalFree(lpBuf->hBuffer);
  130.     
  131.     /* Free the CIRCULARBUFFER structure.
  132.      */
  133.     hMem = lpBuf->hSelf;
  134. #ifndef _WIN32
  135.     GlobalSmartPageUnlock((HGLOBAL)HIWORD(lpBuf));
  136. #endif
  137.     GlobalUnlock(hMem);
  138.     GlobalFree(hMem);
  139. }
  140.  
  141. /* GetEvent - Gets a MIDI event from the circular input buffer.  Events
  142.  *  are removed from the buffer.  The corresponding PutEvent() function
  143.  *  is called by the low-level callback function, so it must reside in
  144.  *  the callback DLL.  PutEvent() is defined in the CALLBACK.C module.
  145.  *
  146.  * Params:  lpBuf - Points to the circular buffer.
  147.  *          lpEvent - Points to an EVENT structure that is filled with the
  148.  *              retrieved event.
  149.  *
  150.  * Return:  Returns non-zero if successful, zero if there are no 
  151.  *   events to get.
  152.  */
  153. WORD FAR PASCAL GetEvent(LPCIRCULARBUFFER lpBuf, LPEVENT lpEvent)
  154. {
  155.     /* If no event available, return.
  156.      */
  157.     if(lpBuf->dwCount <= 0)
  158.         return 0;
  159.     
  160.     /* Get the event.
  161.      */
  162.     *lpEvent = *lpBuf->lpTail;
  163.     
  164.     /* Decrement the byte count, bump the tail pointer.
  165.      */
  166.     --lpBuf->dwCount;
  167.     ++lpBuf->lpTail;
  168.     
  169.     /* Wrap the tail pointer, if necessary.
  170.      */
  171.     if(lpBuf->lpTail >= lpBuf->lpEnd)
  172.         lpBuf->lpTail = lpBuf->lpStart;
  173.  
  174.     return 1;
  175. }
  176.