home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 13 / midvue.c < prev    next >
C/C++ Source or Header  |  1992-03-18  |  12KB  |  375 lines

  1. /*---------------------------------------
  2.    MIDVUE.C -- MIDI Input Viewer
  3.                (c) Charles Petzold, 1992
  4.   ---------------------------------------*/
  5.  
  6.  
  7. #include <windows.h>
  8. extern "C" {
  9. #include <mmsystem.h>
  10. }
  11. #include <stdlib.h>
  12. #include <string.h>
  13.  
  14. typedef unsigned int UINT ;
  15.  
  16. #define IDM_OPEN    0x100
  17. #define IDM_CLOSE   0x101
  18. #define IDM_DEVICE  0x200
  19.  
  20. long FAR PASCAL _export WndProc (HWND, UINT, UINT, LONG);
  21.  
  22. char szAppName [] = "MidVue" ;
  23. int  cxChar, cyChar ;
  24.  
  25. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  26.             LPSTR lpszCmdLine, int nCmdShow)
  27.      {
  28.      MSG      msg;
  29.      HWND     hwnd ;
  30.      WNDCLASS wndclass ;
  31.  
  32.      if (!hPrevInstance) 
  33.           {
  34.           wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  35.           wndclass.lpfnWndProc   = WndProc ;
  36.           wndclass.cbClsExtra    = 0 ;
  37.           wndclass.cbWndExtra    = 0 ;
  38.           wndclass.hInstance     = hInstance ;
  39.           wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  40.           wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  41.           wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
  42.           wndclass.lpszMenuName  = NULL ;
  43.           wndclass.lpszClassName = szAppName ;
  44.  
  45.           RegisterClass (&wndclass) ;
  46.           }
  47.  
  48.      hwnd = CreateWindow (szAppName, "MIDI Input Viewer",
  49.                           WS_OVERLAPPEDWINDOW,
  50.               CW_USEDEFAULT, CW_USEDEFAULT,
  51.                           CW_USEDEFAULT, CW_USEDEFAULT,
  52.                           NULL, NULL, hInstance, NULL) ;
  53.  
  54.      ShowWindow (hwnd, nCmdShow) ;
  55.      UpdateWindow (hwnd); 
  56.  
  57.      while (GetMessage (&msg, NULL, 0, 0))
  58.           {
  59.           TranslateMessage (&msg) ;
  60.           DispatchMessage (&msg) ;
  61.           }
  62.      return msg.wParam ;
  63.      }
  64.  
  65. HMENU CreateTheMenu (int iNumDevs)
  66.      {
  67.      HMENU      hMenu, hMenuPopup ;
  68.      int        i ;
  69.      MIDIINCAPS mic ;
  70.  
  71.      hMenu = CreateMenu () ;
  72.  
  73.                // Create "Status" popup menu
  74.  
  75.      hMenuPopup = CreateMenu () ;
  76.  
  77.      AppendMenu (hMenuPopup, MF_STRING             , IDM_OPEN,  "&Open") ;
  78.      AppendMenu (hMenuPopup, MF_STRING | MF_CHECKED, IDM_CLOSE, "&Closed") ;
  79.  
  80.      AppendMenu (hMenu, MF_STRING | MF_POPUP, hMenuPopup, "&Status") ;
  81.  
  82.                // Create "Device" popup menu
  83.  
  84.      hMenuPopup = CreateMenu () ;
  85.  
  86.      for (i = 0 ; i < iNumDevs ; i++)
  87.           {
  88.           midiInGetDevCaps (i, &mic, sizeof (mic)) ;
  89.           AppendMenu (hMenuPopup, MF_STRING, IDM_DEVICE + i, mic.szPname) ;
  90.           }
  91.  
  92.      CheckMenuItem (hMenuPopup, 0, MF_BYPOSITION | MF_CHECKED) ;
  93.      AppendMenu (hMenu, MF_STRING | MF_POPUP, hMenuPopup, "&Device") ;
  94.  
  95.      return hMenu ;
  96.      }
  97.  
  98. void DisplayTheMessage (HDC hdc, DWORD dwMsg, int iNextRow)
  99.      {
  100.      static char * szStatus [] = { "Note Off", "Note On",
  101.                                    "Polyphonic Aftertouch",
  102.                                    "Control Change", "Program Change",
  103.                                    "Channel Aftertouch", "Pitch Bend" } ;
  104.  
  105.      static char * szModes  [] = { "Reset All Controllers", "Local Control",
  106.                                    "All Notes Off", "Omni Mode Off",
  107.                                    "Omni Mode On", "Mono Mode Off",
  108.                                    "Poly Mode On" } ;
  109.      char  szBuffer [48] ;
  110.      DWORD dwTime ;
  111.      RECT  rect ;
  112.      WORD  wStatus, wData1, wData2 ;
  113.  
  114.                // Display white rectangle to blank line
  115.  
  116.      if (dwMsg == 0)
  117.           {
  118.           rect.left   = 0 ;
  119.           rect.top    = cyChar * iNextRow ;
  120.           rect.right  = cxChar * 80 ;
  121.           rect.bottom = cyChar * (iNextRow + 1) ;
  122.  
  123.           FillRect (hdc, &rect, GetStockObject (WHITE_BRUSH)) ;
  124.           }
  125.      else
  126.           {
  127.           MoveTo (hdc, 0, cyChar * iNextRow) ;
  128.           SetTextAlign (hdc, TA_UPDATECP) ;
  129.  
  130.                // Display system time
  131.  
  132.           dwTime = timeGetTime () ;
  133.           wsprintf (szBuffer, "%04X-%04X ", HIWORD (dwTime), LOWORD (dwTime)) ;
  134.           TextOut (hdc, 0, 0, szBuffer, strlen (szBuffer)) ;
  135.  
  136.                // Break down MIDI message
  137.  
  138.           wStatus = 0x00FF & (LOBYTE (LOWORD (dwMsg)))  ;
  139.           wData1  = 0x00FF & (HIBYTE (LOWORD (dwMsg)))  ;
  140.           wData2  = 0x00FF & (LOBYTE (HIWORD (dwMsg)))  ;
  141.  
  142.                // Display the three bytes
  143.  
  144.           wsprintf (szBuffer, " %02X %02X %02X ", wStatus, wData1, wData2) ;
  145.           TextOut (hdc, 0, 0, szBuffer, strlen (szBuffer)) ;
  146.  
  147.           if (wStatus < 0xF0)
  148.                {
  149.                     // Display channel and message type
  150.  
  151.                wsprintf (szBuffer, " Channel %d, %s, ",
  152.                     (wStatus & 0x0F) + 1,
  153.                     (LPSTR) szStatus [((wStatus >> 4) & 0x0F) - 8]) ;
  154.  
  155.                TextOut (hdc, 0, 0, szBuffer, strlen (szBuffer)) ;
  156.  
  157.                     // Display message-specific information
  158.  
  159.                if (wStatus < 0xA0)
  160.                     wsprintf (szBuffer, "Key %d, Velocity %d", wData1, wData2);
  161.  
  162.                else if (wStatus < 0xB0)
  163.                     wsprintf (szBuffer, "Key %d, Pressure %d", wData1, wData2);
  164.  
  165.                else if (wStatus < 0xC0)
  166.                     switch (wData1)
  167.                          {
  168.                          case 121:
  169.                          case 123:
  170.                          case 124:
  171.                          case 125:
  172.                          case 127:
  173.                               wsprintf (szBuffer, "%s",
  174.                                         (LPSTR) szModes [wData1 - 121]) ;
  175.                               break ;
  176.  
  177.                          case 122:
  178.                               wsprintf (szBuffer, "%s %s",
  179.                                         (LPSTR) szModes [wData1 - 121],
  180.                                         (LPSTR) (wData2 ? "On" : "Off")) ;
  181.                               break ;
  182.  
  183.                          case 126:
  184.                               wsprintf (szBuffer, "%s, %d Channels",
  185.                                         (LPSTR) szModes [wData1 - 121],
  186.                                         wData2) ;
  187.                               break ;
  188.  
  189.                          default:
  190.                               wsprintf (szBuffer, "Controller %d, Value %d",
  191.                                         wData1, wData2) ;
  192.                               break ;
  193.                          }
  194.  
  195.                else if (wStatus < 0xD0)
  196.                     wsprintf (szBuffer, "Voice %d", wData1 + 1) ;
  197.  
  198.                else if (wStatus < 0xE0)
  199.                     wsprintf (szBuffer, "Pressure %d", wData1) ;
  200.  
  201.                else if (wStatus < 0xF0)
  202.                     wsprintf (szBuffer, "Value %d", wData2 * 128 + wData1) ;
  203.                }
  204.           else
  205.                {
  206.                wsprintf (szBuffer, " System Message") ;
  207.                }
  208.  
  209.           TextOut (hdc, 0, 0, szBuffer, strlen (szBuffer)) ;
  210.           }
  211.      }
  212.  
  213. long FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT wParam,
  214.                                                           LONG lParam)
  215.      {
  216.      static BOOL    bOpened = FALSE ;
  217.      static DWORD * pdwMsg ;
  218.      static HMIDIIN hMidiIn ;
  219.      static int     iNumRows, iNextRow ;
  220.      static WORD    wDevice ;
  221.      DWORD          dwExtent ;
  222.      HDC            hdc ;
  223.      HMENU          hMenu ;
  224.      PAINTSTRUCT    ps ;
  225.      short          i, iNumDevs, cyClient ;
  226.  
  227.      switch (message)
  228.           {
  229.           case WM_CREATE:
  230.                          // Get character size of fixed point font
  231.  
  232.                hdc = GetDC (hwnd) ;
  233.  
  234.                SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
  235.  
  236.                dwExtent = GetTextExtent (hdc, "M", 1) ;
  237.                cxChar   = LOWORD (dwExtent) ;
  238.                cyChar   = HIWORD (dwExtent) ;
  239.  
  240.                ReleaseDC (hwnd, hdc) ;
  241.  
  242.                          // Get number of MIDI input devices and set up menu
  243.  
  244.                if (0 == (iNumDevs = midiInGetNumDevs ()))
  245.                     {
  246.                     MessageBeep (MB_ICONSTOP) ;
  247.                     MessageBox (hwnd, "No MIDI input devices!",
  248.                                 szAppName, MB_OK | MB_ICONEXCLAMATION) ;
  249.                     DestroyWindow (hwnd) ;
  250.                     }
  251.                else
  252.                     {
  253.                     SetMenu (hwnd, CreateTheMenu (iNumDevs)) ;
  254.                     }
  255.  
  256.                return 0 ;
  257.  
  258.           case WM_SIZE:
  259.                cyClient = HIWORD (lParam) ;
  260.                iNumRows = cyClient / cyChar ;
  261.                iNextRow = 0 ;
  262.  
  263.                     // Allocate memory for storing information
  264.  
  265.                if (pdwMsg != NULL)
  266.                     free (pdwMsg) ;
  267.  
  268.                pdwMsg = (DWORD *) calloc (iNumRows, sizeof (DWORD)) ;
  269.  
  270.                return 0 ;
  271.  
  272.           case WM_COMMAND:
  273.                hMenu = GetMenu (hwnd) ;
  274.  
  275.                          // "Open" menu command
  276.  
  277.                if (wParam == IDM_OPEN && !bOpened)
  278.                     {
  279.                     if (midiInOpen (&hMidiIn, wDevice, (DWORD) hwnd,
  280.                                     0L, CALLBACK_WINDOW))
  281.                          {
  282.                          MessageBeep (MB_ICONEXCLAMATION) ;
  283.                          MessageBox (hwnd, "Cannot open MIDI In device",
  284.                                      szAppName, MB_OK | MB_ICONEXCLAMATION) ;
  285.                          }
  286.                     else
  287.                          {
  288.                          CheckMenuItem (hMenu, IDM_OPEN,  MF_CHECKED) ;
  289.                          CheckMenuItem (hMenu, IDM_CLOSE, MF_UNCHECKED) ;
  290.  
  291.                          midiInStart (hMidiIn) ;
  292.                          bOpened = TRUE ;
  293.                          }
  294.                     }
  295.  
  296.                          // "Close" menu command
  297.  
  298.                else if (wParam == IDM_CLOSE && bOpened)
  299.                     {
  300.                     CheckMenuItem (hMenu, IDM_OPEN,  MF_UNCHECKED) ;
  301.                     CheckMenuItem (hMenu, IDM_CLOSE, MF_CHECKED) ;
  302.  
  303.                               // Close device
  304.  
  305.                     midiInStop (hMidiIn) ;
  306.                     midiInClose (hMidiIn) ;
  307.                     bOpened = FALSE ;
  308.                     }
  309.  
  310.                          // Change MIDI "Device" menu command
  311.  
  312.                else if (wParam >= IDM_DEVICE - 1)
  313.                     {
  314.                     CheckMenuItem (hMenu, IDM_DEVICE + wDevice, MF_UNCHECKED) ;
  315.                     wDevice = wParam - IDM_DEVICE ;
  316.                     CheckMenuItem (hMenu, IDM_DEVICE + wDevice, MF_CHECKED) ;
  317.  
  318.                               // Close and reopen MIDI device
  319.  
  320.                     if (bOpened)
  321.                          {
  322.                          SendMessage (hwnd, WM_COMMAND, IDM_CLOSE, 0L) ;
  323.                          SendMessage (hwnd, WM_COMMAND, IDM_OPEN,  0L) ;
  324.                          }
  325.                     }
  326.  
  327.                InvalidateRect (hwnd, NULL, TRUE) ;
  328.                return 0 ;
  329.  
  330.           case MM_MIM_DATA:
  331.  
  332.                     // Skip "Active Sensing" messages
  333.  
  334.                if (lParam == 0x00FE)
  335.                     return 0 ;
  336.  
  337.                     // Display the message
  338.  
  339.                hdc = GetDC (hwnd) ;
  340.                SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
  341.  
  342.                pdwMsg [iNextRow] = lParam ;
  343.                DisplayTheMessage (hdc, pdwMsg [iNextRow], iNextRow) ;
  344.  
  345.                     // Blank out the next row
  346.  
  347.                iNextRow = (iNextRow + 1) % iNumRows ;
  348.  
  349.                pdwMsg [iNextRow] = 0L ;
  350.                DisplayTheMessage (hdc, pdwMsg [iNextRow], iNextRow) ;
  351.  
  352.                ReleaseDC (hwnd, hdc) ;
  353.                return 0 ;
  354.  
  355.           case WM_PAINT:
  356.                hdc = BeginPaint (hwnd, &ps) ;
  357.  
  358.                SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
  359.  
  360.                for (i = 0 ; i < iNumRows ; i++)
  361.                     if (0L != (pdwMsg [i]))
  362.                          DisplayTheMessage (hdc, pdwMsg [i], i) ;
  363.  
  364.                EndPaint (hwnd, &ps) ;
  365.                return 0 ;
  366.  
  367.           case WM_DESTROY :
  368.                SendMessage (hwnd, WM_COMMAND, IDM_CLOSE, 0L) ;
  369.  
  370.                PostQuitMessage (0) ;
  371.                return 0 ;
  372.           }
  373.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  374.      }
  375.