home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mmpm21tk.zip / TK / ADMCT / STRMSUBS.C < prev    next >
C/C++ Source or Header  |  1993-04-08  |  38KB  |  1,322 lines

  1. /*****************************************************************************
  2. *
  3. * SOURCE FILE NAME:             STRMSUBS.C
  4. *
  5. *
  6. *
  7. *              Copyright (c) IBM Corporation  1991, 1993
  8. *                        All Rights Reserved
  9. *
  10. * DESCRIPTIVE NAME:     Support functions for wave streaming requests
  11. *
  12. * NOTES: Conecpts illustrated in this source file.
  13. *         1. How to close mmio files, and temp files (CloseFile).
  14. *         2. How to stop a record/playback stream (StopStream).
  15. *         3. How to use a semaphore to protect in progress commands
  16. *            from being aborted in sensitive areas.
  17. *         4. Why a stream must be destroyed after an MCI_SET (DestroySetStream).
  18. *         5. How to handle superceding and aborting of notifies.
  19. *         6. How and why to set a cue time pause event for
  20. *            MCI_TO (ProccessFromToFlags).
  21. *         7. How to enable cuepoints and positionchanges (EnableEvents).
  22. *
  23. *    DEPENDENCIES: NONE
  24. *    RESTRICTIONS: NONE
  25. *
  26. * FUNCTIONS: CloseFile
  27. *            StopStream
  28. *            GetNotifyAbortAccess
  29. *            DestroySetStream
  30. *            AbortInProgressNotify
  31. *            PrepareAndCreateStream
  32. *            ProcessFromToFlags
  33. *            EnableEvents
  34. *            QualityofService
  35. *
  36. *********************** END OF SPECIFICATIONS ********************************/
  37. #define INCL_BASE
  38. #define INCL_DOSMODULEMGR
  39. #define INCL_DOSSEMAPHORES
  40.  
  41. #include <os2.h>                        // OS2 defines.
  42. #include <string.h>                     // String functions.
  43. #include <os2medef.h>                   // MME includes files.
  44. #include <math.h>                       // Standard Math Lib
  45. #include <stdlib.h>                     // Standard Library
  46. #include <audio.h>                      // Audio Device defines
  47. #include <ssm.h>                        // SSM spi includes.
  48. #include <meerror.h>                    // MM Error Messages.
  49. #include <mmioos2.h>                    // MMIO Include.
  50. #include <mcios2.h>                     // MM System Include.
  51. #include <mmdrvos2.h>                   // MCI Driver include.
  52. #include <mcd.h>                        // AudioIFDriverInterface.
  53. #include <hhpheap.h>                    // Heap Manager Definitions
  54. #include <qos.h>
  55. #include <audiomcd.h>                   // Component Definitions.
  56. #include <admcfunc.h>
  57.  
  58.  
  59.  
  60.  
  61. /********************* START OF SPECIFICATIONS *********************
  62. *
  63. * SUBROUTINE NAME: GetNotifyAbortAccess
  64. *
  65. * DESCRIPTIVE NAME:
  66. *
  67. * FUNCTION:     Allows functions to obtain access to abort notifications
  68. *
  69. * NOTES:
  70. *
  71. * INPUT:
  72. *
  73. * EXIT-NORMAL:  NO_ERROR
  74. *
  75. * EXIT_ERROR:
  76. *
  77. *********************** END OF SPECIFICATIONS *********************************/
  78.  
  79. void  GetNotifyAbortAccess ( INSTANCE *ulpInstance,
  80.                              PULONG   pulAbortNotify )
  81.  
  82. {
  83. ULONG   ulCount;
  84.  
  85.   /****************************************************
  86.   * This semaphore controls whether or not it is safe
  87.   * to abort a previous notify thread.
  88.   * If the thread is in a critical section, it will have
  89.   * access to this semaphore and we will wait till it
  90.   * completes.
  91.   ****************************************************/
  92.  
  93.   DosRequestMutexSem( ulpInstance->hmtxNotifyAccess, -1 );
  94.  
  95.   /****************************************************
  96.   * The fNotifyPending boolean indicates whether or not
  97.   * a command is currently in progress (i.e. a play notify
  98.   * was done before the current command).   If there is
  99.   * a command in progress, set a few flags and let the
  100.   * caller know that they must abort the in progress
  101.   * operation.
  102.   ********************************************************/
  103.  
  104.   /* investigate--change this usNotifyPending to fNotifyPending */
  105.  
  106.   if (ulpInstance->usNotifyPending == TRUE)
  107.      {
  108.      ulpInstance->ulNotifyAborted = TRUE;
  109.      ulpInstance->usNotifyPending = FALSE;
  110.      *pulAbortNotify = TRUE;
  111.      DosResetEventSem ( ulpInstance->hThreadSem, &ulCount);
  112.      }
  113.  
  114.   DosReleaseMutexSem( ulpInstance->hmtxNotifyAccess );
  115.  
  116.  
  117. } /* GetNotifyAbortAccess */
  118.  
  119. /********************* START OF SPECIFICATIONS *********************
  120. *
  121. * SUBROUTINE NAME: DestroySetSream
  122. *
  123. * DESCRIPTIVE NAME: Destroys a stream because a set has made it invalid
  124. *
  125. * FUNCTION:     Since sets to a created stream cannot be communicated
  126.                 to a stream handler, then stream must be destroyed
  127.                 and created anew.
  128. *
  129. * NOTES:
  130. *
  131. * INPUT:
  132. *
  133. * EXIT-NORMAL:  NO_ERROR
  134. *
  135. * EXIT_ERROR:
  136. *
  137. *********************** END OF SPECIFICATIONS *********************************/
  138.  
  139. void DestroySetStream ( INSTANCE     *ulpInstance )
  140.  
  141. {
  142.    /***********************************************
  143.    * If a set was performed on an existing stream,
  144.    * destroy the stream and get new spcb keys
  145.    ***********************************************/
  146.  
  147.    if ( STRMSTATE == STREAM_SET_STATE )
  148.      {
  149.      DestroyStream ( &STREAM.hStream);
  150.  
  151.      ulpInstance->ulCreateFlag = CREATE_STATE;
  152.  
  153.      }
  154.  
  155.    return;
  156.  
  157. } /* DestorySetStream */
  158.  
  159.  
  160. /********************* START OF SPECIFICATIONS *********************
  161. *
  162. * SUBROUTINE NAME: AbortInProgressNotify
  163. *
  164. * DESCRIPTIVE NAME: Stops a notify which was already in progress
  165. *
  166. * FUNCTION: Stops save, record and playback notifies
  167. *
  168. * NOTES:
  169. *
  170. * ENTRY POINTS:
  171. *
  172. * INPUT: INSTANCE pointer
  173. *        ULONG ulMessage -- either MCI_RECORD or MCI_PLAY
  174. *        ULONG ulParam1
  175. *
  176. *
  177. * EXIT-NORMAL: Return Code 0.
  178. *
  179. * EXIT_ERROR:
  180. *
  181. * EFFECTS:
  182. *
  183. * INTERNAL REFERENCES: MCIERR ().
  184. *
  185. * EXTERNAL REFERENCES: spiStopStream()    - SSM Spi
  186. *
  187. *********************** END OF SPECIFICATIONS **********************/
  188.  
  189. ULONG AbortInProgressNotify( INSTANCE             *ulpInstance,
  190.                              FUNCTION_PARM_BLOCK  *pFuncBlock,
  191.                              ULONG                ulParam1,
  192.                              ULONG                ulMessage )
  193.  
  194. {
  195.    USHORT usAbortType;
  196.    HWND   hwndHoldHandle;
  197.  
  198.    /***************************************************
  199.    * Here is how an MCD should interrupt an
  200.    * operation which was in progress. If the
  201.    * currently active operation is the same as the
  202.    * new operation, then we should post a
  203.    * superceded message (e.g. if a play interrupts
  204.    * a play, a "Play superceded" should be posted.
  205.    * If a play interrupts a record, then an
  206.    * aborted message should be posted (i.e. "record
  207.    * aborted".
  208.    ***************************************************/
  209.  
  210.    /***************************************************
  211.    * Are we interrupting the same operation (i.e. play
  212.    * interrupting a play)?
  213.    ****************************************************/
  214.  
  215.    if ( ulpInstance->usNotPendingMsg == MCI_SAVE )
  216.        {
  217.        /***********************************
  218.        * Can't interrupt a save because data
  219.        * can be lost
  220.        ************************************/
  221.  
  222.        DosWaitEventSem( ulpInstance->hThreadSem, (ULONG ) -1 );
  223.  
  224.        }
  225.  
  226.     else
  227.       {
  228.  
  229.       /* Stop the pending thread */
  230.  
  231.       ThreadedStop ( ulpInstance );
  232.  
  233.  
  234.       if ( ulpInstance->usNotPendingMsg == ulMessage &&
  235.            !ulpInstance->fFakeNotify                 &&
  236.            (ulParam1 & MCI_NOTIFY) )
  237.          {
  238.          /************************************************
  239.          * If the new operation is a notify, then we are
  240.          * superceded.  If not, then it is aborted.
  241.          ************************************************/
  242.         
  243.          usAbortType = MCI_NOTIFY_SUPERSEDED;
  244.          }   /* Case of a Play Superseeding a Play */
  245.  
  246.       else
  247.          {
  248.          /************************************************
  249.          * If the new operation is a notify, then we are
  250.          * superceded.  If not, then it is aborted.
  251.          ************************************************/
  252.         
  253.          usAbortType = MCI_NOTIFY_ABORTED;
  254.         
  255.          /*****************************************
  256.          * Before we destroy the stream determine
  257.          * where we were
  258.          *****************************************/
  259.         
  260.          GetOldStreamPosition( ulpInstance );
  261.         
  262.          DestroyStream ( &STREAM.hStream);
  263.         
  264.          ulpInstance->ulCreateFlag = PLAY_STREAM;
  265.  
  266.          } /* if we are aborting a different command */
  267.  
  268.  
  269.        /*---------------------------------------------
  270.        * If we are aborting a command, ensure that
  271.        * we notify it on the correct callback handle
  272.        *---------------------------------------------*/
  273.        hwndHoldHandle = ulpInstance->hwndCallBack;
  274.  
  275.        if ( ulParam1 & MCI_NOTIFY )
  276.           {
  277.           ulpInstance->hwndCallBack = ulpInstance->hwndOldCallBack;
  278.           }
  279.  
  280.        /*---------------------------------------------
  281.        * Inform the caller that the previous command
  282.        * has be officially terminated.
  283.        *---------------------------------------------*/
  284.  
  285.  
  286.        PostMDMMessage ( usAbortType,
  287.                         ulpInstance->usNotPendingMsg ,
  288.                         pFuncBlock);
  289.  
  290.  
  291.        /*---------------------------------------------
  292.        * now ensure that we will notify the caller
  293.        * on the correct window handle.
  294.        *---------------------------------------------*/
  295.  
  296.        ulpInstance->hwndCallBack = hwndHoldHandle;
  297.  
  298.  
  299.        if (ulParam1 & MCI_NOTIFY)
  300.            ulpInstance->usUserParm = pFuncBlock->usUserParm;
  301.  
  302.  
  303.  
  304.       } /* else save is not pending */
  305.  
  306.   return ( MCIERR_SUCCESS );
  307.  
  308. } /* AbortInProgressNotify */
  309.  
  310.  
  311. /********************* START OF SPECIFICATIONS *********************
  312. *
  313. * SUBROUTINE NAME: GetOldStreamPosition
  314. *
  315. * DESCRIPTIVE NAME: Remembers current position in the stream.
  316. *
  317. * FUNCTION:
  318. *
  319. * NOTES:
  320. *
  321. * ENTRY POINTS:
  322. *
  323. * INPUT: INSTANCE ptr
  324. *        ULONG ulMessage -- either MCI_RECORD or MCI_PLAY
  325. *
  326. * EXIT-NORMAL: Return Code 0.
  327. *
  328. * EXIT_ERROR:
  329. *
  330. * NOTES: This function remembers our position in the stream when
  331. *        the caller switches between play and record streams.  This
  332. *        allows the user to pick up at the same position.
  333. *
  334. * INTERNAL REFERENCES:
  335. *
  336. * EXTERNAL REFERENCES: SpiGetTime
  337. *
  338. *********************** END OF SPECIFICATIONS **********************/
  339.  
  340.  
  341. ULONG GetOldStreamPosition( INSTANCE *ulpInstance )
  342.  
  343. {
  344.   ULONG ulrc = MCIERR_SUCCESS;
  345.  
  346.   if ( !ulpInstance->ulOldStreamPos )
  347.      {
  348.      ulrc = SpiGetTime( STREAM.hStream,
  349.                         ( PMMTIME ) &ulpInstance->ulOldStreamPos );
  350.  
  351.      /**********************************************
  352.      * if an error occurred, then don't remember our
  353.      * position in the stream.
  354.      ***********************************************/
  355.  
  356.      if ( ulrc )
  357.        {
  358.        ulpInstance->ulOldStreamPos = 0;
  359.        }
  360.      } /* if we have no old stream position. */
  361.  
  362.      return ( MCIERR_SUCCESS );
  363.  
  364. } /* GetOldStreamPosition */
  365.  
  366. /********************* START OF SPECIFICATIONS *********************
  367. *
  368. * SUBROUTINE NAME: PrepareAndCreateStream
  369. *
  370. * DESCRIPTIVE NAME: Does work to create a stream
  371. *
  372. * FUNCTION: Inits variables and creates a stream
  373. *           Boolean determines whether card must be set up also.
  374. *
  375. * NOTES:
  376. *
  377. * ENTRY POINTS:
  378. *
  379. * INPUT: INSTANCE ptr
  380. *        ULONG ulMessage -- either MCI_RECORD or MCI_PLAY
  381. *
  382. * EXIT-NORMAL: Return Code 0.
  383. *
  384. * EXIT_ERROR:
  385. *
  386. * EFFECTS:
  387. *
  388. * INTERNAL REFERENCES: MCIERR ().
  389. *
  390. * EXTERNAL REFERENCES: spiCreateStream()    - SSM Spi
  391. *
  392. *********************** END OF SPECIFICATIONS **********************/
  393.  
  394. ULONG PrepareAndCreateStream( INSTANCE *ulpInstance,
  395.                               ULONG    ulOperation,
  396.                               BOOL     fSetUpCard )
  397.  
  398.  
  399. {
  400.     ULONG               ulrc = MCIERR_SUCCESS;   // return codes
  401.     ULONG               ulAssocFlag;             // stream association flag
  402.  
  403.     MCI_WAVE_SET_PARMS  SetParms;      // MCI Wave Set Parms
  404.  
  405.     ULONG               ulSetAll;        // Set all flags
  406.  
  407.     ulSetAll = MCI_WAVE_SET_BITSPERSAMPLE| MCI_WAVE_SET_FORMATTAG     |
  408.                MCI_WAVE_SET_CHANNELS     | MCI_WAVE_SET_SAMPLESPERSEC;
  409.  
  410.  
  411.  
  412.      if (ulpInstance->ulCreateFlag != PREROLL_STATE)
  413.         {
  414.  
  415.         /************************************************************
  416.         * Determine which type of stream we will have to associate
  417.         * Playlists will associate the memory stream handler,
  418.         * and non-playlists will use the file system SH.
  419.         *************************************************************/
  420.         if (ulpInstance->usPlayLstStrm == TRUE)
  421.            {
  422.            ulAssocFlag = (ULONG)NULL;
  423.            }
  424.         else
  425.            {
  426.  
  427.            /******************************************************
  428.            * Set a flag to indicate which direction the stream
  429.            * handlers should go (e.g. play and record streams
  430.            * go in different directions.
  431.            ******************************************************/
  432.  
  433.            if ( ulOperation == OPERATION_RECORD )
  434.               {
  435.               ulAssocFlag = RECORD_STREAM;
  436.               }
  437.            else
  438.               {
  439.               ulAssocFlag = PLAY_STREAM;
  440.               }
  441.            }
  442.  
  443.  
  444.          /********************************************
  445.          * Tell the amp mixer that we are about to
  446.          * switch to the desired operation
  447.          *********************************************/
  448.  
  449.          AMPMIX.ulOperation = ulOperation;
  450.  
  451.          if ( fSetUpCard )
  452.             {
  453.             /*************************************************
  454.             * Always Reinit The Device before stream creation.
  455.             *************************************************/
  456.       
  457.       
  458.             VSDInstToWaveSetParms (&SetParms, ulpInstance);
  459.  
  460.             ulrc = SetAudioDevice ( ulpInstance,
  461.                                     (PMCI_WAVE_SET_PARMS) &SetParms,
  462.                                     ulSetAll );
  463.  
  464.             if ( ulrc )
  465.                {
  466.                return ( ulrc );
  467.                }
  468.  
  469.  
  470.             } /* If the card must be inited */
  471.  
  472.          /*************************************************
  473.          * If the init caused a new global sys file, use it
  474.          *************************************************/
  475.  
  476.          STREAM.AudioDCB.ulSysFileNum = AMPMIX.ulGlobalFile;
  477.  
  478.          /********************************************
  479.          * Create and associate a playback stream
  480.          * This stream has the file system as the
  481.          * source stream handler and audio stream
  482.          * handler as the target.
  483.          *********************************************/
  484.          if ( ulOperation == OPERATION_RECORD )
  485.             {
  486.  
  487.             ulrc = CreateNAssocStream ( STREAM.hidBSource,
  488.                                         STREAM.hidATarget,
  489.                                         &STREAM.hStream,
  490.                                         ulpInstance,
  491.                                         ulAssocFlag,
  492.                                         (PEVFN)RecordEventRoutine );
  493.  
  494.             }
  495.          else
  496.             {
  497.             /********************************************
  498.             * Create and associate a playback stream
  499.             * This stream has the audio stream handler
  500.             * as the source stream handler and file
  501.             * system stream handler as the target.
  502.             *********************************************/
  503.  
  504.             ulrc = CreateNAssocStream ( STREAM.hidASource,
  505.                                         STREAM.hidBTarget,
  506.                                         &STREAM.hStream,
  507.                                         ulpInstance,
  508.                                         ulAssocFlag,
  509.                                         (PEVFN) PlayEventRoutine );
  510.             }
  511.  
  512.          if (ulrc)
  513.              return ulrc;
  514.  
  515.          /*****************************************************
  516.          * In case of playlist do the associate seperately
  517.          * Playlists associate the playlist with the memory
  518.          * stream handlers.
  519.          ******************************************************/
  520.  
  521.          if ( ulAssocFlag == (ULONG) NULL )
  522.             {
  523.             if ( ulOperation == OPERATION_RECORD )
  524.               {
  525.               ulAssocFlag = RECORD_STREAM;
  526.               }
  527.             else
  528.               {
  529.               ulAssocFlag = PLAY_STREAM;
  530.               }
  531.  
  532.             ulrc = AssociatePlayList ( ulpInstance, ulAssocFlag );
  533.  
  534.             }
  535.  
  536.  
  537.         } /* Play/Record Cue Stream */
  538.  
  539.     return ( ulrc );
  540.  
  541.  
  542. } /* PrepareAndCreateStream */
  543.  
  544.  
  545.  
  546.  
  547. /********************* START OF SPECIFICATIONS *********************
  548. *
  549. * SUBROUTINE NAME: RememberStreamState
  550. *
  551. * DESCRIPTIVE NAME: remembers cuepoints + position accross streams
  552. *
  553. * FUNCTION: After a stream has been destroyed, this function will
  554. *           set the new one up so that position advises, cue points
  555. *           and stream position will be just like the old one.
  556. *
  557. * NOTES:
  558. *
  559. * ENTRY POINTS:
  560. *
  561. * INPUT: INSTANCE ptr
  562. *        ULONG ulMessage -- either MCI_RECORD or MCI_PLAY
  563. *
  564. * EXIT-NORMAL: Return Code 0.
  565. *
  566. * EXIT_ERROR:
  567. *
  568. * EFFECTS:
  569. *
  570. * INTERNAL REFERENCES: MCIERR ().
  571. *
  572. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  573. *
  574. *********************** END OF SPECIFICATIONS **********************/
  575.  
  576. ULONG RememberStreamState( INSTANCE  *ulpInstance,
  577.                            ULONG     ulParam1,
  578.                            BOOL      fSeekNeeded )
  579.  
  580. {
  581.    ULONG ulrc = MCIERR_SUCCESS;
  582.  
  583.  
  584.    /*******************************************
  585.    * Stream is destroyed. Reset cuepopint and
  586.    * position advise flags to enabled state
  587.    * and send it down on the new stream
  588.    ********************************************/
  589.  
  590.    if (ulpInstance->usPosAdvise == EVENT_ENABLED)
  591.        ulpInstance->usPosAdvise = TRUE;
  592.  
  593.    if (ulpInstance->usCuePt == EVENT_ENABLED)
  594.        ulpInstance->usCuePt = TRUE;
  595.    /*---------------------------------------
  596.    * If we previously destroyed a stream,
  597.    * seek to the position where we were
  598.    * else just seek to 0
  599.    *--------------------------------------*/
  600.  
  601.    if ( !(ulParam1 & MCI_FROM ) && fSeekNeeded )
  602.       {
  603.       ulrc = SpiSeekStream ( STREAM.hStream,
  604.                              SPI_SEEK_ABSOLUTE,
  605.                              ulpInstance->ulOldStreamPos );
  606.  
  607.       if (ulrc)
  608.         {
  609.  
  610.         /*-------------------------------------------------------------
  611.         * it is possible that the card may report a position that is
  612.         * greater than what is actually recorded, so work around this
  613.         * problem
  614.         *-------------------------------------------------------------*/
  615.  
  616.         if ( ulrc == ERROR_SEEK_PAST_END )
  617.            {
  618.            ulrc = SpiSeekStream ( STREAM.hStream,
  619.                                  SPI_SEEK_FROMEND,
  620.                                  0 );
  621.  
  622.            if ( ulrc )
  623.               {
  624.               return ( ulrc );
  625.               }
  626.            }
  627.         else
  628.            {
  629.            return (ulrc);
  630.            }
  631.  
  632.         } /* if an error occurred */
  633.  
  634.       } /* if no from parameter */
  635.  
  636.  
  637.     ulpInstance->ulOldStreamPos = 0;
  638.  
  639.     /************************************
  640.     * place the stream in a stopped state
  641.     * since no activity has occurred
  642.     *************************************/
  643.  
  644.     STRMSTATE = MCI_STOP;
  645.  
  646.     return ( ulrc );
  647.  
  648.  
  649.  } /* RememberStreamState */
  650.  
  651.  
  652.  
  653.  
  654. /********************* START OF SPECIFICATIONS *********************
  655. *
  656. * SUBROUTINE NAME: ProcessFromToFlags
  657. *
  658. * DESCRIPTIVE NAME: Uses from to flags to ensure to place stream
  659. *
  660. * FUNCTION: Uses MCI_FROM flag to seek to the correct position and
  661. *           the MCI_TO to determine where to stop streaming.
  662. *           Note: with new SPI API this will no longer be needed
  663. *
  664. * NOTES:
  665. *
  666. * ENTRY POINTS:
  667. *
  668. * INPUT: FUNCTION_PARM_BLOCK
  669. *        INSTANCE *ptr
  670. *        ULONG    ulMessage -- either MCI_RECORD or MCI_PLAY
  671. *
  672. * EXIT-NORMAL: Return Code 0.
  673. *
  674. * EXIT_ERROR:
  675. *
  676. * EFFECTS:
  677. *
  678. * INTERNAL REFERENCES: MCIERR ().
  679. *
  680. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  681. *
  682. *********************** END OF SPECIFICATIONS **********************/
  683.  
  684. ULONG ProcessFromToFlags( FUNCTION_PARM_BLOCK  *pFuncBlock,
  685.                           INSTANCE             *ulpInstance,
  686.                           ULONG                ulOperation,
  687.                           ULONG                ulParam1 )
  688.  
  689.  
  690. {
  691.  
  692.    PMCI_PLAY_PARMS        pPlayParms;        // Msg Data Ptr
  693.    PMCI_RECORD_PARMS      pRecordParms;      // MCI Record Parms
  694.  
  695.  
  696.    ULONG                   ulConvertNumber;    // convert number to mmtime
  697.    ULONG                   ulrc = MCIERR_SUCCESS;
  698.    ULONG                   ulCount;            // Semphore counter
  699.  
  700.  
  701.    /***********************************
  702.    * Do a Seek to support FROM
  703.    ***********************************/
  704.  
  705.    if (ulParam1 & MCI_FROM)
  706.       {
  707.       if (STRMSTATE != MCI_STOP )
  708.         {
  709.         /**************************************
  710.         * Reset semaphore used to indicate when
  711.         * streaming event has occurred.
  712.         ****************************************/
  713.  
  714.         DosResetEventSem (ulpInstance->hEventSem, &ulCount);
  715.  
  716.         /**************************************
  717.         * Stop the stream (discard buffers)
  718.         **************************************/
  719.  
  720.         ulrc = SpiStopStream (STREAM.hStream, SPI_STOP_DISCARD);
  721.  
  722.         if (!ulrc)
  723.           {
  724.           /*****************************************
  725.           * Wait for the stream to be stopped
  726.           *****************************************/
  727.  
  728.           DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1);
  729.           }
  730.  
  731.         }
  732.  
  733.        /******************************************
  734.        * Convert the number that the user passed in
  735.        * (i.e. from samples) to mmtime so that we
  736.        * can seek to the point in the stream.
  737.        *******************************************/
  738.  
  739.  
  740.        if ( ulOperation == MCI_RECORD )
  741.           {
  742.           pRecordParms= (PMCI_RECORD_PARMS )pFuncBlock->ulParam2;
  743.  
  744.           ulrc = ConvertToMM ( ulpInstance,
  745.                                &ulConvertNumber,
  746.                                pRecordParms->ulFrom);
  747.           }
  748.        else
  749.           {
  750.           pPlayParms= (PMCI_PLAY_PARMS )pFuncBlock->ulParam2;
  751.  
  752.           ulrc = ConvertToMM ( ulpInstance,
  753.                                &ulConvertNumber,
  754.                                pPlayParms->ulFrom);
  755.           }
  756.  
  757.  
  758.         /*********************************
  759.         * Do the Seek Thing
  760.         **********************************/
  761.  
  762.         if ( !ulrc )
  763.            {
  764.            ulrc = SpiSeekStream ( STREAM.hStream,
  765.                                   SPI_SEEK_ABSOLUTE,
  766.                                   ulConvertNumber);
  767.  
  768.            if ( ulrc )
  769.               {
  770.               return ( ulrc ) ;
  771.               }
  772.            }
  773.  
  774.       } /* Play From */
  775.  
  776.    /*************************************************
  777.    * If the caller specified a to position via
  778.    * MCI_TO, then convert the number to mm time
  779.    * (we do this because it simplifies the code,
  780.    * only dealing with one time base).  Then
  781.    * set a cue time pause event in the stream at
  782.    * the to point.  The streaming operation will
  783.    * proceed till the pause event, report the event
  784.    * and thus, it appears to the caller like we
  785.    * stopped right at the to spot.
  786.    *************************************************/
  787.  
  788.    if (ulParam1 & MCI_TO)
  789.       {
  790.       if ( ulOperation == MCI_RECORD )
  791.           {
  792.           pRecordParms= ( PMCI_RECORD_PARMS )pFuncBlock->ulParam2;
  793.  
  794.           ulrc = ConvertToMM ( ulpInstance,
  795.                                &ulConvertNumber,
  796.                                pRecordParms->ulTo );
  797.           }
  798.        else
  799.           {
  800.           pPlayParms= ( PMCI_PLAY_PARMS )pFuncBlock->ulParam2;
  801.  
  802.           ulrc = ConvertToMM ( ulpInstance,
  803.                                &ulConvertNumber,
  804.                                pPlayParms->ulTo );
  805.           }
  806.  
  807.        /* Place the cue time pause event in the stream */
  808.  
  809.        if ( !ulrc )
  810.           {
  811.           ulrc = CreateToEvent ( ulpInstance, ulConvertNumber );
  812.           }
  813.  
  814.        ulpInstance->fToEvent = TRUE;
  815.  
  816.       } // Of Play Till XXXX
  817.  
  818.  
  819.   return ( ulrc );
  820.  
  821. } /* ProcessFromToFlags */
  822.  
  823.  
  824.  
  825. /********************* START OF SPECIFICATIONS *********************
  826. *
  827. * SUBROUTINE NAME: EnableEvents
  828. *
  829. * DESCRIPTIVE NAME: enables cue points and position advises
  830. *
  831. * FUNCTION: For newly created streams, this will enable cue points
  832. *           and position advises which were sent to the previously
  833. *           destroyed stream (i.e. a play following a record).
  834. *
  835. * NOTES:
  836. *
  837. * ENTRY POINTS:
  838. *
  839. * INPUT:
  840. *
  841. * EXIT-NORMAL: Return Code 0.
  842. *
  843. * EXIT_ERROR:
  844. *
  845. * EFFECTS:
  846. *
  847. * INTERNAL REFERENCES: MCIERR ().
  848. *
  849. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  850. *
  851. *********************** END OF SPECIFICATIONS **********************/
  852.  
  853. ULONG EnableEvents( INSTANCE *ulpInstance )
  854.  
  855. {
  856.  
  857.    ULONG         ulrc = MCIERR_SUCCESS;
  858.  
  859.    MTIME_EVCB    *pMCuePtEVCB;  // pointer
  860.  
  861.  
  862.    /***************************************
  863.    * Enable Position Advise if Needed
  864.    ****************************************/
  865.  
  866.  
  867.    if (ulpInstance->usPosAdvise == TRUE)
  868.       {
  869.  
  870.       /*********************************
  871.       * Correct The hStream Value
  872.       **********************************/
  873.       STREAM.PosAdvEvcb.evcb.hstream = STREAM.hStream;
  874.  
  875.       /**********************************************
  876.       * Stick our instance pointer in the time
  877.       * Event Control Block (EVCB).  This will allow
  878.       * the event procedure to access instance data
  879.       * (see PlayEventProc and RecordEventProc for
  880.       * more information).
  881.       ***********************************************/
  882.  
  883.       STREAM.PosAdvEvcb.ulpInstance = (ULONG) ulpInstance;
  884.  
  885.       /**************************************************************
  886.       * Update position advise cuepoints created in different stream
  887.       **************************************************************/
  888.  
  889.       STREAM.PosAdvEvcb.evcb.mmtimeStream = STREAM.PosAdvEvcb.mmCuePt;
  890.  
  891.       ulrc = SpiEnableEvent( (PEVCB) &(STREAM.PosAdvEvcb),
  892.                              (PHEVENT) &(STREAM.hPosEvent));
  893.  
  894.       /* Set flag to indicate that the position advises were enabled */
  895.  
  896.       ulpInstance->usPosAdvise = EVENT_ENABLED;
  897.  
  898.       } /* if Positionadvise is true */
  899.  
  900.  
  901.    /*******************************
  902.    * Enable Cue points if any
  903.    *******************************/
  904.  
  905.    if (!ulrc)
  906.       {
  907.       // toast this ushort business--use ulongs.
  908.  
  909.       if (ulpInstance->usCuePt == TRUE)
  910.  
  911.          {
  912.          /*********************************
  913.          * Get cue point linked list pointer
  914.          ***********************************/
  915.  
  916.          pMCuePtEVCB = CUEPOINT;
  917.  
  918.  
  919.          /***********************************************
  920.          * The current MCD has a linked list of
  921.          * cuepoints.   Proceed through the linked
  922.          * list and enable each one in the stream.
  923.          * Warning: just because the MCD supports
  924.          * unlimited cuepoints, does not mean that the
  925.          * stream handler does.
  926.          ***********************************************/
  927.  
  928.          while ( pMCuePtEVCB )
  929.            {
  930.            pMCuePtEVCB->evcb.hstream = STREAM.hStream;
  931.  
  932.           /**********************************************
  933.           * Stick our instance pointer in the time
  934.           * Event Control Block (EVCB).  This will allow
  935.           * the event procedure to access instance data
  936.           * (see PlayEventProc and RecordEventProc for
  937.           * more information).
  938.           ***********************************************/
  939.  
  940.            pMCuePtEVCB->ulpInstance = (ULONG ) ulpInstance;
  941.  
  942.            /* Enable the cuepoints */
  943.  
  944.            ulrc = SpiEnableEvent( (PEVCB) pMCuePtEVCB,
  945.                                   (PHEVENT) &pMCuePtEVCB->HCuePtHndl );
  946.  
  947.            pMCuePtEVCB = pMCuePtEVCB->pNextEVCB;
  948.  
  949.            } /* while there are cuepoints to place in the stream */
  950.  
  951.  
  952.          ulpInstance->usCuePt = EVENT_ENABLED;
  953.  
  954.          } /* There are CuePts to be enabled */
  955.  
  956.       } /* if no return codes so far */
  957.  
  958.    return ( ulrc );
  959.  
  960. } /* EnableEvents */
  961.  
  962.  
  963.  
  964. /********************* START OF SPECIFICATIONS *********************
  965. *
  966. * SUBROUTINE NAME: StopStream
  967. *
  968. * DESCRIPTIVE NAME: Stops a stream
  969. *
  970. * FUNCTION: Sets up semaphores, stops the stream and waits for the
  971. *           event.
  972. *
  973. * NOTES:
  974. *
  975. * ENTRY POINTS:
  976. *
  977. * INPUT:
  978. *
  979. * EXIT-NORMAL: Return Code 0.
  980. *
  981. * EXIT_ERROR:
  982. *
  983. * EFFECTS:
  984. *
  985. * INTERNAL REFERENCES: MCIERR ().
  986. *
  987. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  988. *
  989. *********************** END OF SPECIFICATIONS **********************/
  990.  
  991.  
  992. ULONG StopStream( INSTANCE *ulpInstance,
  993.                   ULONG    ulOperation )
  994.  
  995. {
  996.    ULONG        ulCount;                // semaphore counter
  997.    ULONG        ulSpiFlags;             // flags to use on the spi stop
  998.    ULONG        ulrc = MCIERR_SUCCESS;  // return code
  999.  
  1000.    /***************************************
  1001.    * Reset Internal semaphores
  1002.    ****************************************/
  1003.  
  1004.    DosResetEventSem ( ulpInstance->hEventSem, &ulCount);
  1005.    DosResetEventSem ( ulpInstance->hThreadSem, &ulCount);
  1006.  
  1007.    /********************************************
  1008.    * Do different stops based on the stream type
  1009.    * record streams must be flushed so that no
  1010.    * data will be lost, whereas playback streams
  1011.    * are not concerned with data loss since they
  1012.    * create no data.
  1013.    ********************************************/
  1014.  
  1015.    if ( AMPMIX.ulOperation == OPERATION_RECORD )
  1016.       {
  1017.       ulSpiFlags = SPI_STOP_FLUSH;
  1018.       }
  1019.    else
  1020.       {
  1021.       ulSpiFlags = SPI_STOP_DISCARD;
  1022.       }
  1023.  
  1024.    /**********************************
  1025.    * Stop Streaming
  1026.    **********************************/
  1027.    ulrc = SpiStopStream (STREAM.hStream, ulSpiFlags );
  1028.  
  1029.    if (!ulrc)
  1030.       {
  1031.       DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1 );
  1032.       }
  1033.  
  1034.    if ( ulrc == ERROR_STREAM_ALREADY_STOP )
  1035.       {
  1036.       ulrc = MCIERR_SUCCESS;
  1037.       }
  1038.  
  1039.    return ( ulrc );
  1040.  
  1041. } /* StopStream */
  1042.  
  1043.  
  1044.  
  1045.  
  1046. /********************* START OF SPECIFICATIONS *********************
  1047. *
  1048. * SUBROUTINE NAME: CloseFile
  1049. *
  1050. * DESCRIPTIVE NAME: Close a multimedia i/o file
  1051. *
  1052. * FUNCTION: Closes the file and if it was a temporary file which we
  1053. *           opened without saving it, ensure that it is deleted.  If
  1054. *           the file was opened via OPEN_MMIO, DO NOT close the file.
  1055. *
  1056. * NOTES:
  1057. *
  1058. * ENTRY POINTS:
  1059. *
  1060. * INPUT: FUNCTION_PARM_BLOCK
  1061. *
  1062. * EXIT-NORMAL: Return Code 0.
  1063. *
  1064. * EXIT_ERROR:
  1065. *
  1066. * EFFECTS:
  1067. *
  1068. * INTERNAL REFERENCES: MCIERR ().
  1069. *
  1070. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  1071. *
  1072. *********************** END OF SPECIFICATIONS **********************/
  1073.  
  1074. ULONG CloseFile( INSTANCE *ulpInstance )
  1075.  
  1076.  
  1077. {
  1078.   ULONG ulrc = MCIERR_SUCCESS;
  1079.  
  1080.   /********************************************
  1081.   * If there is a file handle to close and
  1082.   * if the caller did not pass in the file
  1083.   * handle via OPEN_MMIO close the file.
  1084.   * If we close an open mmio handle, then
  1085.   * the application will not be able to use
  1086.   * it.
  1087.   ********************************************/
  1088.  
  1089.   if (ulpInstance->hmmio != 0 && !ulpInstance->fOpenMMIO )
  1090.      {
  1091.  
  1092.       ulrc = mmioClose (ulpInstance->hmmio, 0);
  1093.  
  1094.       /* If we created the temporary file and it wasn't saved--delete it */
  1095.  
  1096.       if ( ulpInstance->ulCreatedName )
  1097.          {
  1098.          DosDelete( ( PSZ ) ulpInstance->pszAudioFile );
  1099.          }
  1100.       /* Set flags to clear handle and ensure we don't delete the next temp file */
  1101.  
  1102.       ulpInstance->ulCreatedName = FALSE;
  1103.  
  1104.       ulpInstance->hmmio = 0;
  1105.  
  1106.      } /* hmmio not Null */
  1107.  
  1108.    return ( ulrc );
  1109.  
  1110. } /* CloseFile */
  1111.  
  1112.  
  1113.  
  1114. /********************* START OF SPECIFICATIONS *********************
  1115. *
  1116. * SUBROUTINE NAME: QualityofService
  1117. *
  1118. * FUNCTION: Some OS/2 networks have specific IO procs which can 
  1119. *           manage network traffic.  We will use the mmio messages
  1120. *           begin_stream to inform these io procs
  1121. *           that we wish to stream across the network.
  1122. *
  1123. *           If you are writing a streaming MCD, it is advantageous
  1124. *           to use these messages since performance across LAN's
  1125. *           may be improved.
  1126. *
  1127. * NOTES:
  1128. *
  1129. * ENTRY POINTS:
  1130. *
  1131. * INPUT: FUNCTION_PARM_BLOCK
  1132. *
  1133. * EXIT-NORMAL: MCIERR_SUCCESS
  1134. *
  1135. * EXIT_ERROR:
  1136. *
  1137. * EFFECTS:
  1138. *
  1139. * EXTERNAL REFERENCES: mmioSendMessage()    - MMIO function
  1140. *
  1141. *********************** END OF SPECIFICATIONS **********************/
  1142. ULONG   BeginQualityofService ( INSTANCE      *pInstance,
  1143.                                 LONG          lStreamDirection )
  1144.  
  1145. {
  1146.  
  1147. LONG         rc;
  1148. CUSTOM_QOS   CustomQOS;
  1149.  
  1150.  
  1151.   /* Currently, there are 4 parameters to QOS, this will increase */
  1152.  
  1153.   CustomQOS.QOSParms.lNumQOSParms = 4;
  1154.  
  1155.   /*---------------------------------------------------
  1156.   * The first parameter is the service request. It
  1157.   * can currently contain one of three values:
  1158.   *
  1159.   * A. GUARANTEED.  The MCD wants to know if the
  1160.   *    network can guarantee the traffic we need.
  1161.   *
  1162.   * B. DONTCARE.  We will ask for a certain level of
  1163.   *    support.  However, if it is unavailable, we
  1164.   *    can continue.
  1165.   *
  1166.   * C. DONTRESERVE. The MCD wants no guarantees about
  1167.   *    whether the network can support this transfer.
  1168.   *
  1169.   *----------------------------------------------------*/
  1170.   CustomQOS.QOSParms.QOSParms[0].lQOSParmId  = SERVICE_REQUEST;
  1171.   CustomQOS.QOSParms.QOSParms[0].lQOSValue    = pInstance->lQosValue;
  1172.  
  1173.   /*-------------------------------------------------
  1174.   * QOS needs to know the number of streaming
  1175.   * buffers SSM will be using.  A streaming MCD
  1176.   * can obtain this information via SpiGetProtocol.
  1177.   *-------------------------------------------------*/
  1178.  
  1179. //  pQOS->lQOSParmId  = NUM_STREAM_BUFFERS;
  1180. //  pQOS->lQOSValue    = pInstance->StreamInfo.spcb.ulMinBuf;
  1181. //  pQOS++;
  1182.  
  1183.  
  1184.   /*-----------------------------------------------------
  1185.   * MAX_EE_JITTER describes the allowable amount of
  1186.   * variation the streaming subsystem allows
  1187.   * in end-to-end delay between client and server.
  1188.   *
  1189.   * The generic calculation for max_ee_jitter is
  1190.   * (if x is the number of bytes required for a single
  1191.   * data unit (e.g. # of bytes for a frame of video)
  1192.   * then jitter = ( streaming buffer size - x ) /
  1193.   * max. transfer rate.
  1194.   *
  1195.   *-----------------------------------------------------*/
  1196.  
  1197.  
  1198.   CustomQOS.QOSItem[0].lQOSParmId  = MAX_EE_JITTER;
  1199.   CustomQOS.QOSItem[0].lQOSValue   = ( pInstance->StreamInfo.spcb.ulBufSize - 0 ) /
  1200.                               ( pInstance->ulAverageBytesPerSec / 1000 );
  1201.  
  1202.   /*-------------------------------------------
  1203.   * The following parameters (max_data_rate
  1204.   * and avg_data_rate) are the same for digital
  1205.   * audio.  However, this may differ on a case
  1206.   * by case basis for other MCD's.
  1207.   *
  1208.   * The calculation for avg. bytes per sec is
  1209.   * done in GetAudioHeader in audiosub.c
  1210.   *-------------------------------------------*/
  1211.  
  1212.   CustomQOS.QOSItem[1].lQOSParmId  = MAX_DATA_RATE;
  1213.   CustomQOS.QOSItem[1].lQOSValue    = pInstance->ulAverageBytesPerSec;
  1214.  
  1215.   CustomQOS.QOSItem[2].lQOSParmId  = AVG_DATA_RATE;
  1216.   CustomQOS.QOSItem[2].lQOSValue    = pInstance->ulAverageBytesPerSec;;
  1217.  
  1218.   /* Tell the network io proc that we are about to start streaming */
  1219.  
  1220.   rc = mmioSendMessage( pInstance->hmmio,
  1221.                         MMIOM_BEGINSTREAM,
  1222.                         ( LONG ) lStreamDirection,
  1223.                         ( LONG ) &CustomQOS );
  1224.  
  1225.  
  1226.  
  1227.   return ( rc );
  1228.  
  1229. } /* BeginQualityofService */
  1230.  
  1231.  
  1232. /********************* START OF SPECIFICATIONS *********************
  1233. *
  1234. * SUBROUTINE NAME: EndQualityofService
  1235. *
  1236. * FUNCTION: Some OS/2 networks have specific IO procs which can
  1237. *           manage network traffic.  We will use the mmio messages
  1238. *           begin_stream and end_stream to inform these io procs
  1239. *           that we wish to stream across the network.
  1240. *
  1241. * NOTES:
  1242. *
  1243. * ENTRY POINTS:
  1244. *
  1245. * INPUT: FUNCTION_PARM_BLOCK
  1246. *
  1247. * EXIT-NORMAL: MCIERR_SUCCESS
  1248. *
  1249. * EXIT_ERROR:
  1250. *
  1251. * EFFECTS:
  1252. *
  1253. * EXTERNAL REFERENCES: mmioSendMessage()    - MMIO function
  1254. *
  1255. *********************** END OF SPECIFICATIONS **********************/
  1256.  
  1257. ULONG   EndQualityofService ( INSTANCE      *pInstance )
  1258.  
  1259. {
  1260. LONG         rc;
  1261.  
  1262.   rc = mmioSendMessage( pInstance->hmmio,
  1263.                         MMIOM_ENDSTREAM,
  1264.                         0,
  1265.                         0 );
  1266.  
  1267.   return ( rc );
  1268.  
  1269. } /* EndQualityofService */
  1270.  
  1271.  
  1272. //#ifdef PTRFIX
  1273. //
  1274. ///********************* START OF SPECIFICATIONS *********************
  1275. //*
  1276. //* SUBROUTINE NAME: DataTranslation
  1277. //*
  1278. //* FUNCTION: Some audio devices cannot support specific file formats
  1279. //*           (i.e. 16-bit on a SoundBlaster).  If the device cannot
  1280. //*           do the compression itself, ask the io proc we are
  1281. //*           connected to to decompress.
  1282. //*
  1283. //* NOTES:
  1284. //*
  1285. //* ENTRY POINTS:
  1286. //*
  1287. //* INPUT: FUNCTION_PARM_BLOCK
  1288. //*
  1289. //* EXIT-NORMAL: MCIERR_SUCCESS
  1290. //*
  1291. //* EXIT_ERROR:
  1292. //*
  1293. //* EFFECTS:
  1294. //*
  1295. //* EXTERNAL REFERENCES: mmioSendMessage()    - MMIO function
  1296. //*
  1297. //*********************** END OF SPECIFICATIONS **********************/
  1298. //
  1299. //ULONG   DataTranslation( INSTANCE      *pInstance )
  1300. //
  1301. //{
  1302. //LONG         rc;
  1303. //
  1304. //
  1305. //  rc = mmioSendMessage( pInstance->hmmio,
  1306. //                        MMIOM_TRANSLATETYPE,
  1307. //                        ( LONG ) &pInstance->mmAudioHeader,
  1308. //                        ( LONG ) pInstance->ulRealTimeTranslation );
  1309. //
  1310. //  if ( rc )
  1311. //     {
  1312. //     return (rc);
  1313. //     }
  1314. //
  1315. //  rc = GetAudioHeader( pInstance );
  1316. //
  1317. //  return ( rc );
  1318. //
  1319. //} /* EndQualityofService */
  1320. //
  1321. //#endif
  1322.