/*-----------------------------------------------------------
   MIDIDEVS.C -- Multimedia Windows MIDI Device Capabilities
                 (c) Charles Petzold, 1992
  -----------------------------------------------------------*/

#include <windows.h>
#include <mmsystem.h>
#include <string.h>

#define OUT TextOut (hdc, x, y, szBuffer, strlen (szBuffer)) ; y += cyChar ;

long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
                    LPSTR lpszCmdParam, int nCmdShow)
     {
     static char szAppName[] = "MidiDevs" ;
     HWND        hwnd ;
     MSG         msg ;
     WNDCLASS    wndclass ;

     if (!hPrevInstance)
          {
          wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
          wndclass.lpfnWndProc   = WndProc ;
          wndclass.cbClsExtra    = 0 ;
          wndclass.cbWndExtra    = 0 ;
          wndclass.hInstance     = hInstance ;
          wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
          wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
          wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
          wndclass.lpszMenuName  = NULL ;
          wndclass.lpszClassName = szAppName ;

          RegisterClass (&wndclass) ;
	  }

     hwnd = CreateWindow (szAppName, "MIDI Device Capabilities",
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;

     ShowWindow (hwnd, nCmdShow) ;
     UpdateWindow (hwnd) ;

     while (GetMessage (&msg, NULL, 0, 0))
          {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
          }
     return msg.wParam ;
     }

long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
     {
     static char  *szManuID [] = { "?????",              "MM_MICROSOFT",
                                   "?????"                                  } ;
     static char  *szProdID [] = { "?????",              "MM_MIDI_MAPPER",
                                   "?????",              "MM_SNDBLST_MIDIOUT",
                                   "MM_SNDBLST_MIDIIN",  "MM_SNDBLST_SYNTH",
                                   "MM_SNDBLST_WAVEOUT", "MM_SNDBLST_WAVEIN",
                                   "?????",              "MM_ADLIB",
                                   "MM_MPU401_MIDIOUT",  "MM_MPU401_MIDIIN",
                                   "MM_PC_JOYSTICK",     "?????"            } ;
     static char  *szTechID [] = { "?????",              "MOD_MIDIPORT",
                                   "MOD_SYNTH",          "MOD_SQSYNTH",
                                   "MOD_FMSYNTH",        "MOD_MAPPER",
                                   "?????"                                  } ;
     static char  szBuffer [MAXPNAMELEN + 64] ;
     static short cxChar, cyChar, cxClient, cyClient ;
     HDC          hdc ;
     MIDIINCAPS   mic ;
     MIDIOUTCAPS  moc ;
     PAINTSTRUCT  ps ;
     short        i, x, y, iNumDevs ;

     switch (message)
          {
          case WM_CREATE:
               cxChar = LOWORD (GetDialogBaseUnits ()) ;
               cyChar = HIWORD (GetDialogBaseUnits ()) ;
               return 0 ;

          case WM_SIZE:
               cxClient = LOWORD (lParam) ;
               cyClient = HIWORD (lParam) ;
               return 0 ;

          case WM_PAINT:
               hdc = BeginPaint (hwnd, &ps) ;

               SetBkMode (hdc, TRANSPARENT) ;

               x = cxChar ;
               y = 0 ;

               iNumDevs = midiInGetNumDevs () ;

               for (i = 0 ; i < iNumDevs ; i++)
                    {
                    midiInGetDevCaps (i, &mic, sizeof (MIDIINCAPS)) ;

                    wsprintf (szBuffer, "mic.wMid: %04X (%s)", mic.wMid,
                              (LPSTR) szManuID [min (mic.wMid,
                                  sizeof (szManuID) / sizeof (szManuID[0]))]) ;
                    OUT

                    wsprintf (szBuffer, "mic.wPid: %04X (%s)", mic.wPid,
                              (LPSTR) szProdID [min (mic.wPid,
                                  sizeof (szProdID) / sizeof (szProdID[0]))]) ;
                    OUT

                    wsprintf (szBuffer, "mic.vDriverVersion: 0x%04X",
                              mic.vDriverVersion) ;
                    OUT

                    wsprintf (szBuffer, "mic.szPname: %s",
                              (LPSTR) mic.szPname) ;
                    OUT

                    MoveTo (hdc, x, y) ;
                    LineTo (hdc, x + 39 * cxChar, y) ;
                    }

               x = 40 * cxChar ;
               y = 0 ;

               iNumDevs = midiOutGetNumDevs () ;

               for (i = MIDIMAPPER ; i < iNumDevs ; i++)
                    {
                    midiOutGetDevCaps (i, &moc, sizeof (MIDIOUTCAPS)) ;

                    wsprintf (szBuffer, "moc.wMid: %d (%s)", moc.wMid,
                              (LPSTR) szManuID [min (moc.wMid,
                                  sizeof (szManuID) / sizeof (szManuID[0]))]) ;
                    OUT

                    wsprintf (szBuffer, "moc.wPid: %d (%s)", moc.wPid,
                              (LPSTR) szProdID [min (moc.wPid,
                                  sizeof (szProdID) / sizeof (szProdID[0]))]) ;
                    OUT

                    wsprintf (szBuffer, "moc.vDriverVersion: 0x%04X",
                              moc.vDriverVersion) ;
                    OUT

                    wsprintf (szBuffer, "moc.szPname: %s",
                              (LPSTR) moc.szPname) ;
                    OUT

                    wsprintf (szBuffer, "moc.wTechnology: %d (%s)",
                              moc.wTechnology,
                              (LPSTR) szTechID [min (moc.wTechnology,
                                  sizeof (szTechID) / sizeof (szTechID[0]))]) ;
                    OUT

                    wsprintf (szBuffer, "moc.wVoices: %d", moc.wVoices) ;

                    OUT

                    wsprintf (szBuffer, "moc.wNotes: %d", moc.wNotes) ;

                    OUT

                    wsprintf (szBuffer, "moc.wChannelMask: 0x%04X",
                              moc.wChannelMask) ;
                    OUT

                    wsprintf (szBuffer, "moc.dwSupport: %08X",
                              moc.dwSupport) ;
                    OUT

                    MoveTo (hdc, x, y) ;
                    LineTo (hdc, x + 39 * cxChar, y) ;
                    }

	       EndPaint (hwnd, &ps) ;
               return 0 ;

          case WM_DESTROY:
               PostQuitMessage (0) ;
               return 0 ;
          }

     return DefWindowProc (hwnd, message, wParam, lParam) ;
     }
