home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 19.ddi / SAMPLES / MIDIMON / CIRCBUF.C_ / CIRCBUF.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  4.3 KB  |  153 lines

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