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

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.  * display.c - Functions to manage the display buffer and convert a
  13.  *      MIDI event to a text string for display.
  14.  *
  15.  *      The display buffer is filled by the application's WndProc()
  16.  *      function when it receives an MM_MIDIINPUT message.  This message
  17.  *      is sent by the low-level callback function upon reception of a
  18.  *      MIDI event.  When the display buffer becomes full, newly added
  19.  *      events overwrite the oldest events in the buffer.
  20.  */
  21. #include <windows.h>
  22. #include <stdio.h>
  23. #include "midimon.h"
  24. #include "circbuf.h"
  25. #include "display.h"
  26. /* MIDI event-name strings
  27.  */
  28. char szEventNames[8][24] =
  29. {
  30.                     "Note Off",
  31.                     "Note On",
  32.                     "Key Aftertouch",
  33.                     "Control Change",
  34.                     "Program Change",
  35.                     "Channel Aftertouch",
  36.                     "Pitch Bend",
  37.                     "System Message"
  38. };
  39. char szSysMsgNames[16][24] =
  40. {
  41.                     "System Exclusive",
  42.                     "MTC Quarter Frame",
  43.                     "Song Position Pointer",
  44.                     "Song Select",
  45.                     "Undefined",
  46.                     "Undefined",
  47.                     "Tune Request",
  48.                     "System Exclusive End",
  49.                     "Timing Clock",
  50.                     "Undefined",
  51.                     "Start",
  52.                     "Continue",
  53.                     "Stop",
  54.                     "Undefined",
  55.                     "Active Sensing",
  56.                     "System Reset"
  57. };
  58. /* GetDisplayText - Takes a MIDI event and creates a text string for display.
  59.  *
  60.  * Params:  npText - Points to a string that the function fills.
  61.  *          lpEvent - Points to a MIDI event.
  62.  *
  63.  * Return:  The number of characters in the text string pointed to by npText.
  64.  */
  65. int GetDisplayText(NPSTR npText, LPEVENT lpEvent)
  66. {
  67.     BYTE bStatus, bStatusRaw, bChannel, bData1, bData2;
  68.     char chErr;
  69.     DWORD dwTimestamp;
  70.     bStatusRaw  = LOBYTE(LOWORD(lpEvent->data));
  71.     bStatus     = (BYTE) (bStatusRaw & (BYTE) 0xf0);
  72.     bChannel    = (BYTE) (bStatusRaw & (BYTE) 0x0f);
  73.     bData1      = HIBYTE(LOWORD(lpEvent->data));
  74.     bData2      = LOBYTE(HIWORD(lpEvent->data));
  75.     dwTimestamp = lpEvent->timestamp;
  76.     chErr       = (lpEvent->fdwEvent & EVNT_F_ERROR) ? '*' : ' ';
  77.     switch(bStatus)
  78.     {
  79.         /* Three byte events
  80.          */
  81.         case NOTEOFF:
  82.         case NOTEON:
  83.         case KEYAFTERTOUCH:
  84.         case CONTROLCHANGE:
  85.         case PITCHBEND:
  86.             /* A note on with a velocity of 0 is a note off
  87.              */
  88.             if((bStatus == NOTEON) && (bData2 == 0))
  89.                 bStatus = NOTEOFF;
  90.             return(sprintf(npText, FORMAT3, dwTimestamp, bStatusRaw, bData1,
  91.                     bData2, bChannel, chErr, &szEventNames[(bStatus-0x80) >> 4][0]));
  92.             break;
  93.         /* Two byte events
  94.          */
  95.         case PROGRAMCHANGE:
  96.         case CHANAFTERTOUCH:
  97.             return(sprintf(npText, FORMAT2, dwTimestamp, bStatusRaw, bData1,
  98.                     bChannel, chErr, &szEventNames[(bStatus-0x80) >> 4][0]));
  99.             break;
  100.         /* MIDI system events (0xf0 - 0xff)
  101.          */
  102.         case SYSTEMMESSAGE:
  103.             switch(bStatusRaw)
  104.             {
  105.                 /* Two byte system events
  106.                  */
  107.                 case MTCQUARTERFRAME:
  108.                 case SONGSELECT:
  109.                     return(sprintf(npText, FORMAT2X, dwTimestamp, bStatusRaw,
  110.                             bData1,
  111.                             chErr, 
  112.                             &szSysMsgNames[(bStatusRaw & 0x0f)][0]));
  113.                     break;
  114.                 /* Three byte system events
  115.                  */
  116.                 case SONGPOSPTR:
  117.                     return(sprintf(npText, FORMAT3X, dwTimestamp, bStatusRaw,
  118.                             bData1, bData2, chErr, 
  119.                             &szSysMsgNames[(bStatusRaw & 0x0f)][0]));
  120.                     break;
  121.                 /* One byte system events
  122.                  */
  123.                 default:
  124.                     return(sprintf(npText, FORMAT1X, dwTimestamp, bStatusRaw,
  125.                             chErr, &szSysMsgNames[(bStatusRaw & 0x0f)][0]));
  126.                     break;
  127.             }
  128.             break;
  129.         default:
  130.             return(sprintf(npText, FORMAT3X, dwTimestamp, bStatusRaw, bData1,
  131.                     bData2, chErr, GetStringRes(IDS_UNKNOWN_EVENT)));
  132.             break;
  133.     }
  134. }
  135. /* AddDisplayEvent - Puts a MIDI event in the display buffer.  The display
  136.  *      buffer is a circular buffer.  Once it is full, newly added events
  137.  *      overwrite the oldest events in the buffer.
  138.  *
  139.  * Params:  lpBuf - Points to the display buffer.
  140.  *          lpEvent - Points to a MIDI event.
  141.  *
  142.  * Return:  void
  143.  */
  144. void AddDisplayEvent(LPDISPLAYBUFFER lpBuf, LPEVENT lpEvent)
  145. {
  146.     /* Put the event in the buffer, bump the head pointer and byte count.
  147.      */
  148.     *lpBuf->lpHead = *lpEvent;
  149.     ++lpBuf->lpHead;
  150.     ++lpBuf->dwCount;
  151.     /* Wrap pointer, if necessary.
  152.      */
  153.     if(lpBuf->lpHead == lpBuf->lpEnd)
  154.         lpBuf->lpHead = lpBuf->lpStart;
  155.     /* A full buffer is a full buffer, no more.
  156.      */
  157.     lpBuf->dwCount = min(lpBuf->dwCount, lpBuf->dwSize);
  158. }
  159. /* GetDisplayEvent - Retrieves a MIDI event from the display buffer.
  160.  *      Unlike the input buffer, the event is not removed from the buffer.
  161.  *
  162.  * Params:  lpBuf - Points to the display buffer.
  163.  *          lpEvent - Points to an EVENT structure that is filled with
  164.  *              the retrieved MIDI event.
  165.  *          wNum - Specifies which event to retrieve.
  166.  *
  167.  * Return:  void
  168.  */
  169. void GetDisplayEvent(LPDISPLAYBUFFER lpBuf, LPEVENT lpEvent, DWORD wNum)
  170. {
  171.     LPEVENT lpFirstEvent, lpThisEvent;
  172.     /* Get pointer to the first (oldest) event in buffer.
  173.      */
  174.     if(lpBuf->dwCount < lpBuf->dwSize)      // buffer is not yet full
  175.         lpFirstEvent = lpBuf->lpStart;
  176.     else                                    // buffer is full
  177.         lpFirstEvent = lpBuf->lpHead;
  178.     /* Offset pointer to point to requested event; wrap pointer.
  179.      */
  180.     lpThisEvent = lpFirstEvent + wNum;
  181.     if(lpThisEvent >= lpBuf->lpEnd)
  182.         lpThisEvent = lpBuf->lpStart + (lpThisEvent - lpBuf->lpEnd);
  183.     /* Get the requested event.
  184.      */
  185.     *(lpEvent) = *lpThisEvent;
  186. }
  187. /* AllocDisplayBuffer - Allocates memory for a DISPLAYBUFFER structure
  188.  *      and a buffer of the specified size.  Each memory block is allocated
  189.  *      with GlobalAlloc() using GMEM_SHARE and GMEM_MOVEABLE flags and
  190.  *      locked with GlobalLock().  Since this buffer is only accessed by the
  191.  *      application, and not the low-level callback function, it does not
  192.  *      have to be page locked.
  193.  *
  194.  * Params:  dwSize - The size of the buffer, in events.
  195.  *
  196.  * Return:  A pointer to a DISPLAYBUFFER structure identifying the
  197.  *      allocated display buffer.  NULL if the buffer could not be allocated.
  198. */
  199. LPDISPLAYBUFFER AllocDisplayBuffer(DWORD dwSize)
  200. {
  201.     HANDLE hMem;
  202.     LPDISPLAYBUFFER lpBuf;
  203.     LPEVENT lpMem;
  204.     /* Allocate and lock a DISPLAYBUFFER structure.
  205.      */
  206.     hMem = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE,
  207.                        (DWORD)sizeof(DISPLAYBUFFER));
  208.     if(hMem == NULL)
  209.         return NULL;
  210.     lpBuf = (LPDISPLAYBUFFER)GlobalLock(hMem);
  211.     if(lpBuf == NULL)
  212.     {
  213.         GlobalFree(hMem);
  214.         return NULL;
  215.     }
  216.     /* Save the handle.
  217.      */
  218.     lpBuf->hSelf = hMem;
  219.     /* Allocate and lock memory for the actual buffer.
  220.      */
  221.     hMem = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, dwSize * sizeof(EVENT));
  222.     if(hMem == NULL)
  223.     {
  224.         GlobalUnlock(lpBuf->hSelf);
  225.         GlobalFree(lpBuf->hSelf);
  226.         return NULL;
  227.     }
  228.     lpMem = (LPEVENT)GlobalLock(hMem);
  229.     if(lpMem == NULL)
  230.     {
  231.         GlobalFree(hMem);
  232.         GlobalUnlock(lpBuf->hSelf);
  233.         GlobalFree(lpBuf->hSelf);
  234.         return NULL;
  235.     }
  236.     /* Set up the DISPLAYBUFFER structure.
  237.      */
  238.     lpBuf->hBuffer = hMem;
  239.     lpBuf->wError = 0;
  240.     lpBuf->dwSize = dwSize;
  241.     lpBuf->dwCount = 0L;
  242.     lpBuf->lpStart = lpMem;
  243.     lpBuf->lpEnd = lpMem + dwSize;
  244.     lpBuf->lpTail = lpMem;
  245.     lpBuf->lpHead = lpMem;
  246.     return lpBuf;
  247. }
  248. /* FreeDisplayBuffer - Frees the memory for a display buffer.
  249.  *
  250.  * Params:  lpBuf - Points to the DISPLAYBUFFER to be freed.
  251.  *
  252.  * Return:  void
  253.  */
  254. void FreeDisplayBuffer(LPDISPLAYBUFFER lpBuf)
  255. {
  256.     HANDLE hMem;
  257.     /* Unlock and free the buffer itself.
  258.      */
  259.     GlobalUnlock(lpBuf->hBuffer);
  260.     GlobalFree(lpBuf->hBuffer);
  261.     /* Unlock and free the DISPLAYBUFFER structure.
  262.      */
  263.     hMem = lpBuf->hSelf;
  264.     GlobalUnlock(hMem);
  265.     GlobalFree(hMem);
  266. }
  267. /* ResetDisplayBuffer - Empties a display buffer.
  268.  *
  269.  * Params:  lpBuf - Points to a display buffer.
  270.  *
  271.  * Return:  void
  272.  */
  273. void ResetDisplayBuffer(LPDISPLAYBUFFER lpBuf)
  274. {
  275.     /* Reset the pointers and event count.
  276.      */
  277.     lpBuf->lpHead = lpBuf->lpStart;
  278.     lpBuf->lpTail = lpBuf->lpStart;
  279.     lpBuf->dwCount = 0L;
  280.     lpBuf->wError = 0;
  281. }