home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / mm / admct / audiomcd.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  21KB  |  699 lines

  1.  /*********************** END OF SPECIFICATIONS *******************************
  2. *
  3. * SOURCE FILE NAME:  AUDIOMCD.C
  4. *
  5. * DESCRIPTIVE NAME:  WAVEFORM MCD (PLAYER)
  6. *
  7. *              Copyright (c) IBM Corporation  1991, 1993
  8. *                        All Rights Reserved
  9. *
  10. * FUNCTION: Main switch routine for the Audio MCD.  ALL incoming messages
  11. *           are processed in this routine.  Messages can be divided into
  12. *           four types:
  13. *
  14. *   A. MCI_OPEN:  this is the FIRST message any MCD should receive.
  15. *      Minimum processing should be done on the open, and except for
  16. *      incorrect flags or some major catastrophy--it should succeed.
  17. *
  18. *   B. Messages directly from the Media Device Manager (MDM).
  19. *      MCIDRV_RESTORE
  20. *      MCIDRV_SAVE
  21. *      These messages inform the media driver to pause/resume or
  22. *      initialize itself on the attached device (in our case, the
  23. *      audio card).
  24. *      After an MCI_OPEN, an MCIDRV_RESTORE will be the second
  25. *      command and MCD will receive.  If another instance of our MCD
  26. *      or another MCD is using the audio card, MDM will issue an
  27. *      MCIDRV_SAVE to inform us to save our state since we are being
  28. *      removed from the card.
  29. *
  30. *   C. Necessary commands (this will vary from device to device--
  31. *      in our case play/record--see the switch for more information).
  32. *
  33. *   D. Unnecessary commands (such as masteraudio) which we do no
  34. *      processing.  Note: what may be necessary for one MCD may
  35. *      be needed for another.
  36. *
  37. * NOTES:
  38. *
  39. *
  40. * EXTERNAL ENTRY POINTS:
  41. *
  42. *
  43. * INTERNAL ENTRY POINTS:
  44. *
  45. *
  46. * EXTERNAL REFERENCES (system):
  47. *
  48. *
  49. *
  50. * MODIFICATION HISTORY:
  51. * DATE      DEVELOPER         CHANGE DESCRIPTION
  52. *********************** END OF SPECIFICATIONS ********************************/
  53. #define INCL_BASE
  54. #define INCL_DOSMODULEMGR
  55. #define INCL_DOSSEMAPHORES
  56.  
  57. #include <os2.h>                        // OS2 defines.
  58. #include <string.h>
  59. #include <os2medef.h>                   // MME includes files.
  60. #include <stdlib.h>                     // Math functions
  61. #include <ssm.h>                        // SSM Spi includes.
  62. #include <meerror.h>                    // MM Error Messages.
  63. #include <mmioos2.h>                    // MMIO Include.
  64. #include <mcios2.h>                     // MM System Include.
  65. #include <mcipriv.h>                    // MCI Connection stuff
  66. #include <mmdrvos2.h>                   // MCI Driver include.
  67. #include <mcd.h>                        // AudioIFDriverInterface.
  68. #include <hhpheap.h>                    // Heap Manager Definitions
  69. #include <qos.h>
  70. #include <audiomcd.h>                   // Component Definitions.
  71. #include "admcfunc.h"                   // Function Prototypes.
  72. #include <sw.h>
  73. #include <checkmem.h>
  74.  
  75.  
  76. /********************* START OF SPECIFICATIONS *******************************
  77. *
  78. * SUBROUTINE NAME: mciDriverEntry
  79. *
  80. * DESCRIPTIVE NAME: Single Entry point into Waveform MCD Player.
  81. *
  82. * FUNCTION: Process MCI Waveform messages.
  83. *
  84. * NOTES: Device specific information is obtained via the
  85. *        VSDIDriverEntry interface.
  86. *
  87. * ENTRY POINTS:  mciDriverEntry ()
  88. *     LINKAGE:   CALL FAR
  89. *
  90. * INPUT: MCI_MESSAGES.
  91. *
  92. * PARAMETERS:   ulpInstance  - pointer to waveform  instance structure.
  93. *               usMessage    - MCI message to act on.
  94. *               ulParam1     - MCI Flags for this message.
  95. *               ulParam2     - Message  data.
  96. *               usUserParm   - User Parameter Returned on Notifications.
  97. *
  98. * EXIT-NORMAL: Return Code 0
  99. *
  100. * EXIT_ERROR:  MME Error Code
  101. *
  102. * EFFECTS:
  103. *
  104. * INTERNAL REFERENCES:
  105. *                      ADMCINIT, MCIOPEN, MCDCAPS, MCISET,
  106. *                      MCISTAT, MCICUE,  MCISEEK, MCIPLAY,
  107. *                      MCISCPT, MCDINFO,  MCIPAUS, MCICLOS.
  108. *                      MCISTOP
  109. *
  110. * EXTERNAL REFERENCES: mdmDriverNotify, SSM SPIs, MMIO APIs, AudioIFDriverEntry
  111. *                      heap Allocation and management APIs
  112. *                      OS/2 APIs
  113. *
  114. *********************** END OF SPECIFICATIONS ********************************/
  115.  
  116. /* This MCI driver is compiled with optlink linkage in C-SET/2
  117.    the following pragma allows other dll's etc to call in */
  118.  
  119. ULONG APIENTRY  MM_mciDriverEntryADMC ( PVOID    ulpInstance,     // Instance Ptr
  120.                                         USHORT   usMessage,       // Message
  121.                                         ULONG    ulParam1,        // Flags
  122.                                         ULONG    ulParam2,        // Data
  123.                                         USHORT   usUserParm)      // Data
  124. {
  125.  
  126.   ULONG                   ulrc;        // RC
  127.  
  128.   BOOL                    fNotify=TRUE;// should the main function handle
  129.                                        // notification
  130.   FUNCTION_PARM_BLOCK     ParamBlock;  // Encapsulate Parameters
  131.  
  132.  
  133.  
  134.  
  135.   /****************************************
  136.   * Return any unsupported functions or
  137.   * functions which do nothing right away.
  138.   *****************************************/
  139.  
  140.   if ( usMessage == MCI_SPIN           ||
  141.        usMessage == MCI_DEVICESETTINGS ||
  142.        usMessage == MCI_ESCAPE         ||
  143.        usMessage == MCI_STEP           ||
  144.        usMessage == MCI_UPDATE         ||
  145.        usMessage == MCI_GETTOC )
  146.      {
  147.      return ( MCIERR_UNSUPPORTED_FUNCTION );
  148.      }
  149.   else if ( usMessage == MCI_MASTERAUDIO )
  150.      {
  151.      return ( MCIERR_SUCCESS );
  152.      }
  153.  
  154.   /******************************************
  155.   * Copy the mciDriverEntry parameters to a
  156.   * structure which contains all of them.  This
  157.   * simplifies calling functions etc. since we
  158.   * can pass one parameter rather than 5 or 6.
  159.   /******************************************/
  160.  
  161.   ParamBlock.usMessage   = usMessage;
  162.   ParamBlock.ulpInstance = ulpInstance;
  163.   ParamBlock.pInstance   = (INSTANCE *)ulpInstance;
  164.   ParamBlock.usUserParm  = usUserParm;
  165.   ParamBlock.ulParam1    = ulParam1;
  166.   ParamBlock.ulParam2    = ulParam2;
  167.  
  168.  
  169.  
  170.   /************************************************************************
  171.   * Request The Instance Data Access Sem and block all incoming Threads on
  172.   * this semaphore. In case of MCI_PLAY and MCI_RECORD an earlier Release
  173.   * of the Semaphore occurs. All other Incoming MCI Messages on different
  174.   * threads are serialized.
  175.   ************************************************************************/
  176.  
  177.  
  178.   if ( usMessage != MCI_OPEN )
  179.       {
  180.       if ( !(usMessage == MCI_CLOSE  &&
  181.            ulParam1 & MCI_CLOSE_EXIT ) )
  182.          {
  183.          AbortWaitOperation ((INSTANCE *)ulpInstance);
  184.  
  185.          /*------------------------------------------------------
  186.          * We may potentially have to give up the data access
  187.          * sem we acquired in MCD_EnterCrit in order to prevent
  188.          * a hang with MCIDRV_SAVE (see SetAudioDevice for more
  189.          * info on how this can happen).  Therefore, protect
  190.          * the data access sem with an outer sem (saveaccess).
  191.          *------------------------------------------------------*/
  192.          if ( usMessage != MCIDRV_SAVE )
  193.             {
  194.             GetSaveSem ( (INSTANCE *) ulpInstance);
  195.             }
  196.          GetStreamingSemaphore( ulpInstance );
  197.          MCD_EnterCrit ( (INSTANCE *) ulpInstance);
  198.          }
  199.       }
  200.  
  201.   /************************************
  202.   * Prepare the instance for notify, wait
  203.   * or asychronous operation
  204.   *************************************/
  205.  
  206.   NotifyWaitSetup( &ParamBlock, usMessage, ulParam1, ulParam2 );
  207.  
  208.   switch (usMessage)
  209.   {
  210.  
  211.   case MCI_OPEN:
  212.        {
  213.        /**************************************
  214.        * Check that we have a valid pointer
  215.        * in ulParam2 before attempting to use
  216.        * it
  217.        ***************************************/
  218.  
  219.        if (ulrc = CheckMem ((PVOID)ulParam2,
  220.                             sizeof (ULONG),
  221.                             PAG_READ))
  222.  
  223.            return ( MCIERR_MISSING_PARAMETER );
  224.  
  225.         ulrc = AllocateInstance( &ParamBlock );
  226.  
  227.         if ( ulrc )
  228.            {
  229.            return ( ulrc );
  230.            }
  231.  
  232.          /*************************************************
  233.          * Parse all of the flags and ensure that none are
  234.          * conflicting.  Set up semaphores, memory, files,
  235.          * stream hanlders necessary to perform work if
  236.          * everything appears ok
  237.          **************************************************/
  238.  
  239.          ulrc = MCIOpen ( &ParamBlock);
  240.  
  241.          if (ulrc)
  242.            {
  243.  
  244.             /****************************************
  245.             * Free Up all the Resources if Open Fails
  246.             *****************************************/
  247.  
  248.             DosCloseEventSem (ParamBlock.pInstance->hEventSem);
  249.             DosCloseEventSem (ParamBlock.pInstance->hThreadSem);
  250.             DosCloseMutexSem (ParamBlock.pInstance->hmtxDataAccess);
  251.             CleanUp ( ( PVOID ) ParamBlock.pInstance );
  252.             return ( ulrc );
  253.  
  254.             } /* Error On Open */
  255.  
  256.  
  257.        }
  258.       break;
  259.  
  260.   case MCI_GETDEVCAPS:
  261.        ulrc = MCICaps (&ParamBlock);
  262.       break;
  263.   case MCI_SET:
  264.         ulrc = MCISet (&ParamBlock);
  265.        break;
  266.  
  267.   case MCI_STATUS:
  268.  
  269.        ulrc = MCIStat (&ParamBlock);
  270.       break;
  271.  
  272.   case MCI_CUE:
  273.        ulrc = MCICue (&ParamBlock);
  274.       break;
  275.  
  276.   case MCI_SEEK:
  277.        ulrc = MCISeek(&ParamBlock);
  278.       break;
  279.  
  280.   case MCI_PLAY:
  281.        {
  282.  
  283.        /*************************************************
  284.        * Do the necessary processing to prepare the
  285.        * playback stream (i.e. creation, preparing the
  286.        * card for playback) and start the play.
  287.        **************************************************/
  288.  
  289.        ulrc = MCIPlay ( &ParamBlock);
  290.  
  291.  
  292.        /* Play thread will handle notifications */
  293.        fNotify = FALSE;
  294.  
  295.        }
  296.       break;
  297.  
  298.   case MCI_RECORD:
  299.        {
  300.        /*************************************************
  301.        * Do the necessary processing to prepare the
  302.        * record stream (i.e. creation, preparing the
  303.        * card for playback) and start the play.
  304.        **************************************************/
  305.  
  306.        ulrc = MCIRecd ( &ParamBlock);
  307.  
  308.        /* Record thread will handle notifications */
  309.  
  310.        fNotify = FALSE;
  311.  
  312.  
  313.        }
  314.       break;
  315.  
  316.   case MCI_SET_CUEPOINT:
  317.        ulrc = MCISetCuePoint (&ParamBlock);
  318.       break;
  319.  
  320.   case MCI_INFO:
  321.  
  322.        ulrc = MCIInfo (&ParamBlock);
  323.       break;
  324.  
  325.   case MCI_PAUSE:
  326.        ulrc = MCIPaus (&ParamBlock);
  327.       break;
  328.  
  329.   case MCI_CLOSE:
  330.        /* Close function will handle notifications */
  331.        fNotify = FALSE;
  332.        ulrc = MCIClos (&ParamBlock);
  333.       break;
  334.  
  335.   case MCI_CONNECTOR:
  336.        ulrc = MCIConnector (&ParamBlock);
  337.       break;
  338.  
  339. //  case MCI_TEMPCONNECTION:
  340. //       ulrc = MCIConnection (&ParamBlock);
  341. //      break;
  342.  
  343.   case MCI_STOP:
  344.        ulrc = MCIStop (&ParamBlock);
  345.       break;
  346.  
  347.   case MCIDRV_SAVE:
  348.        ulrc = MCISave (&ParamBlock);
  349.  
  350.        /* Don't notify on save */
  351.        fNotify = FALSE;
  352.       break;
  353.  
  354.   case MCIDRV_RESTORE:
  355.        ulrc = MCIRest (&ParamBlock);
  356.        /* Don't notify on restore will handle notifications */
  357.        fNotify = FALSE;
  358.  
  359.       break;
  360. #ifdef CONNECTION
  361.   case MCIDRV_CONNECT:
  362.        ulrc = MCIMakeConnection(&ParamBlock);
  363.        /* Don't notify on restore will handle notifications */
  364.        fNotify = FALSE;
  365.  
  366.       break;
  367.   case MCIDRV_TEST_CONNECTION:
  368.        ulrc = MCITestConnection (&ParamBlock);
  369.        /* Don't notify on restore will handle notifications */
  370.        fNotify = FALSE;
  371.  
  372.       break;
  373.   case MCIDRV_DISCONNECT:
  374.        ulrc = MCIBreakConnection (&ParamBlock);
  375.        /* Don't notify on restore will handle notifications */
  376.        fNotify = FALSE;
  377.  
  378.       break;
  379.   case MCIDRV_ASSOCIATE:
  380.        ulrc = MCIAssociate (&ParamBlock);
  381.        /* Don't notify on restore will handle notifications */
  382.        fNotify = FALSE;
  383.  
  384.       break;
  385. #endif
  386.   case MCI_RESUME:
  387.        ulrc = MCIResume (&ParamBlock);
  388.       break;
  389.  
  390.  case MCI_SAVE:
  391.        /* Don't notify on save */
  392.        fNotify = FALSE;
  393.  
  394.        ulrc = MCISaveFile( &ParamBlock );
  395.       break;
  396.  
  397.  case MCI_LOAD:
  398.        ulrc = MCILoad (&ParamBlock);
  399.       break;
  400.  
  401.   case MCI_SET_POSITION_ADVISE:
  402.        ulrc = MCISetPositionAdvise (&ParamBlock);
  403.       break;
  404.  
  405. //  case MCI_SET_SYNC_OFFSET:
  406. //       ulrc = MCISync (ParamBlock);
  407. //      break;
  408.  
  409. //  case MCIDRV_SYNC:
  410. //       ulrc = MCISync (&ParamBlock);
  411. //
  412. //      break;
  413.  
  414.  
  415.    case MCI_CUT :
  416.       ulrc = MCICopy ( &ParamBlock, MCI_CUT  );
  417.       /* Don't notify on paste */
  418.       fNotify = FALSE;
  419.  
  420.       break;
  421.  
  422.   case MCI_COPY :
  423.       ulrc = MCICopy( &ParamBlock, MCI_COPY );
  424.       /* Don't notify on paste */
  425.       fNotify = FALSE;
  426.  
  427.       break;
  428.   case MCI_PASTE :
  429.       ulrc = MCIPaste( &ParamBlock );
  430.  
  431.       /* Don't notify on paste */
  432.       fNotify = FALSE;
  433.  
  434.       break;
  435.   case MCI_UNDO :
  436.       ulrc = MCIMagic( &ParamBlock, MMIOM_UNDO );
  437.       break;
  438.   case MCI_REDO :
  439.       ulrc = MCIMagic( &ParamBlock, MMIOM_REDO );
  440.       break;
  441.   case MCI_DELETE :
  442.       ulrc = MCICopy( &ParamBlock, MCI_DELETE );
  443.       /* Don't notify on paste */
  444.       fNotify = FALSE;
  445.  
  446.       break;
  447.  
  448.   default:
  449.           ulrc =  MCIERR_UNRECOGNIZED_COMMAND;
  450.       break;
  451.  
  452.  
  453.   }   /* Switch */
  454.  
  455.  
  456.   /***********************************************************************
  457.   * Post The message if notify for synchronous messages only. Exclusive
  458.   * messages are Open, Close, Play and Record. An Open is not complete
  459.   * until it is restored. So a Restore Postes the Notification for an
  460.   * Open Command.
  461.   ***********************************************************************/
  462.  
  463.   if (ParamBlock.ulNotify == TRUE)
  464.      {
  465.      if ( fNotify )
  466.          {
  467.          if (LOBYTE(ulrc) == MCIERR_SUCCESS)
  468.             {
  469.             /****************************************
  470.             * Tell MDM that the operation has been
  471.             * completed and that the mdmdrivernotify
  472.             * should be called.  MDM will do a
  473.             * winpostmessage and the application will
  474.             * be informed of the completion.
  475.             *****************************************/
  476.  
  477.             PostMDMMessage ( MCI_NOTIFY_SUCCESSFUL, usMessage, &ParamBlock);
  478.             }
  479.  
  480.          }   /* Exclusive Messages */
  481.  
  482.      }  /* Notify is On */
  483.  
  484.   /*********************************************************
  485.   * Release all Blocked Threads (for example, if a MCI_SET
  486.   * is being processed and an MCI_PLAY comes in, we want
  487.   * the play to wait until the set has completed or
  488.   * multiple threads could be operating on the instance.
  489.   *********************************************************/
  490.  
  491.   if (usMessage != MCI_OPEN && usMessage != MCI_CLOSE )
  492.      {
  493.      GiveUpSaveSem ( (INSTANCE *) ulpInstance);
  494.      ReleaseStreamingSemaphore( ulpInstance );
  495.  
  496.      MCD_ExitCrit ((INSTANCE *) ulpInstance);
  497.  
  498.      }
  499.  
  500.  
  501.  
  502.   return (ulrc);    /* Return to MDM */
  503.  
  504. } /* mciDriverEntry */
  505.  
  506.  
  507.  
  508.  
  509.  
  510. /********************* START OF SPECIFICATIONS *********************
  511. *
  512. * SUBROUTINE NAME:  MCISAVE
  513. *
  514. * DESCRIPTIVE NAME: Save Waveform Instance State.
  515. *
  516. * FUNCTION:
  517. * A streaming MCD will receive a save message when it loses
  518. * control of the device they are attached to (for example, someone
  519. * started another application which takes over the waveaudio device).
  520. * On a save, the MCD should perform the following commands.
  521. *
  522. * Check to see if we are currently streaming (either record or playback).
  523. * If so, pause the stream, and set a flag stating that we were saved.
  524. *
  525. *
  526. * NOTES:
  527. *
  528. * ENTRY POINTS:
  529. *
  530. * INPUT:
  531. *
  532. * EXIT-NORMAL: Return Code 0.
  533. *
  534. * EXIT_ERROR:  Error Code.
  535. *
  536. * EFFECTS:
  537. *
  538. * INTERNAL REFERENCES:  MCIERR ().
  539. *
  540. * EXTERNAL REFERENCES:  VSDIDriverInterface()  -  VSD
  541. *
  542. *********************** END OF SPECIFICATIONS **********************/
  543. RC MCISave (FUNCTION_PARM_BLOCK *pFuncBlock)
  544. {
  545.  
  546.  
  547.   INSTANCE     * ulpInstance;
  548.   ULONG        ulrc;
  549.  
  550.   ulpInstance= (INSTANCE *)pFuncBlock->ulpInstance;
  551.  
  552.   /******************************************
  553.   * The only thing that a streaming MCD must
  554.   * be concerned about on a save message is
  555.   * saving the state of the stream.  If no
  556.   * stream has been started, then our work is
  557.   * done.  However, if a stream is active then
  558.   * it must be paused. The create flag
  559.   * indicates the stream status, preroll means
  560.    * the stream is playing/recorded/cued etc.
  561.   ******************************************/
  562.  
  563.   if (ulpInstance->ulCreateFlag == PREROLL_STATE)
  564.       {
  565.  
  566.       /************************************************
  567.       * Pause The Stream for Context Switching.  After
  568.       * the pause has been done, MDM will tell the
  569.       * the connected device (in most cases the amp/mixer)
  570.       * to save the state of the audio card.  Once both
  571.       * of these actions have been done, another instance
  572.       * can operate on the audio card.
  573.       **************************************************/
  574.  
  575.       if ( STRMSTATE == MCI_PLAY   ||
  576.            STRMSTATE == MCI_RECORD )
  577.          {
  578.          ulrc = ADMCStopStream (ulpInstance, SPI_STOP_STREAM);
  579.  
  580.          if ( ulrc )
  581.             {
  582.             return ( ulrc );
  583.             }
  584.  
  585.          // make this a BOOL
  586.  
  587.          ulpInstance->usSaveFlag = TRUE;
  588.          } /* if the stream must be paused */
  589.  
  590.       } /* Stream Created */
  591.  
  592.   ulpInstance->ulHoldState = STRMSTATE;
  593.  
  594.   STRMSTATE = SAVEPAUS_STATE;
  595.  
  596.  
  597.   return (MCIERR_SUCCESS); // Dont Return Error Conditions
  598. }
  599.  
  600.  
  601.  
  602. /********************* START OF SPECIFICATIONS *********************
  603. *
  604. * SUBROUTINE NAME:  MCIREST
  605. *
  606. * DESCRIPTIVE NAME: Restore Waveform Instance State.
  607. *
  608. * FUNCTION:
  609. *  A streaming MCD will receive a restore message when it regains
  610. *  control of the device they are attached to (for example, someone
  611. *  quit another application causing us to gain use of the device).
  612. *  On a restore, the MCD should perform the following commands:
  613. *
  614. *  Check to see if we are in paused state.  If so, resume the stream.
  615. *
  616. *
  617. * NOTES:
  618. *
  619. * ENTRY POINTS:
  620. *
  621. * INPUT:
  622. *
  623. * EXIT-NORMAL: MCIERR_SUCCESS.
  624. *
  625. * EXIT_ERROR:  Error Code.
  626. *
  627. * EFFECTS:
  628. *
  629. *********************** END OF SPECIFICATIONS **********************/
  630.  
  631. RC MCIRest (FUNCTION_PARM_BLOCK *pFuncBlock)
  632. {
  633.  
  634.  
  635.   INSTANCE        * ulpInstance;
  636.   ULONG           ulrc = MCIERR_SUCCESS;
  637.  
  638.  
  639.   ulpInstance= (INSTANCE *)pFuncBlock->ulpInstance;
  640.  
  641.   /**************************************************
  642.   * Restore will only perform work when a stream has
  643.   * been paused after it was started (see comments
  644.   * in MCISave).  If the saveflag is true and the
  645.   * createflag is in a preroll state then resume the
  646.   * stream.
  647.   ***************************************************/
  648.  
  649.   if (ulpInstance->usSaveFlag == TRUE)
  650.       {
  651.       if (ulpInstance->ulCreateFlag == PREROLL_STATE)
  652.           {
  653.           /*******************************************
  654.           * If The Stream was in a running state
  655.           * before Context switch start the stream
  656.           * else just set the restored flag to true
  657.           ********************************************/
  658.  
  659.           if (STRMSTATE == SAVEPAUS_STATE)
  660.               {
  661.  
  662.               /***********************************************
  663.               * Start the stream from this position
  664.               ************************************************/
  665.               ulrc = SpiStartStream (STREAM.hStream,
  666.                                      SPI_START_STREAM);
  667.  
  668.               if (ulrc)
  669.                   return (ulrc);
  670.  
  671. //              STRMSTATE = MCI_PLAY;
  672.               } /* Save Pause State */
  673.  
  674.           } /* PreRoll State */
  675.      /*--------------------------------------------------
  676.      * Ensure that other restores will not falsely
  677.      * restart the stream by setting a flag.
  678.      *--------------------------------------------------*/
  679.  
  680.      ulpInstance->usSaveFlag = FALSE;
  681.  
  682.      } /* True Save Flag */
  683.  
  684.   if ( STRMSTATE == SAVEPAUS_STATE )
  685.      {
  686.      STRMSTATE = ulpInstance->ulHoldState;
  687.      }
  688.  
  689.   /* If this is the first restore, get information from the mixer */
  690.  
  691. //  if ( ulpInstance->ulFlags & FIRST_RESTORE )
  692. //     {
  693. //     ulrc = GetMixerInfo( ulpInstance );
  694. //     ulpInstance->ulFlags &= ~FIRST_RESTORE;
  695. //     }
  696.   return (ulrc); // Dont Return Error Conditions
  697. }
  698.  
  699.