home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / mm / daudio / daudio.c next >
Text File  |  1999-05-11  |  27KB  |  869 lines

  1.  
  2.  
  3.  /***************************************************************************
  4.  *                                                                          *
  5.  * File Name        : DAUDIO.C                                              *
  6.  *                                                                          *
  7.  * Description      : This program provides sample code for using the       *
  8.  *                    Multimedia API's related to direct audio support.     *
  9.  *                                                                          *
  10.  *                                                                          *
  11.  * Concepts         : A high speed audio interface has been created by      *
  12.  *                    allowing an application to send audio data directly   *
  13.  *                    to the Amp-Mixer device. This application will        *
  14.  *                    demonstrate the steps required to setup and use ths   *
  15.  *                    new interface for recording and playback of digital   *
  16.  *                    audio.                                                *
  17.  *                                                                          *
  18.  * Entry Points     :                                                       *
  19.  *                    MyEvent                                               *
  20.  *                    MciError                                              *
  21.  *                    Close                                                 *
  22.  *                    LoadFile                                              *
  23.  *                    ResetRecord                                            *
  24.  *                    OpenPlayBack                                          *
  25.  *                    StartPlayBack                                         *
  26.  *                    MainDialogProc                                        *
  27.  *                    main                                                  *
  28.  *                                                                          *
  29.  *                                                                          *
  30.  *                                                                          *
  31.  *                                                                          *
  32.  * Copyright        : COPYRIGHT IBM CORPORATION, 1991, 1992, 1993           *
  33.  *                                                                          *
  34.  *       DISCLAIMER OF WARRANTIES.  The following [enclosed] code is        *
  35.  *       sample code created by IBM Corporation. This sample code is not    *
  36.  *       part of any standard or IBM product and is provided to you solely  *
  37.  *       for  the purpose of assisting you in the development of your       *
  38.  *       applications.  The code is provided "AS IS", without               *
  39.  *       warranty of any kind.  IBM shall not be liable for any damages     *
  40.  *       arising out of your use of the sample code, even if they have been *
  41.  *       advised of the possibility of such damages.                        *
  42.  *                                                                          *
  43.  ****************************************************************************/
  44.  
  45.  
  46. #define  INCL_PM                    /* required to use PM APIs.            */
  47. #define  INCL_OS2MM                 /* required for MCI and MMIO headers   */
  48. #define  INCL_DOS
  49.  
  50. #include <os2.h>
  51. #include <os2me.h>
  52. #include <string.h>
  53. #include <malloc.h>
  54. #include "daudio.h"
  55.  
  56. USHORT               usDeviceID;                /* Amp Mixer device id     */
  57. HWND                 hwndFrame;                 /* Dialog fram window id   */
  58.  
  59. ULONG                ulBufferCount;             /* Current file buffer     */
  60. ULONG                ulNumBuffers;              /* Number of file buffers  */
  61. ULONG                ulNumReturnedBuffers;      /* Num of returned buffers */
  62.  
  63. MCI_MIX_BUFFER       MixBuffers[MAX_BUFFERS];   /* Device buffers          */
  64. MCI_MIXSETUP_PARMS   MixSetupParms;             /* Mixer parameters        */
  65. MCI_BUFFER_PARMS     BufferParms;               /* Device buffer parms     */
  66.  
  67.  
  68. /***************************************************************************
  69.  * Name        : MyEvent
  70.  *
  71.  * Description : The address to this procedure is passed to the mixer
  72.  *               device in the MIX_SETUP_PARMS structure. The mixer
  73.  *               device then calls this procedure when it has expended
  74.  *               a buffer.
  75.  *
  76.  *               NOTE: This is a high priority thread. Too much code here
  77.  *                     will bog the system down.
  78.  *
  79.  * Parameters  : ulStatus - Detailed error message
  80.  *               pBuffer  - Pointer to expended buffer
  81.  *               ulFlags  - Indicates the type of event
  82.  *
  83.  *
  84.  * Return      : BOOL   - TRUE  = failure
  85.  *                      - FALSE = success
  86.  *
  87.  ***************************************************************************/
  88.  
  89. LONG APIENTRY MyEvent ( ULONG ulStatus,
  90.                         PMCI_MIX_BUFFER  pBuffer,
  91.                         ULONG  ulFlags  )
  92.  
  93. {
  94.    ulNumReturnedBuffers++;                      /* Adjust buffer count   */
  95.    switch( ulFlags )
  96.    {
  97.    case MIX_STREAM_ERROR | MIX_READ_COMPLETE :  /* error occur in device */
  98.    case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE:  /* error occur in device */
  99.  
  100.       if ( ulStatus == ERROR_DEVICE_UNDERRUN)
  101.       {
  102.          /* handle ERROR_DEVICE_UNDERRUN or OVERRUN here
  103.           */
  104.  
  105.          if( ulBufferCount < ulNumBuffers )
  106.          {
  107.             MixSetupParms.pmixWrite( MixSetupParms.ulMixHandle,
  108.                                      &MixBuffers[ulBufferCount],
  109.                                      1 );
  110.             ulBufferCount++;
  111.          }
  112.  
  113.          if( ulNumReturnedBuffers  == (ulNumBuffers - 1) )
  114.          {
  115.             WinPostMsg( hwndFrame, WM_COMMAND, ( PVOID )ID_STOP, 0L );
  116.          }
  117.       }
  118.  
  119.       break;
  120.  
  121.    case MIX_READ_COMPLETE :           /* for recording */
  122.  
  123.       if( ulBufferCount < ulNumBuffers )
  124.       {
  125.          MixSetupParms.pmixRead( MixSetupParms.ulMixHandle,
  126.                                  &MixBuffers[ulBufferCount],
  127.                                  1 );
  128.          ulBufferCount++;
  129.       }
  130.  
  131.       if( ulNumReturnedBuffers  == (ulNumBuffers - 1) )
  132.       {
  133.          WinPostMsg( hwndFrame, WM_COMMAND, ( PVOID )ID_STOP, 0L );
  134.       }
  135.       break;
  136.  
  137.    case MIX_WRITE_COMPLETE:           /* for playback  */
  138.  
  139.       if( ulBufferCount < ulNumBuffers )
  140.       {
  141.          MixSetupParms.pmixWrite( MixSetupParms.ulMixHandle,
  142.                                   &MixBuffers[ulBufferCount],
  143.                                   1 );
  144.          ulBufferCount++;
  145.       }
  146.  
  147.       if( ulNumReturnedBuffers  == (ulNumBuffers - 1) )
  148.       {
  149.          WinPostMsg( hwndFrame, WM_COMMAND, ( PVOID )ID_STOP, 0L );
  150.       }
  151.       break;
  152.  
  153.    } /* end switch */
  154.  
  155.    return( TRUE );
  156.  
  157. } /* end MyEvent */
  158.  
  159.  
  160.  
  161.  
  162. /***************************************************************************
  163.  * Name        : MciError
  164.  *
  165.  * Description : Display a message box with the string corresponding to
  166.  *               the passed mci error code.
  167.  *
  168.  * Parameters  : ulError = mci error code
  169.  *
  170.  * Return      : None
  171.  *
  172.  ***************************************************************************/
  173. VOID MciError( ULONG ulError )
  174. {
  175.    SZ       szBuffer[ STRING_LENGTH ];
  176.    ULONG    rc;
  177.  
  178.    rc = mciGetErrorString( ulError, szBuffer, STRING_LENGTH );
  179.  
  180.    WinMessageBox( HWND_DESKTOP,
  181.                   HWND_DESKTOP,
  182.                   szBuffer,
  183.                   "MCI ERROR",
  184.                   0,
  185.                   MB_OK | MB_ERROR | MB_MOVEABLE);
  186.  
  187. }
  188.  
  189.  
  190. /***************************************************************************
  191.  * Name        : Close
  192.  *
  193.  * Description : Deallocate memory and close the Amp-Mixer Device.
  194.  *
  195.  *
  196.  * Parameters  : None
  197.  *
  198.  * Return      : BOOL   - TRUE  = failure
  199.  *                      - FALSE = success
  200.  *
  201.  ***************************************************************************/
  202. VOID Close( VOID )
  203. {
  204.    MCI_GENERIC_PARMS    GenericParms;
  205.    ULONG                rc;
  206.  
  207.    rc = mciSendCommand( usDeviceID,
  208.                         MCI_BUFFER,
  209.                         MCI_WAIT | MCI_DEALLOCATE_MEMORY,
  210.                         ( PVOID )&BufferParms,
  211.                         0 );
  212.  
  213.    if ( rc != MCIERR_SUCCESS )
  214.    {
  215.       MciError( rc );
  216.       return;
  217.    }
  218.  
  219.    rc = mciSendCommand( usDeviceID,
  220.                         MCI_CLOSE,
  221.                         MCI_WAIT ,
  222.                         ( PVOID )&GenericParms,
  223.                         0 );
  224.  
  225.    if ( rc != MCIERR_SUCCESS )
  226.    {
  227.       MciError( rc );
  228.       return;
  229.    }
  230.  
  231. }
  232.  
  233.  
  234.  
  235. /***************************************************************************
  236.  * Name        : LoadFile
  237.  *
  238.  * Description : Allocate application buffers for audio file and load
  239.  *               audio file. These buffers will be copied to device
  240.  *               buffers by another thread.
  241.  *
  242.  *               Before this procedure loads the audio file, the global
  243.  *               MixSetupParms data structure is loaded with information
  244.  *               from the audio files header.
  245.  *
  246.  *
  247.  * Parameters  : CHAR szFilename[]     - Name of wave file to open
  248.  *
  249.  * Return      : BOOL   - TRUE  = failure
  250.  *                      - FALSE = success
  251.  *
  252.  ***************************************************************************/
  253. BOOL LoadFile( CHAR szFileName[] )
  254. {
  255.    MMIOINFO             mmioInfo;
  256.    MMAUDIOHEADER        mmAudioHeader;
  257.    HMMIO                hmmio;
  258.    LONG                 lBytesRead;
  259.    LONG                 ulBufferOffset;
  260.    MCI_AMP_OPEN_PARMS   AmpOpenParms;
  261.    ULONG                rc, ulIndex;
  262.  
  263.  
  264.  
  265.    /* open the mixer device
  266.     */
  267.    memset ( &AmpOpenParms, '\0', sizeof ( MCI_AMP_OPEN_PARMS ) );
  268.    AmpOpenParms.usDeviceID = ( USHORT ) 0;
  269.    AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
  270.  
  271.    rc = mciSendCommand( 0,
  272.                        MCI_OPEN,
  273.                        MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
  274.                        ( PVOID ) &AmpOpenParms,
  275.                        0 );
  276.  
  277.    if ( rc != MCIERR_SUCCESS )
  278.    {
  279.       MciError( rc );
  280.       return( TRUE );
  281.    }
  282.  
  283.    usDeviceID = AmpOpenParms.usDeviceID;
  284.  
  285.  
  286.  
  287.    /* Open the audio file.
  288.     */
  289.    memset( &mmioInfo, '\0', sizeof( MMIOINFO ));
  290.    mmioInfo.fccIOProc = mmioFOURCC( 'W', 'A', 'V', 'E' );
  291.    hmmio = mmioOpen( szFileName, &mmioInfo, MMIO_READ | MMIO_DENYNONE );
  292.  
  293.    if( !hmmio )
  294.    {
  295.       WinMessageBox( HWND_DESKTOP,
  296.                      HWND_DESKTOP,
  297.                      "Unable to open wave file",
  298.                      "MMIO Error",
  299.                      0,
  300.                      MB_OK | MB_ERROR | MB_MOVEABLE);
  301.  
  302.       return( TRUE );
  303.    }
  304.  
  305.    /* Get the audio file header.
  306.     */
  307.    mmioGetHeader( hmmio,
  308.                   &mmAudioHeader,
  309.                   sizeof( MMAUDIOHEADER ),
  310.                   &lBytesRead,
  311.                   0,
  312.                   0);
  313.  
  314.    /* Set the MixSetupParms data structure to match the loaded file.
  315.     * This is a global that is used to setup the mixer.
  316.     */
  317.    memset( &MixSetupParms, '\0', sizeof( MCI_MIXSETUP_PARMS ) );
  318.  
  319.    MixSetupParms.ulBitsPerSample =
  320.          mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample;
  321.  
  322.    MixSetupParms.ulFormatTag =
  323.          mmAudioHeader.mmXWAVHeader.WAVEHeader.usFormatTag;
  324.  
  325.    MixSetupParms.ulSamplesPerSec =
  326.          mmAudioHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec;
  327.  
  328.    MixSetupParms.ulChannels =
  329.          mmAudioHeader.mmXWAVHeader.WAVEHeader.usChannels;
  330.  
  331.    /* Setup the mixer for playback of wave data
  332.     */
  333.    MixSetupParms.ulFormatMode = MCI_PLAY;
  334.    MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
  335.    MixSetupParms.pmixEvent    = MyEvent;
  336.  
  337.    rc = mciSendCommand( usDeviceID,
  338.                         MCI_MIXSETUP,
  339.                         MCI_WAIT | MCI_MIXSETUP_INIT,
  340.                         ( PVOID ) &MixSetupParms,
  341.                         0 );
  342.  
  343.    if ( rc != MCIERR_SUCCESS )
  344.    {
  345.       MciError( rc );
  346.       return( TRUE );
  347.    }
  348.  
  349.    /* Use the suggested buffer size provide by the mixer device
  350.     * and the size of the audio file to calculate the required
  351.     * number of Amp-Mixer buffers.
  352.     * Note: The result is rounded up 1 to make sure we get the
  353.     *       tail end of the file.
  354.     */
  355.    ulNumBuffers =
  356.          mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes
  357.          / ( MixSetupParms.ulBufferSize ) + 1;
  358.  
  359.  
  360.    /* Set up the BufferParms data structure and allocate
  361.     * device buffers from the Amp-Mixer
  362.     */
  363.    BufferParms.ulNumBuffers = ulNumBuffers;
  364.    BufferParms.ulBufferSize = MixSetupParms.ulBufferSize;
  365.    BufferParms.pBufList = MixBuffers;
  366.  
  367.    rc = mciSendCommand( usDeviceID,
  368.                         MCI_BUFFER,
  369.                         MCI_WAIT | MCI_ALLOCATE_MEMORY,
  370.                         ( PVOID ) &BufferParms,
  371.                         0 );
  372.  
  373.     if ( ULONG_LOWD( rc) != MCIERR_SUCCESS )
  374.     {
  375.       MciError( rc );
  376.       return( TRUE );
  377.     }
  378.  
  379.    /* Fill all device buffers with data from the audio file.
  380.     */
  381.    for( ulIndex = 0; ulIndex < ulNumBuffers; ulIndex++)
  382.    {
  383.       memset( MixBuffers[ ulIndex ].pBuffer, '\0', BufferParms.ulBufferSize );
  384.       MixBuffers[ ulIndex ].ulBufferLength = BufferParms.ulBufferSize;
  385.  
  386.       rc = mmioRead ( hmmio,
  387.                       MixBuffers[ ulIndex ].pBuffer,
  388.                       MixBuffers[ ulIndex ].ulBufferLength );
  389.  
  390.    }
  391.  
  392.    /* Set the "end-of-stream" flag
  393.     */
  394.    MixBuffers[ulNumBuffers - 1].ulFlags = MIX_BUFFER_EOS;
  395.  
  396.    mmioClose( hmmio, 0 );
  397.  
  398.    return( FALSE );
  399.  
  400. }
  401.  
  402.  
  403.  
  404. /***************************************************************************
  405.  * Name        : ResetRecord
  406.  *
  407.  * Description : Using the information stored in the MixSetupParms data
  408.  *               structure, the Amp-Mixer device is opened for recording.
  409.  *               Enough device buffers are allocated to fill preallocated
  410.  *               application buffers. Recording is then started and will
  411.  *               continue until all of the device buffers are full ( or
  412.  *               until the user selects the STOP button.
  413.  *
  414.  *
  415.  * Parameters  : None
  416.  *
  417.  * Return      : BOOL   - TRUE  = failure
  418.  *                      - FALSE = success
  419.  *
  420.  ***************************************************************************/
  421. BOOL ResetRecord( VOID )
  422. {
  423.    MCI_CONNECTOR_PARMS  ConnectorParms;
  424.    MCI_AMP_SET_PARMS    AmpSetParms ;
  425.    ULONG                rc;
  426.  
  427.  
  428.    /* Deinitialize the Amp-Mixer to reset for record mode
  429.     */
  430.    rc = mciSendCommand( usDeviceID,
  431.                         MCI_MIXSETUP,
  432.                         MCI_WAIT | MCI_MIXSETUP_DEINIT,
  433.                         ( PVOID )&MixSetupParms,
  434.                         0 );
  435.  
  436.    if ( rc != MCIERR_SUCCESS )
  437.    {
  438.       MciError( rc );
  439.       return( TRUE );
  440.    }
  441.  
  442.  
  443.    /* Setup the mixer for record
  444.     * Note: MixSetupParms is a global data structure. Most of this
  445.     *       structure must be set before this point. The LoadFile
  446.     *       procedure is the first place that this is done.
  447.     */
  448.    MixSetupParms.ulFormatMode = MCI_RECORD;
  449.  
  450.    rc = mciSendCommand( usDeviceID,
  451.                         MCI_MIXSETUP,
  452.                         MCI_WAIT | MCI_MIXSETUP_INIT,
  453.                         ( PVOID ) &MixSetupParms,
  454.                         0 );
  455.  
  456.    if ( rc != MCIERR_SUCCESS )
  457.    {
  458.       MciError( rc );
  459.       return( TRUE );
  460.    }
  461.  
  462.  
  463.  
  464.    /* Zero out the device buffers.
  465.     */
  466.    for( ulBufferCount = 0; ulBufferCount < ulNumBuffers; ulBufferCount++ )
  467.       memset( MixBuffers[ulBufferCount].pBuffer,
  468.               '/0',
  469.               MixBuffers[ulBufferCount].ulBufferLength );
  470.  
  471.   /* Set the connector to 'line in'
  472.    */
  473.   memset( &ConnectorParms, '\0', sizeof( MCI_CONNECTOR_PARMS ) );
  474.   ConnectorParms.ulConnectorType = MCI_LINE_IN_CONNECTOR;
  475.   rc = mciSendCommand( usDeviceID,
  476.                        MCI_CONNECTOR,
  477.                        MCI_WAIT |
  478.                        MCI_ENABLE_CONNECTOR |
  479.                        MCI_CONNECTOR_TYPE,
  480.                        ( PVOID ) &ConnectorParms,
  481.                        0 );
  482.  
  483.   /* Allow the user to hear what is being recorded
  484.    * by turning the monitor on
  485.    */
  486.   memset( &AmpSetParms, '\0', sizeof( MCI_AMP_SET_PARMS ) );
  487.   AmpSetParms.ulItem = MCI_AMP_SET_MONITOR;
  488.   rc = mciSendCommand( usDeviceID,
  489.                        MCI_SET,
  490.                        MCI_WAIT | MCI_SET_ON | MCI_SET_ITEM,
  491.                        ( PVOID ) &AmpSetParms,
  492.                        0 );
  493.  
  494.   /* Set volume to max
  495.    */
  496.   memset( &AmpSetParms, '\0', sizeof( MCI_AMP_SET_PARMS ) );
  497.   AmpSetParms.ulAudio = MCI_SET_AUDIO_ALL;
  498.   AmpSetParms.ulItem = 0;
  499.   AmpSetParms.ulLevel = 100L;
  500.   rc = mciSendCommand( usDeviceID,
  501.                        MCI_SET,
  502.                        MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
  503.                        ( PVOID ) &AmpSetParms,
  504.                        0 );
  505.  
  506.    /* Set the buffer counter
  507.     */
  508.    ulBufferCount = ulNumBuffers;
  509.    ulNumReturnedBuffers = 0;              /* Reset Num of returned buffers */
  510.  
  511.    /* Kick off the mixer.
  512.     */
  513.    if( ulNumBuffers < 2)
  514.    {
  515.    /* If there is only one buffer to read  then tell the mixer that
  516.     * this is the end of the stream. If this flag is not set then
  517.     * the mixer would not start with less than two buffers.
  518.     */
  519.       MixBuffers[0].ulFlags = MIX_BUFFER_EOS;
  520.  
  521.       MixSetupParms.pmixRead( MixSetupParms.ulMixHandle,
  522.                               &MixBuffers[ulBufferCount],
  523.                               1 );
  524.    }
  525.    else
  526.    {
  527.       MixSetupParms.pmixRead( MixSetupParms.ulMixHandle,
  528.                               MixBuffers,
  529.                               ulNumBuffers );
  530.    }
  531.  
  532.  
  533.    return( FALSE );
  534.  
  535.  
  536. }
  537.  
  538.  
  539.  
  540.  
  541. /****************************************************************************
  542.  * Name        : ResetPlayBack
  543.  *
  544.  * Description : Reinit the Amp-Mix device for play-back, allocate  device
  545.  *               buffers, copy audio data to device buffers and kick off
  546.  *               the Amp-Mixer device.
  547.  *
  548.  * Parameters  : None
  549.  *
  550.  * Return      : None
  551.  *
  552.  ***************************************************************************/
  553. BOOL ResetPlayBack( VOID )
  554. {
  555.    MCI_CONNECTOR_PARMS  ConnectorParms;
  556.    MCI_AMP_SET_PARMS    AmpSetParms ;
  557.    ULONG                rc;
  558.  
  559.  
  560.    /* Deinitialize the Amp-Mixer to reset for record mode
  561.     */
  562.    rc = mciSendCommand( usDeviceID,
  563.                         MCI_MIXSETUP,
  564.                         MCI_WAIT | MCI_MIXSETUP_DEINIT,
  565.                         ( PVOID )&MixSetupParms,
  566.                         0 );
  567.  
  568.    if ( rc != MCIERR_SUCCESS )
  569.    {
  570.       MciError( rc );
  571.       return( TRUE );
  572.    }
  573.  
  574.  
  575.    /* Setup the mixer for play-back
  576.     * Note: MixSetupParms is a global data structure. Most of this
  577.     *       structure must be set before this point. The LoadFile
  578.     *       procedure is the first place that this is done.
  579.     */
  580.    MixSetupParms.ulFormatMode = MCI_PLAY;
  581.  
  582.    rc = mciSendCommand( usDeviceID,
  583.                         MCI_MIXSETUP,
  584.                         MCI_WAIT | MCI_MIXSETUP_INIT,
  585.                         ( PVOID ) &MixSetupParms,
  586.                         0 );
  587.  
  588.    if ( rc != MCIERR_SUCCESS )
  589.    {
  590.       MciError( rc );
  591.       return( TRUE );
  592.    }
  593.  
  594.  
  595.    return( FALSE );
  596. }
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.  
  604. /****************************************************************************
  605.  * Name        : StartPlayBack
  606.  *
  607.  * Description : Copy all of the application buffers to device buffers
  608.  *               and kick off the Amp-Mixer device.
  609.  *
  610.  * Parameters  : None
  611.  *
  612.  * Return      : None
  613.  *
  614.  ***************************************************************************/
  615. VOID StartPlayBack( VOID )
  616. {
  617.    ULONG       ulIndex;                /* Device buffer index           */
  618.    ULONG       ulCount;                /* Number of posts               */
  619.  
  620.  
  621.  
  622.    if( ulNumBuffers > 8 )
  623.       ulBufferCount = 8;
  624.    else
  625.       ulBufferCount = ulNumBuffers;
  626.    ulNumReturnedBuffers = 0;              /* Reset Num of returned buffers */
  627.  
  628.    /* Write buffers to kick off the amp mixer.
  629.     */
  630.    MixSetupParms.pmixWrite( MixSetupParms.ulMixHandle,
  631.                             MixBuffers,
  632.                             ulBufferCount );
  633.  
  634. }
  635.  
  636.  
  637.  
  638. /***************************************************************************
  639.  * Name        : MainDialogProc
  640.  *
  641.  * Description : This function controls the main dialog box.  It will handle
  642.  *               received messages such as pushbutton notifications, and
  643.  *               entry field messages.
  644.  *
  645.  *
  646.  ***************************************************************************/
  647. MRESULT EXPENTRY MainDialogProc( HWND hwnd,
  648.                                  ULONG msg,
  649.                                  MPARAM mp1,
  650.                                  MPARAM mp2)
  651. {
  652.  
  653.    MCI_GENERIC_PARMS    GenericParms;
  654.    static HWND          hwndPlayButton,
  655.                         hwndRecordButton,
  656.                         hwndStopButton;
  657.    static BOOL          fPassedDevice = TRUE,
  658.                         fRecording = FALSE;
  659.  
  660.    ULONG                ulIndex,
  661.                         rc;
  662.  
  663.    switch (msg)
  664.    {
  665.    case WM_INITDLG:
  666.  
  667.       /* Get the handles for the PLAY and RECORD buttons
  668.        */
  669.       hwndPlayButton = WinWindowFromID( hwnd, ID_PLAY );
  670.       hwndRecordButton = WinWindowFromID( hwnd, ID_RECORD );
  671.       hwndStopButton = WinWindowFromID( hwnd, ID_STOP );
  672.  
  673.       /* Disable the stop button
  674.        */
  675.       WinEnableWindow( hwndStopButton, FALSE );
  676.  
  677.       /* Load the audio file and setup for playback.
  678.        */
  679.       rc = LoadFile( DEFAULT_FILE );
  680.  
  681.       if( rc )
  682.       {
  683.          MciError( rc );
  684.          WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
  685.          break;
  686.       }
  687.  
  688.       break;
  689.  
  690.    case MM_MCIPASSDEVICE:
  691.  
  692.       /* Check if we are gaining or passing use of the amp-mixer device
  693.        */
  694.       if( SHORT1FROMMP( mp2 ) == MCI_GAINING_USE )
  695.          fPassedDevice = FALSE;
  696.       else
  697.          fPassedDevice = TRUE;
  698.  
  699.       break;
  700.  
  701.    case WM_ACTIVATE:
  702.  
  703.       /* Check if this window is the active window and if we have passed
  704.        * use of the Amp-Mixer device. If yes, then send MCI_ACQUIREDEVICE
  705.        * message.
  706.        */
  707.       if( ( BOOL )mp1 && fPassedDevice )
  708.       {
  709.          GenericParms.hwndCallback = hwnd;
  710.  
  711.          rc = mciSendCommand( usDeviceID,
  712.                               MCI_ACQUIREDEVICE,
  713.                               MCI_NOTIFY | MCI_ACQUIRE_QUEUE,
  714.                               ( PVOID )&GenericParms,
  715.                               0 );
  716.          if( rc )
  717.             MciError( rc );
  718.       }
  719.  
  720.       break;
  721.  
  722.    case WM_COMMAND:
  723.  
  724.       switch ( SHORT1FROMMP ( mp1 ) )
  725.       {
  726.       case ID_PLAY:
  727.  
  728.          /* Disable the play and record buttons
  729.           * Enable the stop button.
  730.           */
  731.          WinEnableWindow( hwndPlayButton, FALSE );
  732.          WinEnableWindow( hwndRecordButton, FALSE );
  733.          WinEnableWindow( hwndStopButton, TRUE );
  734.  
  735.          /* Start playing
  736.           */
  737.          StartPlayBack();
  738.  
  739.          return( FALSE );
  740.  
  741.       case ID_RECORD:
  742.  
  743.          /* The new recording will overwrite the file that was loaded
  744.           * at the start of the program. If the user presses the PLAY
  745.           * button, the newly recorded file will be played.
  746.           */
  747.          if( !ResetRecord() )
  748.          {
  749.             fRecording = TRUE;
  750.  
  751.             /* Disable the play and record buttons
  752.              * Enable the stop button.
  753.              */
  754.             WinEnableWindow( hwndPlayButton, FALSE );
  755.             WinEnableWindow( hwndRecordButton, FALSE );
  756.             WinEnableWindow( hwndStopButton, TRUE );
  757.          }
  758.  
  759.          return( FALSE );
  760.  
  761.       case ID_STOP:
  762.  
  763.          /* Send message to stop the audio device
  764.           */
  765.          mciSendCommand( usDeviceID,
  766.                          MCI_STOP,
  767.                          MCI_WAIT,
  768.                          ( PVOID )&GenericParms,
  769.                          0 );
  770.  
  771.          /* If we were recording then reset for playback
  772.           */
  773.          if( fRecording )
  774.          {
  775.  
  776.             /* Reset the Amp-Mixer device for playback
  777.              */
  778.             ResetPlayBack();
  779.             fRecording = FALSE;
  780.  
  781.          } /* end if */
  782.  
  783.  
  784.          /* Enable the play and record buttons
  785.           */
  786.          WinEnableWindow( hwndRecordButton, TRUE );
  787.          WinEnableWindow( hwndPlayButton, TRUE );
  788.          WinEnableWindow( hwndStopButton, FALSE );
  789.  
  790.          return( FALSE );
  791.       } /* end switch */
  792.  
  793.    case WM_CLOSE:
  794.  
  795.       Close();
  796.  
  797.       WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
  798.       return( FALSE );
  799.  
  800.    } /* end switch */
  801.  
  802.    /* Pass messages on to the frame window
  803.     */
  804.    return ( WinDefDlgProc( hwnd, msg, mp1, mp2 ) );
  805.  
  806. } /* End MainDialogProc */
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  /*************************************************************************
  815.  * Name         : main
  816.  *
  817.  * Description  : Before sending messages to the dialog procedure, the
  818.  *                input file is loaded and the Amp-Mixer device is
  819.  *                setup for playback. This is done to minimise the
  820.  *                percieved delay when the user selects the PLAY button
  821.  *
  822.  * Parameters   : None.
  823.  *
  824.  * Return       : None.
  825.  *
  826.  *************************************************************************/
  827.  
  828. main ( void )
  829. {
  830.    ULONG    rc;
  831.  
  832.    HAB      hab;
  833.    HMQ      hmq;
  834.    QMSG     qmsg;
  835.    ULONG    ulIndex;
  836.  
  837.    /* Initialize PM
  838.     */
  839.    hab = WinInitialize(0);
  840.  
  841.    /* create a message queue for the window
  842.     */
  843.    hmq = WinCreateMsgQueue(hab,0);
  844.  
  845.    /* Load the Dialog - This will return the Handle to the Frame
  846.     */
  847.    hwndFrame = WinLoadDlg( HWND_DESKTOP,
  848.                            HWND_DESKTOP,
  849.                            ( PFNWP )MainDialogProc,
  850.                            NULLHANDLE,
  851.                            ID_DIALOG,
  852.                            NULL );
  853.  
  854.    /* Dispatch messages
  855.     */
  856.    while( WinGetMsg( hab, &qmsg, (HWND) NULL, 0, 0 ) )
  857.       WinDispatchMsg( hab, &qmsg );
  858.  
  859.  
  860.    WinDismissDlg( hwndFrame, TRUE );
  861.    WinDestroyMsgQueue( hmq );
  862.    WinTerminate( hab );
  863.  
  864.    return( FALSE );
  865.  
  866.  
  867.  
  868. } /* end main */
  869.