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

1.1       root        1: /* midimon.c - WinMain() and WndProc() functions for MIDIMon, along
                      2:  *      with some initialization and error reporting functions.
                      3:  *
                      4:  * MIDIMon is a Windows with Multimedia application that records and displays 
                      5:  *  incoming MIDI information.  It uses a low-level callback function to 
                      6:  *  get timestamped MIDI input.  The callback function puts the incoming
                      7:  *  MIDI event information (source device, timestamp, and raw MIDI
                      8:  *  data) in a circular input buffer and notifies the application by posting 
                      9:  *  a MM_MIDIINPUT message.  When the application processes the MM_MIDIINPUT
                     10:  *  message, it removes the MIDI event from the input buffer and puts it in
                     11:  *  a display buffer.  Information in the display buffer is converted to
                     12:  *  text and displayed in a scrollable window.  Incoming MIDI data can be sent
                     13:  *  to the MIDI Mapper if the user chooses.  Filtering is provided for the
                     14:  *  display buffer, but not for data sent to the Mapper.
                     15:  *
                     16:  *    (C) Copyright Microsoft Corp. 1991.  All rights reserved.
                     17:  *
                     18:  *    You have a royalty-free right to use, modify, reproduce and 
                     19:  *    distribute the Sample Files (and/or any modified version) in 
                     20:  *    any way you find useful, provided that you agree that 
                     21:  *    Microsoft has no warranty obligations or liability for any 
                     22:  *    Sample Application Files which are modified. 
                     23:  *
                     24:  */
                     25: 
                     26: #include <windows.h>
                     27: #include <mmsystem.h>
                     28: #include <stdio.h>
                     29: #include "midimon.h"
                     30: #include "about.h"
                     31: #include "circbuf.h"
                     32: #include "display.h"
                     33: #include "prefer.h"
                     34: #include "instdata.h"
                     35: #include "callback.h"
                     36: #include "filter.h"
                     37: 
                     38: HANDLE hInst;                           // Instance handle for application
                     39: char szAppName[20];                     // Application name
                     40: HWND hMainWnd;                          // Main window handle
                     41: HMIDIOUT hMapper = 0;                   // Handle to MIDI Mapper
                     42: UINT wNumDevices = 0;                   // Number of MIDI input devices opened
                     43: BOOL bRecordingEnabled = 1;             // Enable/disable recording flag
                     44: LONG nNumBufferLines = 0;               // Number of lines in display buffer
                     45: RECT rectScrollClip;                    // Clipping rectangle for scrolling
                     46: 
                     47: LPCIRCULARBUFFER lpInputBuffer;         // Input buffer structure
                     48: LPDISPLAYBUFFER lpDisplayBuffer;        // Display buffer structure
                     49: PREFERENCES preferences;                // User preferences structure
                     50: EVENT incomingEvent;                    // Incoming MIDI event structure
                     51: 
                     52: MIDIINCAPS midiInCaps[MAX_NUM_DEVICES]; // Device capabilities structures
                     53: HMIDIIN hMidiIn[MAX_NUM_DEVICES];       // MIDI input device handles
                     54: 
                     55: // Callback instance data pointers
                     56: LPCALLBACKINSTANCEDATA lpCallbackInstanceData[MAX_NUM_DEVICES];
                     57: 
                     58: // Display filter structure
                     59: FILTER filter = {
                     60:                     0, 0, 0, 0, 0, 0, 0, 0, 
                     61:                     0, 0, 0, 0, 0, 0, 0, 0, 
                     62:                     0, 0, 0, 0, 0, 0, 0, 0, 
                     63:                     0, 0, 0, 0, 0, 0, 0, 0
                     64:                 };
                     65: 
                     66: // Virtual key to scroll message translation structure
                     67: KEYTOSCROLL keyToScroll [] = { 
                     68:                                 VK_HOME,  WM_VSCROLL, SB_TOP,
                     69:                                 VK_END,   WM_VSCROLL, SB_BOTTOM,
                     70:                                 VK_PRIOR, WM_VSCROLL, SB_PAGEUP,
                     71:                                 VK_NEXT,  WM_VSCROLL, SB_PAGEDOWN,
                     72:                                 VK_UP,    WM_VSCROLL, SB_LINEUP,
                     73:                                 VK_DOWN,  WM_VSCROLL, SB_LINEDOWN,
                     74:                                 VK_LEFT,  WM_HSCROLL, SB_LINEUP,
                     75:                                 VK_RIGHT, WM_HSCROLL, SB_LINEDOWN 
                     76:                              };
                     77: 
                     78: #define NUMKEYS (sizeof (keyToScroll) / sizeof (keyToScroll[0]))
                     79: 
                     80: 
                     81:                                                                         //
                     82: /* WinMain - Entry point for MIDIMon.
                     83:  */
                     84: int PASCAL WinMain(hInstance,hPrevInstance,lpszCmdLine,cmdShow)
                     85: HANDLE hInstance,hPrevInstance;
                     86: LPSTR lpszCmdLine;
                     87: int cmdShow;
                     88: {
                     89:     MSG msg;
                     90:     UINT  wRtn;
                     91:     PREFERENCES preferences;
                     92:     char szErrorText[256];
                     93:     unsigned int i;
                     94: 
                     95:     UNREFERENCED_PARAMETER(lpszCmdLine);
                     96: 
                     97:     hInst = hInstance;
                     98: 
                     99:     /* Get preferred user setup.
                    100:      */
                    101:     getPreferences(&preferences);
                    102:     
                    103:     /* Initialize application.
                    104:      */
                    105:     LoadString(hInstance, IDS_APPNAME, szAppName, sizeof(szAppName)); 
                    106:     if (hPrevInstance || !InitFirstInstance(hInstance))
                    107:         return 0;
                    108: 
                    109:     /* Create a display window.
                    110:      */
                    111:     hMainWnd = CreateWindow(szAppName,
                    112:                         szAppName,
                    113:                         WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
                    114:                         preferences.iInitialX,
                    115:                         preferences.iInitialY,
                    116:                         preferences.iInitialW,
                    117:                         preferences.iInitialH,
                    118:                         (HWND)NULL,
                    119:                         (HMENU)NULL,
                    120:                         hInstance,
                    121:                         (LPSTR)NULL);
                    122: 
                    123:     if (!hMainWnd)
                    124:         return 1;
                    125: 
                    126:     /* Hide scroll bars for now.
                    127:      */
                    128:     SetScrollRange(hMainWnd, SB_VERT, 0, 0, FALSE);
                    129:     SetScrollRange(hMainWnd, SB_HORZ, 0, 0, FALSE);
                    130:     
                    131:     /* Show the display window.
                    132:      */
                    133:     ShowWindow(hMainWnd, cmdShow);
                    134:     UpdateWindow(hMainWnd);
                    135:     
                    136:     /* Get the number of MIDI input devices.  Then get the capabilities of
                    137:      * each device.  We don't use the capabilities information right now,
                    138:      * but we could use it to report the name of the device that received
                    139:      * each MIDI event.
                    140:      */
                    141:     wNumDevices = midiInGetNumDevs();
                    142:     if (!wNumDevices) {
                    143:         Error("There are no MIDI input devices.");
                    144:         PostQuitMessage(0);
                    145:     }
                    146:     for (i=0; (i<wNumDevices) && (i<MAX_NUM_DEVICES); i++) {
                    147:         wRtn = midiInGetDevCaps(i, (LPMIDIINCAPS) &midiInCaps[i],
                    148:                                 sizeof(MIDIINCAPS));
                    149:         if(wRtn) {
                    150:             midiInGetErrorText(wRtn, (LPSTR)szErrorText, 
                    151:                                sizeof(szErrorText));
                    152:             Error(szErrorText);
                    153:         }
                    154:     }
                    155: 
                    156:     /* Allocate a circular buffer for low-level MIDI input.  This buffer
                    157:      * is filled by the low-level callback function and emptied by the
                    158:      * application when it receives MM_MIDIINPUT messages.
                    159:      */
                    160:     lpInputBuffer = AllocCircularBuffer(
                    161:                         (DWORD)(INPUT_BUFFER_SIZE * sizeof(EVENT)));
                    162:     if (lpInputBuffer == NULL) {
                    163:         Error("Not enough memory available for input buffer.");
                    164:         return 1;
                    165:     }
                    166: 
                    167:     /* Allocate a display buffer.  Incoming events from the circular input
                    168:      * buffer are put into this buffer for display.
                    169:      */
                    170:     lpDisplayBuffer = AllocDisplayBuffer((DWORD)(DISPLAY_BUFFER_SIZE));
                    171:     if (lpDisplayBuffer == NULL) {
                    172:         Error("Not enough memory available for display buffer.");
                    173:         FreeCircularBuffer(lpInputBuffer);
                    174:         return 1;
                    175:     }
                    176: 
                    177:     /* Open all MIDI input devices after allocating and setting up
                    178:      * instance data for each device.  The instance data is used to
                    179:      * pass buffer management information between the application and
                    180:      * the low-level callback function.  It also includes a device ID,
                    181:      * a handle to the MIDI Mapper, and a handle to the application's
                    182:      * display window, so the callback can notify the window when input
                    183:      * data is available.  A single callback function is used to service
                    184:      * all opened input devices.
                    185:      */
                    186:     for (i=0; (i<wNumDevices) && (i<MAX_NUM_DEVICES); i++)
                    187:     {
                    188:         if ((lpCallbackInstanceData[i] = AllocCallbackInstanceData()) == NULL)
                    189:         {
                    190:             Error("Not enough memory available.");
                    191:             FreeCircularBuffer(lpInputBuffer);
                    192:             FreeDisplayBuffer(lpDisplayBuffer);
                    193:             return 1;
                    194:         }
                    195:         lpCallbackInstanceData[i]->hWnd = hMainWnd;         
                    196:         lpCallbackInstanceData[i]->dwDevice = i;
                    197:         lpCallbackInstanceData[i]->lpBuf = lpInputBuffer;
                    198:         lpCallbackInstanceData[i]->hMapper = hMapper;
                    199:         
                    200:         wRtn = midiInOpen((LPHMIDIIN)&hMidiIn[i],
                    201:                           i,
                    202:                           (DWORD)midiInputHandler,
                    203:                           (DWORD)lpCallbackInstanceData[i],
                    204:                           CALLBACK_FUNCTION);
                    205:         if(wRtn)
                    206:         {
                    207:             FreeCallbackInstanceData(lpCallbackInstanceData[i]);
                    208:             midiInGetErrorText(wRtn, (LPSTR)szErrorText, sizeof(szErrorText));
                    209:             Error(szErrorText);
                    210:         }
                    211:     }
                    212: 
                    213:     /* Start MIDI input.
                    214:      */
                    215:     for (i=0; (i<wNumDevices) && (i<MAX_NUM_DEVICES); i++) {
                    216:         if (hMidiIn[i])
                    217:             midiInStart(hMidiIn[i]);
                    218:     }
                    219: 
                    220:     /* Standard Windows message processing loop.  We don't drop out of
                    221:      * this loop until the user quits the application.
                    222:      */
                    223:     while (GetMessage(&msg, NULL, 0, 0)) {
                    224:          TranslateMessage(&msg);
                    225:          DispatchMessage(&msg);
                    226:     }
                    227: 
                    228:     /* Stop, reset, close MIDI input.  Free callback instance data.
                    229:      */
                    230:     for (i=0; (i<wNumDevices) && (i<MAX_NUM_DEVICES); i++) {
                    231:         if (hMidiIn[i]) {
                    232:             midiInStop(hMidiIn[i]);
                    233:             midiInReset(hMidiIn[i]);
                    234:             midiInClose(hMidiIn[i]);
                    235:             FreeCallbackInstanceData(lpCallbackInstanceData[i]);
                    236:         }
                    237:     }
                    238: 
                    239:     /* Close the MIDI Mapper, if it's open.
                    240:      */
                    241:     if (hMapper)
                    242:         midiOutClose(hMapper);
                    243:     
                    244:     /* Free input and display buffers.
                    245:      */
                    246:     FreeCircularBuffer(lpInputBuffer);
                    247:     FreeDisplayBuffer(lpDisplayBuffer);
                    248: 
                    249:     return (msg.wParam);
                    250: }
                    251: 
                    252:                                                                         //
                    253: /* WndProc - Main window procedure function.
                    254:  */
                    255: LRESULT FAR PASCAL WndProc(
                    256:   HWND   hWnd,
                    257:   UINT   message,
                    258:   WPARAM  wParam,
                    259:   LPARAM  lParam)
                    260: {
                    261:     PAINTSTRUCT ps;
                    262:     HFONT hFont;
                    263:     HBRUSH hBrush;
                    264: //!!    HPEN hPen;
                    265:     HDC hDC;
                    266:     TEXTMETRIC tm;
                    267:     static BOOL  bWindowCreated = 0;
                    268:     static LONG         wChar, hChar;
                    269:     static LONG  maxClientWidth;
                    270:     static LONG         wClient, hClient;
                    271:     static LONG         nVscrollMax = 0;
                    272:     static LONG         nHscrollMax = 0;
                    273:     static LONG         nVscrollPos = 0;
                    274:     static LONG         nHscrollPos = 0;
                    275:     static LONG  nNumCharsPerLine = 0;
                    276:     static LONG  nNumDisplayLines = 0;
                    277:     static LONG  nNumDisplayChars = 0;
                    278:     BOOL        bNeedToUpdate = FALSE;
                    279:     LONG        nVscrollInc, nHscrollInc;
                    280:     LONG        nPaintBeg, nPaintEnd;
                    281:     LONG  i;
                    282:     SIZE  size;
                    283:         
                    284:     char szDisplayTextBuffer[120];
                    285: 
                    286:     switch(message)
                    287:     {
                    288:         case WM_CREATE:
                    289:             hDC = GetDC(hWnd);
                    290: 
                    291:             /* Set the font we want to use.
                    292:              */
                    293:             hFont = GetStockObject(ANSI_FIXED_FONT);
                    294:             SelectObject(hDC, hFont);
                    295:             
                    296:             /* Get text metrics and calculate the number of characters
                    297:              * per line and the maximum width required for the client area.
                    298:              */
                    299:             GetTextMetrics(hDC, &tm);
                    300:            wChar = (LONG) tm.tmAveCharWidth;
                    301:            hChar = (LONG) (tm.tmHeight + tm.tmExternalLeading);
                    302:            nNumCharsPerLine = sizeof(LABEL) - 1;
                    303: 
                    304:            GetTextExtentPoint(hDC,
                    305:                               szDisplayTextBuffer,
                    306:                               sprintf(szDisplayTextBuffer, LABEL),
                    307:                               &size);
                    308:            maxClientWidth = size.cx;
                    309: 
                    310:             ReleaseDC(hWnd, hDC);
                    311:             
                    312:             bWindowCreated = 1;
                    313:             break;
                    314: 
                    315:         case WM_SIZE:
                    316:            hClient = (LONG) HIWORD(lParam);
                    317:            wClient = (LONG) LOWORD(lParam);
                    318: 
                    319:             /* Get new client area and adjust scroll clip rectangle.
                    320:              */
                    321:             GetClientRect(hWnd, (LPRECT)&rectScrollClip);
                    322:             rectScrollClip.top += hChar;
                    323:             
                    324:             /* Calculate new display metrics.  We subtract 1 from
                    325:              * nNumDisplayLines to allow room for the label line.
                    326:              */
                    327:             nNumDisplayLines = hClient / hChar - 1;
                    328:             nNumDisplayChars = wClient / wChar;
                    329: 
                    330:             /* Calculate and set new scroll bar calibrations.
                    331:              */
                    332:            nVscrollMax = (LONG) max(0, nNumBufferLines - nNumDisplayLines);
                    333:            nVscrollPos = (LONG) min(nVscrollPos, nVscrollMax);
                    334:            nHscrollMax = (LONG) max(0, nNumCharsPerLine - nNumDisplayChars);
                    335:            nHscrollPos = (LONG) min(nHscrollPos, nHscrollMax);
                    336:             SetScrollRange(hWnd, SB_VERT, 0, nVscrollMax, FALSE);
                    337:             SetScrollPos(hWnd, SB_VERT, nVscrollPos, TRUE);
                    338:             SetScrollRange(hWnd, SB_HORZ, 0, nHscrollMax, FALSE);
                    339:             SetScrollPos(hWnd, SB_HORZ, nHscrollPos, TRUE);
                    340:             break;
                    341: 
                    342:         case WM_GETMINMAXINFO:
                    343:             /* Limit the maximum width of the window.
                    344:              */
                    345:            if(bWindowCreated) {
                    346:                ((LPPOINT)lParam)[4].x = maxClientWidth +
                    347:                                         (2 * GetSystemMetrics(SM_CXFRAME)) +
                    348:                                         (GetSystemMetrics(SM_CXVSCROLL));
                    349:            }
                    350: 
                    351:   //           *((LPWORD)lParam + 8) = maxClientWidth +
                    352:   //                                    (2 * GetSystemMetrics(SM_CXFRAME)) +
                    353:   //                                   (GetSystemMetrics(SM_CXVSCROLL));
                    354:             break;
                    355:             
                    356:         case WM_COMMAND:
                    357:             /* Process menu messages. 
                    358:              */
                    359:             CommandMsg(hWnd, wParam, lParam); 
                    360:             break;
                    361: 
                    362:         case WM_VSCROLL:
                    363:             /* Determine how much to scroll vertically.
                    364:              */
                    365:            switch (LOWORD(wParam))
                    366:             {
                    367:                 case SB_TOP:
                    368:                     nVscrollInc = -nVscrollPos;
                    369:                     break;
                    370:                     
                    371:                 case SB_BOTTOM:
                    372:                     nVscrollInc = nVscrollMax - nVscrollPos;
                    373:                     break;
                    374: 
                    375:                 case SB_LINEUP:
                    376:                     nVscrollInc = -1;
                    377:                     break;
                    378: 
                    379:                 case SB_LINEDOWN:
                    380:                     nVscrollInc = 1;
                    381:                     break;
                    382: 
                    383:                 case SB_PAGEUP:
                    384:                     nVscrollInc = min (-1, -nNumDisplayLines);
                    385:                     break;
                    386: 
                    387:                 case SB_PAGEDOWN:
                    388:                    nVscrollInc = (LONG) max(1, nNumDisplayLines);
                    389:                     break;
                    390: 
                    391:                 case SB_THUMBTRACK:
                    392:                    nVscrollInc = ((LONG)HIWORD(wParam) - nVscrollPos);
                    393:                     break;
                    394: 
                    395:                 default:
                    396:                     nVscrollInc = 0;
                    397:             
                    398:             }
                    399:             
                    400:             /* Limit the scroll range and do the scroll.  We use the
                    401:              * rectScrollClip rectangle because we don't want to scroll
                    402:              * the entire window, only the part below the display label line.
                    403:              */
                    404:            if(nVscrollInc = max(-nVscrollPos,
                    405:                                 min(nVscrollInc,
                    406:                                     nVscrollMax - nVscrollPos)))
                    407:             {
                    408:                 nVscrollPos += nVscrollInc;
                    409:                 ScrollWindow(hWnd, 0, -hChar * nVscrollInc,
                    410:                               (LPRECT)&rectScrollClip,
                    411:                               (LPRECT)&rectScrollClip);
                    412:                 UpdateWindow(hWnd);
                    413:                 SetScrollPos(hWnd, SB_VERT, nVscrollPos, TRUE);
                    414:             }
                    415:             break;
                    416: 
                    417:         case WM_HSCROLL:
                    418:             /* Determine how much to scroll horizontally.
                    419:              */
                    420:            switch (LOWORD(wParam))
                    421:             {
                    422:                 case SB_LINEUP:
                    423:                     nHscrollInc = -1;
                    424:                     break;
                    425: 
                    426:                 case SB_LINEDOWN:
                    427:                     nHscrollInc = 1;
                    428:                     break;
                    429: 
                    430:                 case SB_PAGEUP:
                    431:                    nHscrollInc = (LONG) min(-1, -nNumDisplayChars);
                    432:                     break;
                    433: 
                    434:                 case SB_PAGEDOWN:
                    435:                    nHscrollInc = (LONG) max(1, nNumDisplayChars);
                    436:                     break;
                    437: 
                    438:                 case SB_THUMBTRACK:
                    439:                    nHscrollInc = ((LONG)HIWORD(wParam) - nHscrollPos);
                    440:                     break;
                    441: 
                    442:                 default:
                    443:                     nHscrollInc = 0;
                    444:             }
                    445:             
                    446:             /* Limit the scroll range and to the scroll.
                    447:              */
                    448:            if(nHscrollInc = max(-nHscrollPos,
                    449:                                 min(nHscrollInc,
                    450:                                     nHscrollMax - nHscrollPos)))
                    451:             {
                    452:                 nHscrollPos += nHscrollInc;
                    453:                 ScrollWindow(hWnd, -wChar * nHscrollInc, 0, NULL, NULL);
                    454:                 UpdateWindow(hWnd);
                    455:                 SetScrollPos(hWnd, SB_HORZ, nHscrollPos, TRUE);
                    456:             }
                    457:             break;
                    458: 
                    459:         case WM_KEYDOWN:
                    460:             /* Translate keystrokes to scroll message.
                    461:              */
                    462:             for (i = 0; i < NUMKEYS; i++)
                    463:                 if (wParam == keyToScroll[i].wVirtKey)
                    464:                 {
                    465:                     SendMessage(hWnd, keyToScroll[i].iMessage,
                    466:                                 keyToScroll[i].wRequest, 0L);
                    467:                     break;
                    468:                 }
                    469:             break;
                    470: 
                    471:         case WM_PAINT:
                    472:             BeginPaint(hWnd, &ps);
                    473: 
                    474:             hBrush = CreateSolidBrush(GetSysColor(COLOR_APPWORKSPACE));
                    475:             FillRect(ps.hdc, &ps.rcPaint, hBrush);
                    476:             DeleteObject(hBrush);
                    477: 
                    478:             /* Set up text attributes.
                    479:              */
                    480:             hFont = GetStockObject(ANSI_FIXED_FONT);
                    481:             SelectObject(ps.hdc, hFont);
                    482:             SetBkMode(ps.hdc, TRANSPARENT);
                    483: 
                    484:             /* Put up the display label if we're asked to repaint the
                    485:              * top line of the screen.
                    486:              */
                    487:            if(ps.rcPaint.top < hChar)
                    488:             {
                    489:                 TextOut(ps.hdc, wChar * (0 - nHscrollPos),
                    490:                         0, szDisplayTextBuffer,
                    491:                         sprintf(szDisplayTextBuffer, LABEL));
                    492:                MoveToEx(ps.hdc, wChar * (0 - nHscrollPos), hChar - 1, NULL);
                    493:                 LineTo(ps.hdc, wClient, hChar - 1);
                    494: 
                    495:                 ps.rcPaint.top = hChar;
                    496:             }
                    497:                 
                    498:             /* Calculate the beginning and ending line numbers that we need
                    499:              * to paint.  These line numbers refer to lines in the display
                    500:              * buffer, not to lines in the display window.
                    501:              */
                    502:            nPaintBeg = max (0, nVscrollPos + ps.rcPaint.top / hChar - 1);
                    503:             nPaintEnd = min(nNumBufferLines,
                    504:                               nVscrollPos + ps.rcPaint.bottom / hChar + 1);
                    505: 
                    506:             /* Get the appropriate events from the display buffer, convert
                    507:              * to a text string and paint the text on the display.
                    508:              */
                    509:             for (i = nPaintBeg; i < nPaintEnd; i++)
                    510:             {
                    511:                 GetDisplayEvent(lpDisplayBuffer, (LPEVENT)&incomingEvent, i);
                    512:                 TextOut(ps.hdc, 
                    513:                         wChar * (0 - nHscrollPos),
                    514:                         hChar * (1 - nVscrollPos + i),
                    515:                         szDisplayTextBuffer, 
                    516:                         GetDisplayText(szDisplayTextBuffer,
                    517:                                        (LPEVENT)&incomingEvent));
                    518:             }
                    519:                 
                    520:             EndPaint(hWnd, &ps);
                    521:             break;
                    522: 
                    523:         case WM_DESTROY:
                    524:             PostQuitMessage(0);
                    525:             break;
                    526: 
                    527:         case MM_MIDIINPUT:
                    528:             /* This is a custom message sent by the low level callback
                    529:              * function telling us that there is at least one MIDI event
                    530:              * in the input buffer.  We empty the input buffer, and put
                    531:              * each event in the display buffer, if it's not filtered.
                    532:              * If the input buffer is being filled as fast we can empty
                    533:              * it, then we'll stay in this loop and not process any other
                    534:              * Windows messages, or yield to other applications.  We need
                    535:              * something to restrict the amount of time we spend here...
                    536:              */
                    537:             while(GetEvent(lpInputBuffer, (LPEVENT)&incomingEvent))
                    538:             {
                    539:                 if(!bRecordingEnabled)
                    540:                     continue;
                    541: 
                    542:                 if(!CheckEventFilter((LPEVENT)&incomingEvent,
                    543:                                     (LPFILTER)&filter))
                    544:                 {
                    545:                     AddDisplayEvent(lpDisplayBuffer, 
                    546:                                     (LPEVENT)&incomingEvent);
                    547:                     ++nNumBufferLines;
                    548:                     nNumBufferLines = min(nNumBufferLines,
                    549:                                          DISPLAY_BUFFER_SIZE - 1);
                    550:                    bNeedToUpdate = TRUE;
                    551:                 }
                    552:             }
                    553:             
                    554:             /* Recalculate vertical scroll bar range, and force
                    555:              * the display to be updated.
                    556:             */
                    557: 
                    558:            if (bNeedToUpdate) {
                    559:              nVscrollMax = (LONG) max(0, nNumBufferLines - nNumDisplayLines);
                    560:              nVscrollPos = nVscrollMax;
                    561:              SetScrollRange(hWnd, SB_VERT, 0, nVscrollMax, FALSE);
                    562:              SetScrollPos(hWnd, SB_VERT, nVscrollPos, TRUE);
                    563:              InvalidateRect(hMainWnd, (LPRECT)&rectScrollClip, 0);
                    564:              UpdateWindow(hMainWnd);
                    565:            }
                    566:             
                    567:             break;
                    568: 
                    569:         default:
                    570:             return DefWindowProc(hWnd, message, wParam, lParam);
                    571:             break;
                    572:     }
                    573:     return NULL;
                    574: }
                    575: 
                    576:                                                                         //
                    577: /* CommandMsg - Processes WM_COMMAND messages.
                    578:  *
                    579:  * Params:  hWnd - Handle to the window receiving the message.
                    580:  *         wParam - Parameter of the WM_COMMAND message.
                    581:  *         lParam - Parameter of the WM_COMMAND message.
                    582:  *
                    583:  * Return:  void
                    584:  */
                    585: VOID  CommandMsg(
                    586:   HWND   hWnd,
                    587:   WPARAM  wParam,
                    588:   LPARAM  lParam)
                    589: {
                    590:     PREFERENCES preferences;
                    591:     RECT rectWindow;
                    592:     UINT  wRtn;
                    593:     HMENU hMenu;
                    594:     unsigned int i;
                    595:     char szErrorText[80];
                    596:     WORD  wCommand;
                    597: 
                    598:     UNREFERENCED_PARAMETER(lParam);
                    599: 
                    600:     wCommand = LOWORD(wParam);
                    601:     
                    602:     /* Process any WM_COMMAND messages we want */
                    603:     switch (wCommand) {
                    604:         case IDM_ABOUT:
                    605:             About(hInst, hWnd);
                    606:             break;
                    607: 
                    608:         case IDM_EXIT:
                    609:             PostMessage(hWnd, WM_CLOSE, 0, 0l);
                    610:             break;
                    611: 
                    612:         case IDM_SENDTOMAPPER:
                    613:             /* We use hMapper as a toggle between sending events to the
                    614:              * Mapper and not sending events.
                    615:              */
                    616:             if(hMapper) {
                    617:                 /* Close the Mapper and reset hMapper.  Uncheck the menu item.
                    618:                  * Clear Mapper handle in the instance data for each device.
                    619:                  */
                    620:                 wRtn = midiOutClose(hMapper);
                    621:                 if(wRtn != 0)
                    622:                 {
                    623:                     midiOutGetErrorText(wRtn, (LPSTR)szErrorText, 
                    624:                                         sizeof(szErrorText));
                    625:                     Error(szErrorText);
                    626:                 }
                    627:                 hMapper = 0;
                    628: 
                    629:                 for (i=0; (i<wNumDevices) && (i<MAX_NUM_DEVICES); i++)
                    630:                     lpCallbackInstanceData[i]->hMapper = hMapper;
                    631: 
                    632:                DoMenuItemCheck(hWnd, wCommand, FALSE);
                    633:             }
                    634:             
                    635:             else {
                    636:                 /* Open the MIDI Mapper, put the Mapper handle in the instance
                    637:                  * data for each device and check the menu item.
                    638:                  */
                    639:                wRtn = midiOutOpen((LPHMIDIOUT) &hMapper, (UINT) MIDIMAPPER,
                    640:                                     0L, 0L, 0L);
                    641:                                 
                    642:                 if(wRtn != 0) {             // error opening Mapper
                    643:                     midiOutGetErrorText(wRtn, (LPSTR)szErrorText, 
                    644:                                         sizeof(szErrorText));
                    645:                     Error(szErrorText);
                    646:                     hMapper = 0;
                    647:                 }
                    648: 
                    649:                 else {                      // Mapper opened successfully
                    650:                     for (i=0; (i<wNumDevices) && (i<MAX_NUM_DEVICES); i++)
                    651:                         lpCallbackInstanceData[i]->hMapper = hMapper;
                    652: 
                    653:                    DoMenuItemCheck(hWnd, wCommand, TRUE);
                    654:                 }
                    655:             }
                    656:             
                    657:             break;
                    658:             
                    659:         case IDM_SAVESETUP:
                    660:             /* Save the current location and size of the display window
                    661:              * in the MIDIMON.INI file.
                    662:              */
                    663:             GetWindowRect(hMainWnd, (LPRECT)&rectWindow);
                    664:             preferences.iInitialX = rectWindow.left;
                    665:             preferences.iInitialY = rectWindow.top;
                    666:             preferences.iInitialW = rectWindow.right - rectWindow.left;
                    667:             preferences.iInitialH = rectWindow.bottom - rectWindow.top;
                    668: 
                    669:             setPreferences((LPPREFERENCES) &preferences);
                    670:             break;
                    671: 
                    672:         case IDM_STARTSTOP:
                    673:             /* Toggle between recording into the display buffer and not
                    674:              * recording.  Toggle the menu item between "Start" to "Stop"
                    675:              * accordingly.
                    676:              */
                    677:             hMenu = GetMenu(hWnd);
                    678:             if(bRecordingEnabled)
                    679:             {
                    680:                 ModifyMenu(hMenu, IDM_STARTSTOP, MF_BYCOMMAND, IDM_STARTSTOP,
                    681:                            "&Start");
                    682:                 bRecordingEnabled = 0;
                    683:             }
                    684:             else
                    685:             {
                    686:                 ModifyMenu(hMenu, IDM_STARTSTOP, MF_BYCOMMAND, IDM_STARTSTOP,
                    687:                            "&Stop");
                    688:                 bRecordingEnabled = 1;
                    689:             }
                    690:             DrawMenuBar(hWnd);
                    691:             break;
                    692: 
                    693:         case IDM_CLEAR:
                    694:             /* Reset the display buffer, recalibrate the scroll bars,
                    695:              * and force an update of the display.
                    696:              */
                    697:             ResetDisplayBuffer(lpDisplayBuffer);
                    698:             nNumBufferLines = 0;
                    699:             SetScrollRange(hWnd, SB_VERT, 0, 0, FALSE);
                    700: 
                    701:             InvalidateRect(hWnd, (LPRECT)&rectScrollClip, 0);
                    702:             UpdateWindow(hWnd);
                    703: 
                    704:             break;
                    705:             
                    706:         /* Set up filter structure for MIDI channel filtering.
                    707:          */
                    708:         case IDM_FILTCHAN0:
                    709:         case IDM_FILTCHAN1:
                    710:         case IDM_FILTCHAN2:
                    711:         case IDM_FILTCHAN3:
                    712:         case IDM_FILTCHAN4:
                    713:         case IDM_FILTCHAN5:
                    714:         case IDM_FILTCHAN6:
                    715:         case IDM_FILTCHAN7:
                    716:         case IDM_FILTCHAN8:
                    717:         case IDM_FILTCHAN9:
                    718:         case IDM_FILTCHAN10:
                    719:         case IDM_FILTCHAN11:
                    720:         case IDM_FILTCHAN12:
                    721:         case IDM_FILTCHAN13:
                    722:         case IDM_FILTCHAN14:
                    723:         case IDM_FILTCHAN15:
                    724:            filter.channel[wCommand - IDM_FILTCHAN0] =
                    725:                !filter.channel[wCommand - IDM_FILTCHAN0];
                    726:            DoMenuItemCheck(hWnd, wCommand,
                    727:                filter.channel[wCommand - IDM_FILTCHAN0]);
                    728:             break;
                    729:             
                    730:         /* Setup filter structure for MIDI event filtering.
                    731:          */
                    732:         case IDM_NOTEOFF:
                    733:             filter.event.noteOff = !filter.event.noteOff;
                    734:            DoMenuItemCheck(hWnd, wCommand, filter.event.noteOff);
                    735:             break;
                    736:         case IDM_NOTEON:
                    737:             filter.event.noteOn = !filter.event.noteOn;
                    738:            DoMenuItemCheck(hWnd, wCommand, filter.event.noteOn);
                    739:             break;
                    740:         case IDM_POLYAFTERTOUCH:
                    741:             filter.event.keyAftertouch = !filter.event.keyAftertouch;
                    742:            DoMenuItemCheck(hWnd, wCommand, filter.event.keyAftertouch);
                    743:             break;
                    744:         case IDM_CONTROLCHANGE:
                    745:             filter.event.controller = !filter.event.controller;
                    746:            DoMenuItemCheck(hWnd, wCommand, filter.event.controller);
                    747:             break;
                    748:         case IDM_PROGRAMCHANGE:
                    749:             filter.event.progChange = !filter.event.progChange;
                    750:            DoMenuItemCheck(hWnd, wCommand, filter.event.progChange);
                    751:             break;
                    752:         case IDM_CHANNELAFTERTOUCH:
                    753:             filter.event.chanAftertouch = !filter.event.chanAftertouch;
                    754:            DoMenuItemCheck(hWnd, wCommand, filter.event.chanAftertouch);
                    755:             break;
                    756:         case IDM_PITCHBEND:
                    757:             filter.event.pitchBend = !filter.event.pitchBend;
                    758:            DoMenuItemCheck(hWnd, wCommand, filter.event.pitchBend);
                    759:             break;
                    760:         case IDM_CHANNELMODE:
                    761:             filter.event.channelMode = !filter.event.channelMode;
                    762:            DoMenuItemCheck(hWnd, wCommand, filter.event.channelMode);
                    763:             break;
                    764:         case IDM_SYSTEMEXCLUSIVE:
                    765:             filter.event.sysEx = !filter.event.sysEx;
                    766:            DoMenuItemCheck(hWnd, wCommand, filter.event.sysEx);
                    767:             break;
                    768:         case IDM_SYSTEMCOMMON:
                    769:             filter.event.sysCommon = !filter.event.sysCommon;
                    770:            DoMenuItemCheck(hWnd, wCommand, filter.event.sysCommon);
                    771:             break;
                    772:         case IDM_SYSTEMREALTIME:
                    773:             filter.event.sysRealTime = !filter.event.sysRealTime;
                    774:            DoMenuItemCheck(hWnd, wCommand, filter.event.sysRealTime);
                    775:             break;
                    776:         case IDM_ACTIVESENSE:
                    777:             filter.event.activeSense = !filter.event.activeSense;
                    778:            DoMenuItemCheck(hWnd, wCommand, filter.event.activeSense);
                    779:             break;
                    780: 
                    781:         default:
                    782:             break;
                    783:     }
                    784: }
                    785: 
                    786:                                                                         //
                    787: /* InitFirstInstance - Performs initializaion for the first instance 
                    788:  *      of the application.
                    789:  *
                    790:  * Params:  hInstance - Instance handle.
                    791:  *
                    792:  * Return:  Returns 1 if there were no errors.  Otherwise, returns 0.
                    793:  */
                    794: BOOL InitFirstInstance(hInstance)
                    795: HANDLE hInstance;
                    796: {
                    797:     WNDCLASS wc;
                    798:     
                    799:     /* Define the class of window we want to register.
                    800:      */
                    801:     wc.lpszClassName    = szAppName;
                    802:     wc.style            = CS_HREDRAW | CS_VREDRAW;
                    803:     wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
                    804:     wc.hIcon            = LoadIcon(hInstance,"Icon");
                    805:     wc.lpszMenuName     = "Menu";
                    806:     wc.hbrBackground    = (HBRUSH)(COLOR_APPWORKSPACE + 1);
                    807:     wc.hInstance        = hInstance;
                    808:     wc.lpfnWndProc      = WndProc;
                    809:     wc.cbClsExtra       = 0;
                    810:     wc.cbWndExtra       = 0;
                    811:     
                    812:     if(!RegisterClass(&wc))
                    813:         return FALSE;
                    814:     
                    815:     return TRUE;
                    816: }
                    817: 
                    818:                                                                         //
                    819: /* DoMenuItemCheck - Checks and unchecks menu items.
                    820:  *
                    821:  * Params:  hWnd - Window handle for window associated with menu items.
                    822:  *          wMenuItem - The menu ID for the menu item.
                    823:  *          newState - The new checked/unchecked state of the menu item.
                    824:  *
                    825:  * Return:  void
                    826: */
                    827: void  DoMenuItemCheck(
                    828:   HWND hWnd,
                    829:   WORD wMenuItem,
                    830:   BOOL newState)
                    831: {
                    832:     HMENU hMenu;
                    833:     
                    834:     hMenu = GetMenu(hWnd);
                    835:     CheckMenuItem(hMenu, wMenuItem, (newState ? MF_CHECKED: MF_UNCHECKED));
                    836: }
                    837: 
                    838: 
                    839: /* Error - Beeps and shows an error message.
                    840:  *
                    841:  * Params:  szMsg - Points to a NULL-terminated string containing the
                    842:  *              error message.
                    843:  *
                    844:  * Return:  Returns the return value from the MessageBox() call.
                    845:  *          Since this message box has only a single button, the
                    846:  *          return value isn't too meaningful.
                    847:  */
                    848: int Error(szMsg)
                    849: LPSTR szMsg;
                    850: {
                    851:     MessageBeep(0);
                    852:     return MessageBox(hMainWnd, szMsg, szAppName, MB_OK);
                    853: }

unix.superglobalmegacorp.com

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