|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.