home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cset21v6.zip / MMPM2TK / TK / ADMCT / AUDIOMCD.C < prev    next >
C/C++ Source or Header  |  1993-04-08  |  19KB  |  666 lines

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