home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / mm / admct / strmsubs.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  51KB  |  1,737 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. *         8. How to install Spi Protocols for speed purposes.
  23. *
  24. *    DEPENDENCIES: NONE
  25. *    RESTRICTIONS: NONE
  26. *
  27. * FUNCTIONS: CloseFile
  28. *            StopStream
  29. *            GetNotifyAbortAccess
  30. *            DestroySetStream
  31. *            AbortInProgressNotify
  32. *            PrepareAndCreateStream
  33. *            ProcessFromToFlags
  34. *            EnableEvents
  35. *            QualityofService
  36. *            InstallProtocol
  37. *
  38. *********************** END OF SPECIFICATIONS ********************************/
  39. #define INCL_BASE
  40. #define INCL_DOSMODULEMGR
  41. #define INCL_DOSSEMAPHORES
  42. #define INCL_MMIO_CODEC
  43. #define INCL_AUDIO_CODEC_ONLY
  44.  
  45. #include <os2.h>                        // OS2 defines.
  46. #include <string.h>                     // String functions.
  47. #include <os2medef.h>                   // MME includes files.
  48. #include <math.h>                       // Standard Math Lib
  49. #include <stdlib.h>                     // Standard Library
  50. #include <ssm.h>                        // SSM spi includes.
  51. #include <meerror.h>                    // MM Error Messages.
  52. #include <mmioos2.h>                    // MMIO Include.
  53. #include <mcios2.h>                     // MM System Include.
  54. #include <mmdrvos2.h>                   // MCI Driver include.
  55. #include <mcd.h>                        // AudioIFDriverInterface.
  56. #include <hhpheap.h>                    // Heap Manager Definitions
  57. #include <qos.h>
  58. #include <audiomcd.h>                   // Component Definitions.
  59. #include <admcfunc.h>
  60.  
  61. // CODEC stuff
  62. #include <codec.h>
  63.  
  64.  
  65.  
  66.  
  67.  
  68. /********************* START OF SPECIFICATIONS *********************
  69. *
  70. * SUBROUTINE NAME: GetNotifyAbortAccess
  71. *
  72. * DESCRIPTIVE NAME:
  73. *
  74. * FUNCTION:     Allows functions to obtain access to abort notifications
  75. *
  76. * NOTES:
  77. *
  78. * INPUT:
  79. *
  80. * EXIT-NORMAL:  NO_ERROR
  81. *
  82. * EXIT_ERROR:
  83. *
  84. *********************** END OF SPECIFICATIONS *********************************/
  85.  
  86. void  GetNotifyAbortAccess ( INSTANCE *ulpInstance,
  87.                              PULONG   pulAbortNotify )
  88.  
  89. {
  90. ULONG   ulCount;
  91.  
  92.   /****************************************************
  93.   * This semaphore controls whether or not it is safe
  94.   * to abort a previous notify thread.
  95.   * If the thread is in a critical section, it will have
  96.   * access to this semaphore and we will wait till it
  97.   * completes.
  98.   ****************************************************/
  99.  
  100.   DosRequestMutexSem( ulpInstance->hmtxNotifyAccess, -1 );
  101.  
  102.   /****************************************************
  103.   * The fNotifyPending boolean indicates whether or not
  104.   * a command is currently in progress (i.e. a play notify
  105.   * was done before the current command).   If there is
  106.   * a command in progress, set a few flags and let the
  107.   * caller know that they must abort the in progress
  108.   * operation.
  109.   ********************************************************/
  110.  
  111.   /* investigate--change this usNotifyPending to fNotifyPending */
  112.  
  113.   if (ulpInstance->usNotifyPending == TRUE)
  114.      {
  115.      ulpInstance->ulNotifyAborted = TRUE;
  116.      ulpInstance->usNotifyPending = FALSE;
  117.      *pulAbortNotify = TRUE;
  118.      DosResetEventSem ( ulpInstance->hThreadSem, &ulCount);
  119.      }
  120.  
  121.   DosReleaseMutexSem( ulpInstance->hmtxNotifyAccess );
  122.  
  123.  
  124. } /* GetNotifyAbortAccess */
  125.  
  126. /********************* START OF SPECIFICATIONS *********************
  127. *
  128. * SUBROUTINE NAME: DestroySetSream
  129. *
  130. * DESCRIPTIVE NAME: Destroys a stream because a set has made it invalid
  131. *
  132. * FUNCTION:     Since sets to a created stream cannot be communicated
  133.                 to a stream handler, then stream must be destroyed
  134.                 and created anew.
  135. *
  136. * NOTES:
  137. *
  138. * INPUT:
  139. *
  140. * EXIT-NORMAL:  NO_ERROR
  141. *
  142. * EXIT_ERROR:
  143. *
  144. *********************** END OF SPECIFICATIONS *********************************/
  145.  
  146. void DestroySetStream ( INSTANCE     *ulpInstance )
  147.  
  148. {
  149.    /***********************************************
  150.    * If a set was performed on an existing stream,
  151.    * destroy the stream and get new spcb keys
  152.    ***********************************************/
  153.  
  154.    if ( STRMSTATE == STREAM_SET_STATE )
  155.      {
  156. // CONNECTOR FEATURE--CONCB only needs to be updated or reassociated
  157. #ifndef CONNECTION
  158.      DestroyStream ( ulpInstance );
  159. #endif
  160. // CONNECTOR FEATURE--CONCB only needs to be updated or reassociated
  161.  
  162.      ulpInstance->ulCreateFlag = CREATE_STATE;
  163.  
  164.      }
  165.  
  166.    return;
  167.  
  168. } /* DestorySetStream */
  169.  
  170.  
  171. /********************* START OF SPECIFICATIONS *********************
  172. *
  173. * SUBROUTINE NAME: AbortInProgressNotify
  174. *
  175. * DESCRIPTIVE NAME: Stops a notify which was already in progress
  176. *
  177. * FUNCTION: Stops save, record and playback notifies
  178. *
  179. * NOTES:
  180. *
  181. * ENTRY POINTS:
  182. *
  183. * INPUT: INSTANCE pointer
  184. *        ULONG ulMessage -- either MCI_RECORD or MCI_PLAY
  185. *        ULONG ulParam1
  186. *
  187. *
  188. * EXIT-NORMAL: Return Code 0.
  189. *
  190. * EXIT_ERROR:
  191. *
  192. * EFFECTS:
  193. *
  194. * INTERNAL REFERENCES: MCIERR ().
  195. *
  196. * EXTERNAL REFERENCES: spiStopStream()    - SSM Spi
  197. *
  198. *********************** END OF SPECIFICATIONS **********************/
  199.  
  200. ULONG AbortInProgressNotify( INSTANCE             *ulpInstance,
  201.                              FUNCTION_PARM_BLOCK  *pFuncBlock,
  202.                              ULONG                ulParam1,
  203.                              ULONG                ulMessage )
  204.  
  205. {
  206.    USHORT usAbortType;
  207.    HWND   hwndHoldHandle;
  208.  
  209.    /***************************************************
  210.    * Here is how an MCD should interrupt an
  211.    * operation which was in progress. If the
  212.    * currently active operation is the same as the
  213.    * new operation, then we should post a
  214.    * superceded message (e.g. if a play interrupts
  215.    * a play, a "Play superceded" should be posted.
  216.    * If a play interrupts a record, then an
  217.    * aborted message should be posted (i.e. "record
  218.    * aborted".
  219.    ***************************************************/
  220.  
  221.    /***************************************************
  222.    * Are we interrupting the same operation (i.e. play
  223.    * interrupting a play)?
  224.    ****************************************************/
  225.  
  226.    if ( ulpInstance->usNotPendingMsg == MCI_SAVE )
  227.        {
  228.        /***********************************
  229.        * Can't interrupt a save because data
  230.        * can be lost
  231.        ************************************/
  232.  
  233.        DosWaitEventSem( ulpInstance->hThreadSem, (ULONG ) -1 );
  234.  
  235.        }
  236.  
  237.     else
  238.       {
  239.  
  240.       /* Stop the pending thread */
  241.  
  242.       ThreadedStop ( ulpInstance );
  243.  
  244.  
  245.       if ( ulpInstance->usNotPendingMsg == ulMessage &&
  246.            !ulpInstance->fFakeNotify                 &&
  247.            (ulParam1 & MCI_NOTIFY) )
  248.          {
  249.          /************************************************
  250.          * If the new operation is a notify, then we are
  251.          * superceded.  If not, then it is aborted.
  252.          ************************************************/
  253.  
  254.          usAbortType = MCI_NOTIFY_SUPERSEDED;
  255.          }   /* Case of a Play Superseeding a Play */
  256.  
  257.       else
  258.          {
  259.          /************************************************
  260.          * If the new operation is a notify, then we are
  261.          * superceded.  If not, then it is aborted.
  262.          ************************************************/
  263.  
  264.          usAbortType = MCI_NOTIFY_ABORTED;
  265.  
  266.          /*****************************************
  267.          * Before we destroy the stream determine
  268.          * where we were
  269.          *****************************************/
  270.  
  271.          GetOldStreamPosition( ulpInstance );
  272.  
  273. #ifndef CONNECTION
  274.          DestroyStream ( ulpInstance );
  275. #endif
  276.          ulpInstance->ulCreateFlag = PLAY_STREAM;
  277.  
  278.          } /* if we are aborting a different command */
  279.  
  280.  
  281.        /*---------------------------------------------
  282.        * If we are aborting a command, ensure that
  283.        * we notify it on the correct callback handle
  284.        *---------------------------------------------*/
  285.        hwndHoldHandle = ulpInstance->hwndCallBack;
  286.  
  287.        if ( ulParam1 & MCI_NOTIFY )
  288.           {
  289.           ulpInstance->hwndCallBack = ulpInstance->hwndOldCallBack;
  290.           }
  291.  
  292.        /*---------------------------------------------
  293.        * Inform the caller that the previous command
  294.        * has be officially terminated.
  295.        *---------------------------------------------*/
  296.  
  297.  
  298.        PostMDMMessage ( usAbortType,
  299.                         ulpInstance->usNotPendingMsg ,
  300.                         pFuncBlock);
  301.  
  302.  
  303.        /*---------------------------------------------
  304.        * now ensure that we will notify the caller
  305.        * on the correct window handle.
  306.        *---------------------------------------------*/
  307.  
  308.        ulpInstance->hwndCallBack = hwndHoldHandle;
  309.  
  310.  
  311.        if (ulParam1 & MCI_NOTIFY)
  312.            ulpInstance->usUserParm = pFuncBlock->usUserParm;
  313.  
  314.  
  315.  
  316.       } /* else save is not pending */
  317.  
  318.   return ( MCIERR_SUCCESS );
  319.  
  320. } /* AbortInProgressNotify */
  321.  
  322.  
  323. /********************* START OF SPECIFICATIONS *********************
  324. *
  325. * SUBROUTINE NAME: GetOldStreamPosition
  326. *
  327. * DESCRIPTIVE NAME: Remembers current position in the stream.
  328. *
  329. * FUNCTION:
  330. *
  331. * NOTES:
  332. *
  333. * ENTRY POINTS:
  334. *
  335. * INPUT: INSTANCE ptr
  336. *        ULONG ulMessage -- either MCI_RECORD or MCI_PLAY
  337. *
  338. * EXIT-NORMAL: Return Code 0.
  339. *
  340. * EXIT_ERROR:
  341. *
  342. * NOTES: This function remembers our position in the stream when
  343. *        the caller switches between play and record streams.  This
  344. *        allows the user to pick up at the same position.
  345. *
  346. * INTERNAL REFERENCES:
  347. *
  348. * EXTERNAL REFERENCES: SpiGetTime
  349. *
  350. *********************** END OF SPECIFICATIONS **********************/
  351.  
  352.  
  353. ULONG GetOldStreamPosition( INSTANCE *ulpInstance )
  354.  
  355. {
  356.   ULONG ulrc = MCIERR_SUCCESS;
  357.  
  358.   if ( !ulpInstance->ulOldStreamPos )
  359.      {
  360.      ulrc = SpiGetTime( STREAM.hStream,
  361.                         ( PMMTIME ) &ulpInstance->ulOldStreamPos );
  362.  
  363.      /**********************************************
  364.      * if an error occurred, then don't remember our
  365.      * position in the stream.
  366.      ***********************************************/
  367.  
  368.      if ( ulrc )
  369.        {
  370.        ulpInstance->ulOldStreamPos = 0;
  371.        }
  372.      } /* if we have no old stream position. */
  373.  
  374.      return ( MCIERR_SUCCESS );
  375.  
  376. } /* GetOldStreamPosition */
  377.  
  378.  
  379. // CONNECTION FEATURE--should there be an init (i.e. a create and then a
  380. // start?????????
  381. // without this--there
  382.  
  383. /********************* START OF SPECIFICATIONS *********************
  384. *
  385. * SUBROUTINE NAME: PrepareAndCreateStream
  386. *
  387. * DESCRIPTIVE NAME: Does work to create a stream
  388. *
  389. * FUNCTION: Inits variables and creates a stream
  390. *           Boolean determines whether card must be set up also.
  391. *
  392. * NOTES:
  393. *
  394. * ENTRY POINTS:
  395. *
  396. * INPUT: INSTANCE ptr
  397. *        ULONG ulMessage -- either MCI_RECORD or MCI_PLAY
  398. *
  399. * EXIT-NORMAL: Return Code 0.
  400. *
  401. * EXIT_ERROR:
  402. *
  403. * EFFECTS:
  404. *
  405. * INTERNAL REFERENCES: MCIERR ().
  406. *
  407. * EXTERNAL REFERENCES: spiCreateStream()    - SSM Spi
  408. *
  409. *********************** END OF SPECIFICATIONS **********************/
  410.  
  411. ULONG PrepareAndCreateStream( INSTANCE *ulpInstance,
  412.                               ULONG    ulDirection,  // CONNECTION feature--can remove
  413.                               BOOL     fSetUpCard ) // 6421 may have removed need for fsetup
  414.  
  415.  
  416. {
  417.     ULONG               ulrc = MCIERR_SUCCESS;   // return codes
  418. //    ULONG               ulAssocFlag = FALSE;     // stream association flag
  419. //    ULONG               ulStreamDirection;
  420.  
  421.     CONCB      concb;
  422.  
  423.     /* If we reach this point, we know we are connected */
  424.  
  425. // CONNECTOR FEATURE--is this if necessary --can we be called outside this state????
  426.      if (ulpInstance->ulCreateFlag != PREROLL_STATE)
  427.         {
  428.  
  429. //        if (ulpInstance->ulOperation == MCIDRV_OUTPUT )
  430. //           {
  431. //           ulStreamDirection = MCIDRV_START_PLAYBACK;
  432. //           }
  433. //        else
  434. //           {
  435. //           ulStreamDirection = MCIDRV_START_RECORD;
  436. //           }
  437.  
  438.         /************************************************************
  439.         * Determine which type of stream we will have to associate
  440.         * Playlists will associate the memory stream handler,
  441.         * and non-playlists will use the file system SH.
  442.         *************************************************************/
  443. //        if (ulpInstance->usPlayLstStrm == TRUE)
  444. //           {
  445. //           ulAssocFlag = TRUE;
  446. //           }
  447. //        else
  448. //           {
  449. //
  450. //           /******************************************************
  451. //           * Set a flag to indicate which direction the stream
  452. //           * handlers should go (e.g. play and record streams
  453. //           * go in different directions.
  454. //           ******************************************************/
  455. //
  456. //           if ( ulOperation == MCIDRV_INPUT )
  457. //              {
  458. //              ulAssocFlag = RECORD_STREAM;
  459. //              }
  460. //           else
  461. //              {
  462. //              ulAssocFlag = PLAY_STREAM;
  463. //              }
  464. //          }
  465.  
  466. // FEATURE --6421--Connectors
  467.             /*------------------------------------------------
  468.             * Rather than sending the set command to the VSD
  469.             * we will do an MCI_CONNECTION message and pass the
  470.             * streaming SPCB.
  471.             *
  472.             * Also, stream creation will be removed--its done
  473.             * by the mciConnection.
  474.             *------------------------------------------------*/
  475. // FEATURE --6421--Connectors
  476.  
  477.  
  478.          /********************************************
  479.          * Tell the amp mixer that we are about to
  480.          * switch to the desired operation
  481.          *********************************************/
  482.  
  483. //       AMPMIX.ulOperation = ulOperation;
  484.  
  485.          /* Note--using instance variable rather than amp instance --6421 */
  486.  
  487. // CONNECTION FEATURE--is this really necessary????
  488.  
  489.          ulpInstance->ulOperation = ulDirection;
  490.  
  491. // 6421 may have eliminated the need for this variable
  492. // also--amp will take care of re-initing the device.
  493.  
  494. //debug hack--remove!!!!!!
  495. #ifndef CONNECTION
  496.          if ( fSetUpCard )
  497.             {
  498.             /*************************************************
  499.             * Always Reinit The Device before stream creation.
  500.             *************************************************/
  501.  
  502.  
  503. //            VSDInstToWaveSetParms (&SetParms, ulpInstance);
  504.  
  505.             ulrc = ModifyConnection( ulpInstance );
  506.  
  507.             if ( ulrc )
  508.                {
  509.                return ( ulrc );
  510.                }
  511.  
  512.  
  513.             } /* If the card must be inited */
  514. #endif
  515.          /*************************************************
  516.          * If the init caused a new global sys file, use it
  517.          *************************************************/
  518. // 6421 -- removed the need for this function.
  519.  
  520. //         STREAM.AudioDCB.ulSysFileNum = AMPMIX.ulGlobalFile;
  521.  
  522.  
  523. // 6421-- MUCH simpler.
  524.  
  525. //         if ( ulOperation == MCIDRV_CONNECT_TARGET )
  526. //            {
  527. //
  528. //            ulrc = CreateNAssocStream ( STREAM.hidBSource,
  529. //                                        STREAM.hidATarget,
  530. //                                        &STREAM.hStream,
  531. //                                        ulpInstance,
  532. //                                        ulAssocFlag,
  533. //                                        (PEVFN)RecordEventRoutine );
  534. //
  535. //            }
  536. //         else
  537. //            {
  538. //            /********************************************
  539. //            * Create and associate a playback stream
  540. //            * This stream has the audio stream handler
  541. //            * as the source stream handler and file
  542. //            * system stream handler as the target.
  543. //            *********************************************/
  544. //
  545. //            ulrc = CreateNAssocStream ( STREAM.hidASource,
  546. //                                        STREAM.hidBTarget,
  547. //                                        &STREAM.hStream,
  548. //                                        ulpInstance,
  549. //                                        ulAssocFlag,
  550. //                                        (PEVFN) PlayEventRoutine );
  551. //            }
  552.  
  553. // CONNECTOR FEATURE--must fill in concb????
  554.          /*---------------------------------------------
  555.          * Inform the other MCDs (if any) of the direction
  556.          * i.e. source/target and media header we will
  557.          * be using.
  558.          *---------------------------------------------*/
  559.          concb.pMediaHeader = (PVOID) &ulpInstance->mmAudioHeader;
  560.  
  561.  
  562.          ReleaseStreamingSemaphore(ulpInstance);
  563. #ifndef CONNECTION
  564.          /********************************************
  565.          * Create and associate a playback stream
  566.          * This stream has the file system as the
  567.          * source stream handler and audio stream
  568.          * handler as the target.
  569.          *********************************************/
  570.             ulrc = CreateStream ( ulpInstance );
  571.  
  572. #else
  573.  
  574.          /*----------------------------------------------
  575.          * When we perform this command, it is possible
  576.          * that we could receive an ASSOCIATE.  Release
  577.          * the semaphore so a hang does not occur.
  578.          *-----------------------------------------------*/
  579.          MCD_ExitCrit( ulpInstance );
  580.  
  581.          if ( fSetUpCard )
  582.             {
  583.             ulrc = mciSendCommand ( ulpInstance->usWaveDeviceID,
  584.                                     MCIDRV_MODIFY_CONNECTION,
  585.                                     ulDirection,
  586.                                     &concb,
  587.                                     0 );
  588.             }
  589.          if ( !ulrc )
  590.             {
  591.             ulrc = mciSendCommand ( ulpInstance->usWaveDeviceID,
  592.                                     MCIDRV_INIT_CONNECTION,
  593.                                     ( ulpInstance->ulOperation == MCIDRV_OUTPUT )
  594.                                      ? MCIDRV_START_PLAYBACK : MCIDRV_START_RECORD,
  595.                                     0L,
  596.                                     0 );
  597.  
  598.  
  599.             }
  600.          /* Reacquire the main semaphore */
  601.  
  602.          MCD_EnterCrit( ulpInstance );
  603. #endif
  604.          GetStreamingSemaphore( ulpInstance );
  605.  
  606.  
  607.          if (ulrc)
  608.              return ulrc;
  609.  
  610.          /*****************************************************
  611.          * In case of playlist do the associate seperately
  612.          * Playlists associate the playlist with the memory
  613.          * stream handlers.
  614.          ******************************************************/
  615.  
  616. //         if ( ulAssocFlag )
  617. //            {
  618.  
  619. // 6421--reduce ifs--
  620. //            ulAssocFlag = ulOperation;
  621.  
  622. //            if ( ulOperation == MCIDRV_CONNECT_TARGET )
  623. //              {
  624. //              ulAssocFlag = RECORD_STREAM;
  625. //              }
  626. //            else
  627. //              {
  628. //             ulAssocFlag = PLAY_STREAM;
  629. //              }
  630.  
  631. // 6421--make one parameter
  632.  
  633. //            ulrc = AssociatePlayList ( ulpInstance );
  634. //
  635. //            }
  636.  
  637.  
  638.         } /* Play/Record Cue Stream */
  639.  
  640.     return ( ulrc );
  641.  
  642.  
  643. } /* PrepareAndCreateStream */
  644.  
  645.  
  646.  
  647.  
  648. /********************* START OF SPECIFICATIONS *********************
  649. *
  650. * SUBROUTINE NAME: RememberStreamState
  651. *
  652. * DESCRIPTIVE NAME: remembers cuepoints + position accross streams
  653. *
  654. * FUNCTION: After a stream has been destroyed, this function will
  655. *           set the new one up so that position advises, cue points
  656. *           and stream position will be just like the old one.
  657. *
  658. * NOTES:
  659. *
  660. * ENTRY POINTS:
  661. *
  662. * INPUT: INSTANCE ptr
  663. *        ULONG ulMessage -- either MCI_RECORD or MCI_PLAY
  664. *
  665. * EXIT-NORMAL: Return Code 0.
  666. *
  667. * EXIT_ERROR:
  668. *
  669. * EFFECTS:
  670. *
  671. * INTERNAL REFERENCES: MCIERR ().
  672. *
  673. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  674. *
  675. *********************** END OF SPECIFICATIONS **********************/
  676.  
  677. ULONG RememberStreamState( INSTANCE  *ulpInstance,
  678.                            ULONG     ulParam1,
  679.                            BOOL      fSeekNeeded )
  680.  
  681. {
  682.    ULONG ulrc = MCIERR_SUCCESS;
  683.  
  684.  
  685.    /*******************************************
  686.    * Stream is destroyed. Reset cuepopint and
  687.    * position advise flags to enabled state
  688.    * and send it down on the new stream
  689.    ********************************************/
  690.  
  691.    if (ulpInstance->usPosAdvise == EVENT_ENABLED)
  692.        ulpInstance->usPosAdvise = TRUE;
  693.  
  694.    if (ulpInstance->usCuePt == EVENT_ENABLED)
  695.        ulpInstance->usCuePt = TRUE;
  696.    /*---------------------------------------
  697.    * If we previously destroyed a stream,
  698.    * seek to the position where we were
  699.    * else just seek to 0
  700.    *--------------------------------------*/
  701.  
  702.    if ( !(ulParam1 & MCI_FROM ) && fSeekNeeded )
  703.       {
  704.       ulrc = ADMCSeekStream ( ulpInstance,
  705.                              SPI_SEEK_ABSOLUTE,
  706.                              ulpInstance->ulOldStreamPos );
  707.  
  708.       if (ulrc)
  709.         {
  710.  
  711.         /*-------------------------------------------------------------
  712.         * it is possible that the card may report a position that is
  713.         * greater than what is actually recorded, so work around this
  714.         * problem
  715.         *-------------------------------------------------------------*/
  716.  
  717.         if ( ulrc == ERROR_SEEK_PAST_END )
  718.            {
  719.            ulrc = ADMCSeekStream ( ulpInstance,
  720.                                  SPI_SEEK_FROMEND,
  721.                                  0 );
  722.  
  723.            if ( ulrc )
  724.               {
  725.               return ( ulrc );
  726.               }
  727.            }
  728.         else
  729.            {
  730.            return (ulrc);
  731.            }
  732.  
  733.         } /* if an error occurred */
  734.  
  735.       } /* if no from parameter */
  736.  
  737.  
  738.     ulpInstance->ulOldStreamPos = 0;
  739.  
  740.     /************************************
  741.     * place the stream in a stopped state
  742.     * since no activity has occurred
  743.     *************************************/
  744.  
  745.     STRMSTATE = MCI_STOP;
  746.  
  747.     return ( ulrc );
  748.  
  749.  
  750.  } /* RememberStreamState */
  751.  
  752.  
  753.  
  754.  
  755. /********************* START OF SPECIFICATIONS *********************
  756. *
  757. * SUBROUTINE NAME: ProcessFromToFlags
  758. *
  759. * DESCRIPTIVE NAME: Uses from to flags to ensure to place stream
  760. *
  761. * FUNCTION: Uses MCI_FROM flag to seek to the correct position and
  762. *           the MCI_TO to determine where to stop streaming.
  763. *           Note: with new SPI API this will no longer be needed
  764. *
  765. * NOTES:
  766. *
  767. * ENTRY POINTS:
  768. *
  769. * INPUT: FUNCTION_PARM_BLOCK
  770. *        INSTANCE *ptr
  771. *        ULONG    ulMessage -- either MCI_RECORD or MCI_PLAY
  772. *
  773. * EXIT-NORMAL: Return Code 0.
  774. *
  775. * EXIT_ERROR:
  776. *
  777. * EFFECTS:
  778. *
  779. * INTERNAL REFERENCES: MCIERR ().
  780. *
  781. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  782. *
  783. *********************** END OF SPECIFICATIONS **********************/
  784.  
  785. ULONG ProcessFromToFlags( FUNCTION_PARM_BLOCK  *pFuncBlock,
  786.                           INSTANCE             *ulpInstance,
  787.                           ULONG                ulOperation,
  788.                           ULONG                ulParam1 )
  789.  
  790.  
  791. {
  792.  
  793.    PMCI_PLAY_PARMS        pPlayParms;        // Msg Data Ptr
  794.    PMCI_RECORD_PARMS      pRecordParms;      // MCI Record Parms
  795.  
  796.  
  797.    ULONG                   ulConvertNumber;    // convert number to mmtime
  798.    ULONG                   ulrc = MCIERR_SUCCESS;
  799.    ULONG                   ulCount;            // Semphore counter
  800.  
  801.  
  802.    /***********************************
  803.    * Do a Seek to support FROM
  804.    ***********************************/
  805.  
  806.    if (ulParam1 & MCI_FROM)
  807.       {
  808.       if (STRMSTATE != MCI_STOP )
  809.         {
  810.         /**************************************
  811.         * Reset semaphore used to indicate when
  812.         * streaming event has occurred.
  813.         ****************************************/
  814.  
  815.         DosResetEventSem (ulpInstance->hEventSem, &ulCount);
  816.  
  817. // connector feature
  818.         ulrc = StopStream2( ulpInstance, MCIDRV_DISCARD_STREAM_NETWORK );
  819.  
  820.         /**************************************
  821.         * Stop the stream (discard buffers)
  822.         **************************************/
  823.  
  824. //        ulrc = SpiStopStream (STREAM.hStream, SPI_STOP_DISCARD);
  825. //
  826. //        if (!ulrc)
  827. //          {
  828. //          /*****************************************
  829. //          * Wait for the stream to be stopped
  830. //          *****************************************/
  831. //
  832. //          DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1);
  833. //         }
  834. // connector feature
  835.  
  836.         }
  837.  
  838.        /******************************************
  839.        * Convert the number that the user passed in
  840.        * (i.e. from samples) to mmtime so that we
  841.        * can seek to the point in the stream.
  842.        *******************************************/
  843.  
  844.  
  845.        if ( ulOperation == MCI_RECORD )
  846.           {
  847.           pRecordParms= (PMCI_RECORD_PARMS )pFuncBlock->ulParam2;
  848.  
  849.           ulrc = ConvertToMM ( ulpInstance,
  850.                                &ulConvertNumber,
  851.                                pRecordParms->ulFrom);
  852.           }
  853.        else
  854.           {
  855.           pPlayParms= (PMCI_PLAY_PARMS )pFuncBlock->ulParam2;
  856.  
  857.           ulrc = ConvertToMM ( ulpInstance,
  858.                                &ulConvertNumber,
  859.                                pPlayParms->ulFrom);
  860.           }
  861.  
  862.  
  863.         /*********************************
  864.         * Do the Seek Thing
  865.         **********************************/
  866.  
  867.         if ( !ulrc )
  868.            {
  869.            ulrc = ADMCSeekStream ( ulpInstance,
  870.                                   SPI_SEEK_ABSOLUTE,
  871.                                   ulConvertNumber);
  872.  
  873.            if ( ulrc )
  874.               {
  875.               return ( ulrc ) ;
  876.               }
  877.            }
  878.  
  879.       } /* Play From */
  880.  
  881.    /*************************************************
  882.    * If the caller specified a to position via
  883.    * MCI_TO, then convert the number to mm time
  884.    * (we do this because it simplifies the code,
  885.    * only dealing with one time base).  Then
  886.    * set a cue time pause event in the stream at
  887.    * the to point.  The streaming operation will
  888.    * proceed till the pause event, report the event
  889.    * and thus, it appears to the caller like we
  890.    * stopped right at the to spot.
  891.    *************************************************/
  892.  
  893.    if (ulParam1 & MCI_TO)
  894.       {
  895.       if ( ulOperation == MCI_RECORD )
  896.           {
  897.           pRecordParms= ( PMCI_RECORD_PARMS )pFuncBlock->ulParam2;
  898.  
  899.           ulrc = ConvertToMM ( ulpInstance,
  900.                                &ulConvertNumber,
  901.                                pRecordParms->ulTo );
  902.           }
  903.        else
  904.           {
  905.           pPlayParms= ( PMCI_PLAY_PARMS )pFuncBlock->ulParam2;
  906.  
  907.           ulrc = ConvertToMM ( ulpInstance,
  908.                                &ulConvertNumber,
  909.                                pPlayParms->ulTo );
  910.           }
  911.  
  912.        /* Place the cue time pause event in the stream */
  913.  
  914.        if ( !ulrc )
  915.           {
  916.           ulrc = CreateToEvent ( ulpInstance, ulConvertNumber );
  917.           }
  918.  
  919.        ulpInstance->fToEvent = TRUE;
  920.  
  921.       } // Of Play Till XXXX
  922.  
  923.  
  924.   return ( ulrc );
  925.  
  926. } /* ProcessFromToFlags */
  927.  
  928.  
  929.  
  930. /********************* START OF SPECIFICATIONS *********************
  931. *
  932. * SUBROUTINE NAME: EnableEvents
  933. *
  934. * DESCRIPTIVE NAME: enables cue points and position advises
  935. *
  936. * FUNCTION: For newly created streams, this will enable cue points
  937. *           and position advises which were sent to the previously
  938. *           destroyed stream (i.e. a play following a record).
  939. *
  940. * NOTES:
  941. *
  942. * ENTRY POINTS:
  943. *
  944. * INPUT:
  945. *
  946. * EXIT-NORMAL: Return Code 0.
  947. *
  948. * EXIT_ERROR:
  949. *
  950. * EFFECTS:
  951. *
  952. * INTERNAL REFERENCES: MCIERR ().
  953. *
  954. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  955. *
  956. *********************** END OF SPECIFICATIONS **********************/
  957.  
  958. ULONG EnableEvents( INSTANCE *ulpInstance )
  959.  
  960. {
  961.  
  962.    ULONG         ulrc = MCIERR_SUCCESS;
  963.    HID           hidEvents;     // SH which can detect events
  964. //  extern     HID                 hidBSource;
  965. //  extern     HID                 hidBTarget;
  966.  
  967.    MTIME_EVCB    *pMCuePtEVCB;  // pointer
  968.  
  969.   hidEvents = ulpInstance->hidAttached;
  970.  
  971. //   if ( ulpInstance->ulOperation == MCIDRV_INPUT )
  972. //      {
  973. //      hidEvents = hidBSource;
  974. //      }
  975. //   else
  976. //      {
  977. //      hidEvents = hidBTarget;
  978. //      }
  979.  
  980.    /***************************************
  981.    * Enable Position Advise if Needed
  982.    ****************************************/
  983.  
  984.  
  985.    if (ulpInstance->usPosAdvise == TRUE)
  986.       {
  987.  
  988.       /*********************************
  989.       * Correct The hStream Value
  990.       **********************************/
  991.       STREAM.PosAdvEvcb.evcb.hstream = STREAM.hStream;
  992.       STREAM.PosAdvEvcb.evcb.hid     = hidEvents;
  993.  
  994.       /**********************************************
  995.       * Stick our instance pointer in the time
  996.       * Event Control Block (EVCB).  This will allow
  997.       * the event procedure to access instance data
  998.       * (see PlayEventProc and RecordEventProc for
  999.       * more information).
  1000.       ***********************************************/
  1001.  
  1002.       STREAM.PosAdvEvcb.ulpInstance = (ULONG) ulpInstance;
  1003.  
  1004.       /**************************************************************
  1005.       * Update position advise cuepoints created in different stream
  1006.       **************************************************************/
  1007.  
  1008.       STREAM.PosAdvEvcb.evcb.mmtimeStream = STREAM.PosAdvEvcb.mmCuePt;
  1009.  
  1010.       ulrc = ADMCEnableEvent( (PEVCB) &(STREAM.PosAdvEvcb),
  1011.                              (PHEVENT) &(STREAM.hPosEvent));
  1012.  
  1013.       /* Set flag to indicate that the position advises were enabled */
  1014.  
  1015.       ulpInstance->usPosAdvise = EVENT_ENABLED;
  1016.  
  1017.       } /* if Positionadvise is true */
  1018.  
  1019.  
  1020.    /*******************************
  1021.    * Enable Cue points if any
  1022.    *******************************/
  1023.  
  1024.    if (!ulrc)
  1025.       {
  1026.       // toast this ushort business--use ulongs.
  1027.  
  1028.       if (ulpInstance->usCuePt == TRUE)
  1029.  
  1030.          {
  1031.          /*********************************
  1032.          * Get cue point linked list pointer
  1033.          ***********************************/
  1034.  
  1035.          pMCuePtEVCB = CUEPOINT;
  1036.  
  1037.  
  1038.          /***********************************************
  1039.          * The current MCD has a linked list of
  1040.          * cuepoints.   Proceed through the linked
  1041.          * list and enable each one in the stream.
  1042.          * Warning: just because the MCD supports
  1043.          * unlimited cuepoints, does not mean that the
  1044.          * stream handler does.
  1045.          ***********************************************/
  1046.  
  1047.          while ( pMCuePtEVCB )
  1048.            {
  1049.            pMCuePtEVCB->evcb.hstream = STREAM.hStream;
  1050.            pMCuePtEVCB->evcb.hid = hidEvents;
  1051.  
  1052.           /**********************************************
  1053.           * Stick our instance pointer in the time
  1054.           * Event Control Block (EVCB).  This will allow
  1055.           * the event procedure to access instance data
  1056.           * (see PlayEventProc and RecordEventProc for
  1057.           * more information).
  1058.           ***********************************************/
  1059.  
  1060.            pMCuePtEVCB->ulpInstance = (ULONG ) ulpInstance;
  1061.  
  1062.            /* Enable the cuepoints */
  1063.  
  1064.            ulrc = ADMCEnableEvent( (PEVCB) pMCuePtEVCB,
  1065.                                   (PHEVENT) &pMCuePtEVCB->HCuePtHndl );
  1066.  
  1067.            pMCuePtEVCB = pMCuePtEVCB->pNextEVCB;
  1068.  
  1069.            } /* while there are cuepoints to place in the stream */
  1070.  
  1071.  
  1072.          ulpInstance->usCuePt = EVENT_ENABLED;
  1073.  
  1074.          } /* There are CuePts to be enabled */
  1075.  
  1076.          /* Enable Status Level */
  1077.  
  1078. #ifdef STATUS_LEVEL
  1079.          if (ulpInstance->ulStatusLevelState != STATUS_LEVEL_OFF)
  1080.              {
  1081.  
  1082.              if (STREAM.hStatusLevelEvent)
  1083.                 {
  1084.                 SpiDisableEvent (STREAM.hStatusLevelEvent);
  1085.                 }
  1086.  
  1087.              STREAM.StatusLevelEvcb.pMCDInstance = (ULONG) ulpInstance;
  1088.              STREAM.StatusLevelEvcb.ulType = EVENT_STATUS_LEVEL;
  1089.              STREAM.StatusLevelEvcb.ulSubType = 0;
  1090.              STREAM.StatusLevelEvcb.hid = 0;
  1091.              STREAM.StatusLevelEvcb.hstream = STREAM.hStream;
  1092.  
  1093.              ulrc = SpiEnableEvent( (PEVCB) &(STREAM.StatusLevelEvcb),
  1094.                                     (PHEVENT) &(STREAM.hStatusLevelEvent));
  1095.  
  1096.             } /* Status level event is active */
  1097. #endif
  1098.  
  1099.       } /* if no return codes so far */
  1100.  
  1101.    return ( ulrc );
  1102.  
  1103. } /* EnableEvents */
  1104.  
  1105.  
  1106.  
  1107. /********************* START OF SPECIFICATIONS *********************
  1108. *
  1109. * SUBROUTINE NAME: StopStream2
  1110. *
  1111. * DESCRIPTIVE NAME: Stops a stream and waits for an event
  1112. *
  1113. * FUNCTION: Sets up semaphores, stops the stream and waits for the
  1114. *           event.
  1115. *
  1116. * NOTES:
  1117. *
  1118. * ENTRY POINTS:
  1119. *
  1120. * INPUT:
  1121. *
  1122. * EXIT-NORMAL: Return Code 0.
  1123. *
  1124. * EXIT_ERROR:
  1125. *
  1126. * EFFECTS:
  1127. *
  1128. * INTERNAL REFERENCES: MCIERR ().
  1129. *
  1130. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  1131. *
  1132. *********************** END OF SPECIFICATIONS **********************/
  1133.  
  1134.  
  1135. ULONG StopStream2( INSTANCE *ulpInstance,
  1136.                    ULONG    ulOperation )
  1137.  
  1138. {
  1139.    ULONG        ulCount;                // semaphore counter
  1140.    ULONG        ulSpiFlags;             // flags to use on the spi stop
  1141.    ULONG        ulrc = MCIERR_SUCCESS;  // return code
  1142.  
  1143.    /***************************************
  1144.    * Reset Internal semaphores
  1145.    ****************************************/
  1146.  
  1147.    DosResetEventSem ( ulpInstance->hEventSem, &ulCount);
  1148.    DosResetEventSem ( ulpInstance->hThreadSem, &ulCount);
  1149.  
  1150.    /********************************************
  1151.    * Do different stops based on the stream type
  1152.    * record streams must be flushed so that no
  1153.    * data will be lost, whereas playback streams
  1154.    * are not concerned with data loss since they
  1155.    * create no data.
  1156.    ********************************************/
  1157. // CONNECTOR FEATURE--why can't we just use ulOperation?????
  1158. // INVESTIGATE!!!!!!!!!!!!!!
  1159.  
  1160.  
  1161.    /**********************************
  1162.    * Stop Streaming
  1163.    **********************************/
  1164. // CONNECTOR FEATURE
  1165. #ifdef CONNECTION
  1166.    ulrc = mciSendCommand ( ulpInstance->usWaveDeviceID,
  1167.                            MCIDRV_STOP,  // ?????
  1168.                            ulSpiFlags,
  1169.                            0,
  1170.                            0 );
  1171. #else
  1172.    if ( ulOperation == MCIDRV_FLUSH_STREAM_NETWORK )
  1173.       {
  1174.       ulSpiFlags = SPI_STOP_FLUSH;
  1175.       }
  1176.    else
  1177.       {
  1178.       ulSpiFlags = SPI_STOP_DISCARD;
  1179.       }
  1180.  
  1181.    ulrc = SpiStopStream (STREAM.hStream, ulSpiFlags );
  1182. #endif
  1183. // CONNECTOR FEATURE
  1184.  
  1185.    if (!ulrc)
  1186.       {
  1187.       DosWaitEventSem (ulpInstance->hEventSem, (ULONG) -1 );
  1188.       }
  1189.  
  1190.    if ( ulrc == ERROR_STREAM_ALREADY_STOP )
  1191.       {
  1192.       ulrc = MCIERR_SUCCESS;
  1193.       }
  1194.  
  1195.    return ( ulrc );
  1196.  
  1197. } /* StopStream2 */
  1198.  
  1199.  
  1200.  
  1201.  
  1202. /********************* START OF SPECIFICATIONS *********************
  1203. *
  1204. * SUBROUTINE NAME: CloseFile
  1205. *
  1206. * DESCRIPTIVE NAME: Close a multimedia i/o file
  1207. *
  1208. * FUNCTION: Closes the file and if it was a temporary file which we
  1209. *           opened without saving it, ensure that it is deleted.  If
  1210. *           the file was opened via OPEN_MMIO, DO NOT close the file.
  1211. *
  1212. * NOTES:
  1213. *
  1214. * ENTRY POINTS:
  1215. *
  1216. * INPUT: FUNCTION_PARM_BLOCK
  1217. *
  1218. * EXIT-NORMAL: Return Code 0.
  1219. *
  1220. * EXIT_ERROR:
  1221. *
  1222. * EFFECTS:
  1223. *
  1224. * INTERNAL REFERENCES: MCIERR ().
  1225. *
  1226. * EXTERNAL REFERENCES: spiSeekStream()    - SSM Spi
  1227. *
  1228. *********************** END OF SPECIFICATIONS **********************/
  1229.  
  1230. ULONG CloseFile( INSTANCE *ulpInstance )
  1231.  
  1232.  
  1233. {
  1234.   ULONG ulrc = MCIERR_SUCCESS;
  1235.  
  1236.   /********************************************
  1237.   * If there is a file handle to close and
  1238.   * if the caller did not pass in the file
  1239.   * handle via OPEN_MMIO close the file.
  1240.   * If we close an open mmio handle, then
  1241.   * the application will not be able to use
  1242.   * it.
  1243.   ********************************************/
  1244.  
  1245.   if (ulpInstance->hmmio != 0 && !ulpInstance->fOpenMMIO )
  1246.      {
  1247.  
  1248.       ulrc = mmioClose (ulpInstance->hmmio, 0);
  1249.  
  1250.       /* If we created the temporary file and it wasn't saved--delete it */
  1251.  
  1252.       if ( ulpInstance->ulCreatedName )
  1253.          {
  1254.          DosDelete( ( PSZ ) ulpInstance->pszAudioFile );
  1255.          }
  1256.       /* Set flags to clear handle and ensure we don't delete the next temp file */
  1257.  
  1258.       ulpInstance->ulCreatedName = FALSE;
  1259.  
  1260.       ulpInstance->hmmio = 0;
  1261.  
  1262.      } /* hmmio not Null */
  1263.  
  1264.    return ( ulrc );
  1265.  
  1266. } /* CloseFile */
  1267.  
  1268.  
  1269.  
  1270. /********************* START OF SPECIFICATIONS *********************
  1271. *
  1272. * SUBROUTINE NAME: QualityofService
  1273. *
  1274. * FUNCTION: Some OS/2 networks have specific IO procs which can
  1275. *           manage network traffic.  We will use the mmio messages
  1276. *           begin_stream to inform these io procs
  1277. *           that we wish to stream across the network.
  1278. *
  1279. *           If you are writing a streaming MCD, it is advantageous
  1280. *           to use these messages since performance across LAN's
  1281. *           may be improved.
  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. ULONG   BeginQualityofService ( INSTANCE      *pInstance,
  1299.                                 LONG          lStreamDirection )
  1300.  
  1301. {
  1302.  
  1303. LONG         rc;
  1304. CUSTOM_QOS   CustomQOS;
  1305.  
  1306.  
  1307.   /* Currently, there are 4 parameters to QOS, this will increase */
  1308.  
  1309.   CustomQOS.QOSParms.lNumQOSParms = 4;
  1310.  
  1311.   /*---------------------------------------------------
  1312.   * The first parameter is the service request. It
  1313.   * can currently contain one of three values:
  1314.   *
  1315.   * A. GUARANTEED.  The MCD wants to know if the
  1316.   *    network can guarantee the traffic we need.
  1317.   *
  1318.   * B. DONTCARE.  We will ask for a certain level of
  1319.   *    support.  However, if it is unavailable, we
  1320.   *    can continue.
  1321.   *
  1322.   * C. DONTRESERVE. The MCD wants no guarantees about
  1323.   *    whether the network can support this transfer.
  1324.   *
  1325.   *----------------------------------------------------*/
  1326.   CustomQOS.QOSParms.QOSParms[0].lQOSParmId  = SERVICE_REQUEST;
  1327.   CustomQOS.QOSParms.QOSParms[0].lQOSValue    = pInstance->lQosValue;
  1328.  
  1329.   /*-------------------------------------------------
  1330.   * QOS needs to know the number of streaming
  1331.   * buffers SSM will be using.  A streaming MCD
  1332.   * can obtain this information via SpiGetProtocol.
  1333.   *-------------------------------------------------*/
  1334.  
  1335. //  pQOS->lQOSParmId  = NUM_STREAM_BUFFERS;
  1336. //  pQOS->lQOSValue    = pInstance->StreamInfo.spcb.ulMinBuf;
  1337. //  pQOS++;
  1338.  
  1339.  
  1340.   /*-----------------------------------------------------
  1341.   * MAX_EE_JITTER describes the allowable amount of
  1342.   * variation the streaming subsystem allows
  1343.   * in end-to-end delay between client and server.
  1344.   *
  1345.   * The generic calculation for max_ee_jitter is
  1346.   * (if x is the number of bytes required for a single
  1347.   * data unit (e.g. # of bytes for a frame of video)
  1348.   * then jitter = ( streaming buffer size - x ) /
  1349.   * max. transfer rate.
  1350.   *
  1351.   *-----------------------------------------------------*/
  1352.  
  1353.  
  1354.   CustomQOS.QOSItem[0].lQOSParmId  = MAX_EE_JITTER;
  1355.   if ( pInstance->ulAverageBytesPerSec && pInstance->ulAverageBytesPerSec > 1000 )
  1356.      {
  1357.      CustomQOS.QOSItem[0].lQOSValue   = ( pInstance->StreamInfo.spcb.ulBufSize - 0 ) /
  1358.                                  ( pInstance->ulAverageBytesPerSec / 1000 );
  1359.      }
  1360.   else
  1361.      {
  1362.      CustomQOS.QOSItem[0].lQOSValue   = 0;
  1363.      }
  1364.  
  1365.   /*-------------------------------------------
  1366.   * The following parameters (max_data_rate
  1367.   * and avg_data_rate) are the same for digital
  1368.   * audio.  However, this may differ on a case
  1369.   * by case basis for other MCD's.
  1370.   *
  1371.   * The calculation for avg. bytes per sec is
  1372.   * done in GetAudioHeader in audiosub.c
  1373.   *-------------------------------------------*/
  1374.  
  1375.   CustomQOS.QOSItem[1].lQOSParmId  = MAX_DATA_RATE;
  1376.   CustomQOS.QOSItem[1].lQOSValue    = pInstance->ulAverageBytesPerSec;
  1377.  
  1378.   CustomQOS.QOSItem[2].lQOSParmId  = AVG_DATA_RATE;
  1379.   CustomQOS.QOSItem[2].lQOSValue    = pInstance->ulAverageBytesPerSec;;
  1380.  
  1381.   /* Tell the network io proc that we are about to start streaming */
  1382.  
  1383.   rc = mmioSendMessage( pInstance->hmmio,
  1384.                         MMIOM_BEGINSTREAM,
  1385.                         ( LONG ) lStreamDirection,
  1386.                         ( LONG ) &CustomQOS );
  1387.  
  1388.  
  1389.  
  1390.   return ( rc );
  1391.  
  1392. } /* BeginQualityofService */
  1393.  
  1394.  
  1395. /********************* START OF SPECIFICATIONS *********************
  1396. *
  1397. * SUBROUTINE NAME: EndQualityofService
  1398. *
  1399. * FUNCTION: Some OS/2 networks have specific IO procs which can
  1400. *           manage network traffic.  We will use the mmio messages
  1401. *           begin_stream and end_stream to inform these io procs
  1402. *           that we wish to stream across the network.
  1403. *
  1404. * NOTES:
  1405. *
  1406. * ENTRY POINTS:
  1407. *
  1408. * INPUT: FUNCTION_PARM_BLOCK
  1409. *
  1410. * EXIT-NORMAL: MCIERR_SUCCESS
  1411. *
  1412. * EXIT_ERROR:
  1413. *
  1414. * EFFECTS:
  1415. *
  1416. * EXTERNAL REFERENCES: mmioSendMessage()    - MMIO function
  1417. *
  1418. *********************** END OF SPECIFICATIONS **********************/
  1419.  
  1420. ULONG   EndQualityofService ( INSTANCE      *pInstance )
  1421.  
  1422. {
  1423. LONG         rc;
  1424.  
  1425.   rc = mmioSendMessage( pInstance->hmmio,
  1426.                         MMIOM_ENDSTREAM,
  1427.                         0,
  1428.                         0 );
  1429.  
  1430.   return ( rc );
  1431.  
  1432. } /* EndQualityofService */
  1433.  
  1434.  
  1435. /********************* START OF SPECIFICATIONS *********************
  1436. *
  1437. * SUBROUTINE NAME: InstallProtocol
  1438. *
  1439. * FUNCTION: For situations such as system sounds or playback of
  1440. *           very small wave files, ssm will still allocate large
  1441. *           number of buffers.  However, since we are potentially
  1442. *           playing a very small wave file, there is no need to
  1443. *           allocate such large quantities of memory.  Therefore
  1444. *           this routine will check the size of the file and
  1445. *           determine the minimum number of buffers necessary to
  1446. *           play the file.
  1447. *
  1448. * NOTES:
  1449. *
  1450. * ENTRY POINTS:
  1451. *
  1452. * INPUT: FUNCTION_PARM_BLOCK
  1453. *
  1454. * EXIT-NORMAL: MCIERR_SUCCESS
  1455. *
  1456. * EXIT_ERROR:
  1457. *
  1458. * EFFECTS:
  1459. *
  1460. * EXTERNAL REFERENCES: mmioSendMessage()    - MMIO function
  1461. *
  1462. *********************** END OF SPECIFICATIONS **********************/
  1463.  
  1464. ULONG   InstallProtocol( INSTANCE      *pInstance )
  1465.  
  1466. {
  1467.   ULONG      ulNumBuffersNeeded;  /* NumBuffers required for streaming */
  1468.   ULONG      ulrc = MCIERR_SUCCESS;
  1469.   extern     HID     hidBTarget;  /* Stream handler to install to */
  1470.  
  1471. //debug code
  1472. //  SPCBKEY   spcbkeys[100];
  1473. //  ULONG     ulNumKeys=100;
  1474. //end debug code
  1475.  
  1476.  
  1477.   /*-----------------------------------------------------
  1478.   * Determine the number of buffers required in order
  1479.   * to begin streaming.  Division of size of the file by
  1480.   * the buffer size used.
  1481.   * Add one to ensure that integer division round off
  1482.   * is accounted for.
  1483.   *-----------------------------------------------------*/
  1484.   ulNumBuffersNeeded = ( pInstance->ulDataSize / pInstance->StreamInfo.spcb.ulBufSize ) + 1;
  1485.  
  1486.   /*---------------------------------------
  1487.   * Our minimum request will be two buffers
  1488.   * to avoid streaming errors
  1489.   *-----------------------------------------*/
  1490.  
  1491.   if ( ulNumBuffersNeeded < 2 )
  1492.      {
  1493.      ulNumBuffersNeeded = 2;
  1494.      }
  1495.  
  1496.   /*----------------------------------------
  1497.   * Check to see if we require less
  1498.   * memory than what the ssm defaults to
  1499.   *---------------------------------------*/
  1500.  
  1501.   if ( ulNumBuffersNeeded < pInstance->StreamInfo.spcb.ulMinBuf ||
  1502.        ulNumBuffersNeeded < pInstance->StreamInfo.spcb.ulMaxBuf)
  1503.      {
  1504.      /* This key must be unique--therefore use our instance number */
  1505.  
  1506.      pInstance->StreamInfo.SpcbKey.ulIntKey = ( ULONG ) pInstance;
  1507.      pInstance->StreamInfo.spcb.spcbkey.ulIntKey  = ( ULONG ) pInstance;
  1508.  
  1509.      /*---------------------------------------------
  1510.      * Indicate to SSM that we want to a smaller
  1511.      * number of buffers allocated for this stream
  1512.      *---------------------------------------------*/
  1513.  
  1514.      if ( ulNumBuffersNeeded < pInstance->StreamInfo.spcb.ulMinBuf )
  1515.         {
  1516.         pInstance->StreamInfo.spcb.ulMinBuf   =
  1517.         pInstance->StreamInfo.spcb.ulTgtStart =
  1518.         pInstance->StreamInfo.spcb.ulMaxBuf   = ulNumBuffersNeeded;
  1519.         }
  1520.      else if ( ulNumBuffersNeeded < pInstance->StreamInfo.spcb.ulMaxBuf)
  1521.         {
  1522.         pInstance->StreamInfo.spcb.ulMaxBuf   = ulNumBuffersNeeded;
  1523.         }
  1524.      /* Install the protocol */
  1525.  
  1526. // debug code ONLY!!!!!!!
  1527.  
  1528.  
  1529.    /*----------------------------------------------------------------------
  1530.    -  enumerate handlers in the system
  1531.    ----------------------------------------------------------------------*/
  1532. //   ulrc = SpiEnumerateProtocols( hidBTarget,
  1533. //                                 &spcbkeys,
  1534. //                                 &ulNumKeys);
  1535.  
  1536.  
  1537.      ulrc = SpiInstallProtocol( hidBTarget,
  1538.                                 &pInstance->StreamInfo.SpcbKey,
  1539.                                 &pInstance->StreamInfo.spcb,
  1540.                                 SPI_INSTALL_PROTOCOL );
  1541.  
  1542.      /* The install failed--regress back to the default key */
  1543.  
  1544.      if ( ulrc )
  1545.         {
  1546.         pInstance->StreamInfo.SpcbKey.ulIntKey = 0;
  1547.         return ( ulrc );
  1548.         }
  1549.      else
  1550.         {
  1551. // debug code ONLY!!!!!!!
  1552.  
  1553.  
  1554.    /*----------------------------------------------------------------------
  1555.    -  enumerate handlers in the system
  1556.    ----------------------------------------------------------------------*/
  1557. //   ulrc = SpiEnumerateProtocols( hidBTarget,
  1558. //                                 &spcbkeys,
  1559. //                                 &ulNumKeys);
  1560.  
  1561.  
  1562.  
  1563.       /*------------------------------------------------------
  1564.       * Get certain streaming information from the stream handler
  1565.       * we have loaded.
  1566.       *--------------------------------------------------------*/
  1567.       ulrc = SpiGetProtocol( hidBTarget,
  1568.                              &pInstance->StreamInfo.SpcbKey,
  1569.                              &pInstance->StreamInfo.spcb );
  1570.  
  1571.       if ( ulrc )
  1572.          {
  1573.          return ( ulrc );
  1574.          }
  1575.  
  1576.  
  1577. // end debug code
  1578.         }
  1579.  
  1580.      pInstance->fInstalledProtocol = TRUE;
  1581.  
  1582.      } /* we can save memory by installing a new protocol */
  1583.   return ( ulrc ) ;
  1584.  
  1585. } /* EndQualityofService */
  1586.  
  1587. #ifndef CONNECTION
  1588.  
  1589. /********************* START OF SPECIFICATIONS *********************
  1590. *
  1591. * SUBROUTINE NAME: DataTranslation
  1592. *
  1593. * FUNCTION: Some audio devices cannot support specific file formats
  1594. *           (i.e. 16-bit on a SoundBlaster).  If the device cannot
  1595. *           do the compression itself, ask the io proc we are
  1596. *           connected to to decompress.
  1597. *
  1598. * NOTES:
  1599. *
  1600. * ENTRY POINTS:
  1601. *
  1602. * INPUT: FUNCTION_PARM_BLOCK
  1603. *
  1604. * EXIT-NORMAL: MCIERR_SUCCESS
  1605. *
  1606. * EXIT_ERROR:
  1607. *
  1608. * EFFECTS:
  1609. *
  1610. * EXTERNAL REFERENCES: mmioSendMessage()    - MMIO function
  1611. *
  1612. *********************** END OF SPECIFICATIONS **********************/
  1613.  
  1614. ULONG   DataTranslation( INSTANCE      *pInstance )
  1615.  
  1616. {
  1617.   LONG              rc;
  1618. //  REALTIME_XLATE    xlate;
  1619.  
  1620.   MMEXTENDINFO      mmExtInfo;
  1621.   PCODECOPEN        pcodecopen = (PCODECOPEN) pInstance->pcodecopen;
  1622.   CODECASSOC        codecAssoc;
  1623.   PCODECINIFILEINFO pcodecini;
  1624. //  ULONG             ulFlags;
  1625.   //MMAUDIOOPEN *pbufferinfo;
  1626.  
  1627.  
  1628.  
  1629. //  xlate.ulFlags = pInstance->ulRealTimeTranslation;
  1630.  
  1631.   mmExtInfo.ulStructLen = sizeof( MMEXTENDINFO );
  1632.   mmExtInfo.ulFlags = MMIO_CODEC_ASSOC;
  1633.  
  1634.   if ( pInstance->ulRealTimeTranslation ==MMIO_REALTIME )
  1635.      {
  1636.      mmExtInfo.ulFlags |= MMIO_REALTIME_CODEC;
  1637.      }
  1638.   else
  1639.      {
  1640.      /* Translation is unnecessary if the file is PCM */
  1641.  
  1642. // what was this code for????????
  1643.  
  1644. //     if ( pInstance->mmRealHeader.mmXWAVHeader.WAVEHeader.usFormatTag  ==
  1645. //           DATATYPE_WAVEFORM )
  1646.  
  1647.         return (MMIO_SUCCESS);
  1648.      }
  1649.  
  1650.   if ( !pcodecopen )
  1651.      {
  1652.      return ( MMIO_ERROR );
  1653.      }
  1654.  
  1655.   mmExtInfo.ulNumCODECs = 1;
  1656.   mmExtInfo.pCODECAssoc = &codecAssoc;
  1657.   codecAssoc.pCodecOpen = pcodecopen;
  1658.   if ( pInstance->ulCodecDescription & MAKE_SOURCE )
  1659.      {
  1660.      pcodecopen->pSrcHdr = ( PVOID ) &pInstance->mmRealHeader;
  1661.      pcodecopen->pDstHdr = ( PVOID ) &pInstance->mmAudioHeader;
  1662.      }
  1663.   else
  1664.      {
  1665.      pcodecopen->pSrcHdr = ( PVOID ) &pInstance->mmAudioHeader;
  1666.      pcodecopen->pDstHdr = ( PVOID ) &pInstance->mmRealHeader;
  1667.      }
  1668.  
  1669.   pcodecopen->ulFlags = 0;
  1670.  
  1671. // Is this necessary?
  1672.  
  1673. //  pbufferinfo = pcodecopen->pOtherInfo;
  1674.  
  1675.   codecAssoc.pCODECIniFileInfo = pcodecini = pInstance->pcodecini;
  1676.  
  1677.   rc = mmioSet( pInstance->hmmio,
  1678.                 &mmExtInfo,
  1679.                 MMIO_SET_EXTENDEDINFO );
  1680.  
  1681.   if ( rc )
  1682.      {
  1683.      return (rc);
  1684.      }
  1685.  
  1686.   /* Get the codec open structure modifications */
  1687.  
  1688.   rc = mmioSet( pInstance->hmmio,
  1689.                 &mmExtInfo,
  1690.                 MMIO_QUERY_EXTENDEDINFO_ALL );
  1691.  
  1692.   if ( rc )
  1693.      {
  1694.      return (rc);
  1695.      }
  1696.  
  1697.  
  1698.   rc = GetAudioHeader( pInstance, 0 );
  1699.  
  1700.   /*-------------------------------------------------
  1701.   * If we will be doing real-time translations
  1702.   * then, it is important to examine the capabilities
  1703.   * of the io proc.
  1704.   *-------------------------------------------------*/
  1705.   if ( pInstance->ulRealTimeTranslation ==MMIO_REALTIME )
  1706.      {
  1707.      if ( pcodecini->ulCapsFlags & CODEC_COMPRESS )
  1708.         {
  1709.         pInstance->ulCapabilities |= CAN_SAVE;
  1710.         }
  1711.      else
  1712.         {
  1713.         pInstance->ulCapabilities &= ~CAN_SAVE;
  1714.         }
  1715.  
  1716.      if ( pcodecini->ulCapsFlags & CODEC_COMP_REALTIME )
  1717.         {
  1718.         pInstance->ulCapabilities |= CAN_RECORD;
  1719.         }
  1720.      else
  1721.         {
  1722.         pInstance->ulCapabilities &= ~CAN_RECORD;
  1723.         }
  1724.  
  1725.  
  1726.  
  1727.      } /* if realtime translation is on */
  1728.  
  1729.  
  1730.  
  1731.   return ( rc );
  1732.  
  1733. } /* DataTranslation */
  1734.  
  1735. #endif
  1736.  
  1737.