home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / MSTREAM / MSTRHELP.C < prev    next >
C/C++ Source or Header  |  1996-08-28  |  19KB  |  503 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:   mstream.c
  6.  *  Content:   Illustrates streaming data from a disk MIDI file to a
  7.  *             midiStream buffer for playback.
  8.  *
  9.  ***************************************************************************/
  10. #include <windows.h>
  11. #include <windowsx.h>
  12. #include <commctrl.h>
  13. #include <memory.h>
  14. #include <mmreg.h>
  15.  
  16. #include "debug.h"
  17. #include "resource.h"
  18. #include "midstuff.h"
  19. #include "mstream.h"
  20.  
  21. extern char szAppTitle[64];
  22. extern char szAppCaption[64];
  23. extern char szFileBuffer[64];
  24. extern char szFileTitle[64];
  25. extern char szTempo[64];
  26. extern char szVolume[64];
  27. extern char szProgress[64];
  28. extern char szTemp[256];
  29. extern char szDebug[256];
  30.  
  31. extern HWND hWndMain, hWndTempo, hWndVol, hWndProg, hWndPlay, hWndPause;
  32. extern HWND hWndStop, hWndTempoText, hWndVolText, hWndLoopCheck, hWndProgText;
  33. extern HINSTANCE hInst;
  34. extern HMIDISTRM    hStream;
  35.  
  36. extern BOOL bFileOpen, bPlaying, bPaused, bInsertTempo;
  37. extern int  nTextControlHeight;
  38. extern DWORD    dwBufferTickLength, dwTempoMultiplier, dwCurrentTempo;
  39. extern DWORD    dwProgressBytes, dwVolumePercent, dwVolCache[NUM_CHANNELS];
  40.  
  41. #ifdef DEBUG
  42. extern HWND hWndList;
  43. #endif
  44.  
  45. /*****************************************************************************/
  46. /* CreateChildren()                                                          */
  47. /*                                                                           */
  48. /*   This function creates a bunch of child controls for the main window.    */
  49. /* Most of them are used for controling various things about a playing sound */
  50. /* file, like volume and panning. Returns FALSE if no errors, TRUE otherwise.*/
  51. /*                                                                           */
  52. /*****************************************************************************/
  53. int CreateChildren( RECT crect )
  54.     {
  55.     SIZE  Size;
  56.     HDC   hDC;
  57.     int   x, y;
  58.     UINT  uType;
  59.     char  szTemplate[128], szType[32];
  60.     LPSTR lpszControl;
  61.  
  62.     LoadString( hInst, IDS_ERROR_CHILDTEMPLATE, szTemplate, sizeof(szTemplate));
  63.  
  64.     /* Don't handle failure for this one, because the app will still run fine */
  65.     CreateWindow( "static", NULL, WS_CHILD | WS_VISIBLE | SS_ETCHEDHORZ,
  66.             0, 0, crect.right, 2, hWndMain, (HMENU)0, hInst, NULL );
  67.  
  68.     hDC = GetDC( hWndMain );
  69.     if( !GetTextExtentPoint32( hDC, szProgress, strlen(szProgress), &Size ))
  70.     {
  71.     ErrorMessageBox( IDS_ERROR_GETTEXTEXTENT, MB_ICONEXCLAMATION );
  72.     ReleaseDC( hWndMain, hDC );
  73.     return( TRUE );
  74.     }
  75.     ReleaseDC( hWndMain, hDC );
  76.     nTextControlHeight = Size.cy;
  77.  
  78.     y = BORDER_SPACE_CY;
  79.  
  80.     /* STATIC control -- text label for the TEMPO trackbar */
  81.     if(( hWndTempoText = CreateWindow( "static", szTempo,
  82.                                     WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP, 
  83.                                     BORDER_SPACE_CX,
  84.                                     y,
  85.                                     TEMPO_TEXT_CX, nTextControlHeight,
  86.                                     hWndMain, (HMENU)0, hInst, NULL)) == NULL )
  87.         {
  88.         lpszControl = szTempo;
  89.     uType = IDS_ERROR_STATICTEXT;
  90.         goto DISPLAY_CREATE_FAILURE;
  91.     }
  92.  
  93.     /* Create the TEMPO trackbar */
  94.     if(( hWndTempo = CreateWindow( TRACKBAR_CLASS, NULL,
  95.                 WS_CHILD | WS_VISIBLE | TBS_HORZ | TBS_BOTTOM,
  96.                 BORDER_SPACE_CX,
  97.                 y + nTextControlHeight + TEXT_SPACE_CY,
  98.                 TEMPO_TB_CX, TEMPO_TB_CY,
  99.                 hWndMain, (HMENU)0, hInst, NULL)) == NULL )
  100.         {
  101.         lpszControl = szTempo;
  102.     uType = IDS_ERROR_TRACKBAR;
  103.         goto DISPLAY_CREATE_FAILURE;
  104.     }
  105.  
  106.     dwTempoMultiplier = 100;
  107.     SendMessage( hWndTempo, TBM_SETRANGE, FALSE,
  108.                                         MAKELONG( TEMPO_MIN, TEMPO_MAX ));
  109.     SendMessage( hWndTempo, TBM_SETPOS, TRUE, dwTempoMultiplier );
  110.  
  111.     /* STATIC control -- text label for the VOLUME trackbar */
  112.     if(( hWndVolText = CreateWindow( "static", szVolume,
  113.                                     WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP, 
  114.                                     BORDER_SPACE_CX + TEMPO_TB_CX
  115.                                     + CONTROL_SPACE_CX,
  116.                                     y,
  117.                                     VOL_TEXT_CX, nTextControlHeight,
  118.                                     hWndMain, (HMENU)0, hInst, NULL)) == NULL )
  119.         {
  120.         lpszControl = szVolume;
  121.     uType = IDS_ERROR_STATICTEXT;
  122.         goto DISPLAY_CREATE_FAILURE;
  123.     }
  124.     y += nTextControlHeight + TEXT_SPACE_CY;
  125.  
  126.     /* Create the VOLUME trackbar */
  127.     if(( hWndVol = CreateWindow( TRACKBAR_CLASS, NULL,
  128.                 WS_CHILD | WS_VISIBLE | TBS_HORZ | TBS_BOTTOM,
  129.                 BORDER_SPACE_CX + TEMPO_TB_CX
  130.                 + CONTROL_SPACE_CX,
  131.                 y, VOL_TB_CX, VOL_TB_CY,
  132.                 hWndMain, (HMENU)0, hInst, NULL)) == NULL )
  133.         {
  134.         lpszControl = szVolume;
  135.     uType = IDS_ERROR_TRACKBAR;
  136.         goto DISPLAY_CREATE_FAILURE;
  137.     }
  138.  
  139.     SendMessage( hWndVol, TBM_SETRANGE, FALSE,
  140.                                         MAKELONG( VOL_TB_MIN, VOL_TB_MAX ));
  141.     SendMessage( hWndVol, TBM_SETPOS, TRUE, VOL_TB_MAX );
  142.     SendMessage( hWndVol, TBM_SETPAGESIZE, 0L, VOL_PAGESIZE );
  143.  
  144.     x = BORDER_SPACE_CX + TEMPO_TB_CX + 2 * CONTROL_SPACE_CX + VOL_TB_CX;
  145.     y = BORDER_SPACE_CY;
  146.  
  147.     /* Create the LOOPED CHECKBOX */
  148.     LoadString( hInst, IDS_CHECK_LOOPED, szTemp, sizeof(szTemp));
  149.     if(( hWndLoopCheck = CreateWindow( "button", szTemp,
  150.                                 WS_CHILD | WS_VISIBLE | BS_CHECKBOX,
  151.                                 x, y, CHECK_CX, CHECK_CY, hWndMain,
  152.                                 (HMENU)IDC_LOOPCHECK, hInst, NULL )) == NULL )
  153.         {
  154.         lpszControl = szTemp;
  155.     uType = IDS_ERROR_CHECK;
  156.         goto DISPLAY_CREATE_FAILURE;
  157.     }
  158.  
  159.     x = BORDER_SPACE_CX + TEMPO_TB_CX + VOL_TB_CX + 2 * CONTROL_SPACE_CX + CHECK_CX
  160.     - 3 * BUTTON_CX - 2 * BUTTON_SPACE_CX;
  161.     y = BORDER_SPACE_CY + nTextControlHeight + TEXT_SPACE_CY + TEMPO_TB_CY
  162.     + CONTROL_SPACE_CY;
  163.  
  164.     /* STATIC control -- text label for the progress trackbar. */
  165.     if(( hWndProgText = CreateWindow( "static", szProgress,
  166.                                     WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP,
  167.                                     BORDER_SPACE_CX,
  168.                                     y,
  169.                                     x - BORDER_SPACE_CX, nTextControlHeight,
  170.                                     hWndMain, (HMENU)0, hInst, NULL)) == NULL )
  171.         {
  172.         lpszControl = szProgress;
  173.     uType = IDS_ERROR_STATICTEXT;
  174.         goto DISPLAY_CREATE_FAILURE;
  175.     }
  176.  
  177.     /* Create the PLAY BUTTON */
  178.     LoadString( hInst, IDS_BUTTON_PLAY, szTemp, sizeof(szTemp));
  179.     if(( hWndPlay = CreateWindow( "button", szTemp,
  180.                                     WS_CHILD | WS_VISIBLE | WS_DISABLED,
  181.                                     x, y, BUTTON_CX, BUTTON_CY, hWndMain,
  182.                                     (HMENU)IDC_PLAY, hInst, NULL )) == NULL )
  183.         {
  184.         lpszControl = szTemp;
  185.     uType = IDS_ERROR_BUTTON;
  186.         goto DISPLAY_CREATE_FAILURE;
  187.     }
  188.     x += BUTTON_CX + BUTTON_SPACE_CX;
  189.  
  190.     /* Create the PAUSE BUTTON */
  191.     LoadString( hInst, IDS_BUTTON_PAUSE, szTemp, sizeof(szTemp));
  192.     if(( hWndPause = CreateWindow( "button", szTemp,
  193.                     WS_CHILD | WS_VISIBLE | WS_DISABLED,
  194.                     x, y, BUTTON_CX, BUTTON_CY, hWndMain,
  195.                     (HMENU)IDC_PAUSE, hInst, NULL )) == NULL )
  196.     {
  197.     lpszControl = szTemp;
  198.     uType = IDS_ERROR_BUTTON;
  199.     goto DISPLAY_CREATE_FAILURE;
  200.     }
  201.     x += BUTTON_CX + BUTTON_SPACE_CX;
  202.  
  203.     /* Create the STOP BUTTON */
  204.     LoadString( hInst, IDS_BUTTON_STOP, szTemp, sizeof(szTemp));
  205.     if(( hWndStop = CreateWindow( "button", szTemp,
  206.                                     WS_CHILD | WS_VISIBLE | WS_DISABLED,
  207.                                     x, y, BUTTON_CX, BUTTON_CY, hWndMain,
  208.                                     (HMENU)IDC_STOP, hInst, NULL )) == NULL )
  209.         {
  210.         lpszControl = szTemp;
  211.     uType = IDS_ERROR_BUTTON;
  212.         goto DISPLAY_CREATE_FAILURE;
  213.     }
  214.  
  215.     UpdateFromControls();
  216.     goto RETURN_NORMAL;
  217.  
  218. DISPLAY_CREATE_FAILURE:
  219.     LoadString( hInst, uType, szType, sizeof(szType));
  220.     wsprintf( szTemp, szTemplate, lpszControl, szType );
  221.     MessageBox( GetActiveWindow(), szTemp,
  222.                         szAppTitle, MB_OK | MB_ICONEXCLAMATION );
  223.     return( TRUE );
  224.  
  225. RETURN_NORMAL:
  226.     return( FALSE );
  227.     }
  228.  
  229.  
  230. /********************************************************************************/
  231. /* HandleTempoScroll()                                                          */
  232. /*                                                                              */
  233. /*   Handles the tempo trackbar scroll when a WM_HSCROLL is received.           */
  234. /*                                                                              */
  235. /********************************************************************************/
  236. void HandleTempoScroll( int nCode, int nPos )
  237.     {
  238.     long  lTempo, lDelta;
  239.  
  240.     lTempo = (LONG)SendMessage( hWndTempo, TBM_GETPOS, (WPARAM)0, (LPARAM)0 );
  241.  
  242.     switch( nCode )
  243.         {
  244.         case TB_LINEUP:
  245.             if( lTempo >= TEMPO_MIN-1 )
  246.                 lDelta = -1;
  247.             break;
  248.         case TB_LINEDOWN:
  249.             if( lTempo <= TEMPO_MAX+1 )
  250.                 lDelta = 1;
  251.             break;
  252.         case TB_PAGEUP:
  253.             if( lTempo >= TEMPO_MIN - TEMPO_PAGESIZE )
  254.                 lDelta = -TEMPO_PAGESIZE;
  255.             break;
  256.         case TB_PAGEDOWN:
  257.             if( lTempo <= TEMPO_MAX + TEMPO_PAGESIZE )
  258.                 lDelta = TEMPO_PAGESIZE;
  259.             break;
  260.         case TB_ENDTRACK:
  261.             return;
  262.         default:
  263.             lDelta = 0;
  264.         }
  265.  
  266.     if( lDelta )
  267.     {
  268.     SendMessage( hWndTempo, TBM_SETPOS, TRUE, lTempo + lDelta );
  269.     dwTempoMultiplier = (DWORD)( lTempo + lDelta );
  270.     }
  271.     else
  272.     {
  273.     SendMessage( hWndTempo, TBM_SETPOS, TRUE, (long)nPos );
  274.     dwTempoMultiplier = (DWORD)nPos;
  275.     }
  276.  
  277.     UpdateFromControls();
  278.     }
  279.  
  280.  
  281. /********************************************************************************/
  282. /* HandleVolScroll()                                                            */
  283. /*                                                                              */
  284. /*   Handles the volume trackbar scrolling when a WM_HSCROLL is received.       */
  285. /*                                                                              */
  286. /********************************************************************************/
  287. void HandleVolScroll( int nCode, int nPos )
  288.     {
  289.     long  lVol, lDelta;
  290.  
  291.     lVol = (LONG)SendMessage( hWndVol, TBM_GETPOS, (WPARAM)0, (LPARAM)0 );
  292.  
  293.     switch( nCode )
  294.         {
  295.         case TB_LINEDOWN:
  296.             if( lVol <= VOL_TB_MAX - 1 )
  297.                 lDelta = 1;
  298.             break;
  299.         case TB_LINEUP:
  300.             if( lVol >= VOL_TB_MIN + 1 )
  301.                 lDelta = -1;
  302.             break;
  303.         case TB_PAGEDOWN:
  304.             if( lVol <= VOL_TB_MAX - VOL_PAGESIZE )
  305.                 lDelta = VOL_PAGESIZE;
  306.             break;
  307.         case TB_PAGEUP:
  308.             if( lVol >= VOL_TB_MIN + VOL_PAGESIZE )
  309.                 lDelta = -VOL_PAGESIZE;
  310.             break;
  311.         case TB_ENDTRACK:
  312.             return;
  313.         default:
  314.             lDelta = 0;
  315.         }
  316.  
  317.     if( lDelta )
  318.         SendMessage( hWndVol, TBM_SETPOS, TRUE, (lVol + lDelta));
  319.     else
  320.         SendMessage( hWndVol, TBM_SETPOS, TRUE, (long)nPos );
  321.  
  322.     UpdateFromControls();
  323.     }
  324.  
  325.  
  326. /********************************************************************************/
  327. /* UpdateFromControls()                                                         */
  328. /*                                                                              */
  329. /*    This function gets all the required values from the DirectSoundBuffer and */
  330. /* updates the screen interface controls.                                       */
  331. /*                                                                              */
  332. /********************************************************************************/
  333. void UpdateFromControls( void )
  334.     {
  335.     long    lTempo;
  336.  
  337.     lTempo = (LONG)SendMessage( hWndTempo, TBM_GETPOS, (WPARAM)0, (LPARAM)0 );
  338.     dwVolumePercent = (WORD)SendMessage( hWndVol, TBM_GETPOS,
  339.                                 (WPARAM)0, (LPARAM)0 );
  340.  
  341.     /* Set the Volume text */
  342.     wsprintf( szTemp, "%s: %lu%%", szVolume, dwVolumePercent / 10 );
  343.     Static_SetText( hWndVolText, szTemp );
  344.     if( hStream )
  345.     SetAllChannelVolumes( dwVolumePercent );
  346.  
  347.     /* Set the Tempo text */
  348.     wsprintf( szTemp, "%s: %li%%", szTempo, lTempo );
  349.     Static_SetText( hWndTempoText, szTemp );
  350.     bInsertTempo = TRUE;
  351.  
  352.     /* Set the Progress text */
  353.     wsprintf( szTemp, "%s: %lu bytes", szProgress, dwProgressBytes );
  354.     Static_SetText( hWndProgText, szTemp );
  355.  
  356.     return;
  357.     }
  358.  
  359.  
  360. /****************************************************************************/
  361. /* ErrorMessageBox()                                                        */
  362. /*                                                                          */
  363. /*   A little routine to load error messages from the string resource table */
  364. /* and pop them up in a MessageBox() for the world to see. The dwMBFlags    */
  365. /* parameter allows the caller to specify the type of icon to use.          */
  366. /*                                                                          */
  367. /****************************************************************************/
  368. void ErrorMessageBox( UINT uID, DWORD dwMBFlags )
  369.     {
  370.     LoadString( hInst, uID, szTemp, sizeof(szTemp));
  371.     MessageBox( GetActiveWindow(), szTemp, szAppTitle, MB_OK | dwMBFlags );
  372. #ifdef DEBUG
  373.     wsprintf( szDebug, "General error: %s", szTemp );
  374.     DebugPrint( szDebug );
  375. #endif
  376.     }
  377.  
  378.  
  379. /****************************************************************************/
  380. /* MidiErrorMessageBox()                                                    */
  381. /*                                                                          */
  382. /*   Calls the midiOutGetErrorText() function and displays the text which   */
  383. /* corresponds to a midi subsystem error code.                              */
  384. /*                                                                          */
  385. /****************************************************************************/
  386. void MidiErrorMessageBox( MMRESULT mmr )
  387.     {
  388.     midiOutGetErrorText( mmr, szTemp, sizeof(szTemp));
  389.     MessageBox( GetActiveWindow(), szTemp, szAppTitle,
  390.                 MB_OK | MB_ICONSTOP );
  391. #ifdef DEBUG
  392.     wsprintf( szDebug, "Midi subsystem error: %s", szTemp );
  393.     DebugPrint( szDebug );
  394. #endif
  395.     }
  396.  
  397.  
  398. /*****************************************************************************/
  399. /* HandleCommDlgError()                                                      */
  400. /*                                                                           */
  401. /*    The function translates extended common dialog error codes into a      */
  402. /* string resource ID, loads that string from our module, and displays it in */
  403. /* a message box. This implementation only covers the general CD error codes.*/
  404. /*                                                                           */
  405. /*****************************************************************************/
  406. int HandleCommDlgError( DWORD dwError )
  407.     {
  408.     char szTitle[128];
  409.     UINT uMsgID;
  410.  
  411.     if( dwError == CDERR_DIALOGFAILURE )
  412.         uMsgID = IDS_CDERR_DIALOGFAILURE;
  413.     else
  414.         uMsgID = (UINT)dwError + IDS_CDERR_GENERAL_BASE;
  415.  
  416.     LoadString( hInst, uMsgID, szTemp, sizeof(szTemp));
  417.     LoadString( hInst, IDS_CDERR_TITLESTRING, szTitle, sizeof(szTitle));
  418.     MessageBox( GetActiveWindow(), szTemp, szTitle,
  419.                     MB_OK | MB_ICONEXCLAMATION );
  420.         
  421.     return( 0 );
  422.     }
  423.  
  424.  
  425. /****************************************************************************/
  426. /* BuildTitleBarText()                                                      */
  427. /*                                                                          */
  428. /*   Helper function designed to updated the title bar text of the main     */
  429. /* window to reflect the currently loaded file (if there is one).           */
  430. /*                                                                          */
  431. /****************************************************************************/
  432. void BuildTitleBarText( void )
  433.     {
  434.     char szTitle[sizeof(szAppCaption) + MAX_PATH + sizeof( " -  (Paused)")];
  435.  
  436.     lstrcpy( szTitle, szAppCaption );
  437.     if( bFileOpen )
  438.     {
  439.     lstrcat( szTitle, " - " );
  440.     lstrcat( szTitle, szFileTitle );
  441.     }
  442.     if( bPaused )
  443.         lstrcat( szTitle, " (Paused)" );
  444.     SetWindowText( hWndMain, szTitle );
  445.     }
  446.  
  447.  
  448. /****************************************************************************/
  449. /* SetAllChannelVolumes()                                                   */
  450. /*                                                                          */
  451. /*   Given a percent in tenths of a percent, sets volume on all channels to */
  452. /* reflect the new value.                                                   */
  453. /****************************************************************************/
  454. void SetAllChannelVolumes( DWORD dwVolumePercent )
  455.     {
  456.     DWORD   dwEvent, dwStatus, dwVol, idx;
  457.     MMRESULT    mmrRetVal;
  458.  
  459.     if( !bPlaying )
  460.     return;
  461.  
  462.  
  463.     for( idx = 0, dwStatus = MIDI_CTRLCHANGE; idx < NUM_CHANNELS; idx++,
  464.                                 dwStatus++ )
  465.     {
  466.     dwVol = ( dwVolCache[idx] * dwVolumePercent ) / 1000;
  467.     dwEvent = dwStatus | ((DWORD)MIDICTRL_VOLUME << 8)
  468.             | ((DWORD)dwVol << 16);
  469.     if(( mmrRetVal = midiOutShortMsg( (HMIDIOUT)hStream, dwEvent ))
  470.                             != MMSYSERR_NOERROR )
  471.         {
  472.         MidiErrorMessageBox( mmrRetVal );
  473.         return;
  474.         }
  475.     }
  476.     }
  477.  
  478.  
  479. /****************************************************************************/
  480. /* SetChannelVolume()                                                       */
  481. /*                                                                          */
  482. /*   Given a percent in tenths of a percent, sets volume on a specified     */
  483. /* channel to reflect the new value.                                        */
  484. /****************************************************************************/
  485. void SetChannelVolume( DWORD dwChannel, DWORD dwVolumePercent )
  486.     {
  487.     DWORD   dwEvent, dwVol;
  488.     MMRESULT    mmrRetVal;
  489.  
  490.     if( !bPlaying )
  491.     return;
  492.  
  493.     dwVol = ( dwVolCache[dwChannel] * dwVolumePercent ) / 1000;
  494.     dwEvent = MIDI_CTRLCHANGE | dwChannel | ((DWORD)MIDICTRL_VOLUME << 8)
  495.                             | ((DWORD)dwVol << 16);
  496.     if(( mmrRetVal = midiOutShortMsg( (HMIDIOUT)hStream, dwEvent ))
  497.                             != MMSYSERR_NOERROR )
  498.     {
  499.     MidiErrorMessageBox( mmrRetVal );
  500.     return;
  501.     }
  502.     }
  503.