home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional Developers Kit 1992 November / Disc01 / Disc01.mdf / runnable / mmos2 / mmtoolkt / samples / admct / admcrest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-06  |  69.5 KB  |  2,293 lines

  1. /*static char *SCCSID = "@(#)admcrest.c    13.18 92/04/29";*/
  2. /********************* START OF SPECIFICATIONS *********************
  3. *
  4. * SUBROUTINE NAME: MCIREST.c
  5. *
  6. * DESCRIPTIVE NAME: Audio MCD WaveAudio Playback Function.
  7. *
  8. * FUNCTION:Play an Waveform Audio Element.
  9. *
  10. * NOTES:
  11. *
  12. * ENTRY POINTS:
  13. *     LINKAGE:   CALL FAR
  14. *
  15. * INPUT:
  16. *
  17. *
  18. *
  19. * EXIT-NORMAL: Return Code 0.
  20. *
  21. * EXIT_ERROR:  Error Code.
  22. *
  23. * EFFECTS:
  24. *
  25. *
  26. * INTERNAL REFERENCES:   MCICUE, MCIPAUS, MCISEEK,
  27. *                        MCISTOP, MCISTPA, MCISCPT
  28. *                        MCICNCT
  29. *                        CreateNAssocStream ().
  30. *                        DestroyStream ().
  31. *                        AssocMemPlayToAudioStream ().
  32. *                        PostMDMMessage ().
  33. *                        DoTillEvent().
  34. *                        ConvertTimeUnits ().
  35. *                        StartPlay().
  36. *                        PlEventProc().
  37. *                        SetAudioDevice().
  38. *                        InitAudioDevice().
  39. *                        SetWaveDeviceDefaults().
  40. *                        OpenFile().
  41. *                        CheckMem ().
  42. *
  43. * EXTERNAL REFERENCES:   DosResetEventSem ()        - OS/2 API
  44. *                        DosPostEventSem  ()        - OS/2 API
  45. *                        DosCreateThread  ()        - OS/2 API
  46. *                        SpiEnableEvent   ()        - MME API
  47. *                        SpiStopStream    ()        - MME API
  48. *                        SpiCreateStream  ()        - MME API
  49. *                        SpiAssociate     ()        - MME API
  50. *                        SpiSeekStream    ()        - MME API
  51. *                        mdmDriverNotify  ()        - MME API
  52. *                        mmioGetHeader    ()        - MME API
  53. *
  54. *********************** END OF SPECIFICATIONS **********************/
  55.  
  56. #define INCL_DOSSEMAPHORES
  57. #define INCL_DOSPROCESS
  58. #define INCL_ERRORS
  59.  
  60. #include <os2.h>                        // OS2 defines.
  61. #include <string.h>                     // String functions.
  62. #include <os2medef.h>                   // MME includes files.
  63. #include <audio.h>                      // Audio Device Defines.
  64. #include <ssm.h>                        // SSM spi includes.
  65. #include <meerror.h>                    // MM Error Messages.
  66. #include <mmsystem.h>                   // MM System Include.
  67. #include <mcidrv.h>                     // MCI Driver Include.
  68. #include <mmio.h>                       // MMIO Include.
  69. #include <mcd.h>                        // AudioIFDriverInterface.
  70. #include <hhpheap.h>                    // Heap Manager Definitions
  71. #include <audiomcd.h>                   // Component Definitions
  72. #include "admcfunc.h"                   // Function Prototypes
  73.  
  74. /********************* START OF SPECIFICATIONS *********************
  75. *
  76. * SUBROUTINE NAME: MCICUE..C
  77. *
  78. * DESCRIPTIVE NAME: Cue Waveform Device.
  79. *
  80. * FUNCTION: Prepare a Waveform Device or an Device Element for Record/Playback.
  81. *
  82. * NOTES: Cueing a Waveform Device translates to mean prerolling of streams
  83. *        in the streaming context. It is presumed that MCI_OPEN precedes
  84. *        MCI_CUE. The validity of this presumption can be checked by looking
  85. *        at ulState. Preroll means source handler fills the buffers and is
  86. *        to roll. The Target handlers are not started, meaning buffers are
  87. *        are not consumed.
  88. *
  89. * ENTRY POINTS:
  90. *     LINKAGE:   CALL FAR
  91. *
  92. * INPUT: MCI_CUE message.
  93. *
  94. * EXIT-NORMAL: Return Code 0.
  95. *
  96. * EXIT_ERROR:  Error Code.
  97. *
  98. * EFFECTS:
  99. *
  100. * INTERNAL REFERENCES:
  101. *
  102. * EXTERNAL REFERENCES: AudioIFDriverEntry()       - AudioDevice MCD
  103. *
  104. *********************** END OF SPECIFICATIONS **********************/
  105. RC MCICue (FUNCTION_PARM_BLOCK *pFuncBlock)
  106. {
  107.   ULONG          ulrc;                 // Error Value
  108.   ULONG          ulErr;                // Holds error values
  109.   ULONG          ulParam1;             // Msg Flags
  110.   ULONG          ulParam2;             // Msg data
  111.   ULONG          ulAbortNotify = FALSE;// whether or not a action must be aborted
  112.                                        // in case other thread overwrites it
  113.   INSTANCE *     ulpInstance;          // Local Instance
  114.   ULONG          lCnt;                 // Number of Posts
  115.   DWORD          dwCueFlags;           // Mask For Incoming MCI Flags
  116.   DWORD          dwStopFlags;          // Flush or Discard Stop.
  117.   DWORD          dwSetAll;             // Set all flags
  118.   LPMCI_GENERIC_PARMS lpCueParams;     // Msg data ptr
  119.   MCI_WAVE_SET_PARMS  lpSetParms;      // MCI Wave Set Parms
  120.  
  121.   ULONG         ulAssocFlag = 0;
  122.  
  123.   /******************************
  124.   * Derefernce pointers.
  125.   ******************************/
  126.   ulParam1 =    pFuncBlock->ulParam1;
  127.   ulParam2 =    pFuncBlock->ulParam2;
  128.   ulpInstance= (INSTANCE *)pFuncBlock->ulpInstance;
  129.  
  130.   ulrc = MCIERR_SUCCESS;
  131.   dwStopFlags = SPI_STOP_DISCARD;
  132.  
  133.   dwSetAll = MCI_WAVE_SET_BITSPERSAMPLE| MCI_WAVE_SET_FORMATTAG|
  134.              MCI_WAVE_SET_CHANNELS| MCI_WAVE_SET_SAMPLESPERSEC;
  135.   /******************************
  136.   * Check for Invalid Flags
  137.   *******************************/
  138.   dwCueFlags = ulParam1;
  139.   dwCueFlags &= ~MCI_NOTIFY;
  140.   dwCueFlags &= ~MCI_WAIT;
  141.   dwCueFlags &= ~(MCI_CUE_INPUT + MCI_CUE_OUTPUT +
  142.                   MCI_WAVE_INPUT + MCI_WAVE_OUTPUT);
  143.   /****************************************
  144.   * Check for Invalid flags
  145.   *****************************************/
  146.   if (dwCueFlags > 0)
  147.       return MCIERR_INVALID_FLAG;
  148.  
  149.   ulrc = CheckMem (((PVOID)ulParam2),
  150.                    sizeof (MCI_GENERIC_PARMS), PAG_READ);
  151.  
  152.   if (ulrc == MCIERR_SUCCESS)
  153.       lpCueParams = (LPMCI_GENERIC_PARMS)ulParam2;
  154.  
  155.   if (ulpInstance == (ULONG)NULL )
  156.       return MCIERR_INSTANCE_INACTIVE;
  157.  
  158.   if (ulpInstance->ulInstanceSignature != ACTIVE)
  159.       return MCIERR_INSTANCE_INACTIVE;
  160.  
  161.   /******************************************
  162.   * Check for incompatible flags
  163.   *******************************************/
  164.   if (((ulParam1 & MCI_WAVE_INPUT)||(ulParam1 & MCI_CUE_INPUT)) &&
  165.       ((ulParam1 & MCI_WAVE_OUTPUT) || (ulParam1 & MCI_CUE_OUTPUT)))
  166.  
  167.       return MCIERR_FLAGS_NOT_COMPATIBLE;
  168.  
  169.   /****************************************
  170.   * If No Element return error
  171.   *****************************************/
  172.  
  173.   if ( ( ulpInstance->usFileExists == FALSE) || (ulpInstance->usFileExists == UNUSED) )
  174.      {
  175.      return (MCIERR_FILE_NOT_FOUND);
  176.      }
  177.  
  178.   /******************************************
  179.   * If a temp file was not opened, then we
  180.   * cannot use recording features
  181.   *******************************************/
  182.  
  183.   if ( ( (ulParam1 & MCI_WAVE_INPUT)||(ulParam1 & MCI_CUE_INPUT) ) &&
  184.        !ulpInstance->ulUsingTemp &&
  185.        !ulpInstance->usPlayLstStrm )
  186.     {
  187.     return MCIERR_UNSUPPORTED_FUNCTION;
  188.     }
  189.  
  190.   /******************************************
  191.   * Check for Missing flags
  192.   *******************************************/
  193.   if (!(ulParam1 & MCI_WAVE_INPUT || ulParam1 & MCI_WAVE_OUTPUT ||
  194.       ulParam1 & MCI_CUE_INPUT || ulParam1 & MCI_CUE_OUTPUT))
  195.       {
  196.       // don't return a missing flag, default to output
  197.  
  198.       ulParam1 &= MCI_WAVE_OUTPUT;
  199.  
  200.       }
  201.  
  202.   /**********************************
  203.   * Open The Instance Event Sem
  204.   ***********************************/
  205.   ulrc = DosOpenEventSem ((PSZ)NULL,
  206.                           (PHEV)&(ulpInstance->hEventSem));
  207.   if (ulrc)
  208.       return ulrc;
  209.  
  210.  
  211.   /*************************************************
  212.   * PlayList in Paused State an Exclusive state ??
  213.   *************************************************/
  214.  
  215.  
  216.   if (ulpInstance->usPlayLstStrm == TRUE )
  217.      {
  218.  
  219.      // notifies will stop the stream on their own
  220.      // we are only concerned with waits, and previously stopped
  221.      // streams
  222.  
  223.      if ( STRMSTATE == MCI_PAUSE &&
  224.           !(ulpInstance->usNotifyPending) )
  225.        {
  226.  
  227.        DosResetEventSem (ulpInstance->hThreadSem, &lCnt);
  228.        ulrc = SpiStopStream (STREAM.hStream,
  229.                                SPI_STOP_DISCARD);
  230.        if (!ulrc)
  231.          {
  232.          DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1);
  233.          }
  234.        }
  235.      } /* PlayList Pause */
  236.  
  237.   /************************************
  238.   *  Pause is an exclusive State
  239.   **************************************/
  240.   if (ulpInstance->usPlayLstStrm != TRUE )
  241.       {
  242.       if ((STRMSTATE == MCI_PAUSE  ||
  243.            STRMSTATE == MCI_STOP   ||
  244.            STRMSTATE == STOP_PAUSED ) &&
  245.  
  246.           (ulpInstance->ulCreateFlag == PREROLL_STATE )
  247.           && !ulpInstance->usNotifyPending                     )
  248.           {
  249.           /***********************************************
  250.           *  Discard Stop the Stream if in Paused State
  251.           ***********************************************/
  252.           DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  253.           ulrc = SpiStopStream (STREAM.hStream, SPI_STOP_DISCARD);
  254.           if (!ulrc)
  255.               DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1);
  256.           ulpInstance->ulCreateFlag = PREROLL_STATE;
  257.  
  258.           }   /* Exclusive States */
  259.       }  /* Non PlayList */
  260.  
  261.   /**********************************************
  262.   * Create and Cue The Playback Stream A --> B
  263.   ***********************************************/
  264.   if ((ulParam1 & MCI_CUE_OUTPUT) || (ulParam1 & MCI_WAVE_OUTPUT))
  265.      {
  266.  
  267.      DosRequestMutexSem( ulpInstance->hmtxNotifyAccess, -1 );
  268.      if (ulpInstance->usNotifyPending == TRUE)
  269.         {
  270.         ulpInstance->ulNotifyAborted = TRUE;
  271.         ulpInstance->usNotifyPending = FALSE;
  272.         ulAbortNotify = TRUE;
  273.         }
  274.      DosReleaseMutexSem( ulpInstance->hmtxNotifyAccess );
  275.  
  276.      /*****************************************************
  277.      * If a stream is currently in use, destroy or stop it!
  278.      ******************************************************/
  279.      if ( ulAbortNotify == TRUE)
  280.         {
  281.         if ( ulpInstance->usNotPendingMsg == MCI_SAVE )
  282.           {
  283.           // Save is a non-interruptible operation
  284.           // wait for completion
  285.  
  286.           DosWaitEventSem( ulpInstance->hThreadSem, (ULONG ) -1 );
  287.  
  288.           }
  289.         else
  290.           {
  291.           PostMDMMessage ( MCI_NOTIFY_ABORTED,
  292.                            ulpInstance->usNotPendingMsg,
  293.                            pFuncBlock );
  294.  
  295.           if ( ulpInstance->usNotPendingMsg == MCI_PLAY )
  296.              {
  297.              DosResetEventSem( ulpInstance->hEventSem, &lCnt );
  298.              DosResetEventSem( ulpInstance->hThreadSem, &lCnt );
  299.              ulrc = SpiStopStream( STREAM.hStream, SPI_STOP_DISCARD );
  300.              if ( !ulrc )
  301.                 {
  302.                 DosWaitEventSem( ulpInstance->hThreadSem, -1 );
  303.  
  304.                 // ***************************************
  305.                 // ***************************************
  306.                 // perform error checking HERE!!!!!!!!!!!!
  307.                 // ***************************************
  308.                 // ***************************************
  309.                 }
  310.              } /* if this is play stream */
  311.  
  312.           else
  313.              {
  314.              /**************************************
  315.              * Destroy The Previous Stream
  316.              ***************************************/
  317.  
  318.              DestroyStream (STREAM.hStream);
  319.  
  320.              /***************************************
  321.              * Update Create Stream Flag
  322.              ****************************************/
  323.  
  324.              ulpInstance->ulCreateFlag = CREATE_STATE;
  325.  
  326.              } /* else this is a  record stream */
  327.  
  328.  
  329.  
  330.           } /* if !save */
  331.  
  332.  
  333.         } /* if notify pending is true */
  334.       else
  335.         {
  336.         } /* not notify pending */
  337.  
  338.  
  339.  
  340.  
  341.  
  342.       /*****************************
  343.       * Set Operation Flag
  344.       ******************************/
  345.       AMPMIX.ulOperation = OPERATION_PLAY;
  346.  
  347.       /***********************************************
  348.       * If a set was performed on an existing stream,
  349.       * destroy the stream and get new spcb keys
  350.       ***********************************************/
  351.       if ( STRMSTATE == STREAM_SET_STATE )
  352.         {
  353.         DestroyStream (STREAM.hStream);
  354.  
  355.         // get new spcb key
  356.  
  357.         ulrc = InitAudioDevice (ulpInstance, OPERATION_PLAY );
  358.  
  359.         if (ulrc)
  360.            {
  361.            return ( ulrc );
  362.            }
  363.  
  364.         ulpInstance->ulCreateFlag = CREATE_STATE;
  365.  
  366.         }
  367.  
  368.       if (ulpInstance->ulCreateFlag != PREROLL_STATE)
  369.          {
  370.           if (ulpInstance->usPlayLstStrm == TRUE)
  371.               {
  372.               ulAssocFlag = (ULONG)NULL;
  373.               }
  374.           else
  375.               ulAssocFlag = PLAY_STREAM;
  376.  
  377.           /*************************************************
  378.           * Always Reinit The Device before stream creation.
  379.           *************************************************/
  380.  
  381.           ulrc = InitAudioDevice (ulpInstance, OPERATION_PLAY);
  382.  
  383.           if (ulrc)
  384.             {
  385.             return ulrc;
  386.             }
  387.  
  388.           SetAmpDefaults(ulpInstance);
  389.  
  390.           AMPMIX.ulOperation = OPERATION_PLAY;
  391.  
  392.           VSDInstToWaveSetParms (&lpSetParms,ulpInstance);
  393.           if (!ulrc)
  394.             {
  395.             ulrc = SetAudioDevice (ulpInstance,
  396.                                    (LPMCI_WAVE_SET_PARMS)&lpSetParms,
  397.                                    dwSetAll );
  398.             }
  399.  
  400.           if ( ulrc )
  401.             {
  402.             return ( ulrc );
  403.             }
  404.  
  405.           /*************************************************
  406.           * If the init caused a new global sys file, use it
  407.           *************************************************/
  408.  
  409.           STREAM.AudioDCB.ulSysFileNum = AMPMIX.ulGlobalFile;
  410.  
  411.           /********************************************
  412.           * Create and associate a playback stream
  413.           * This stream has the file system as the
  414.           * source stream handler and audio stream
  415.           * handler as the target.
  416.           *********************************************/
  417.           ulrc = CreateNAssocStream (STREAM.hidASource,
  418.                                      STREAM.hidBTarget,
  419.                                      (HSTREAM *)&(STREAM.hStream),
  420.                                      (INSTANCE *) ulpInstance,
  421.                                      (ULONG)ulAssocFlag,
  422.                                      (PEVFN)PlEventProc);
  423.           if (ulrc)
  424.               return ulrc;
  425.  
  426.           /*****************************************************
  427.           * In Case of PlayList Do the Associate Seperately
  428.           ******************************************************/
  429.           if (ulAssocFlag == (ULONG)NULL)
  430.               ulrc = AssocMemPlayToAudioStrm (ulpInstance,
  431.                                               PLAY_STREAM);
  432.  
  433.  
  434.          }     /* Play Back Stream */
  435.       ulpInstance->ulCreateFlag = PREROLL_STATE;
  436.  
  437.      /*******************************
  438.      * Preroll Start the stream.
  439.      *******************************/
  440.      DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  441.  
  442.      if (STRMSTATE != CUEPLAY_STATE)
  443.          {
  444.  
  445.          ulrc = SpiStartStream (STREAM.hStream,
  446.                                 SPI_START_PREROLL);
  447.  
  448.          if (ulrc)
  449.              return ulrc;
  450.          /*************************************
  451.          * Wait till you Recieve PREROLL Event
  452.          *************************************/
  453.          DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1);
  454.  
  455.          } /* Preroll Start */
  456.  
  457.      /*************************************
  458.      * UpDate State To Preroll
  459.      **************************************/
  460.      STRMSTATE = CUEPLAY_STATE;
  461.      ulpInstance->ulCreateFlag = PREROLL_STATE;
  462.  
  463.      } /* default case is wave output */
  464.  
  465.   /********************************************
  466.   * Create and Cue The Record Stream B --> A
  467.   *********************************************/
  468.  
  469.   if ((ulParam1 & MCI_CUE_INPUT) || (ulParam1 & MCI_WAVE_INPUT))
  470.  
  471.      {
  472.  
  473.      DosRequestMutexSem( ulpInstance->hmtxNotifyAccess, -1 );
  474.      if (ulpInstance->usNotifyPending == TRUE)
  475.         {
  476.         ulpInstance->ulNotifyAborted = TRUE;
  477.         ulpInstance->usNotifyPending = FALSE;
  478.         ulAbortNotify = TRUE;
  479.         }
  480.      DosReleaseMutexSem( ulpInstance->hmtxNotifyAccess );
  481.  
  482.      /*****************************************************
  483.      * If a stream is currently in use, destroy or stop it!
  484.      ******************************************************/
  485.      if ( ulAbortNotify == TRUE)
  486.         {
  487.         if ( ulpInstance->usNotPendingMsg == MCI_SAVE )
  488.           {
  489.           // Save is a non-interruptible operation
  490.           // wait for completion
  491.  
  492.           DosWaitEventSem( ulpInstance->hThreadSem, (ULONG ) -1 );
  493.  
  494.           }
  495.         else
  496.           {
  497.           PostMDMMessage ( MCI_NOTIFY_ABORTED,
  498.                            ulpInstance->usNotPendingMsg,
  499.                            pFuncBlock );
  500.  
  501.           if ( ulpInstance->usNotPendingMsg == MCI_RECORD )
  502.  
  503.              {
  504.              DosResetEventSem( ulpInstance->hEventSem, &lCnt );
  505.              DosResetEventSem( ulpInstance->hThreadSem, &lCnt );
  506.              ulrc = SpiStopStream( STREAM.hStream, SPI_STOP_FLUSH );
  507.              if ( !ulrc )
  508.                 {
  509.                 DosWaitEventSem( ulpInstance->hThreadSem, ONE_MINUTE );
  510.  
  511.                 // ***************************************
  512.                 // ***************************************
  513.                 // perform error checking HERE!!!!!!!!!!!!
  514.                 // ***************************************
  515.                 // ***************************************
  516.                 }
  517.              } /* if this is record stream */
  518.  
  519.           else
  520.              {
  521.              /**************************************
  522.              * Destroy The Previous Stream
  523.              ***************************************/
  524.  
  525.              DestroyStream (STREAM.hStream);
  526.  
  527.              /***************************************
  528.              * Update Create Stream Flag
  529.              ****************************************/
  530.  
  531.              ulpInstance->ulCreateFlag = CREATE_STATE;
  532.  
  533.              } /* else this is a play stream */
  534.  
  535.            } /* notify pending was not a !save */
  536.  
  537.  
  538.         } /* if notify pending is true */
  539.       else
  540.         {
  541.  
  542.         } /* not notify pending */
  543.  
  544.  
  545.       if (ulpInstance->usPlayLstStrm != TRUE)
  546.           {
  547.  
  548.           /********************************************
  549.           * The Open has not yet been done (Record).
  550.           *********************************************/
  551.  
  552.           if (ulpInstance->usFileExists == UNUSED)
  553.               return (MCIERR_FILE_NOT_FOUND);
  554.  
  555.           if (ulpInstance->usFileExists == TRUE)
  556.               {
  557.               /************************************
  558.               * Open with Write Flag ON
  559.               ************************************/
  560.               if ( !( ulpInstance->dwmmioOpenFlag & MMIO_EXCLUSIVE ) )
  561.                   {
  562.                   ulrc = mmioClose (ulpInstance->hmmio, 0);
  563.  
  564.                   ulpInstance->dwmmioOpenFlag = MMIO_READWRITE | MMIO_EXCLUSIVE;
  565.  
  566.                   ulErr = OpenFile ( ulpInstance, ulpInstance->dwmmioOpenFlag );
  567.  
  568.                   if ( ulErr )
  569.                      {
  570.                      ulpInstance->dwmmioOpenFlag = MMIO_READ | MMIO_DENYNONE;
  571.  
  572.                      ulrc = OpenFile ( ulpInstance, ulpInstance->dwmmioOpenFlag );
  573.                      if ( ulrc )
  574.                         {
  575.                         ulpInstance->usFileExists = FALSE;
  576.                         }
  577.  
  578.                      return ( ulErr );
  579.                      }
  580.                   }
  581.               } /* File Exists */
  582.           else
  583.               {
  584.               ulpInstance->dwmmioOpenFlag = MMIO_READWRITE | MMIO_CREATE | MMIO_EXCLUSIVE;
  585.  
  586.               ulrc = OpenFile (ulpInstance, ulpInstance->dwmmioOpenFlag );
  587.               if (ulrc)
  588.                   return (ulrc);
  589.               }
  590.  
  591.           } /* Not PlayList */
  592.  
  593.       /**********************************************
  594.       * Look for State Transition variables
  595.       *  and change State accordingly (FSA Approach)
  596.       ***********************************************/
  597.  
  598.       if ((STRMSTATE == CUEPLAY_STATE)|| (STRMSTATE == MCI_PLAY)||
  599.           (STRMSTATE == MCI_PAUSE)) {
  600.            /******************************************
  601.            * Stop The Previous stream
  602.            *******************************************/
  603.            ulrc = SpiStopStream (STREAM.hStream,
  604.                                  SPI_STOP_DISCARD);
  605.  
  606.            /**************************************
  607.            * Destroy the previous stream
  608.            ***************************************/
  609.            DestroyStream (STREAM.hStream);
  610.  
  611.            /*******************************************
  612.            * Set Stream Creation flag to create state
  613.            ********************************************/
  614.            ulpInstance->ulCreateFlag = CREATE_STATE;
  615.       }
  616.  
  617.  
  618.       /***********************************************
  619.       * If a set was performed on an existing stream,
  620.       * destroy the stream and get new spcb keys
  621.       ***********************************************/
  622.       if ( STRMSTATE == STREAM_SET_STATE )
  623.         {
  624.         DestroyStream (STREAM.hStream);
  625.  
  626.         // get new spcb key
  627.  
  628.         ulrc = InitAudioDevice (ulpInstance, OPERATION_PLAY );
  629.  
  630.         if (ulrc)
  631.            {
  632.            return ( ulrc );
  633.            }
  634.         ulpInstance->ulCreateFlag = CREATE_STATE;
  635.  
  636.         }
  637.  
  638.       if (ulpInstance->ulCreateFlag != PREROLL_STATE) {
  639.           if (ulpInstance->usPlayLstStrm == TRUE) {
  640.               ulAssocFlag = (ULONG)NULL;
  641.           }
  642.           else
  643.               ulAssocFlag = RECORD_STREAM;
  644.  
  645.           // get new spcb key
  646.  
  647.           ulrc = InitAudioDevice (ulpInstance, OPERATION_RECORD);
  648.  
  649.           if (ulrc)
  650.             {
  651.             return ( ulrc );
  652.             }
  653.  
  654.           AMPMIX.ulOperation = OPERATION_RECORD;
  655.  
  656.           VSDInstToWaveSetParms (&lpSetParms,ulpInstance);
  657.  
  658.  
  659.           if (!ulrc)
  660.             ulrc = SetAudioDevice ( ulpInstance,
  661.                                     (LPMCI_WAVE_SET_PARMS)&lpSetParms,
  662.                                     dwSetAll);
  663.  
  664.           if ( ulrc )
  665.             {
  666.             return ( ulrc );
  667.             }
  668.  
  669.           /*************************************************
  670.           * If the init caused a new global sys file, use it
  671.           *************************************************/
  672.  
  673.           STREAM.AudioDCB.ulSysFileNum = AMPMIX.ulGlobalFile;
  674.  
  675.           /*****************************************************
  676.           * Create The Stream from ADSH ---> FSSH
  677.           ******************************************************/
  678.           ulrc = CreateNAssocStream ( STREAM.hidBSource,
  679.                                       STREAM.hidATarget,
  680.                                       (HSTREAM *)&(STREAM.hStream),
  681.                                       (INSTANCE *) ulpInstance,
  682.                                       (ULONG) ulAssocFlag,
  683.                                       (PEVFN)ReEventProc);
  684.           if (ulrc)
  685.               return ulrc;
  686.  
  687.           /*******************************************************
  688.           * In Case of PlayList Do the Associate Seperately
  689.           *******************************************************/
  690.           if (ulAssocFlag == (ULONG)NULL)         // Do the Associate Seperately
  691.               ulrc = AssocMemPlayToAudioStrm (ulpInstance,
  692.                                               RECORD_STREAM);
  693.  
  694.       } /* Create Flag */
  695.  
  696.       ulpInstance->ulCreateFlag = PREROLL_STATE;
  697.       /***********************************
  698.       * Preroll start the Stream
  699.       ************************************/
  700.  
  701.       DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  702.  
  703.       if (STRMSTATE != CUERECD_STATE) {
  704.           ulrc = SpiStartStream (STREAM.hStream,
  705.                                  SPI_START_PREROLL);
  706.           if (ulrc)
  707.               return ulrc;
  708.           /*************************************
  709.           * Wait till you Recieve PREROLL Event
  710.           *************************************/
  711.           DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1);
  712.       } /* preroll Start */
  713.  
  714.       /**************************************
  715.       * UpDate State To Preroll
  716.       **************************************/
  717.       STRMSTATE = CUERECD_STATE;
  718.       ulpInstance->ulCreateFlag = PREROLL_STATE;
  719.  
  720.       }   /* Cue Input */
  721.  
  722.   /****************************************
  723.   * Close The Event Semaphore
  724.   ****************************************/
  725.   DosCloseEventSem (ulpInstance->hEventSem);
  726.  
  727.   return (ULONG)(ulrc);
  728. }
  729.  
  730.  
  731. /********************* START OF SPECIFICATIONS *********************
  732. *
  733. * SUBROUTINE NAME: MCISCPT.C
  734. *
  735. * DESCRIPTIVE NAME: Set Cue Point Waveform Device.
  736. *
  737. * FUNCTION: Establish Cue points during playback on Waveform Device.
  738. *
  739. * NOTES:
  740. *
  741. * ENTRY POINTS:
  742. *     LINKAGE:   CALL FAR
  743. *
  744. * INPUT: MCI_SET_CUEPOINT message.
  745. *
  746. * EXIT-NORMAL: Return Code 0.
  747. *
  748. * EXIT_ERROR:  Error Code.
  749. *
  750. * EFFECTS:
  751. *
  752. * INTERNAL REFERENCES: MCIERR ().
  753. *
  754. * EXTERNAL REFERENCES: spiEnableEvent()    - SSM Spi
  755. *
  756. *********************** END OF SPECIFICATIONS **********************/
  757. RC MCIScpt (FUNCTION_PARM_BLOCK *pFuncBlock)
  758. {
  759.   ULONG           ulrc;               // Propogated MME Error Code
  760.   ULONG           ulParam1;           // Incoming MCI Flag
  761.   ULONG           ulParam2;           // Incoming MCI Data PTR
  762.   DWORD           dwCPTFlags;         // Mask For Incoming Flags
  763.   INSTANCE        * ulpInstance;      // Local Instance
  764.   HWND            hWnd;               // Call Back Window Hndl
  765.   USHORT          usEvcbIndex;        // Local Index
  766.   ULONG           ulTemp1;            // Conversion Var
  767.   USHORT          usFound;            // Flag
  768.   PID             pid;
  769.   TID             tid;
  770.   LPMCI_CUEPOINT_PARMS lpCueParms;    // Msg MCI Data Structure
  771.  
  772.   /****************************
  773.   * Intialize Local Vars
  774.   *****************************/
  775.   ulrc = MCIERR_SUCCESS;
  776.   dwCPTFlags = 0;
  777.   usEvcbIndex = 0;
  778.   hWnd = 0;
  779.   ulTemp1 = 0;
  780.   usFound = FALSE;
  781.  
  782.   /****************************
  783.   * Dereference Pointers
  784.   *****************************/
  785.   ulParam1 = pFuncBlock->ulParam1;
  786.   ulParam2 = pFuncBlock->ulParam2;
  787.   ulpInstance= (INSTANCE *)pFuncBlock->ulpInstance;
  788.  
  789.   /**************************
  790.   * Mask unWanted Bits
  791.   **************************/
  792.   dwCPTFlags = ulParam1;
  793.   dwCPTFlags &= ~MCI_WAIT;
  794.   dwCPTFlags &= ~MCI_NOTIFY;
  795.   /*******************************
  796.   * Check for Valid Flags
  797.   *******************************/
  798.   dwCPTFlags &= ~(MCI_SET_CUEPOINT_ON + MCI_SET_CUEPOINT_OFF);
  799.  
  800.   if (dwCPTFlags > 0 )
  801.       return MCIERR_INVALID_FLAG;
  802.   /****************************************
  803.   * Check to see if ulParam2 Good
  804.   ****************************************/
  805.   ulrc = CheckMem (((PVOID)ulParam2),
  806.                    sizeof (MCI_CUEPOINT_PARMS), PAG_READ);
  807.  
  808.   if (ulrc != MCIERR_SUCCESS)
  809.       return MCIERR_MISSING_PARAMETER;
  810.  
  811.   lpCueParms = (LPMCI_CUEPOINT_PARMS)ulParam2;
  812.  
  813.   if (ulpInstance == (ULONG)NULL )
  814.       return MCIERR_INSTANCE_INACTIVE;
  815.  
  816.   /************************************
  817.   * Check call back handle
  818.   ************************************/
  819.   hWnd = (HWND)lpCueParms->dwCallback;
  820.  
  821.  
  822.   if (!WinQueryWindowProcess(hWnd, &pid, &tid))
  823.       return(MCIERR_INVALID_CALLBACK_HANDLE);
  824.  
  825.   /************************************************
  826.   * Check For Valid Flags but Invalid Combo
  827.   *************************************************/
  828.   if (ulParam1 & MCI_SET_CUEPOINT_ON && ulParam1 & MCI_SET_CUEPOINT_OFF)
  829.       return MCIERR_FLAGS_NOT_COMPATIBLE;
  830.  
  831.   if (!(ulParam1 & MCI_SET_CUEPOINT_ON || ulParam1 & MCI_SET_CUEPOINT_OFF))
  832.        return MCIERR_MISSING_FLAG;
  833.  
  834.   /*****************************************
  835.   * No Element Loaded Reject Cuepoint
  836.   ******************************************/
  837.   if (ulpInstance->usFileExists == UNUSED)
  838.       return MCIERR_FILE_NOT_FOUND;
  839.  
  840.   /*************************
  841.   * Check for Range Errors
  842.   *************************/
  843.   if (lpCueParms->dwCuepoint <= 0)
  844.       return MCIERR_OUTOFRANGE;
  845.  
  846.   /****************************
  847.   * Enable Cuepoints
  848.   *****************************/
  849.   if (ulParam1 & MCI_SET_CUEPOINT_ON) {
  850.  
  851.       if (CUEPTINDX >= MAX_CUEPOINTS)
  852.           return MCIERR_CUEPOINT_LIMIT_REACHED;
  853.  
  854.       for (usEvcbIndex = 0; usEvcbIndex < CUEPTINDX; usEvcbIndex++) {
  855.            if (CUEPTEVCB[usEvcbIndex].mmCuePt == lpCueParms->dwCuepoint)
  856.                return MCIERR_DUPLICATE_CUEPOINT;
  857.       }   /* break out of this */
  858.  
  859.       CUEPTEVCB[CUEPTINDX].dwCallback = hWnd;
  860.       CUEPTEVCB[CUEPTINDX].wDeviceID = ulpInstance->wWaveDeviceID;
  861.  
  862.       /********************************************
  863.       * Fill In Time Event Control Block
  864.       *********************************************/
  865.       CUEPTEVCB[CUEPTINDX].evcb.ulType = EVENT_CUE_TIME;
  866.       CUEPTEVCB[CUEPTINDX].evcb.ulFlags = EVENT_SINGLE;
  867.       CUEPTEVCB[CUEPTINDX].evcb.hstream = STREAM.hStream;
  868.  
  869.       /*******************************************************
  870.       * Time At Which Cue Point Notifucation is generated
  871.       ********************************************************/
  872.       ulrc = ConvertToMM (ulpInstance, (DWORD*)&(ulTemp1),
  873.                                (DWORD)lpCueParms->dwCuepoint);
  874.  
  875.       CUEPTEVCB[CUEPTINDX].evcb.mmtimeStream =ulTemp1;
  876.       CUEPTEVCB[CUEPTINDX].mmCuePt = lpCueParms->dwCuepoint;
  877.  
  878.       /*****************************************************
  879.       * Stick In INSTANCE Pointer in The Time EVCB
  880.       ******************************************************/
  881.       CUEPTEVCB[CUEPTINDX].ulpInstance = (ULONG)ulpInstance;
  882.  
  883.  
  884.       /*****************************************************
  885.       * Copy CuePoint User Parm into EVCB Structure
  886.       ******************************************************/
  887.       CUEPTEVCB[CUEPTINDX].usCueUsrParm =lpCueParms->wUserParm;
  888.  
  889.       /****************************
  890.       * Enable the Time Event
  891.       ****************************/
  892.       if (ulpInstance->ulCreateFlag == PREROLL_STATE)
  893.          {
  894.          ulrc = SpiEnableEvent( (PEVCB) &(CUEPTEVCB[CUEPTINDX]),
  895.                                 (PHEVENT) &(STREAM.HCuePtHndl[CUEPTINDX]));
  896.          ulpInstance->usCuePt = EVENT_ENABLED;
  897.          }
  898.       else
  899.          {
  900.          ulpInstance->usCuePt = TRUE;
  901.          }
  902.  
  903.       if (ulrc == ERROR_INVALID_EVENT)
  904.           ulrc = MCIERR_OUTOFRANGE;
  905.  
  906.       if (ulrc)
  907.           return ulrc;
  908.       /*****************************
  909.       * Increment CuePt Index
  910.       ******************************/
  911.       CUEPTINDX++;
  912.  
  913.   } /* Set Cue Point On */
  914.  
  915.  
  916.   /************************
  917.   * Disable CuePoints
  918.   *************************/
  919.  
  920.   if (ulParam1 & MCI_SET_CUEPOINT_OFF) {
  921.       for (usEvcbIndex = 0; usEvcbIndex < CUEPTINDX; usEvcbIndex++) {
  922.            if (CUEPTEVCB[usEvcbIndex].mmCuePt == lpCueParms->dwCuepoint) {
  923.                if (ulpInstance->ulCreateFlag == PREROLL_STATE) {
  924.                        /**********************************************
  925.                        * Check Validity of hCuePointEvent
  926.                        **********************************************/
  927.                        ulrc = SpiDisableEvent (STREAM.HCuePtHndl[usEvcbIndex]);
  928.                        CUEPTEVCB[usEvcbIndex].mmCuePt = 0;
  929.                        usFound = TRUE;
  930.  
  931.                } /* CreateFlag == PrerollState */
  932.                else
  933.                {
  934.                    usFound = TRUE;
  935.                    ulpInstance->usCuePt = FALSE;
  936.                    CUEPTEVCB[usEvcbIndex].mmCuePt = 0;
  937.                }
  938.            } /* Found the CuePoint Block */
  939.       } /* for Loop */
  940.  
  941.       if (ulrc == ERROR_INVALID_EVENT)
  942.           ulrc = MCIERR_OUTOFRANGE;
  943.  
  944.       if (usFound == FALSE)
  945.           return MCIERR_INVALID_CUEPOINT;
  946.  
  947.       if (ulrc)
  948.           return ulrc;
  949.   }   /* CuePoint Off */
  950.  
  951.  
  952.   return (ULONG)(MCIERR_SUCCESS);
  953. }
  954.  
  955.  
  956. /********************* START OF SPECIFICATIONS *********************
  957. *
  958. * SUBROUTINE NAME: MCISEEK.C
  959. *
  960. * DESCRIPTIVE
  961. *
  962. * FUNCTION:  Waveform Seek.
  963. *
  964. * NOTES:
  965. *
  966. * ENTRY POINTS:
  967. *     LINKAGE:   CALL FAR
  968. *
  969. * INPUT: MCI_SEEK message.
  970. *
  971. * EXIT-NORMAL: Return Code 0.
  972. *
  973. * EXIT_ERROR:  Error Code.
  974. *
  975. * EFFECTS:
  976. *
  977. * INTERNAL REFERENCES: MCIERR ().
  978. *
  979. * EXTERNAL REFERENCES: spiStopStream()     - SSM Spi
  980. *                      spiSeekStream()     - SSM Spi
  981. *
  982. *********************** END OF SPECIFICATIONS **********************/
  983. RC MCISeek (FUNCTION_PARM_BLOCK *pFuncBlock)
  984. {
  985.   ULONG         ulrc;                    // Return Code
  986.   ULONG         ulParam1;                // Flags For this message
  987.   ULONG         ulParam2;                // Data for this message
  988.   ULONG         ulAbortNotify = FALSE;   // abort notification messages
  989.   INSTANCE      * ulpInstance;           // Local Instance Ptr
  990.   ULONG         ulAssocFlag;             // Type of SpiAssociate
  991.   ULONG         lCnt;                    // Semaphore Post Count
  992.   DWORD         dwSeekPoint;             // Seek Point
  993.   ULONG         ulTemp1;                 // Temporary Variable
  994.   DWORD         SpiFlags;                // Flags For Spi Seek
  995.   DWORD         dwSeekFlags;             // Incoming Seek Flags From MCI
  996.   DWORD         dwFileLength;            // Element Length in MM
  997.   LPMCI_SEEK_PARMS   lpSeekParms = NULL; // Message Data Structure
  998.  
  999.  
  1000.   /********************************************
  1001.   * Dereference Pointers From Thread Block
  1002.   ********************************************/
  1003.   ulParam1 = pFuncBlock->ulParam1;
  1004.   ulParam2 = pFuncBlock->ulParam2;
  1005.   ulrc = MCIERR_SUCCESS;
  1006.   dwSeekPoint = 0;
  1007.   ulTemp1 = 0;
  1008.  
  1009.   /*******************************************
  1010.   * Mask Wait and Notify Bits
  1011.   ********************************************/
  1012.   ulParam1 &= ~ MCI_NOTIFY;
  1013.   ulParam1 &= ~MCI_WAIT;
  1014.   dwSeekFlags = ulParam1;
  1015.   /********************************************
  1016.   * Mask For Valid Flags on MCI_SEEK
  1017.   *********************************************/
  1018.   dwSeekFlags &= ~(MCI_TO + MCI_TO_START+ MCI_TO_END);
  1019.  
  1020.   if (dwSeekFlags > 0)
  1021.       return MCIERR_INVALID_FLAG;
  1022.  
  1023.   if (ulParam1 & MCI_TO_START && ulParam1 & MCI_TO_END)
  1024.       return MCIERR_FLAGS_NOT_COMPATIBLE;
  1025.  
  1026.   if (ulParam1 & MCI_TO_START && ulParam1 & MCI_TO)
  1027.       return MCIERR_FLAGS_NOT_COMPATIBLE;
  1028.  
  1029.   if (ulParam1 & MCI_TO && ulParam1 & MCI_TO_END)
  1030.       return MCIERR_FLAGS_NOT_COMPATIBLE;
  1031.  
  1032.  
  1033.   if (!(ulParam1 & MCI_TO_START || ulParam1 & MCI_TO_END ||
  1034.        ulParam1 & MCI_TO))
  1035.  
  1036.       return MCIERR_MISSING_FLAG;
  1037.  
  1038.   ulpInstance= (INSTANCE *)pFuncBlock->ulpInstance;
  1039.  
  1040.   if (ulParam1 & MCI_TO) {
  1041.       ulrc = CheckMem (((PVOID)ulParam2),
  1042.                        sizeof (MCI_SEEK_PARMS), PAG_READ);
  1043.       if (ulrc != MCIERR_SUCCESS)
  1044.           return MCIERR_MISSING_PARAMETER;
  1045.       lpSeekParms = (LPMCI_SEEK_PARMS)ulParam2;
  1046.   }
  1047.   if (ulpInstance == (ULONG)NULL )
  1048.       return MCIERR_INSTANCE_INACTIVE;
  1049.  
  1050.   if (ulpInstance->ulInstanceSignature != ACTIVE)
  1051.       return MCIERR_INSTANCE_INACTIVE;
  1052.   /************************************
  1053.   * No Element Cant Seek
  1054.   *************************************/
  1055.   if (ulpInstance->usFileExists == FALSE ||
  1056.       ulpInstance->usFileExists == UNUSED)
  1057.           return MCIERR_FILE_NOT_FOUND;
  1058.  
  1059.   /*********************************************
  1060.   * MCI_SEEK aborts any ongoing PLAY/RECORD.
  1061.   *********************************************/
  1062.   DosRequestMutexSem( ulpInstance->hmtxNotifyAccess, -1 );
  1063.   if (ulpInstance->usNotifyPending == TRUE)
  1064.      {
  1065.      ulpInstance->ulNotifyAborted = TRUE;
  1066.      ulpInstance->usNotifyPending = FALSE;
  1067.      ulAbortNotify = TRUE;
  1068.      }
  1069.   DosReleaseMutexSem( ulpInstance->hmtxNotifyAccess );
  1070.  
  1071.   if ( ulAbortNotify )
  1072.      {
  1073.  
  1074.      if ( ulpInstance->usNotPendingMsg == MCI_SAVE )
  1075.         {
  1076.         // Save is a non-interruptible operation
  1077.         // wait for completion
  1078.         DosWaitEventSem( ulpInstance->hThreadSem, (ULONG ) -1 );
  1079.  
  1080.         }
  1081.       else
  1082.         {
  1083.         PostMDMMessage ( MCI_NOTIFY_ABORTED,
  1084.                          ulpInstance->usNotPendingMsg, pFuncBlock);
  1085.         DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  1086.         DosResetEventSem (ulpInstance->hThreadSem, &lCnt);
  1087.  
  1088.         if (AMPMIX.ulOperation == OPERATION_PLAY)
  1089.            {
  1090.            SpiFlags = SPI_STOP_DISCARD;
  1091.            }
  1092.         else
  1093.            {
  1094.            SpiFlags = SPI_STOP_FLUSH;
  1095.            }
  1096.  
  1097.         /*****************************************************
  1098.         * Stop discard for play or stop flush for record.
  1099.         *****************************************************/
  1100.  
  1101.         ulrc = SpiStopStream (STREAM.hStream, SpiFlags);
  1102.         SpiFlags = 0;
  1103.  
  1104.         if (!ulrc)
  1105.           {
  1106.           DosWaitEventSem (ulpInstance->hThreadSem, (ULONG) -1);
  1107.           }
  1108.  
  1109.         DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  1110.  
  1111.         STRMSTATE = MCI_STOP;
  1112.  
  1113.         } /* if !save pending */
  1114.  
  1115.  
  1116.  
  1117.       }  /* There was a pending Notify */
  1118.  
  1119.   /*****************************************
  1120.   * Ensure that Stream is stopped.
  1121.   * if not stop it discarding all buffers.
  1122.   *****************************************/
  1123.  
  1124.   if ((STRMSTATE == CUERECD_STATE) ||
  1125.       (STRMSTATE == MCI_RECORD)) {
  1126.        DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  1127.  
  1128.        /*****************************************************
  1129.        * Stop discard for play or stop flush for record.
  1130.        ******************************************************/
  1131.        ulrc = SpiStopStream (STREAM.hStream, SPI_STOP_DISCARD);
  1132.        if (!ulrc)
  1133.            DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1);
  1134.  
  1135.   }   /* Exclusive Cue Recd and Recd States */
  1136.  
  1137.   /*********************************************
  1138.   * Return Error if No Element is Specified
  1139.   **********************************************/
  1140.   if (ulpInstance->usFileExists == FALSE)
  1141.       return MCIERR_FILE_NOT_FOUND;
  1142.  
  1143.   if (ulpInstance->ulCreateFlag != PREROLL_STATE) {
  1144.       if (ulpInstance->usPlayLstStrm == TRUE)
  1145.  
  1146.           ulAssocFlag = (ULONG)NULL;
  1147.       else
  1148.           ulAssocFlag = PLAY_STREAM;
  1149.       /**********************************************
  1150.       * Create a Stream with A = Src & B = Tgt
  1151.       ***********************************************/
  1152.       ulrc = CreateNAssocStream ( STREAM.hidASource,
  1153.                                   STREAM.hidBTarget,
  1154.                                   &(STREAM.hStream),
  1155.                                   (INSTANCE *) ulpInstance,
  1156.                                   (ULONG)ulAssocFlag,
  1157.                                   (PEVFN)PlEventProc);
  1158.       if (ulrc)
  1159.           return ulrc;
  1160.  
  1161.       if (ulAssocFlag == (ULONG)NULL) // Do the Associate Seperately
  1162.  
  1163.           ulrc = AssocMemPlayToAudioStrm (ulpInstance, PLAY_STREAM);
  1164.  
  1165.       if (ulrc)
  1166.           return (ulrc);
  1167.       /******************************
  1168.       * UpDate State to created
  1169.       *******************************/
  1170.       ulpInstance->ulCreateFlag = PREROLL_STATE;
  1171.  
  1172.   }  /* Stream Creation */
  1173.  
  1174.   /**********************************************
  1175.   * Check For Valid Transition States
  1176.   ***********************************************/
  1177.     DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  1178.  
  1179.     /***************************************************
  1180.     * Stop discard for play or stop flush for record.
  1181.     ****************************************************/
  1182.     ulrc = SpiStopStream (STREAM.hStream, SPI_STOP_DISCARD);
  1183.  
  1184.     if (!ulrc)
  1185.        {
  1186.        DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1);
  1187.        }
  1188.  
  1189.     STRMSTATE = MCI_STOP;
  1190.  
  1191.    ulrc = MCIERR_SUCCESS;
  1192.  
  1193.   /********************
  1194.   * Stream Seek.
  1195.   *******************/
  1196.   if (ulpInstance->usPlayLstStrm != TRUE) {
  1197.  
  1198.      if (ulParam1 & MCI_TO) {
  1199.          ConvertTimeUnits (ulpInstance, (DWORD*)& (dwFileLength),
  1200.                            FILE_LENGTH);
  1201.  
  1202.          /****************************************
  1203.          * Convert Seek to its base
  1204.          ******************************************/
  1205.         // ConvertToMM (ulpInstance, (DWORD*)& (ulTemp1),
  1206.         //            (DWORD)(lpSeekParms->dwTo));
  1207.  
  1208.          ulTemp1 = lpSeekParms->dwTo;
  1209.  
  1210.          if (ulTemp1 > dwFileLength)
  1211.              return MCIERR_OUTOFRANGE;
  1212.  
  1213.      } /* To Flag On */
  1214.   } /* Non PlayList */
  1215.  
  1216.   /********************************************************
  1217.   * Parse Different Seek Flags to Translate into SpiFlags
  1218.   ********************************************************/
  1219.   if (ulParam1 & MCI_TO_START) {
  1220.       dwSeekPoint = 0;
  1221.       ulTemp1 = 0;
  1222.       SpiFlags = SPI_SEEK_ABSOLUTE;
  1223.   }
  1224.  
  1225.   if (ulParam1 & MCI_TO_END) {
  1226.       dwSeekPoint = 0;
  1227.       ulTemp1 = 0;
  1228.       SpiFlags = SPI_SEEK_FROMEND;
  1229.   }
  1230.   if (ulParam1 & MCI_TO) {
  1231.       dwSeekPoint = lpSeekParms->dwTo;
  1232.       SpiFlags = SPI_SEEK_ABSOLUTE;
  1233.   }
  1234.   if (ulpInstance->usPlayLstStrm == TRUE) {
  1235.  
  1236.       DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  1237.       ulrc = SpiStopStream (STREAM.hStream,
  1238.                             SPI_STOP_DISCARD);
  1239.  
  1240.       if (!ulrc)
  1241.           DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1);
  1242.   }   /* Non PlayList */
  1243.  
  1244.  
  1245.  
  1246.    /*********************************************
  1247.    * Convert Seek Units to MMTime
  1248.    * This translates Stream Seek units to MMTIME
  1249.    * ONLY if the user requested a number
  1250.    *********************************************/
  1251.    if ( lpSeekParms )
  1252.       {
  1253.       ConvertToMM (ulpInstance, (DWORD*)& (ulTemp1),
  1254.                    (DWORD)(lpSeekParms->dwTo));
  1255.       }
  1256.  
  1257.   /*************************
  1258.   * Do the Seek Thing
  1259.   *************************/
  1260.   ulrc = SpiSeekStream (STREAM.hStream, SpiFlags,
  1261.                         (LONG)(ulTemp1));
  1262.   if (ulrc)
  1263.       return (ulrc);
  1264.  
  1265.   STRMSTATE = MCI_SEEK;  // UpDate Current State
  1266.  
  1267.   return (ULONG)(ulrc);
  1268.  
  1269. }
  1270.  
  1271. /********************* START OF SPECIFICATIONS *********************
  1272. *
  1273. * SUBROUTINE NAME: MCISTOP.C
  1274. *
  1275. * DESCRIPTIVE
  1276. *
  1277. * FUNCTION:  Stop Playing/Recording.
  1278. *
  1279. * NOTES:
  1280. *
  1281. * ENTRY POINTS:
  1282. *     LINKAGE:   CALL FAR
  1283. *
  1284. * INPUT: MCI_STOP message.
  1285. *
  1286. * EXIT-NORMAL: Return Code 0.
  1287. *
  1288. * EXIT_ERROR:  Error Code.
  1289. *
  1290. * EFFECTS:
  1291. *
  1292. * INTERNAL REFERENCES:  MCIERR ().
  1293. *
  1294. * EXTERNAL REFERENCES: spiStopStream ()   -   SSM Spi
  1295. *
  1296. *********************** END OF SPECIFICATIONS **********************/
  1297. RC MCIStop ( FUNCTION_PARM_BLOCK *pFuncBlock)
  1298. {
  1299.    ULONG               ulrc;               // MME Error Value Propogated
  1300.    INSTANCE         * ulpInstance;         // Local Instance
  1301.    ULONG           ulParam1;               // Incoming MCI Flags
  1302.    ULONG           lCnt;                   // Semaphore Posts Freq
  1303.    ULONG           ulAbortNotify = FALSE;  // whether or not to abort a notify
  1304.    DWORD           dwStopFlags;            // Mask for Incoming MCI Flags
  1305.    DWORD           dwSpiFlags;
  1306.  
  1307.    /**************************
  1308.    * Intialize the Vars
  1309.    ***************************/
  1310.    ulrc = MCIERR_SUCCESS;
  1311.    dwStopFlags = 0;
  1312.    dwSpiFlags = 0;
  1313.  
  1314.    /*****************************
  1315.    * Do Some Flag Checking
  1316.    ******************************/
  1317.    ulParam1 = pFuncBlock->ulParam1;
  1318.    dwStopFlags = ulParam1;
  1319.    dwStopFlags &= ~MCI_WAIT;
  1320.    dwStopFlags &= ~MCI_NOTIFY;
  1321.  
  1322.    if (dwStopFlags > 0)
  1323.        return MCIERR_INVALID_FLAG;
  1324.    ulpInstance = (INSTANCE *)pFuncBlock->ulpInstance;
  1325.  
  1326.    /*********************************************
  1327.    * Check whether this a valid Instance
  1328.    *********************************************/
  1329.    if (ulpInstance == (ULONG)NULL )
  1330.        return MCIERR_INSTANCE_INACTIVE;
  1331.  
  1332.    if (ulpInstance->ulInstanceSignature != ACTIVE)
  1333.        return MCIERR_INSTANCE_INACTIVE;
  1334.  
  1335.    /***************************************************
  1336.    * Pending Notifies (asynchronous Play/Record Threads)
  1337.    ****************************************************/
  1338.    DosRequestMutexSem( ulpInstance->hmtxNotifyAccess, -1 );
  1339.    if (ulpInstance->usNotifyPending == TRUE)
  1340.       {
  1341.       ulpInstance->ulNotifyAborted = TRUE;
  1342.       ulpInstance->usNotifyPending = FALSE;
  1343.       ulAbortNotify = TRUE;
  1344.       }
  1345.    DosReleaseMutexSem( ulpInstance->hmtxNotifyAccess );
  1346.  
  1347.    if (ulAbortNotify == TRUE)
  1348.      {
  1349.  
  1350.  
  1351.      if ( ulpInstance->usNotPendingMsg == MCI_SAVE )
  1352.         {
  1353.         // Save is a non-interruptible operation
  1354.         // wait for completion
  1355.  
  1356.         DosWaitEventSem( ulpInstance->hThreadSem, (ULONG ) -1 );
  1357.  
  1358.         }
  1359.      else
  1360.         {
  1361.         PostMDMMessage ( MCI_NOTIFY_ABORTED,
  1362.                          ulpInstance->usNotPendingMsg,
  1363.                          pFuncBlock);
  1364.  
  1365.         DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  1366.         DosResetEventSem (ulpInstance->hThreadSem, &lCnt);
  1367.  
  1368.         if ( ulpInstance->usNotPendingMsg == MCI_RECORD ||
  1369.              AMPMIX.ulOperation == OPERATION_RECORD )
  1370.           {
  1371.           dwSpiFlags = SPI_STOP_FLUSH;
  1372.           }
  1373.         else
  1374.           {
  1375.           dwSpiFlags = SPI_STOP_STREAM;
  1376.           }
  1377.  
  1378.         /***********************************
  1379.         * Stop The Stream
  1380.         ************************************/
  1381.         ulrc = SpiStopStream (STREAM.hStream, dwSpiFlags);
  1382.  
  1383.         if ( AMPMIX.ulOperation == OPERATION_RECORD )
  1384.           {
  1385.           if (!ulrc)
  1386.              {
  1387.              /*****************************
  1388.              * Wait for the stopped event
  1389.              ******************************/
  1390.              DosWaitEventSem (ulpInstance->hThreadSem, (ULONG) -1);
  1391.              }
  1392.  
  1393.           /***********************************
  1394.           * Record streams go into a stopped state
  1395.           ************************************/
  1396.           STRMSTATE = MCI_STOP;
  1397.  
  1398.           }
  1399.         else
  1400.           {
  1401.           /*****************************************
  1402.           * Since a pause does not generate an event
  1403.           * create a fake one so our play thread can
  1404.           * clean up
  1405.           *****************************************/
  1406.           ulpInstance->StreamEvent = EVENT_STREAM_STOPPED;
  1407.           ulrc = DosPostEventSem (ulpInstance->hEventSem);
  1408.  
  1409.           DosWaitEventSem (ulpInstance->hThreadSem, (ULONG) -1);
  1410.  
  1411.           /***************************************
  1412.           * Play streams go into a stopped/paused state
  1413.           ****************************************/
  1414.           STRMSTATE = STOP_PAUSED;
  1415.           }
  1416.  
  1417.  
  1418.         } /* if no pending save */
  1419.  
  1420.         ulpInstance->usNotifyPending = FALSE;
  1421.  
  1422.      } /* if notify pending */
  1423.  
  1424.  
  1425.    if (STRMSTATE != MCI_STOP && STRMSTATE != STOP_PAUSED )
  1426.       {
  1427.       DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  1428.       ulrc = SpiStopStream (STREAM.hStream, SPI_STOP_STREAM );
  1429.  
  1430.       if (ulrc == ERROR_STREAM_ALREADY_STOP)
  1431.          {
  1432.          ulrc = MCIERR_SUCCESS;
  1433.          }
  1434.  
  1435.        STRMSTATE = STOP_PAUSED;
  1436.       }
  1437.  
  1438.    return (ULONG)(MCIERR_SUCCESS);
  1439.  
  1440. }
  1441.  
  1442.  
  1443. /********************* START OF SPECIFICATIONS *********************
  1444. *
  1445. * SUBROUTINE NAME: MCIPAUS.C
  1446. *
  1447. * DESCRIPTIVE
  1448. *
  1449. * FUNCTION:  Waveform Pause.
  1450. *
  1451. * NOTES:
  1452. *
  1453. * ENTRY POINTS:
  1454. *     LINKAGE:   CALL FAR
  1455. *
  1456. * INPUT: MCI_PAUSE message.
  1457. *
  1458. * EXIT-NORMAL: Return Code 0.
  1459. *
  1460. * EXIT_ERROR:  Error Code.
  1461. *
  1462. * EFFECTS:
  1463. *
  1464. * INTERNAL REFERENCES:  MCIERR ().
  1465. *
  1466. * EXTERNAL REFERENCES: spiStopStream ()   -   SSM Spi
  1467. *
  1468. *********************** END OF SPECIFICATIONS **********************/
  1469. RC MCIPaus (FUNCTION_PARM_BLOCK *pFuncBlock)
  1470.  
  1471. {
  1472.     ULONG           ulrc;
  1473.     INSTANCE *      ulpInstance;
  1474.     DWORD           dwPausFlags;
  1475.  
  1476.     dwPausFlags = 0;
  1477.     ulrc = MCIERR_SUCCESS;
  1478.     dwPausFlags = pFuncBlock->ulParam1;
  1479.     dwPausFlags &= ~MCI_WAIT;
  1480.     dwPausFlags &= ~MCI_NOTIFY;
  1481.  
  1482.     if (dwPausFlags > 0 )
  1483.         return MCIERR_INVALID_FLAG;
  1484.  
  1485.     ulpInstance= (INSTANCE *)pFuncBlock->ulpInstance;
  1486.  
  1487.     if (ulpInstance == (ULONG)NULL )
  1488.         return MCIERR_INSTANCE_INACTIVE;
  1489.  
  1490.     if (ulpInstance->ulInstanceSignature != ACTIVE)
  1491.         return MCIERR_INSTANCE_INACTIVE;
  1492.  
  1493.  
  1494.     /****************************************************
  1495.     * The default action on an spiStopstream is pause.
  1496.     *****************************************************/
  1497.     if ((STRMSTATE == MCI_PLAY ) || (STRMSTATE == MCI_RECORD)) {
  1498.  
  1499.         ulrc = SpiStopStream (STREAM.hStream, SPI_STOP_STREAM);
  1500.         STRMSTATE = MCI_PAUSE;    /* update Instance */
  1501.  
  1502.         if (ulrc == ERROR_STREAM_ALREADY_PAUSE)
  1503.             ulrc = MCIERR_SUCCESS;
  1504.     }
  1505.  
  1506.     return (MCIERR_SUCCESS);
  1507.  
  1508. }
  1509.  
  1510.  
  1511.  
  1512. /********************* START OF SPECIFICATIONS *********************
  1513. *
  1514. * SUBROUTINE NAME: MCIRESM
  1515. *
  1516. * DESCRIPTIVE      Audio MCD Resume.
  1517. *
  1518. * FUNCTION:  Resume Playback/Record from Paused State.
  1519. *
  1520. * NOTES:
  1521. *
  1522. * ENTRY POINTS:
  1523. *     LINKAGE:   CALL FAR
  1524. *
  1525. * INPUT: MCI_RESUME message.
  1526. *
  1527. * EXIT-NORMAL: Return Code 0.
  1528. *
  1529. * EXIT_ERROR:  Error Code.
  1530. *
  1531. * EFFECTS:
  1532. *
  1533. * INTERNAL REFERENCES:  MCIERR ().
  1534. *
  1535. * EXTERNAL REFERENCES: SpiStartStream ()        -   SSM Spi
  1536. *
  1537. *********************** END OF SPECIFICATIONS **********************/
  1538. RC  MCIResm (FUNCTION_PARM_BLOCK * pFuncBlock)
  1539. {
  1540.  
  1541.    ULONG                  ulrc;            // MME Error Value Propogated
  1542.    INSTANCE               * ulpInstance;   // Local Instance
  1543.    DWORD                  dwResmFlags;     // Incoming MCI Flags
  1544.    DWORD                  dwSetAll;        // Internal Set Flags
  1545.    MCI_WAVE_SET_PARMS     lpSetParms;      // Internal Set Struct
  1546.  
  1547.    ulrc = MCIERR_SUCCESS;
  1548.    /*********************************/
  1549.    // Check for invalid flags
  1550.    /*********************************/
  1551.    dwResmFlags = pFuncBlock->ulParam1;
  1552.    dwResmFlags &= ~MCI_WAIT;
  1553.    dwResmFlags &= ~MCI_NOTIFY;
  1554.    dwSetAll = MCI_WAVE_SET_BITSPERSAMPLE|MCI_WAVE_SET_FORMATTAG|MCI_WAVE_SET_CHANNELS|
  1555.               MCI_WAVE_SET_SAMPLESPERSEC;
  1556.  
  1557.    if (dwResmFlags > 0 )
  1558.            return MCIERR_INVALID_FLAG;
  1559.  
  1560.  
  1561.    /************************************/
  1562.    // Derefernce pointers.
  1563.    /***********************************/
  1564.    ulpInstance= (INSTANCE *)pFuncBlock->ulpInstance;
  1565.  
  1566.    if (ulpInstance == (ULONG)NULL )
  1567.        return MCIERR_INSTANCE_INACTIVE;
  1568.  
  1569.    if (ulpInstance->ulInstanceSignature != ACTIVE)
  1570.        return MCIERR_INSTANCE_INACTIVE;
  1571.    /*******************************
  1572.    * Set Amp Defaults
  1573.    ********************************/
  1574.    SetAmpDefaults (ulpInstance);  // Always Restore Amp Stuff
  1575.  
  1576.    VSDInstToWaveSetParms (&lpSetParms,ulpInstance);
  1577.  
  1578.    /**********************************************************
  1579.    * No State Transition if already in States Play or Record
  1580.    **********************************************************/
  1581.    if ((STRMSTATE == MCI_PLAY) || (STRMSTATE == MCI_RECORD) ||
  1582.        (STRMSTATE == MCI_STOP) || (STRMSTATE == MCI_SEEK )  ||
  1583.        (STRMSTATE == STREAM_SET_STATE ) || ( STRMSTATE == STOP_PAUSED ) )
  1584.  
  1585.        return MCIERR_SUCCESS;
  1586.  
  1587.    /*****************************************************
  1588.    * Resume PlayBack/Record. only if not in States 8, 9
  1589.    *****************************************************/
  1590.    if ((STRMSTATE != CUEPLAY_STATE) && (STRMSTATE != CUERECD_STATE) &&
  1591.        (STRMSTATE != CREATE_STATE)) {
  1592.  
  1593.        ulrc = SpiStartStream (STREAM.hStream, SPI_START_STREAM);
  1594.  
  1595.        if (ulrc == ERROR_STREAM_NOT_STOP)
  1596.            ulrc = MCIERR_SUCCESS;
  1597.  
  1598.        if ( AMPMIX.ulOperation == OPERATION_PLAY )
  1599.           {
  1600.           STRMSTATE = MCI_PLAY;      // update Instance
  1601.           }
  1602.        else
  1603.           {
  1604.           STRMSTATE = MCI_RECORD;
  1605.           }
  1606.    }            // valid Transition States
  1607.  
  1608.    return (MCIERR_SUCCESS);
  1609.  
  1610. }
  1611.  
  1612.  
  1613.  
  1614.  
  1615. /********************* START OF SPECIFICATIONS *********************
  1616. *
  1617. * SUBROUTINE NAME: MCISTPA
  1618. *
  1619. * DESCRIPTIVE      Audio MCD Set Position Advice.
  1620. *
  1621. * FUNCTION:  Post Media Position Advice Notification messages.
  1622. *
  1623. * NOTES:
  1624. *
  1625. * ENTRY POINTS:
  1626. *     LINKAGE:   CALL FAR
  1627. *
  1628. * INPUT: MCI_SET_POSITION_ADVISE message.
  1629. *
  1630. * EXIT-NORMAL: Return Code MCIERR_SUCCESS
  1631. *
  1632. * EXIT_ERROR:  Error Code.
  1633. *
  1634. * EFFECTS:
  1635. *
  1636. * INTERNAL REFERENCES:  MCIERR ().
  1637. *
  1638. * EXTERNAL REFERENCES: spiStartStream ()         -   SSM Spi
  1639. *
  1640. *********************** END OF SPECIFICATIONS **********************/
  1641.  
  1642. RC  MCIStpa (FUNCTION_PARM_BLOCK * pFuncBlock)
  1643. {
  1644.   ULONG           ulrc;                      // Error Value
  1645.   ULONG           ulParam1;                  // Incoming MCI Flags
  1646.   INSTANCE        *ulpInstance;              // Local Instance
  1647.   DWORD           dwSTPAFlags;               // Mask For Incoming Flags
  1648.   ULONG           ulCTime;                   // Converted Time
  1649.   PID             pid;
  1650.   TID             tid;
  1651.   HWND            hWnd;
  1652.   LPMCI_POSITION_PARMS lpPositionParms;      // MCI Msg Data
  1653.  
  1654.   /***************************
  1655.   * Intialize Pointers
  1656.   ****************************/
  1657.   ulrc = MCIERR_SUCCESS;
  1658.   ulpInstance = (INSTANCE *)pFuncBlock->ulpInstance;
  1659.   ulParam1 = pFuncBlock->ulParam1;
  1660.   dwSTPAFlags = ulParam1;
  1661.  
  1662.   /**********************************
  1663.   * Check for Validity of Flags
  1664.   ***********************************/
  1665.   dwSTPAFlags &= ~MCI_NOTIFY;
  1666.   dwSTPAFlags &= ~MCI_WAIT;
  1667.   dwSTPAFlags &= ~(MCI_SET_POSITION_ADVISE_ON +
  1668.                    MCI_SET_POSITION_ADVISE_OFF);
  1669.  
  1670.   /*************************************
  1671.   * Return error if flags are not
  1672.   * appropriate for the message
  1673.   *************************************/
  1674.  
  1675.   if (dwSTPAFlags > 0 )
  1676.       return MCIERR_INVALID_FLAG;
  1677.  
  1678.   /********************************
  1679.   * Null Parameter Conditions
  1680.   *********************************/
  1681.   ulrc = CheckMem (((PVOID)pFuncBlock->ulParam2),
  1682.                    sizeof (MCI_POSITION_PARMS), PAG_READ);
  1683.  
  1684.   if (ulrc != MCIERR_SUCCESS)
  1685.       return MCIERR_INVALID_BUFFER;
  1686.  
  1687.  
  1688.   /******************************************************
  1689.   * Dereference MCI Message Data Structure
  1690.   ******************************************************/
  1691.   lpPositionParms = (LPMCI_POSITION_PARMS)pFuncBlock->ulParam2;
  1692.  
  1693.   /******************************************************
  1694.   * Check for Invalid Combination of Valid Flags
  1695.   *******************************************************/
  1696.   if ((ulParam1 & MCI_SET_POSITION_ADVISE_ON) &&
  1697.       (ulParam1 & MCI_SET_POSITION_ADVISE_OFF))
  1698.  
  1699.       return MCIERR_FLAGS_NOT_COMPATIBLE;
  1700.  
  1701.   /************************************************
  1702.   * Check for Invalid Combination of Valid Flags
  1703.   *************************************************/
  1704.   if (!(ulParam1 & MCI_SET_POSITION_ADVISE_ON ||
  1705.       ulParam1 & MCI_SET_POSITION_ADVISE_OFF))
  1706.  
  1707.       return MCIERR_MISSING_FLAG;
  1708.  
  1709.   /******************************************
  1710.   * Enable Position Advise
  1711.   *******************************************/
  1712.  
  1713.   if (ulParam1 & MCI_SET_POSITION_ADVISE_ON) {
  1714.      /******************************
  1715.      * No Element, Return Error
  1716.      ******************************/
  1717.      if (ulpInstance->usFileExists == UNUSED)
  1718.          return MCIERR_FILE_NOT_FOUND;
  1719.  
  1720.      /************************************
  1721.      * Check call back handle
  1722.      ************************************/
  1723.      hWnd = (HWND)lpPositionParms->dwCallback;
  1724.  
  1725.  
  1726.      if (!WinQueryWindowProcess(hWnd, &pid, &tid))
  1727.           return(MCIERR_INVALID_CALLBACK_HANDLE);
  1728.  
  1729.      POSEVCB.dwCallback = (HWND)hWnd;
  1730.  
  1731.      POSEVCB.wDeviceID = ulpInstance->wWaveDeviceID;
  1732.  
  1733.      /******************************
  1734.      * Disable Position Advise
  1735.      *******************************/
  1736.      if ( ulpInstance->ulCreateFlag == PREROLL_STATE &&
  1737.           ulpInstance->usPosAdvise  == TRUE )
  1738.         {
  1739.  
  1740.         ulrc = SpiDisableEvent(STREAM.hPosEvent);
  1741.         }
  1742.  
  1743.      /***************************************
  1744.      * Fill in Pos Time Event Control Block
  1745.      ****************************************/
  1746.      POSEVCB.evcb.ulType = EVENT_CUE_TIME;
  1747.      POSEVCB.evcb.ulFlags = EVENT_RECURRING;
  1748.      POSEVCB.evcb.hstream = STREAM.hStream;
  1749.  
  1750.      /********************************************
  1751.      * Copy current instance into POSEVCB
  1752.      * When the Position Event comes back
  1753.      * asynchronously the current instance
  1754.      * pointer is necessary to do the callback
  1755.      * to the application.
  1756.      *********************************************/
  1757.      POSEVCB.ulpInstance = (ULONG)ulpInstance;
  1758.  
  1759.      /********************************************
  1760.      * Copy Position UserParm into instance.
  1761.      * This User Parameter is returned on
  1762.      * Position change messages to the user.
  1763.      *********************************************/
  1764.      ulpInstance->usPosUserParm = lpPositionParms->wUserParm;
  1765.  
  1766.      ulrc = ConvertToMM (ulpInstance, &(ulCTime),
  1767.                              (DWORD)lpPositionParms->dwUnits);
  1768.  
  1769.      /**********************************************/
  1770.      // Frequency of Position Change Messages
  1771.      /**********************************************/
  1772.  
  1773.      POSEVCB.evcb.mmtimeStream = POSEVCB.mmCuePt = ulCTime;
  1774.  
  1775.      /*********************************************
  1776.      * If dwUnits == 0 return MCIERR_OUTOFRANGE
  1777.      *********************************************/
  1778.  
  1779.      if (ulCTime == 0)
  1780.          return MCIERR_OUTOFRANGE;
  1781.  
  1782.      /*****************************************
  1783.      * Enable the Time Event
  1784.      *****************************************/
  1785.  
  1786.      if (ulpInstance->ulCreateFlag == PREROLL_STATE)
  1787.        {
  1788.        ulrc = SpiEnableEvent( (PEVCB) &(POSEVCB),
  1789.                               (PHEVENT) &(STREAM.hPosEvent));
  1790.        ulpInstance->usPosAdvise = EVENT_ENABLED; // Set The Flag and Return
  1791.        }
  1792.      else
  1793.        {
  1794.        ulpInstance->usPosAdvise = TRUE; // Set The Flag and Return
  1795.        }
  1796.  
  1797.      if (ulrc)
  1798.          return ulrc;
  1799.   }     /* Set Position Advise on */
  1800.  
  1801.   /*****************************************
  1802.   * Disable Position Advise
  1803.   ******************************************/
  1804.  
  1805.   if (ulParam1 & MCI_SET_POSITION_ADVISE_OFF) {
  1806.  
  1807.       if (ulpInstance->ulCreateFlag == PREROLL_STATE)
  1808.  
  1809.           ulrc = SpiDisableEvent (STREAM.hPosEvent);
  1810.       else
  1811.           ulpInstance->usPosAdvise = FALSE;
  1812.  
  1813.       if (ulrc == ERROR_INVALID_EVENT)
  1814.           ulrc = MCIERR_OUTOFRANGE;
  1815.  
  1816.       if (ulrc)
  1817.           return ulrc;
  1818.  
  1819.   }     /* Set Position Advise off */
  1820.  
  1821.   return (ULONG)(ulrc);    // return RC
  1822. }
  1823.  
  1824.  
  1825. /********************* START OF SPECIFICATIONS *********************
  1826. *
  1827. * SUBROUTINE NAME: MCISYNC
  1828. *
  1829. * DESCRIPTIVE      Audio MCD Set Sync Offset.
  1830. *
  1831. * FUNCTION:  Set Synchronization offset.
  1832. *
  1833. * NOTES:
  1834. *
  1835. * ENTRY POINTS:
  1836. *     LINKAGE:   CALL FAR
  1837. *
  1838. * INPUT: MCI_SET_SYNC_OFFSET message.
  1839. *
  1840. * EXIT-NORMAL: Return Code 0.
  1841. *
  1842. * EXIT_ERROR:  Error Code.
  1843. *
  1844. * EFFECTS:
  1845. *
  1846. * INTERNAL REFERENCES:  MCIERR ().
  1847. *
  1848. * EXTERNAL REFERENCES: spiStartStream ()         -   SSM Spi
  1849. *
  1850. *********************** END OF SPECIFICATIONS **********************/
  1851. RC MCISync (FUNCTION_PARM_BLOCK * pFuncBlock)
  1852. {
  1853.   ULONG                ulrc;                 // Error Value
  1854.   INSTANCE             * ulpInstance;       // Local Instance
  1855.   LPMCI_SYNC_OFFSET_PARMS lpSyncOffParms;   // Msg Data
  1856.  
  1857.   ulrc = MCIERR_SUCCESS;
  1858.   ulpInstance = (INSTANCE *)pFuncBlock->ulpInstance;
  1859.   lpSyncOffParms = (LPMCI_SYNC_OFFSET_PARMS)pFuncBlock->ulParam2;
  1860.  
  1861.   /****************************************************************/
  1862.   // Copy The Synchronization Offset to instance member.
  1863.   /****************************************************************/
  1864.  
  1865.   ulpInstance->ulSyncOffset = lpSyncOffParms->dwOffset;
  1866.  
  1867.   /***********************************************/
  1868.   // Flag the offset condition as true.
  1869.   /***********************************************/
  1870.  
  1871.   return (ULONG)(MCIERR_SUCCESS);
  1872.         // Forced RC
  1873. }
  1874.  
  1875.  
  1876. /********************* START OF SPECIFICATIONS *********************
  1877. *
  1878. * SUBROUTINE NAME: MCISAVEFILE
  1879. *
  1880. * DESCRIPTIVE      Audio MCD Save File.
  1881. *
  1882. * FUNCTION:  Save Existing element init of RIFF File.
  1883. *
  1884. * NOTES:
  1885. *
  1886. * ENTRY POINTS:
  1887. *     LINKAGE:   CALL FAR
  1888. *
  1889. * INPUT: MCI_SAVE message.
  1890. *
  1891. * EXIT-NORMAL: Return Code 0.
  1892. *
  1893. * EXIT_ERROR:  Error Code.
  1894. *
  1895. * EFFECTS:
  1896. *
  1897. * INTERNAL REFERENCES:  MCIERR ().
  1898. *
  1899. * EXTERNAL REFERENCES: spiStartStream ()         -   SSM Spi
  1900. *
  1901. *********************** END OF SPECIFICATIONS **********************/
  1902. RC  MCISaveFile (FUNCTION_PARM_BLOCK * pFuncBlock)
  1903. {
  1904.   ULONG                 ulrc;                 // Error Value
  1905.   ULONG                 ulParam1;
  1906.   DWORD                 dwSpiFlags;
  1907.   DWORD                 dwCheckFlags = 0;
  1908.   ULONG                  lCnt;
  1909.  
  1910.   INSTANCE               * ulpInstance;      // Local Instance
  1911.   LPMCI_SAVE_PARMS lpSaveParms;              // Msg Data
  1912.  
  1913.   PSZ                   pszSaveName;
  1914.  
  1915.   ulrc = MCIERR_SUCCESS;
  1916.  
  1917.   ulParam1 =    pFuncBlock->ulParam1;
  1918.   lpSaveParms = (LPMCI_SAVE_PARMS) pFuncBlock->ulParam2;
  1919.   ulpInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  1920.  
  1921.   /*****************************************/
  1922.   // is ulParam2 Good
  1923.   /****************************************/
  1924.   ulrc = CheckMem (((PVOID)lpSaveParms),
  1925.                    sizeof (MCI_SAVE_PARMS), PAG_READ);
  1926.  
  1927.   if (ulrc != MCIERR_SUCCESS)
  1928.         return MCIERR_MISSING_PARAMETER;
  1929.  
  1930.  
  1931.  
  1932.  
  1933.   if (ulpInstance == NULL )
  1934.     return MCIERR_INSTANCE_INACTIVE;
  1935.  
  1936.   if (ulpInstance->ulInstanceSignature != ACTIVE)
  1937.     return MCIERR_INSTANCE_INACTIVE;
  1938.  
  1939.   dwCheckFlags = ulParam1;
  1940.  
  1941.   dwCheckFlags &= ~( MCI_WAIT + MCI_NOTIFY + MCI_SAVE_FILE);
  1942.  
  1943.   if (dwCheckFlags > 0)
  1944.      {
  1945.      return MCIERR_INVALID_FLAG;
  1946.      }
  1947.  
  1948.     /***********************************************************/
  1949.     // Pending Notifies (asynch Play/Record Threads)
  1950.     /***********************************************************/
  1951.     if (ulpInstance->usNotifyPending == TRUE)
  1952.       {
  1953.  
  1954.       PostMDMMessage (MCI_NOTIFY_ABORTED, ulpInstance->usNotPendingMsg, pFuncBlock);
  1955.  
  1956.       DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  1957.       DosResetEventSem (ulpInstance->hThreadSem, &lCnt);
  1958.  
  1959.  
  1960.       if (ulpInstance->usNotPendingMsg == MCI_RECORD)
  1961.           dwSpiFlags = SPI_STOP_FLUSH;
  1962.       else
  1963.           dwSpiFlags = SPI_STOP_DISCARD;
  1964.  
  1965.       ulrc = SpiStopStream (STREAM.hStream, dwSpiFlags);
  1966.  
  1967.       if (!ulrc)
  1968.         {
  1969.  
  1970.         /***************************
  1971.         * Wait Till A thread Dies
  1972.         ***************************/
  1973.  
  1974.         DosWaitEventSem (ulpInstance->hThreadSem, (ULONG) -1);
  1975.  
  1976.         }
  1977.  
  1978.       STRMSTATE = MCI_STOP;
  1979.  
  1980.       ulpInstance->usNotifyPending = FALSE;
  1981.     }
  1982.  
  1983.   if ( STRMSTATE == CUERECD_STATE ||
  1984.        STRMSTATE == CUEPLAY_STATE ||
  1985.        STRMSTATE == MCI_PAUSE        )
  1986.       {
  1987.       ulrc = SpiStopStream (STREAM.hStream, SPI_STOP_DISCARD );
  1988.  
  1989.         if (!ulrc)
  1990.           {
  1991.           DosWaitEventSem (ulpInstance->hEventSem, (ULONG) ONE_MINUTE );
  1992.           }
  1993.  
  1994.       STRMSTATE = MCI_STOP;
  1995.  
  1996.       }
  1997.  
  1998.   // perform the save if it is possible
  1999.  
  2000.   if ( !ulpInstance->ulCanSave )
  2001.     {
  2002.     return MCIERR_UNSUPPORTED_FUNCTION;
  2003.     }
  2004.  
  2005.   if ( ulpInstance->usFileExists != TRUE )
  2006.      {
  2007.      return MCIERR_FILE_NOT_FOUND;
  2008.      }
  2009.  
  2010.   if ( !ulpInstance->ulUsingTemp )
  2011.     {
  2012.     return MCIERR_UNSUPPORTED_FUNCTION;
  2013.     }
  2014.  
  2015.  
  2016.   // did the user pass in a filename?????
  2017.  
  2018.   if ( ulParam1 & MCI_SAVE_FILE )
  2019.     {
  2020.     /*****************************************
  2021.     * is the filename valid????
  2022.     *****************************************/
  2023.     ulrc = CheckMem ( (PVOID) lpSaveParms->lpFileName,
  2024.                       1,
  2025.                       PAG_READ ) ;
  2026.  
  2027.     if (ulrc != MCIERR_SUCCESS)
  2028.         return MCIERR_MISSING_PARAMETER;
  2029.  
  2030.     pszSaveName = (PSZ) lpSaveParms->lpFileName;
  2031.     }
  2032.   else
  2033.     {
  2034.  
  2035.     /*****************************************
  2036.     * If the caller had us generate a filename
  2037.     * on the open, then save w/o a new filename
  2038.     * is invalid
  2039.     *****************************************/
  2040.     if  ( ulpInstance->ulCreatedName || ulpInstance->ulNoSaveWithoutName )
  2041.        {
  2042.        return MCIERR_MISSING_FLAG;
  2043.        }
  2044.  
  2045.     pszSaveName = NULL;
  2046.     }
  2047.  
  2048.  
  2049.     /***********************************************************
  2050.     * If save was requested with temp files, and if no filename
  2051.     * was specified, then we have already accomplished our
  2052.     * job
  2053.     ************************************************************/
  2054.  
  2055.  
  2056.   // perform the save message immediately if there is a wait
  2057.  
  2058.   if ( ulParam1 & MCI_WAIT )
  2059.     {
  2060.     ulrc = mmioSendMessage( ulpInstance->hmmio,
  2061.                             MMIOM_SAVE,
  2062.                             (LONG) pszSaveName,
  2063.                             0 );
  2064.     if ( ulrc )
  2065.       {
  2066.       // Get the error code for the last error
  2067.  
  2068.       ulrc = mmioGetLastError( ulpInstance->hmmio );
  2069.       if ( ulrc == ERROR_FILE_NOT_FOUND ||
  2070.            ulrc == ERROR_PATH_NOT_FOUND ||
  2071.            ulrc == ERROR_INVALID_DRIVE)
  2072.          {
  2073.          ulrc = MCIERR_FILE_NOT_FOUND;
  2074.          }
  2075.       else if ( ulrc == MMIOERR_CANNOTWRITE )
  2076.               {
  2077.               ulrc = MCIERR_TARGET_DEVICE_FULL;
  2078.               }
  2079.       else if ( ulrc == ERROR_ACCESS_DENIED ||
  2080.                 ulrc == ERROR_SHARING_VIOLATION  )
  2081.               {
  2082.               ulrc = MCIERR_FILE_ATTRIBUTE;
  2083.               }
  2084.       }
  2085.  
  2086.  
  2087.     if ( ulParam1 & MCI_SAVE_FILE )
  2088.        {
  2089.       if ( ulpInstance->ulCreatedName )
  2090.          {
  2091.          DosDelete( ( PSZ ) ulpInstance->lpstrAudioFile );
  2092.          }
  2093.  
  2094.        strcpy( ( PSZ ) ulpInstance->lpstrAudioFile,
  2095.                 pszSaveName );
  2096.        }
  2097.  
  2098.     /*******************************************************************
  2099.     * Ensure that if a file handle was passed in and we opened successfully
  2100.     * that we do not open again with the file handle
  2101.     ********************************************************************/
  2102.     ulpInstance->ulCreatedName = FALSE;
  2103.  
  2104.     }
  2105.   else
  2106.     /*********************************************/
  2107.     //  we must perform the save on a thread since
  2108.     // notify was requested (note, if neither notify
  2109.     // or wait are specified, then operated like notify
  2110.     // except without positing the message.
  2111.     /*********************************************/
  2112.  
  2113.     {
  2114.     /***********************************************************/
  2115.     // Let other threads know that a save is about to happen
  2116.     /***********************************************************/
  2117.     ulpInstance->usNotifyPending = TRUE;
  2118.     ulpInstance->usNotPendingMsg = MCI_SAVE;
  2119.  
  2120.     DosResetEventSem (ulpInstance->hThreadSem, &lCnt);
  2121.  
  2122.     ulrc = DosCreateThread ((PTID) &pFuncBlock->pInstance->SaveThreadID,
  2123.                             (PFNTHREAD) StartSave,
  2124.                             (ULONG) pFuncBlock,
  2125.                             0L,
  2126.                             NOTIFY_THREAD_STACKSIZE );
  2127.  
  2128.     DosWaitEventSem (ulpInstance->hThreadSem, (ULONG ) -1 );
  2129.  
  2130.     }
  2131.     return ( ulrc );
  2132.  
  2133. }
  2134.  
  2135.  
  2136.  
  2137. /********************* START OF SPECIFICATIONS *******************************
  2138. *
  2139. * SUBROUTINE NAME: StartSave.
  2140. *
  2141. * DESCRIPTIVE NAME: Saves a file on a different thread
  2142. *
  2143. * FUNCTION:
  2144. *
  2145. *
  2146. * NOTES: This routine is called using  a separate thread spawned by
  2147. *        MCD on MCI Notify.
  2148. *
  2149. * ENTRY POINTS:
  2150. *     LINKAGE:   CALL FAR
  2151. *
  2152. * INPUT:
  2153. *
  2154. * EXIT-NORMAL: Return Code 0.
  2155. *
  2156. * EXIT_ERROR:  Error Code.
  2157. *
  2158. * EFFECTS:
  2159. *
  2160. * INTERNAL REFERENCES: None
  2161. *
  2162. * EXTERNAL REFERENCES: None
  2163. *
  2164. *********************** END OF SPECIFICATIONS *******************************/
  2165. RC StartSave (FUNCTION_PARM_BLOCK *pFuncBlock )
  2166. {
  2167.  
  2168.    ULONG               ulrc;
  2169.    ULONG               ulErr;
  2170.    ULONG               ulParam1;
  2171.  
  2172.    ULONG                  lCnt;
  2173.  
  2174.    INSTANCE            *ulpInstance;
  2175.  
  2176.    LPMCI_SAVE_PARMS    lpSaveParms;
  2177.  
  2178.    CHAR                chSaveName[ CCHMAXPATH ];
  2179.    PSZ                 pszSaveName;
  2180.  
  2181.  
  2182.    ulrc = MCIERR_SUCCESS;
  2183.    ulErr = MCI_NOTIFY_SUCCESSFUL;
  2184.  
  2185.    ulpInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  2186.    lpSaveParms = (LPMCI_SAVE_PARMS) pFuncBlock->ulParam2;
  2187.    ulParam1 = pFuncBlock->ulParam1;
  2188.  
  2189.  
  2190.    if ( ulParam1 & MCI_SAVE_FILE )
  2191.       {
  2192.       // we need to copy this string since it may be cleared
  2193.       // when the calling thread leaves
  2194.  
  2195.       strcpy( chSaveName, ( PSZ ) lpSaveParms->lpFileName );
  2196.       pszSaveName = (PSZ) chSaveName;
  2197.       }
  2198.    else
  2199.       {
  2200.       pszSaveName = NULL;
  2201.       }
  2202.  
  2203.    /*********************************************
  2204.    * We can free the save thread now that we have
  2205.    * obtained any possible file names
  2206.    **********************************************/
  2207.  
  2208.    DosPostEventSem ( ulpInstance->hThreadSem );
  2209.    DosResetEventSem (ulpInstance->hThreadSem, &lCnt);
  2210.  
  2211.  
  2212.      ulrc = mmioSendMessage( ulpInstance->hmmio,
  2213.                             MMIOM_SAVE,
  2214.                             (LONG) pszSaveName,
  2215.                             0 );
  2216.  
  2217.    /*********************************************
  2218.    * If there were no errors, then the filename the
  2219.    * caller requested is the default file name
  2220.    **********************************************/
  2221.  
  2222.    if ( ulParam1 & MCI_SAVE_FILE && !ulrc )
  2223.       {
  2224.       if ( ulpInstance->ulCreatedName )
  2225.          {
  2226.          DosDelete( ( PSZ ) ulpInstance->lpstrAudioFile );
  2227.          }
  2228.  
  2229.       strcpy( ( PSZ ) ulpInstance->lpstrAudioFile,
  2230.                chSaveName );
  2231.  
  2232.       }
  2233.  
  2234.    if (ulParam1 & MCI_NOTIFY)
  2235.       {
  2236.       /*****************************************
  2237.       * If an error occurred, then inform  the caller
  2238.       * of the problem.
  2239.       ******************************************/
  2240.  
  2241.       if ( ulrc )
  2242.          {
  2243.          ulErr = mmioGetLastError( ulpInstance->hmmio );
  2244.          if ( ulrc == ERROR_FILE_NOT_FOUND ||
  2245.               ulrc == ERROR_PATH_NOT_FOUND ||
  2246.               ulrc == ERROR_INVALID_DRIVE)
  2247.             {
  2248.             ulErr = MCIERR_FILE_NOT_FOUND;
  2249.             }
  2250.          else if ( ulrc == MMIOERR_CANNOTWRITE )
  2251.                  {
  2252.                  ulErr = MCIERR_TARGET_DEVICE_FULL;
  2253.                  }
  2254.          else if ( ulrc == ERROR_ACCESS_DENIED ||
  2255.                    ulrc == ERROR_SHARING_VIOLATION  )
  2256.                  {
  2257.                  ulErr = MCIERR_FILE_ATTRIBUTE;
  2258.                  }
  2259.          }
  2260.  
  2261.       PostMDMMessage (ulErr, MCI_SAVE, pFuncBlock);
  2262.  
  2263.       }
  2264.  
  2265.  
  2266.    /*****************************************
  2267.    * Post The Thread Sem To release Notify
  2268.    * Thread Blocked on this sem.
  2269.    ******************************************/
  2270.  
  2271.    DosPostEventSem ( ulpInstance->hThreadSem );
  2272.  
  2273.    STRMSTATE = MCI_STOP;
  2274.    ulpInstance->usNotifyPending = FALSE;
  2275.  
  2276.  
  2277.    ulpInstance->ulCreatedName = FALSE;
  2278.  
  2279.  
  2280.  
  2281.    if (ulParam1 & MCI_NOTIFY)
  2282.       {
  2283.       /*********************************************/
  2284.       // Release Thread Block Memory
  2285.       /*********************************************/
  2286.       ulrc = CleanUp ((PVOID)pFuncBlock);
  2287.       }
  2288.  
  2289.  
  2290.    return ( ulErr );
  2291.  
  2292. } /* Start Save */
  2293.