Annotation of mstools/samples/midimon/display.c, revision 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.