home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mmpm21tk.zip / TK / ADMCT / ADMCREST.C < prev    next >
C/C++ Source or Header  |  1993-03-02  |  25KB  |  833 lines

  1. /********************* START OF SPECIFICATIONS *********************
  2. *
  3. * SUBROUTINE NAME: MCIREST.c
  4. *
  5. * DESCRIPTIVE NAME: A couple of excess functions.
  6. *
  7. *
  8. *
  9. *              Copyright (c) IBM Corporation  1991, 1993
  10. *                        All Rights Reserved
  11. *
  12. * FUNCTION:
  13. *
  14. * NOTES: The following concepts are illustrated in the source file.
  15. *        C. How to pause/resume a stream
  16. *        D. Support stream transition tables.
  17. *        E. Processing INFO_PRODUCT + INFO_FILE
  18. *
  19. * ENTRY POINTS:
  20. *
  21. *********************** END OF SPECIFICATIONS **********************/
  22. #define INCL_DOSSEMAPHORES
  23. #define INCL_DOSPROCESS
  24. #define INCL_ERRORS
  25.  
  26. #include <os2.h>                        // OS2 defines.
  27. #include <string.h>                     // String functions.
  28. #include <os2medef.h>                   // MME includes files.
  29. #include <audio.h>                      // Audio Device Defines.
  30. #include <ssm.h>                        // SSM spi includes.
  31. #include <meerror.h>                    // MM Error Messages.
  32. #include <mmioos2.h>                    // MMIO Include.
  33. #include <mcios2.h>                     // MM System Include.
  34. #include <mmdrvos2.h>                     // MCI Driver Include.
  35. #include <mcd.h>                        // AudioIFDriverInterface.
  36. #include <hhpheap.h>                    // Heap Manager Definitions
  37. #include <qos.h>
  38. #include <audiomcd.h>                   // Component Definitions
  39. #include "admcfunc.h"                   // Function Prototypes
  40.  
  41.  
  42. /********************* START OF SPECIFICATIONS *********************
  43. *
  44. * SUBROUTINE NAME: MCISTOP.C
  45. *
  46. * DESCRIPTIVE
  47. *
  48. * FUNCTION:  Stop Playing/Recording.
  49. *  On a stop, a streaming MCD should perform the following commands:
  50. *
  51. *  A. Verify that the flags passed are valid.
  52. *  B. Stop any commands which are active on another thread.
  53. *  C. If a stream had previously been created, ensure that it is in
  54. *     stopped state.
  55. *  D. If it is a paused stream, then do a STOP_PAUSE to ensure that
  56. *     no data will be lost.
  57. *
  58. * NOTES:
  59. *
  60. * ENTRY POINTS:
  61. *
  62. * INPUT: MCI_STOP message.
  63. *
  64. * EXIT-NORMAL: MCIERR_SUCCESS
  65. *
  66. * EXIT_ERROR:  Error Code.
  67. *
  68. * EFFECTS:
  69. *
  70. * INTERNAL REFERENCES:  MCIERR ().
  71. *
  72. * EXTERNAL REFERENCES: spiStopStream ()   -   SSM Spi
  73. *
  74. *********************** END OF SPECIFICATIONS **********************/
  75. RC MCIStop ( FUNCTION_PARM_BLOCK *pFuncBlock)
  76. {
  77.    ULONG           ulrc;                   // MME Error Value Propogated
  78.    INSTANCE        *ulpInstance;           // Local Instance
  79.    ULONG           ulParam1;               // Incoming MCI Flags
  80.    ULONG           ulCnt;                  // Semaphore Posts Freq
  81.    ULONG           ulAbortNotify = FALSE;  // whether or not to abort a notify
  82.    ULONG           ulStopFlags;            // Mask for Incoming MCI Flags
  83.    ULONG           ulSpiFlags;
  84.  
  85.  
  86.    /*****************************
  87.    * Do Some Flag Checking
  88.    ******************************/
  89.    ulParam1 = pFuncBlock->ulParam1;
  90.  
  91.    /* Mask out illegal file */
  92.  
  93.    ulStopFlags = ulParam1;
  94.    ulStopFlags &= ~(MCI_WAIT + MCI_NOTIFY );
  95.  
  96.    /* If the caller passed in a flag we do not support--return an error */
  97.  
  98.    if (ulStopFlags > 0)
  99.        return (MCIERR_INVALID_FLAG);
  100.  
  101.    ulpInstance = (INSTANCE *)pFuncBlock->ulpInstance;
  102.  
  103.    /*****************************************
  104.    * To ensure proper syncronization, acquire
  105.    * the semaphore which is used to control
  106.    * who can check to see which processes are
  107.    * active. This function will also tell us
  108.    * if there is an operation to abort or
  109.    * supercede.
  110.    ******************************************/
  111.  
  112.    GetNotifyAbortAccess ( ulpInstance, &ulAbortNotify );
  113.  
  114.    /*******************************************
  115.    * If there is an operation active (i.e. a
  116.    * play, record or save) then post a message
  117.    * stating that the command has been
  118.    * aborted (record), superceded (play) or
  119.    * wait for completion (save).
  120.    ********************************************/
  121.  
  122.    if (ulAbortNotify == TRUE)
  123.      {
  124.      if ( ulpInstance->usNotPendingMsg == MCI_SAVE )
  125.         {
  126.         /*****************************************************
  127.         * Save cannot be interrupted or data will be lost, so
  128.         * if there is a save pending, wait for it to complete
  129.         ******************************************************/
  130.  
  131.         DosWaitEventSem( ulpInstance->hThreadSem, (ULONG ) -1 );
  132.  
  133.         }
  134.      else
  135.         {
  136.         PostMDMMessage ( MCI_NOTIFY_ABORTED,
  137.                          ulpInstance->usNotPendingMsg,
  138.                          pFuncBlock);
  139.  
  140.         DosResetEventSem (ulpInstance->hEventSem, &ulCnt);
  141.         DosResetEventSem (ulpInstance->hThreadSem, &ulCnt);
  142.  
  143.         /**********************************************
  144.         * If we are recording information, we must do
  145.         * a full stop so that no information will be
  146.         * lost.  However, if this is a play back stream
  147.         * do a pause so that the next play will resume
  148.         * without audible breakup of information.
  149.         ***********************************************/
  150.  
  151.  
  152.         if ( AMPMIX.ulOperation == OPERATION_RECORD )
  153.           {
  154.       ulSpiFlags = SPI_STOP_FLUSH;
  155.           }
  156.         else
  157.           {
  158.       ulSpiFlags = SPI_STOP_STREAM;
  159.           }
  160.  
  161.         /***********************************
  162.         * Stop The Stream
  163.         ************************************/
  164.     ulrc = SpiStopStream (ulpInstance->StreamInfo.hStream, ulSpiFlags);
  165.  
  166.         if ( AMPMIX.ulOperation == OPERATION_RECORD )
  167.           {
  168.           if (!ulrc)
  169.              {
  170.              /*****************************
  171.              * Wait for the stopped event
  172.              ******************************/
  173.              DosWaitEventSem (ulpInstance->hThreadSem, (ULONG) -1);
  174.              }
  175.  
  176.           /****************************************
  177.           * Record streams go into a stopped state
  178.           *****************************************/
  179.           STRMSTATE = MCI_STOP;
  180.  
  181.           }
  182.         else
  183.           {
  184.           /*****************************************
  185.           * Since a pause does not generate an event
  186.           * create a fake one so our play thread can
  187.           * clean up (if it is active).
  188.           *****************************************/
  189.  
  190.           ulpInstance->StreamEvent = EVENT_STREAM_STOPPED;
  191.           DosPostEventSem (ulpInstance->hEventSem);
  192.  
  193.           DosWaitEventSem (ulpInstance->hThreadSem, (ULONG) -1);
  194.  
  195.           /***************************************
  196.           * Play streams go into a stopped/paused state
  197.           ****************************************/
  198.  
  199.           STRMSTATE = STOP_PAUSED;
  200.           }
  201.  
  202.  
  203.         } /* if no pending save */
  204.  
  205.         ulpInstance->usNotifyPending = FALSE;
  206.  
  207.      } /* if notify pending */
  208.  
  209.  
  210.    if (STRMSTATE != MCI_STOP && STRMSTATE != STOP_PAUSED )
  211.       {
  212.       DosResetEventSem (ulpInstance->hEventSem, &ulCnt);
  213.       SpiStopStream (ulpInstance->StreamInfo.hStream, SPI_STOP_STREAM );
  214.       STRMSTATE = STOP_PAUSED;
  215.       }
  216.  
  217.    return (MCIERR_SUCCESS);
  218.  
  219. }
  220.  
  221.  
  222. /********************* START OF SPECIFICATIONS *********************
  223. *
  224. * SUBROUTINE NAME: MCIPAUS.C
  225. *
  226. * DESCRIPTIVE
  227. *
  228. * FUNCTION:  Waveform Pause.
  229. *
  230. * NOTES:
  231. *  On a MCI_PAUSE, a streaming MCD should perform the following commands:
  232. *
  233. *  A. Ensure that no flags are passed in.
  234. *  B. If we are currently streaming, pause the stream.
  235. *  C. Set flag indicating that we are in paused state.
  236. *
  237. * ENTRY POINTS:
  238. *
  239. * INPUT: MCI_PAUSE message.
  240. *
  241. * EXIT-NORMAL: Return Code 0.
  242. *
  243. * EXIT_ERROR:  Error Code.
  244. *
  245. * EFFECTS:
  246. *
  247. * INTERNAL REFERENCES:  MCIERR ().
  248. *
  249. * EXTERNAL REFERENCES: spiStopStream ()   -   SSM Spi
  250. *
  251. *********************** END OF SPECIFICATIONS **********************/
  252. RC MCIPaus (FUNCTION_PARM_BLOCK *pFuncBlock)
  253.  
  254. {
  255.     INSTANCE *      ulpInstance;
  256.     ULONG           ulPauseFlags;
  257.  
  258.     ulPauseFlags = pFuncBlock->ulParam1;
  259.     ulPauseFlags &= ~(MCI_WAIT + MCI_NOTIFY );
  260.  
  261.    /* If the caller passed in a flag we do not support--return an error */
  262.  
  263.     if (ulPauseFlags > 0 )
  264.        {
  265.        return MCIERR_INVALID_FLAG;
  266.        }
  267.  
  268.     ulpInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  269.  
  270.     /****************************************************
  271.     * The default action on an spiStopstream is pause.
  272.     *****************************************************/
  273.     if ((STRMSTATE == MCI_PLAY ) || (STRMSTATE == MCI_RECORD) )
  274.        {
  275.  
  276.        SpiStopStream (ulpInstance->StreamInfo.hStream, SPI_STOP_STREAM);
  277.  
  278.        STRMSTATE = MCI_PAUSE;    /* update Instance */
  279.  
  280.        }
  281.  
  282.     return (MCIERR_SUCCESS);
  283.  
  284. } /* MCIPause */
  285.  
  286.  
  287.  
  288. /********************* START OF SPECIFICATIONS *********************
  289. *
  290. * SUBROUTINE NAME: MCIRESUME
  291. *
  292. * DESCRIPTIVE      Audio MCD Resume.
  293. *
  294. * FUNCTION:  Resume Playback/Record from Paused State.
  295. *
  296. * NOTES:
  297. * On a MCI_RESUME, a streaming MCD should perform the following commands:
  298. *
  299. * A. Ensure that no flags are passed in.
  300. * B. If we are paused, resume the stream.
  301. *
  302. * ENTRY POINTS:
  303. *
  304. * INPUT: MCI_RESUME message.
  305. *
  306. * EXIT-NORMAL: Return Code 0.
  307. *
  308. * EXIT_ERROR:  Error Code.
  309. *
  310. * EFFECTS:
  311. *
  312. * INTERNAL REFERENCES:  MCIERR ().
  313. *
  314. * EXTERNAL REFERENCES: SpiStartStream ()        -   SSM Spi
  315. *
  316. *********************** END OF SPECIFICATIONS **********************/
  317. RC  MCIResume (FUNCTION_PARM_BLOCK * pFuncBlock)
  318. {
  319.  
  320.    ULONG                  ulResumeFlags;   // Incoming MCI Flags
  321.  
  322.    INSTANCE               * ulpInstance;   // Local Instance
  323.  
  324.    /*********************************
  325.    * Check for invalid flags
  326.    *********************************/
  327.  
  328.    ulResumeFlags = pFuncBlock->ulParam1;
  329.  
  330.    /* Mask out legal flags */
  331.  
  332.    ulResumeFlags &= ~( MCI_WAIT + MCI_NOTIFY );
  333.  
  334.    /* If the caller passed in a flag we do not support--return an error */
  335.  
  336.    if (ulResumeFlags > 0 )
  337.            return ( MCIERR_INVALID_FLAG );
  338.  
  339.    /**********************************
  340.    * Derefernce pointers.
  341.    ***********************************/
  342.  
  343.    ulpInstance= (INSTANCE *) pFuncBlock->ulpInstance;
  344.  
  345.  
  346.    /**********************************************************
  347.    * No State Transition if already in States Play or Record
  348.    **********************************************************/
  349.  
  350.    if ( STRMSTATE == MCI_PAUSE )
  351.       {
  352.  
  353.        SpiStartStream (ulpInstance->StreamInfo.hStream, SPI_START_STREAM);
  354.  
  355.        if ( AMPMIX.ulOperation == OPERATION_PLAY )
  356.           {
  357.           STRMSTATE = MCI_PLAY;      // update Instance
  358.           }
  359.        else
  360.           {
  361.           STRMSTATE = MCI_RECORD;
  362.           }
  363.  
  364.       } /* if in paused state */
  365.  
  366.    return (MCIERR_SUCCESS);
  367.  
  368. } /* MCIResume */
  369.  
  370.  
  371.  
  372.  
  373. /********************* START OF SPECIFICATIONS *********************
  374. *
  375. * SUBROUTINE NAME: MCISTPA
  376. *
  377. * DESCRIPTIVE : Audio MCD Set Position Advice.
  378. *
  379. * FUNCTION: Create Media Position Advice Notification messages.
  380. *
  381. * NOTES:
  382. *  To a streaming MCD, a postion advise simply is a cuepoint which
  383. *  reoccurs every x time units.  To enable position advise, the following
  384. *  steps should be followed:
  385. .*
  386. .
  387. *  Check flags and validate and pointers.
  388. *  If the caller has asked for position advise to be turned on then
  389. *
  390. *    If a stream has been created, then enable the recurring cuepoint event.
  391. *    Else, set a flag and enable the event later.
  392. *  If position advise is to be turned off, then disable the recurring
  393. *  cuepoint event.
  394. *
  395. * ENTRY POINTS:
  396. *
  397. * INPUT: MCI_SET_POSITION_ADVISE message.
  398. *
  399. * EXIT-NORMAL: MCIERR_SUCCESS
  400. *
  401. * EXIT_ERROR:  Error Code.
  402. *
  403. * EFFECTS:
  404. *
  405. * INTERNAL REFERENCES:  MCIERR ().
  406. *
  407. * EXTERNAL REFERENCES: spiStartStream ()         -   SSM Spi
  408. *
  409. *********************** END OF SPECIFICATIONS **********************/
  410.  
  411. RC  MCISetPositionAdvise (FUNCTION_PARM_BLOCK * pFuncBlock)
  412. {
  413.   ULONG           ulrc;                      // Error Value
  414.   ULONG           ulParam1;                  // Incoming MCI Flags
  415.   ULONG           ulPosAdviseFlags;          // Mask For Incoming Flags
  416.   ULONG           ulMMTime;                  // Converted Time
  417.  
  418.   INSTANCE        *ulpInstance;              // Local Instance
  419.  
  420.   PID             pid;
  421.   TID             tid;
  422.   HWND            hWnd;
  423.  
  424.   PMCI_POSITION_PARMS pPositionParms;      // MCI Msg Data
  425.  
  426.   /***************************
  427.   * Intialize Pointers
  428.   ****************************/
  429.  
  430.   ulpInstance = (INSTANCE *)pFuncBlock->ulpInstance;
  431.   ulParam1 = pFuncBlock->ulParam1;
  432.   ulPosAdviseFlags = ulParam1;
  433.   pPositionParms = (PMCI_POSITION_PARMS) pFuncBlock->ulParam2;
  434.  
  435.   /**********************************
  436.   * Check for Validity of Flags
  437.   ***********************************/
  438.   ulPosAdviseFlags &= ~( MCI_NOTIFY  + MCI_WAIT     +
  439.              MCI_SET_POSITION_ADVISE_ON +
  440.              MCI_SET_POSITION_ADVISE_OFF);
  441.  
  442.   /*************************************
  443.   * Return error if flags are not
  444.   * appropriate for the message
  445.   *************************************/
  446.  
  447.   if (ulPosAdviseFlags > 0 )
  448.       return ( MCIERR_INVALID_FLAG );
  449.  
  450.   /********************************
  451.   * Null Parameter Conditions
  452.   *********************************/
  453.   ulrc = CheckMem (((PVOID)pPositionParms),
  454.                    sizeof (MCI_POSITION_PARMS),
  455.                    PAG_READ);
  456.  
  457.   if (ulrc != MCIERR_SUCCESS)
  458.      {
  459.      return (MCIERR_MISSING_PARAMETER);
  460.      }
  461.  
  462.  
  463.  
  464.   /******************************************************
  465.   * Check for Invalid Combination of Valid Flags
  466.   *******************************************************/
  467.   if ((ulParam1 & MCI_SET_POSITION_ADVISE_ON) &&
  468.       (ulParam1 & MCI_SET_POSITION_ADVISE_OFF))
  469.  
  470.       return (MCIERR_FLAGS_NOT_COMPATIBLE);
  471.  
  472.   /************************************************
  473.   * Check for Invalid Combination of Valid Flags
  474.   *************************************************/
  475.   if (!(ulParam1 & MCI_SET_POSITION_ADVISE_ON ||
  476.       ulParam1 & MCI_SET_POSITION_ADVISE_OFF))
  477.  
  478.       return (MCIERR_MISSING_FLAG);
  479.  
  480.  
  481.   /*---------------------------------------
  482.   * To enable position advise, a file or
  483.   * playlist must be loaded.
  484.   *---------------------------------------*/
  485.  
  486.   if (ulpInstance->fFileExists == FALSE )
  487.     return (MCIERR_FILE_NOT_FOUND);
  488.  
  489.   /******************************************
  490.   * Enable Position Advise
  491.   *******************************************/
  492.  
  493.   if (ulParam1 & MCI_SET_POSITION_ADVISE_ON)
  494.      {
  495.      /************************************
  496.      * Ensure that the callback handle that
  497.      * the caller specified is valid.  This case
  498.      * is somewhat special--MDM normally checks
  499.      * the callback handles when MCI_NOTIFY is
  500.      * specified.  However, callback handles can
  501.      * be passed on position advise with the
  502.      * MCI_WAIT flag.
  503.      ************************************/
  504.  
  505.      hWnd = pPositionParms->hwndCallback;
  506.  
  507.  
  508.      if (!WinQueryWindowProcess(hWnd, &pid, &tid))
  509.           return(MCIERR_INVALID_CALLBACK_HANDLE);
  510.  
  511.      ulpInstance->StreamInfo.PosAdvEvcb.hwndCallback = hWnd;
  512.  
  513.      ulpInstance->StreamInfo.PosAdvEvcb.usDeviceID = ulpInstance->usWaveDeviceID;
  514.  
  515.      /**************************************************
  516.      * If we have an existing stream and have already
  517.      * enabled a position advise cuepoint, then
  518.      * disable the previous position advise since the
  519.      * new one has precendence.
  520.      **************************************************/
  521.  
  522.      if ( ulpInstance->usPosAdvise == EVENT_ENABLED )
  523.  
  524.     {
  525.  
  526.     /* why don't we check ulrc? */
  527.  
  528.     ulrc = SpiDisableEvent(ulpInstance->StreamInfo.hPosEvent);
  529.     }
  530.  
  531.      /***************************************
  532.      * Fill in Event Control Block to indicate
  533.      * that we want a recurring cue point.
  534.      ****************************************/
  535.      ulpInstance->StreamInfo.PosAdvEvcb.evcb.ulType = EVENT_CUE_TIME;
  536.      ulpInstance->StreamInfo.PosAdvEvcb.evcb.ulFlags = EVENT_RECURRING;
  537.      ulpInstance->StreamInfo.PosAdvEvcb.evcb.hstream = ulpInstance->StreamInfo.hStream;
  538.  
  539.      /************************************************
  540.      * Copy our instance into the position advise
  541.      * event control block.  The event routine will
  542.      * use this field to obtain a pointer to our
  543.      * instance.  Once it has this pointer, it can
  544.      * manipulate instance variables etc, necessary
  545.      * to inform the caller that the event has
  546.      * happened.  See the PlayEventProc in admcplay.c
  547.      * and the RecordEventProc in admcrecd.c
  548.      ***********************************************
  549.      **/
  550.      ulpInstance->StreamInfo.PosAdvEvcb.ulpInstance = (ULONG)ulpInstance;
  551.  
  552.      /********************************************
  553.      * Copy Position UserParm into instance.
  554.      * This User Parameter is returned on
  555.      * Position change messages to the user.
  556.      *********************************************/
  557.      ulpInstance->usPosUserParm = pPositionParms->usUserParm;
  558.  
  559.      ulrc = ConvertToMM ( ulpInstance,
  560.               &ulMMTime,
  561.               pPositionParms->ulUnits);
  562.  
  563.      /**********************************************
  564.      * Frequency of Position Change Messages
  565.      **********************************************/
  566.  
  567.      ulpInstance->StreamInfo.PosAdvEvcb.evcb.mmtimeStream = ulpInstance->StreamInfo.PosAdvEvcb.mmCuePt = ulMMTime;
  568.  
  569.      /*********************************************
  570.      * If ulUnits == 0 return MCIERR_OUTOFRANGE
  571.      *********************************************/
  572.  
  573.      if ( ulMMTime == 0)
  574.      return (MCIERR_OUTOFRANGE);
  575.  
  576.      /*********************************************
  577.      * Enable the recurring time event.  Note:
  578.      * We are utilizing an extended event control
  579.      * block which we modified to contain window
  580.      * handles, instance pointers etc.  In fact,
  581.      * you can modify the evcb to contain whatever
  582.      * data you wish.  Simply ensure the beginning
  583.      * fields of the structure are what SSM expects
  584.      * and the remainder can be used by the MCD.
  585.      * See admcplay.c or audiosub.c for more info
  586.      **********************************************/
  587.  
  588.      if (ulpInstance->ulCreateFlag == PREROLL_STATE)
  589.        {
  590.        ulrc = SpiEnableEvent( (PEVCB) &ulpInstance->StreamInfo.PosAdvEvcb,
  591.                   (PHEVENT) &ulpInstance->StreamInfo.hPosEvent);
  592.  
  593.        ulpInstance->usPosAdvise = EVENT_ENABLED; // Set The Flag and Return
  594.        }
  595.      else
  596.        {
  597.        ulpInstance->usPosAdvise = TRUE; // Set The Flag and Return
  598.        }
  599.  
  600.      if (ulrc)
  601.          return (ulrc);
  602.      } /* Set Position Advise on */
  603.  
  604.   /*****************************************
  605.   * Disable Position Advise
  606.   ******************************************/
  607.  
  608.   if (ulParam1 & MCI_SET_POSITION_ADVISE_OFF)
  609.      {
  610.      /* If an event has been enabled, remove it */
  611.  
  612.      if ( ulpInstance->usPosAdvise == EVENT_ENABLED )
  613.     {
  614.     ulrc = SpiDisableEvent (ulpInstance->StreamInfo.hPosEvent);
  615.     }
  616.  
  617.      /* Set flag indicating that Position Advise is no longer in effect */
  618.  
  619.      ulpInstance->usPosAdvise = FALSE;
  620.  
  621.      } /* Set position advise off */
  622.  
  623.   return (ulrc);    // return RC
  624. } /* MCISetPositionAdvise */
  625.  
  626.  
  627. /********************* START OF SPECIFICATIONS *********************
  628. *
  629. * SUBROUTINE NAME: MCISYNC
  630. *
  631. * DESCRIPTIVE      Audio MCD Set Sync Offset.
  632. *
  633. * FUNCTION:  Set Synchronization offset.
  634. *
  635. * NOTES:
  636. *
  637. * ENTRY POINTS:
  638. *
  639. * INPUT: MCI_SET_SYNC_OFFSET message.
  640. *
  641. * EXIT-NORMAL: Return Code 0.
  642. *
  643. * EXIT_ERROR:  Error Code.
  644. *
  645. * EFFECTS:
  646. *
  647. * INTERNAL REFERENCES:  MCIERR ().
  648. *
  649. * EXTERNAL REFERENCES: spiStartStream ()         -   SSM Spi
  650. *
  651. *********************** END OF SPECIFICATIONS **********************/
  652. RC MCISync (FUNCTION_PARM_BLOCK * pFuncBlock)
  653. {
  654.   INSTANCE             *pInstance;       // Local Instance
  655.   PMCIDRV_SYNC_PARMS   pSyncParms;
  656.  
  657.   pInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  658.   pSyncParms = ( PMCIDRV_SYNC_PARMS ) pFuncBlock->ulParam2;
  659.  
  660.   pFuncBlock->ulParam1 &= ~(MCI_WAIT | MCI_NOTIFY );
  661.  
  662.   switch ( pFuncBlock->ulParam1 )
  663.      {
  664.      case MCIDRV_SYNC_ENABLE  :
  665.         if ( !pInstance->StreamInfo.hStream )
  666.            {
  667.            return ( MCIERR_UNSUPPORTED_FUNCTION );
  668.            }
  669.         pSyncParms->ulNumStreams = 1;
  670.         pSyncParms->hStreams = &pInstance->StreamInfo.hStream;
  671.         break;
  672.      case MCIDRV_SYNC_DISABLE :
  673.         break;
  674.      default :
  675.         return ( MCIERR_UNSUPPORTED_FUNCTION );
  676.      }
  677.   /***********************************************
  678.   * Flag the offset condition as true.
  679.   ***********************************************/
  680.  
  681.   return (MCIERR_SUCCESS);
  682.         // Forced RC
  683. }
  684.  
  685.  
  686. /********************* START OF SPECIFICATIONS *********************
  687. *
  688. * SUBROUTINE NAME:              MCDINFO
  689. *
  690. * DESCRIPTIVE NAME: Information about Waveform Device.
  691. *
  692. * FUNCTION: Obtain Info about a  Waveform Device.
  693. *
  694. * NOTES:
  695. *
  696. * ENTRY POINTS:
  697. *     LINKAGE:   CALL FAR
  698. *
  699. * INPUT: MCI_INFO message.
  700. *
  701. * EXIT-NORMAL: MCIERR_SUCCESS.
  702. *
  703. * EXIT_ERROR:  Error Code.
  704. *
  705. * EFFECTS:
  706. *
  707. * INTERNAL REFERENCES:
  708. *
  709. * EXTERNAL REFERENCES:
  710. *
  711. *********************** END OF SPECIFICATIONS **********************/
  712.  
  713. RC MCIInfo (FUNCTION_PARM_BLOCK *pFuncBlock)
  714. {
  715.  
  716.   ULONG            ulrc;               // Propogated MME Error Value
  717.   ULONG            ulParam1;           // Incoming MCI Msg Flags
  718.   ULONG            ulInfoFlags;        // Mask for Incoming Flags
  719.   INSTANCE         *ulpInstance;       // Local Instance
  720.   PMCI_INFO_PARMS  pInfoParms;        // Msg Data Ptr
  721.  
  722.   ulParam1 = pFuncBlock->ulParam1 & NOTIFY_MASK;
  723.   pInfoParms = (PMCI_INFO_PARMS) pFuncBlock->ulParam2;
  724.  
  725.   ulInfoFlags = ulParam1;
  726.  
  727.   /*******************************************
  728.   * Turn off Expected Flags Bits
  729.   ********************************************/
  730.   ulInfoFlags &= ~( MCI_INFO_FILE + MCI_INFO_PRODUCT);
  731.  
  732.   /************************************************
  733.   * Return Error if any bits are still set
  734.   ************************************************/
  735.  
  736.   if (ulInfoFlags > 0 )
  737.       return (MCIERR_INVALID_FLAG);
  738.  
  739.   /****************************************************
  740.   * Check For Valid Flags but Invalid combination
  741.   *****************************************************/
  742.  
  743.   if (ulParam1 & MCI_INFO_FILE && ulParam1 & MCI_INFO_PRODUCT)
  744.       return (MCIERR_FLAGS_NOT_COMPATIBLE);
  745.  
  746.  
  747.   if (!(ulParam1 & MCI_INFO_FILE || ulParam1 & MCI_INFO_PRODUCT))
  748.       return (MCIERR_MISSING_FLAG);
  749.  
  750.   /******************************************************
  751.   * Derefernce Instance pointer from the function block
  752.   ******************************************************/
  753.   ulpInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  754.  
  755.   /*************************************************
  756.   * Check For valid MCI Data Struct pointer
  757.   *************************************************/
  758.   if (ulrc = CheckMem ((PVOID)pInfoParms,
  759.                        sizeof (MCI_INFO_PARMS),
  760.                        PAG_READ | PAG_WRITE) )
  761.       {
  762.       return (MCIERR_MISSING_PARAMETER);
  763.       }
  764.  
  765.  
  766.   if (ulParam1 & MCI_INFO_FILE)
  767.       {
  768.       /* An element must be loaded before this is valid */
  769.  
  770.       if (ulpInstance->fFileExists == FALSE )
  771.           {
  772.           return ( MCIERR_FILE_NOT_FOUND );
  773.           }
  774.  
  775.       /************************************
  776.       * Ensure the size of the buffer the
  777.       * user passed is valid for the length
  778.       * the caller says it is (i.e. they may
  779.       * have said it's valid for 8 bytes).
  780.       *************************************/
  781.  
  782.        if (ulrc = CheckMem ((PVOID)pInfoParms->pszReturn,
  783.                 pInfoParms->ulRetSize,
  784.                             PAG_READ | PAG_WRITE) )
  785.  
  786.          {
  787.          return (MCIERR_INVALID_BUFFER);
  788.          }
  789.       /********************************************
  790.       * If the filename is longer that what the
  791.       * caller has allocated, return the length
  792.       * that they should have allocated for the next
  793.       * try.
  794.       ***********************************************/
  795.  
  796.       if (strlen(ulpInstance->pszAudioFile) > pInfoParms->ulRetSize)
  797.         {
  798.     pInfoParms->ulRetSize = strlen (ulpInstance->pszAudioFile);
  799.         return (MCIERR_INVALID_BUFFER);
  800.         }
  801.       else
  802.         {
  803.         /* return to the caller the filename */
  804.  
  805.     strcpy((PSZ)pInfoParms->pszReturn, ulpInstance->pszAudioFile);
  806.         }
  807.  
  808.       } /* If File Info was Requested */
  809.  
  810.   /**********************************
  811.   * Product Information
  812.   ***********************************/
  813.  
  814.   if (ulParam1 & MCI_INFO_PRODUCT)
  815.       {
  816.  
  817.       /*******************************
  818.       * Get Product Information
  819.       * From AudioIF which is the
  820.       * device specific component.
  821.       ********************************/
  822.  
  823.        ulrc = mciSendCommand ( ulpInstance->usAmpDeviceID,
  824.                                MCI_INFO,
  825.                                ulParam1,
  826.                                (PVOID) pInfoParms,
  827.                                pFuncBlock->usUserParm);
  828.  
  829.       }  /* INFO Product */
  830.  
  831.   return (ulrc);
  832. } /* MCIInfo */
  833.