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

Windows编程

开发平台:

Visual C++

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