Annotation of mstools/samples/midimon/display.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.