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