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

  1. /********************* STARTOF SPECIFICATIONS *********************
  2. *
  3. * SUBROUTINE NAME: LOADSUBS.C
  4. *
  5. * DESCRIPTIVE NAME: Audio MCD Load subroutine file.
  6. *
  7. *              Copyright (c) IBM Corporation  1991, 1993
  8. *                        All Rights Reserved
  9. *
  10. * FUNCTION: Contain subroutines for MCI_LOAD/MCI_OPEN.
  11. *
  12. * NOTES: Concepts illustrated in this source module.
  13. *
  14. *         A. Creating temporary filenames (CheckForValidElement)
  15. *         B. Aborting in process commands (LoadAbortNotify)
  16. *         C. Processing the OPEN_MMIO flag (OpenHandle)
  17. *         D. Rational as to when to open the card in record or
  18. *            playback mode (OpenHandle) (ProcessElement).
  19. *         E. Processing temp files (ProcessElement).
  20. *         F. Opening a file with MMIO (ProcessElement).
  21. *         G. Processing the MCI_READ_ONLY flag (ProcessElement).
  22. *         H. Creating a temporary file ( SetupTempFiles).
  23. *         I. Using mmioSendMessage API to talk to an IO Proc (SetupTempFiles).
  24. *         J. Loading a Vendor Specific Device (OpenInit).
  25. *         H. Retrieving a connection and opening the connected device.
  26. *         I. Stream Handler Setup (StreamSetup)
  27. *         J. Processing MCI_NOTIFY or MCI_WAIT and callback window handles
  28. *            (NotifyWaitSetup).
  29.  
  30. *
  31. * ENTRY POINTS:
  32. *
  33. * INPUT: MCI_PLAY message.
  34. *
  35. * EXIT-NORMAL: Return Code 0.
  36. *
  37. * EXIT_ERROR:  Error Code.
  38. *
  39. * EFFECTS:
  40. *
  41. * FUNCTIONS DEFINED :  CopyParms
  42. *                      CheckForValidElement
  43. *                      LoadAbortNotifies
  44. *                      OpenHandle
  45. *                      ProcessElement
  46. *                      SetupTempFiles
  47. *                      OpenInit
  48. *                      DetermineConnections
  49. *                      ConnectToAmp
  50. *                      StreamSetup
  51. *                      NotifyWaitSetup
  52. *                      CreateSemaphores
  53. *                      AllocateInstance
  54. *
  55. *
  56. * INTERNAL REFERENCES:    CreateNAssocStream ().
  57. *
  58. * EXTERNAL REFERENCES:    SpiStopStream  ().
  59. *                         SpiAssociate   ().
  60. *                         SpiDisableEvent().
  61. *                         SpiSeekStream  ().
  62. *                         mmioSendMessage().
  63. *                         mmioClose ().
  64. *
  65. *********************** END OF SPECIFICATIONS **********************/
  66. #define INCL_BASE
  67. #define INCL_DOSMODULEMGR
  68. #define INCL_DOSSEMAPHORES
  69.  
  70. #include <os2.h>
  71. #include <string.h>
  72. #include <os2medef.h>                   // MME includes files.
  73. #include <audio.h>                      // Audio Device defines
  74. #include <ssm.h>                        // SSM spi includes.
  75. #include <meerror.h>                    // MM Error Messages.
  76. #include <mmioos2.h>                    // MMIO Include.
  77. #include <mcios2.h>                     // MM System Include.
  78. #include <mmdrvos2.h>                   // Mci Driver Include.
  79. #include <mcipriv.h>                    // MCI Connection stuff
  80. #include <mcd.h>                        // VSDIDriverInterface.
  81. #include <hhpheap.h>                    // Heap Manager Definitions
  82. #include <qos.h>
  83. #include <audiomcd.h>                   // Component Definitions.
  84. #include "admcfunc.h"                   // Function Prototypes
  85. #include <sw.h>
  86.  
  87.  
  88.  
  89. /********************* START OF SPECIFICATIONS *******************************
  90. *
  91. * SUBROUTINE NAME: CheckForValidElement
  92. *
  93. * DESCRIPTIVE NAME: Ensures that file names are valid
  94. *
  95. * FUNCTION: If the users passed in a file name for open/load this routine
  96. *           will ensure that it is valid.  In addition, it will create a name
  97. *           if the user passed in open element w/no file name
  98. *
  99. *
  100. * NOTES:
  101. * ENTRY POINTS:
  102. *
  103. * INPUT:
  104. *
  105. * EXIT-NORMAL: Return Code 0.
  106. *
  107. * EXIT_ERROR:  Error Code.
  108. *
  109. * EFFECTS:
  110. *
  111. * INTERNAL REFERENCES: HhpAllocMem().
  112. *
  113. * EXTERNAL REFERENCES:
  114. *
  115. *********************** END OF SPECIFICATIONS *******************************/
  116.  
  117.  
  118.  
  119. ULONG CheckForValidElement( INSTANCE   *ulpInstance,
  120.                             PSZ        pszFileName,
  121.                             ULONG      ulParam1 )
  122.  
  123. {
  124.  
  125.   ULONG  ulrc;           // return code
  126.   ULONG  ulPathLength;   // Contains the max length
  127.   LONG   lReturnCode;
  128.  
  129.   /* Did the caller pass a filename on MCI_OPEN/MCI_LOAD */
  130.  
  131.   if ( pszFileName )
  132.      {
  133.  
  134.      /* Ensure that this filename is valid */
  135.  
  136.      if (ulrc = CheckMem ( (PVOID) pszFileName, 1, PAG_WRITE))
  137.         {
  138.         return (MCIERR_MISSING_PARAMETER);
  139.         }
  140.  
  141.      /*************************************************
  142.      * Store the filename for future reference -- i.e.
  143.      * MCI_INFO can request the name of the file
  144.      *************************************************/
  145.  
  146.      strcpy ( ulpInstance->pszAudioFile, pszFileName);
  147.  
  148.      /************************************************************
  149.      * Set flag to say that we did not create a new file--thus
  150.      * we do not have to clean up if the user doesn't save
  151.      ************************************************************/
  152.  
  153.      ulpInstance->ulCreatedName = FALSE;
  154.  
  155.      }
  156.    else
  157.      {
  158.      /**************************************
  159.      * if the user requests a read only file
  160.      * and we must create it, return error
  161.      **************************************/
  162.  
  163.      if ( ulParam1 & MCI_READONLY )
  164.         {
  165.         return ( MCIERR_MISSING_PARAMETER );
  166.         }
  167.  
  168.      /**********************************************
  169.      * Query the default path to place temp files and
  170.      * generate a temporary file name
  171.      **********************************************/
  172.  
  173.      ulrc = mciQuerySysValue( MSV_WORKPATH, &ulpInstance->pszAudioFile );
  174.  
  175.      if ( !ulrc )
  176.         {
  177.         return ( MCIERR_INI_FILE );
  178.         }
  179.  
  180.      ulrc = MCIERR_SUCCESS;
  181.  
  182.      ulPathLength = CCHMAXPATH;
  183.  
  184.      /* Have mmio generate a unique filename */
  185.  
  186.      lReturnCode = DBCSGenerateUniqueFile( &ulpInstance->pszAudioFile,
  187.                                            &ulPathLength,
  188.                                            &ulpInstance->hTempFile );
  189.  
  190.      if ( lReturnCode != MMIO_SUCCESS )
  191.         {
  192.         return ( MCIERR_FILE_NOT_FOUND );
  193.         }
  194.  
  195.      /***************************************************
  196.      * Because we did create a temporary file we will
  197.      * be responsible for cleaning up in case the
  198.      * caller never calls MCI_SAVE (e.g. a bunch of
  199.      * temp files will be left in the workpath
  200.      * otherwise, so set a flag to indicate this fact.
  201.      **************************************************/
  202.  
  203.      ulpInstance->ulCreatedName = TRUE;
  204.  
  205.      } /* else the user did not pass in a name */
  206.  
  207.   return ( ulrc );
  208.  
  209.  
  210. } /* check for valid element */
  211.  
  212.  
  213.  
  214. /********************* START OF SPECIFICATIONS *******************************
  215. *
  216. * SUBROUTINE NAME: LoadAbortNotifies
  217. *
  218. * DESCRIPTIVE NAME: Ensures that notifies are aborted
  219. *
  220. * FUNCTION: Load will stop existing operations (i.e. like play/record ) and
  221. *           ensure that they can complete before loading the new file.
  222. *
  223. *
  224. * NOTES:
  225. * ENTRY POINTS:
  226. *
  227. * INPUT:
  228. *
  229. * EXIT-NORMAL: Return Code 0.
  230. *
  231. * EXIT_ERROR:  Error Code.
  232. *
  233. * EFFECTS:
  234. *
  235. * INTERNAL REFERENCES: HhpAllocMem().
  236. *
  237. * EXTERNAL REFERENCES:
  238. *
  239. *********************** END OF SPECIFICATIONS *******************************/
  240.  
  241. ULONG LoadAbortNotifies( INSTANCE             *ulpInstance,
  242.                          FUNCTION_PARM_BLOCK  *pFuncBlock,
  243.                          ULONG                ulAbortNotify )
  244.  
  245. {
  246.  
  247.   ULONG ulrc;
  248.  
  249.  
  250.   if ( ulAbortNotify == TRUE)
  251.      {
  252.  
  253.      /*****************************************************
  254.      * Save cannot be interrupted or data will be lost, so
  255.      * if there is a save pending, wait for it to complete
  256.      ******************************************************/
  257.  
  258.      if ( ulpInstance->usNotPendingMsg == MCI_SAVE )
  259.         {
  260.         /* Wait for save to complete */
  261.  
  262.         DosWaitEventSem( ulpInstance->hThreadSem, (ULONG ) -1 );
  263.  
  264.         }
  265.       else
  266.         {
  267.         /*****************************************
  268.         * State that we are aborting the operation
  269.         * in process (i.e. play/record).
  270.         *****************************************/
  271.  
  272.         PostMDMMessage ( MCI_NOTIFY_ABORTED,
  273.                          ulpInstance->usNotPendingMsg,
  274.                          pFuncBlock);
  275.  
  276.         /******************************************
  277.         * The previous command was most a streaming
  278.         * command, so stop it from operating
  279.         *******************************************/
  280.  
  281.         ThreadedStop( ulpInstance );
  282.  
  283.         STRMSTATE = MCI_STOP;
  284.  
  285.         } /* if pending message not save */
  286.  
  287.  
  288.      } /* notify pending is true */
  289.  
  290.   else
  291.  
  292.      {
  293.      /***********************************************
  294.      * MCI_STOP may have done a stop_pause to prevent
  295.      * the loss of data--see MCIStop for a more detailed
  296.      * explanation of why--ensure that the stream is
  297.      * stopped before continuing.  If you don't the
  298.      * dreaded stream not stopped will result.
  299.      *************************************************/
  300.  
  301.      if ( STRMSTATE == STOP_PAUSED )
  302.         {
  303.         ulrc = StopStream( ulpInstance, OPERATION_PLAY );
  304.  
  305.         }
  306.  
  307.      }
  308.  
  309.   return ( MCIERR_SUCCESS );
  310.  
  311. } /* LoadAbortNotifies */
  312.  
  313.  
  314. /********************* START OF SPECIFICATIONS *******************************
  315. *
  316. * SUBROUTINE NAME: OpenHandle
  317. *
  318. * DESCRIPTIVE NAME: Sets up for mmio handle passed in on the open
  319. *
  320. * FUNCTION: If a mmio handle is passed in on the open, this routine will
  321. *           do the appropriate setup for it.
  322. *
  323. *
  324. * NOTES:
  325. * ENTRY POINTS:
  326. *
  327. * INPUT:
  328. *
  329. * EXIT-NORMAL: Return Code 0.
  330. *
  331. * EXIT_ERROR:  Error Code.
  332. *
  333. * EFFECTS:
  334. *
  335. * INTERNAL REFERENCES: HhpAllocMem().
  336. *
  337. * EXTERNAL REFERENCES:
  338. *
  339. *********************** END OF SPECIFICATIONS *******************************/
  340.  
  341.  
  342. ULONG OpenHandle( INSTANCE  *ulpInstance,
  343.                   ULONG     ulParam1,
  344.                   HMMIO     hmmio )
  345.  
  346. {
  347.  
  348.   ULONG ulrc = MCIERR_SUCCESS;
  349.  
  350.   if (ulParam1 & MCI_OPEN_MMIO)
  351.      {
  352.       if ( !hmmio )
  353.          {
  354.          return ( MMIOERR_INVALID_HANDLE );
  355.          }
  356.  
  357.       /* Copy the mmio handle to our instance for future use */
  358.  
  359.       ulpInstance->hmmio = hmmio;
  360.  
  361.       /*****************************************************
  362.       * Set a flag which indicates that the caller provided
  363.       * a file handle--therefore NEVER close this handle
  364.       *****************************************************/
  365.  
  366.       ulpInstance->fOpenMMIO = TRUE;
  367.  
  368.       ulrc = GetAudioHeader (ulpInstance);
  369.  
  370.       /***************************************************
  371.       * If the file is non-existent (no data), open the
  372.       * card in record mode so the user can hear if
  373.       * anything is plugged in line-in or the
  374.       * microphone jack (we will assume they want to
  375.       * record since there is no data to play back).
  376.       * By contrast, if there is data, then we will
  377.       * assume that the user wants to be in playback mode
  378.       ****************************************************/
  379.       if ( ulpInstance->ulDataSize != 0 )
  380.          {
  381.          AMPMIX.ulOperation = OPERATION_PLAY;
  382.          }
  383.       else
  384.          {
  385.          AMPMIX.ulOperation = OPERATION_RECORD;
  386.          }
  387.  
  388.       /* Set flag to state that an element has been loaded */
  389.  
  390.       ulpInstance->fFileExists = TRUE;
  391.  
  392.       /* Flag to indicate that card has been inited */
  393.  
  394.      ulpInstance->ulCapabilities =  ( CAN_INSERT | CAN_DELETE | CAN_UNDOREDO +
  395.                                  CAN_SAVE   | CAN_INSERT | CAN_RECORD  );
  396.  
  397.  
  398.      /*-------------------------------------------------------
  399.      * Readonly means we cannot write to the file, therefore,
  400.      * there is no need to create temporary files etc. since we
  401.      * cannot change the original file.
  402.      *--------------------------------------------------------*/
  403.  
  404.      if ( ulParam1 & MCI_READONLY )
  405.  
  406.         {
  407.         ulpInstance->ulOpenTemp = MCI_FALSE;
  408.         ulpInstance->ulCapabilities &= ~( CAN_SAVE | CAN_RECORD );
  409.         }
  410.      else
  411.         {
  412.         ulpInstance->ulOpenTemp = MCI_TRUE;
  413.         } /* else read only flag was NOT specified */
  414.  
  415.  
  416.  
  417.      } /* if open_mmio is passed in */
  418.  
  419.  
  420.   return ( ulrc );
  421.  
  422. } /* OpenHandle */
  423.  
  424.  
  425. /********************* START OF SPECIFICATIONS *******************************
  426. *
  427. * SUBROUTINE NAME: Process Element
  428. *
  429. * DESCRIPTIVE NAME: Opens a file element
  430. *
  431. * FUNCTION: Opens a file and prepares a device to play and record.
  432. *
  433. *
  434. * NOTES:
  435. * ENTRY POINTS:
  436. *
  437. * INPUT:
  438. *
  439. * EXIT-NORMAL: MCIERR_SUCCESS.
  440. *
  441. * EXIT_ERROR:  Error Code.
  442. *
  443. * EFFECTS:
  444. *
  445. *
  446. * EXTERNAL REFERENCES:
  447. *
  448. *********************** END OF SPECIFICATIONS *******************************/
  449.  
  450. ULONG ProcessElement( INSTANCE *ulpInstance,
  451.                       ULONG    ulParam1,
  452.                       ULONG    ulOperation )
  453. {
  454.  
  455.    ULONG   ulrc;
  456.    ULONG   ulmmioOpenFlag;
  457.  
  458.    /******************************************************
  459.    * If the caller wants to open temp, then modify the flags
  460.    * Temp files require that no one else be able to open
  461.    * the same file--so use exclusive.  If we are not
  462.    * using temp files (for instance, if the READ_ONLY flag
  463.    * is passed) then allow anyone to open the file.
  464.    ******************************************************/
  465.  
  466.    if ( ulpInstance->ulOpenTemp )
  467.       {
  468.       ulmmioOpenFlag = MMIO_READWRITE | MMIO_EXCLUSIVE;
  469.       }
  470.    else
  471.       {
  472.       ulmmioOpenFlag = MMIO_READ | MMIO_DENYNONE;
  473.       }
  474.  
  475.    /* Ask mmio to open the file */
  476.  
  477.    ulrc = OpenFile( ulpInstance, ulmmioOpenFlag );
  478.  
  479.    /* If open preceded smoothly, then the file exists!! */
  480.  
  481.    if ( !ulrc )
  482.      {
  483.      /* If we created the file, it has no data so go into record mode */
  484.  
  485.      if ( ulpInstance->ulCreatedName )
  486.         {
  487.         SetWaveDeviceDefaults ( ulpInstance, OPERATION_RECORD );
  488.  
  489.         /* ensure that the header is up to date */
  490.  
  491.         ulrc = SetAudioHeader( ulpInstance );
  492.  
  493.         }
  494.  
  495.      else /* the file has data so default to playback mode */
  496.         {
  497.         AMPMIX.ulOperation = OPERATION_PLAY;
  498.         }
  499.      } /* if no error on OpenFile */
  500.    else
  501.      {
  502.      /******************************************
  503.      * We will get file not found error if the
  504.      * file does not exist, so try to create it.
  505.      *******************************************/
  506.  
  507.      if (ulrc == ERROR_FILE_NOT_FOUND)
  508.         {
  509.         /********************************
  510.         * if this is a read only file then
  511.         * we cannot create a new one
  512.         *********************************/
  513.  
  514.         if ( ulParam1 & MCI_READONLY )
  515.            {
  516.            return ( MCIERR_FILE_NOT_FOUND );
  517.            }
  518.  
  519.         AMPMIX.ulOperation = OPERATION_RECORD;
  520.         ulpInstance->ulCreateFlag = CREATE_STATE;
  521.         ulmmioOpenFlag = MMIO_CREATE | MMIO_READWRITE | MMIO_EXCLUSIVE;
  522.  
  523.         /********************************
  524.         * Try to create the element
  525.         *******************************/
  526.  
  527.         ulrc = OpenFile ( ulpInstance, ulmmioOpenFlag);
  528.  
  529.         /* If we fail, try to return an MCI error */
  530.  
  531.         if (ulrc)
  532.            {
  533.            if ( ulrc == ERROR_FILE_NOT_FOUND )
  534.               {
  535.               return ( MCIERR_FILE_NOT_FOUND );
  536.               }
  537.            else
  538.               {
  539.               return (ulrc);
  540.               }
  541.            } /* if an error occurred */
  542.  
  543.         /* Ensure that the header is up to date */
  544.  
  545.         SetWaveDeviceDefaults (ulpInstance, OPERATION_RECORD);
  546.         ulrc = SetAudioHeader( ulpInstance );
  547.  
  548.         }
  549.      else
  550.         {
  551.         /* if open or load fail--we have no element */
  552.  
  553.         ulpInstance->fFileExists = FALSE;
  554.  
  555.         return ( ulrc );
  556.         }
  557.  
  558.      } /* else there was an error on the load open */
  559.  
  560.    return ( ulrc );
  561.  
  562. } /* ProcessElement */
  563.  
  564.  
  565.  
  566. /********************* START OF SPECIFICATIONS *******************************
  567. *
  568. * SUBROUTINE NAME: SetupTempFiles
  569. *
  570. * DESCRIPTIVE NAME: Prepares for temporary file work
  571. *
  572. * FUNCTION: If the io proc supports temp files and the user has not requested
  573. *           a readonly file, we will try to open a temp file
  574. *
  575. *
  576. * NOTES:
  577. * ENTRY POINTS:
  578. *
  579. * INPUT:
  580. *
  581. * EXIT-NORMAL: Return Code 0.
  582. *
  583. * EXIT_ERROR:  Error Code.
  584. *
  585. * EFFECTS:
  586. *
  587. * INTERNAL REFERENCES: HhpAllocMem().
  588. *
  589. * EXTERNAL REFERENCES:
  590. *
  591. *********************** END OF SPECIFICATIONS *******************************/
  592.  
  593.  
  594. ULONG SetupTempFiles( INSTANCE   *ulpInstance,
  595.                       ULONG      ulParam1 )
  596.  
  597.  
  598. {
  599.  
  600.   ULONG ulrc;
  601.  
  602.   CHAR  TempPath[ CCHMAXPATH ]; // holds path for temp files
  603.  
  604.  
  605.   /**********************************************
  606.   * Query the default path to place temp files and
  607.   * pass it on to the IO Proc
  608.   **********************************************/
  609.  
  610.   ulrc = mciQuerySysValue( MSV_WORKPATH, TempPath );
  611.  
  612.   if ( !ulrc )
  613.      {
  614.      return (MCIERR_INI_FILE);
  615.      }
  616.  
  617.   /*****************************************************
  618.   * This message illustrates the use of mmioSendMessage:
  619.   * we are asking the IO Proc that we have loaded to
  620.   * make all subsequent changes temporary (i.e. if no
  621.   * save message is sent, then the file will remain in
  622.   * the original condition.
  623.   *****************************************************/
  624.  
  625.   ulrc = mmioSendMessage( ulpInstance->hmmio,
  626.                           MMIOM_TEMPCHANGE,
  627.                           ( LONG ) TempPath,
  628.                           0 );
  629.   if (ulrc)
  630.      {
  631.      /* Use mmioGetLastError to get additional detail about the error */
  632.  
  633.      ulrc = mmioGetLastError( ulpInstance->hmmio );
  634.  
  635.      /* Cannot write means that the disk is full */
  636.  
  637.      if (ulrc == MMIOERR_CANNOTWRITE )
  638.         {
  639.         return MCIERR_TARGET_DEVICE_FULL;
  640.         }
  641.      else
  642.         {
  643.         return ( ulrc );
  644.         }
  645.  
  646.      } /* if there is an error */
  647.  
  648.   /* Flag to indicate that temporary changes are active */
  649.  
  650.   ulpInstance->ulUsingTemp = MCI_TRUE;
  651.  
  652.   return ( ulrc );
  653.  
  654.  
  655. } /* SetupTempFiles */
  656.  
  657.  
  658.  
  659. /********************* START OF SPECIFICATIONS *******************************
  660. *
  661. * SUBROUTINE NAME: OpenInit
  662. *
  663. * DESCRIPTIVE NAME: Sets up variables for open
  664. *
  665. * FUNCTION: Initializes variables to be used by the instance
  666. *
  667. *
  668. * NOTES:
  669. * ENTRY POINTS:
  670. *
  671. * INPUT:
  672. *
  673. * EXIT-NORMAL: Return Code 0.
  674. *
  675. * EXIT_ERROR:  Error Code.
  676. *
  677. * EFFECTS:
  678. *
  679. * INTERNAL REFERENCES: HhpAllocMem().
  680. *
  681. * EXTERNAL REFERENCES:
  682. *
  683. *********************** END OF SPECIFICATIONS *******************************/
  684.  
  685.  
  686. void OpenInit( INSTANCE  *ulpInstance )
  687.  
  688.  
  689. {
  690.  
  691.   extern     HID                 hidASource;
  692.   extern     HID                 hidATarget;
  693.   extern     HID                 hidBSource;
  694.   extern     HID                 hidBTarget;
  695.  
  696.   ULONG      ulrc;
  697.  
  698.  
  699.   ulpInstance->ulCapabilities = CAN_RECORD | CAN_SAVE | CAN_INSERT;
  700.  
  701.   /* Stream hid's */
  702.  
  703.   ulpInstance->StreamInfo.hidASource = hidASource;
  704.   ulpInstance->StreamInfo.hidATarget = hidATarget;
  705.   ulpInstance->StreamInfo.hidBSource = hidBSource;
  706.   ulpInstance->StreamInfo.hidBTarget = hidBTarget;
  707.  
  708.   /************************************
  709.   * Wave Record Defaults.
  710.   ***********************************/
  711.  
  712.   SetWaveDeviceDefaults (ulpInstance, OPERATION_RECORD);
  713.  
  714.   /*--------------------------------------------
  715.   * In case no device is opened, default to
  716.   * the mode requested in the ini file.
  717.   *--------------------------------------------*/
  718.  
  719.   AMPMIX.ulOperation = ulpInstance->lDefaultOperation;// Play or Record
  720.  
  721.  
  722.   STRMSTATE = NO_STATE;
  723.  
  724.   /*---------------------------------------------
  725.   * The MMPM2.INI file contains two variables that
  726.   * a streaming MCD should retrieve.  The first one
  727.   * QOS_VALUE (Quality of Service) contains settings
  728.   * which describe the quality of service that the
  729.   * network the user is streaming from will try to
  730.   * support (e.g. GUARANTEED or DONTCARE).  If this
  731.   * quality of service is not available, then another
  732.   * variable (QOSERRORFLAG) describes whether or not
  733.   * to notify the caller.
  734.   *--------------------------------------------------*/
  735.  
  736.  
  737.   ulrc = mciQuerySysValue( MSV_SYSQOSVALUE, &ulpInstance->lQosValue );
  738.  
  739.   if ( !ulrc )
  740.      {
  741.      ulpInstance->lQosValue = DONTRESERVE;
  742.      }
  743.  
  744.   ulrc = mciQuerySysValue( MSV_SYSQOSERRORFLAG, &ulpInstance->lQOSReporting );
  745.  
  746.   if ( !ulrc )
  747.      {
  748.      ulpInstance->lQOSReporting = ERROR_DEFAULT;
  749.      }
  750.  
  751.  
  752.  
  753.  
  754.  
  755. } /* OpenInit */
  756.  
  757.  
  758.  
  759. /********************* START OF SPECIFICATIONS *******************************
  760. *
  761. * SUBROUTINE NAME: DetermineConnections
  762. *
  763. * DESCRIPTIVE NAME: Loads appropriate vendor specific device
  764. *
  765. * FUNCTION: In an ideal world, this function would determine who we are
  766. *           connected to from MDM, load it and let it set up the stream
  767. *           handlers( i.e. probably in the next release).  Currently,
  768. *           it just loads the VSD (i.e. MAJOR hardcode )
  769. *
  770. *
  771. *
  772. * NOTES:
  773. * ENTRY POINTS:
  774. *
  775. * INPUT:
  776. *
  777. * EXIT-NORMAL: Return Code 0.
  778. *
  779. * EXIT_ERROR:  Error Code.
  780. *
  781. * EFFECTS:
  782. *
  783. * INTERNAL REFERENCES: HhpAllocMem().
  784. *
  785. * EXTERNAL REFERENCES:
  786. *
  787. *********************** END OF SPECIFICATIONS *******************************/
  788.  
  789.  
  790. ULONG DetermineConnections( INSTANCE           *ulpInstance,
  791.                             MMDRV_OPEN_PARMS   *pDrvOpenParams )
  792.  
  793.  
  794.   {
  795.   // should this be max path????
  796.  
  797.   CHAR szLoadError[MAX_ERROR_LENGTH];  // DosLoadModule
  798.  
  799.   ULONG ulrc;
  800.  
  801.   /*****************************************************
  802.   * Note, this section will have to change when improved
  803.   * connector support is added!!!
  804.   ******************************************************/
  805.  
  806.   /*******************************
  807.   * Load the Devspcfc DLL
  808.   ********************************/
  809.  
  810.   if ( (ulrc = DosLoadModule ( szLoadError,
  811.                                sizeof( szLoadError ),
  812.                                pDrvOpenParams->szDevDLLName,
  813.                                &(ulpInstance->hModHandle))))
  814.      {
  815.      return ( ulrc );
  816.      }
  817.  
  818.   strcpy ((PSZ)AMPMIX.szDriverName, pDrvOpenParams->szDevDLLName );
  819.  
  820.   /*****************************************
  821.   * Get the AudioIF Driver Entry point
  822.   ******************************************/
  823.  
  824.   ulrc = DosQueryProcAddr ( ulpInstance->hModHandle,
  825.                             0L,
  826.                             VSDI,
  827.                             (PFN *) &ulpInstance->pfnVSD) ;
  828.  
  829.  
  830.   return ( ulrc );
  831.  
  832. } /* DetermineConnections */
  833.  
  834.  
  835.  
  836.  
  837. /********************* START OF SPECIFICATIONS *******************************
  838. *
  839. * SUBROUTINE NAME: ConnectToAmp
  840. *
  841. * DESCRIPTIVE NAME: Connects wave audio to the amp mixer.
  842. *
  843. * FUNCTION: Do the work necessary to ensure that the ini file contains valid
  844. *           information about who we are connected to.  In addition,
  845. *           it will open the amp mixer and receive the associated stream
  846. *           handler from it (next release)?
  847. *
  848. *
  849. *
  850. * NOTES:
  851. * ENTRY POINTS:
  852. *
  853. * INPUT:
  854. *
  855. * EXIT-NORMAL: Return Code 0.
  856. *
  857. * EXIT_ERROR:  Error Code.
  858. *
  859. * EFFECTS:
  860. *
  861. * INTERNAL REFERENCES: HhpAllocMem().
  862. *
  863. * EXTERNAL REFERENCES:
  864. *
  865. *********************** END OF SPECIFICATIONS *******************************/
  866.  
  867.  
  868. ULONG ConnectToAmp( INSTANCE           *ulpInstance,
  869.                     MMDRV_OPEN_PARMS   *pDrvOpenParams,
  870.                     ULONG              ulOpenFlags )
  871.  
  872. {
  873.  
  874.   ULONG                ulDeviceTypeID;         // device id of connected device
  875.   ULONG                ulrc;                   // return code variable
  876.  
  877.   USHORT               usConnLength;           // length of conn struct
  878.  
  879.   MCI_AMP_OPEN_PARMS   MCIAmpOpenParms;          // MCI AmpMixer Open Parameters
  880.   DEFAULTCONNECTIONS2  DefCon;                   // MCI Connections Block
  881.   CHAR                 szPDDName[MAX_PDD_NAME];
  882.  
  883.  
  884.   /*****************************
  885.   * Obtain WaveAudio Device ID
  886.   *****************************/
  887.   ulpInstance->usWaveDeviceID = pDrvOpenParams->usDeviceID;
  888.  
  889.   ulDeviceTypeID = MAKEULONG ( MCI_DEVTYPE_WAVEFORM_AUDIO,
  890.                                pDrvOpenParams->usDeviceOrd);
  891.  
  892.   /******************************************************
  893.   * Ensure that the INI file contains the right device id
  894.   ******************************************************/
  895.  
  896.   if ( pDrvOpenParams->usDeviceType != MCI_DEVTYPE_WAVEFORM_AUDIO )
  897.      {
  898.      return ( MCIERR_INI_FILE );
  899.      }
  900.  
  901.   usConnLength = sizeof(DEFAULTCONNECTIONS2);
  902.  
  903.   ulrc =  mciQueryDefaultConnections ( ulDeviceTypeID,
  904.                                        &DefCon,
  905.                                        &usConnLength);
  906.  
  907.   /******************************************************
  908.   * Ensure that the INI file says that we are connected
  909.   * to an amp mixer.  If it says that we are connected
  910.   * to ourselves, return an error.
  911.   ******************************************************/
  912.  
  913.   if ( ULONG_LOWD( DefCon.dwDeviceTypeID2 ) == MCI_DEVTYPE_WAVEFORM_AUDIO )
  914.      {
  915.      return ( MCIERR_INI_FILE );
  916.      }
  917.  
  918.   /******************************
  919.   * Open an AMP/MIXER Instance
  920.   ******************************/
  921.  
  922.   MCIAmpOpenParms.pszDeviceType = (PSZ) DefCon.dwDeviceTypeID2;
  923.  
  924.   MCIAmpOpenParms.hwndCallback = (ULONG) NULL;
  925.  
  926.   GetPDDName (DefCon.dwDeviceTypeID2, szPDDName);
  927.  
  928.   strcpy ( ulpInstance->szAudioDevName, szPDDName);
  929.  
  930.   /* Copy the name of the pdd + vsd dll to amp structure */
  931.  
  932.   strcpy ((PSZ) AMPMIX.szDeviceName,
  933.           ulpInstance->szAudioDevName);
  934.  
  935.   strcpy ((PSZ) ulpInstance->StreamInfo.AudioDCB.szDevName,
  936.           ulpInstance->szAudioDevName);
  937.  
  938.   /*******************************************
  939.   * The current amp/mixer uses an undocumented
  940.   * structure.  Pass this structure in on the
  941.   * open also.
  942.   ********************************************/
  943.  
  944.   MCIAmpOpenParms.pDevDataPtr = (PVOID) &MIX;
  945.  
  946.   /* Open what we are connected to--usually the amp */
  947.  
  948.   ulrc = mciSendCommand (0,
  949.                          MCI_OPEN,
  950.                          MCI_OPEN_TYPE_ID| MCI_WAIT| ulOpenFlags,
  951.                          (PVOID) &MCIAmpOpenParms,
  952.                          0);
  953.  
  954.   /* Remember the amp device id so that we can close it */
  955.  
  956.   ulpInstance->usAmpDeviceID = MCIAmpOpenParms.usDeviceID;
  957.  
  958.   return ( ulrc );
  959.  
  960.  
  961. } /* ConnectToAmp */
  962.  
  963.  
  964.  
  965. /********************* START OF SPECIFICATIONS *******************************
  966. *
  967. * SUBROUTINE NAME: StreamSetup
  968. *
  969. * DESCRIPTIVE NAME: Gets the stream handlers
  970. *
  971. * FUNCTION: Do the work necessary to load the correct stream handlers.  Currently
  972. *           this is hardcoded, however, in the future we will obtain this info
  973. *           from connections/ampmix etc(?)
  974. *
  975. *
  976. *
  977. * NOTES:
  978. * ENTRY POINTS:
  979. *
  980. * INPUT:
  981. *
  982. * EXIT-NORMAL: Return Code 0.
  983. *
  984. * EXIT_ERROR:  Error Code.
  985. *
  986. * EFFECTS:
  987. *
  988. * INTERNAL REFERENCES: HhpAllocMem().
  989. *
  990. * EXTERNAL REFERENCES:
  991. *
  992. *********************** END OF SPECIFICATIONS *******************************/
  993.  
  994.  
  995. ULONG StreamSetup ( void )
  996.  
  997. {
  998. extern     HID                 hidASource;
  999. extern     HID                 hidATarget;
  1000.  
  1001. extern     HID                 hidBSource;
  1002. extern     HID                 hidBTarget;
  1003.  
  1004.  
  1005.   ULONG ulrc = MCIERR_SUCCESS;
  1006.  
  1007.  
  1008.   /*********************************************************
  1009.   * Get 'A' stream Handler Handles for Source & target operations
  1010.   * The file system stream handler is the default 'A' handler
  1011.   * but the memory stream handler will be used for playlists.
  1012.   **********************************************************/
  1013.  
  1014.  
  1015.      if (ulrc = SpiGetHandler((PSZ)DEFAULT_SOURCE_HANDLER_NAME,
  1016.                                &hidASource,
  1017.                                &hidATarget))
  1018.         {
  1019.         return ( ulrc );
  1020.         }
  1021.  
  1022.  
  1023.   /***********************************************************
  1024.   * Get 'B' stream Handler Handles for Source & target operations
  1025.   * The audio stream handler is considered the B stream handler
  1026.   * since it will usually be the target.
  1027.   *************************************************************/
  1028.  
  1029.   ulrc = SpiGetHandler( (PSZ)DEFAULT_TARGET_HANDLER_NAME,
  1030.                         &hidBSource,
  1031.                         &hidBTarget);
  1032.  
  1033.   return ( ulrc );
  1034.  
  1035. } /* StreamSetup */
  1036.  
  1037.  
  1038.  
  1039. /********************* START OF SPECIFICATIONS *******************************
  1040. *
  1041. * SUBROUTINE NAME: CreateSemaphores
  1042. *
  1043. * DESCRIPTIVE NAME: Creates semaphores for instance
  1044. *
  1045. * FUNCTION: Creates all the semaphores needed for playing, recording and
  1046. *           serializing access to necessary instance data.
  1047. *
  1048. *
  1049. *
  1050. * NOTES:
  1051. * ENTRY POINTS:
  1052. *
  1053. * INPUT:
  1054. *
  1055. * EXIT-NORMAL: Return Code 0.
  1056. *
  1057. * EXIT_ERROR:  Error Code.
  1058. *
  1059. * EFFECTS:
  1060. *
  1061. * INTERNAL REFERENCES: HhpAllocMem().
  1062. *
  1063. * EXTERNAL REFERENCES:
  1064. *
  1065. *********************** END OF SPECIFICATIONS *******************************/
  1066.  
  1067.  
  1068. ULONG CreateSemaphores( FUNCTION_PARM_BLOCK   *pFuncBlock )
  1069.  
  1070.  
  1071. {
  1072.  
  1073.    ULONG        ulrc;
  1074.    INSTANCE     *pInstance = ( INSTANCE * ) pFuncBlock->pInstance;
  1075.  
  1076.    /*********************************************
  1077.    * Create an event semaphore used in the
  1078.    * streaming operations (see admcplay, admcrecd).
  1079.    *********************************************/
  1080.  
  1081.    ulrc = DosCreateEventSem ( (ULONG) NULL,
  1082.                               (PHEV) &pInstance->hEventSem,
  1083.                               DC_SEM_SHARED,
  1084.                               FALSE );
  1085.  
  1086.    if (ulrc)
  1087.       {
  1088.       return (ulrc);
  1089.       }
  1090.  
  1091.    /************************************************
  1092.    * Create an event semaphore used to synchronize
  1093.    * various threads (See admcplay.c + admcrecd.c).
  1094.    *************************************************/
  1095.  
  1096.    ulrc = DosCreateEventSem ( (ULONG) NULL,
  1097.                               (PHEV) &pInstance->hThreadSem,
  1098.                               DC_SEM_SHARED,
  1099.                               FALSE );
  1100.    if (ulrc)
  1101.       {
  1102.       return (ulrc);
  1103.       }
  1104.  
  1105.    ulrc = DosCreateMutexSem ( (ULONG) NULL,
  1106.                               (PHEV) &pInstance->hmtxDataAccess,
  1107.                               DC_SEM_SHARED,
  1108.                               FALSE);
  1109.    if (ulrc)
  1110.       {
  1111.       return (ulrc);      /* Failed Sem Create */
  1112.       }
  1113.  
  1114.    /************************************************
  1115.    * Create semaphore which will prevent MCI_CLOSE
  1116.    * from freeing instance before all threads are
  1117.    * done processing.
  1118.    ************************************************/
  1119.  
  1120.    ulrc = DosCreateMutexSem ( (ULONG) NULL,
  1121.                               (PHEV) &pInstance->hmtxCloseAccess,
  1122.                               DC_SEM_SHARED,
  1123.                               FALSE);
  1124.    if (ulrc)
  1125.       {
  1126.       return (ulrc);      /* Failed Sem Create */
  1127.       }
  1128.  
  1129.  
  1130.  
  1131.    /* Create semaphore to ensure that only one thread can abort another */
  1132.  
  1133.    ulrc = DosCreateMutexSem ( NULL,
  1134.                               &pInstance->hmtxNotifyAccess,
  1135.                               DC_SEM_SHARED,
  1136.                               FALSE);
  1137.    if (ulrc)
  1138.       {
  1139.       return (ulrc);      /* Failed Sem Create */
  1140.       }
  1141.  
  1142.    /* Create semaphore to ensure that MCIDRV_SAVE is never locked out*/
  1143.  
  1144.    ulrc = DosCreateMutexSem ( NULL,
  1145.                               &pInstance->hmtxSaveAccess,
  1146.                               DC_SEM_SHARED,
  1147.                               FALSE);
  1148.  
  1149.  
  1150.    /***********************************************
  1151.    * No need to check the return code, since we have
  1152.    * to do a return to leave anyway
  1153.    ************************************************/
  1154.  
  1155.    return ( ulrc );
  1156.  
  1157.  
  1158. } /* Create Semaphores */
  1159.  
  1160.  
  1161. /********************* START OF SPECIFICATIONS *******************************
  1162. *
  1163. * SUBROUTINE NAME: NotifyWaitSetup
  1164. *
  1165. * DESCRIPTIVE NAME: Prepares instance for either notify/wait/asynchronous operation
  1166. *
  1167. * FUNCTION: Stores callbacks and sets up the instance for either notify, wait
  1168. *           or asynchronous operation.
  1169. *
  1170. *
  1171. *
  1172. * NOTES:
  1173. * ENTRY POINTS:
  1174. *
  1175. * INPUT:
  1176. *
  1177. * EXIT-NORMAL: MCIERR_SUCCESS.
  1178. *
  1179. * EXIT_ERROR:  Error Code.
  1180. *
  1181. * EFFECTS:
  1182. *
  1183. * INTERNAL REFERENCES: HhpAllocMem().
  1184. *
  1185. * EXTERNAL REFERENCES:
  1186. *
  1187. *********************** END OF SPECIFICATIONS *******************************/
  1188.  
  1189.  
  1190. void NotifyWaitSetup( FUNCTION_PARM_BLOCK *pFuncBlock,
  1191.                       USHORT              usMessage,
  1192.                       ULONG               ulParam1,
  1193.                       ULONG               ulParam2 )
  1194.  
  1195. {
  1196.  
  1197.  
  1198.   if (!(ulParam1 & MCI_WAIT) )
  1199.       {
  1200.  
  1201.       if (usMessage != MCI_OPEN)
  1202.           {
  1203.           pFuncBlock->pInstance->fFakeNotify = FALSE;
  1204.  
  1205.  
  1206.           /*****************************
  1207.           * Default to a Notify
  1208.           ******************************/
  1209.           pFuncBlock->ulParam1 |= MCI_NOTIFY;
  1210.  
  1211.  
  1212.           /********************************
  1213.           * Turn The Notify Flag On
  1214.           *********************************/
  1215.  
  1216.           pFuncBlock->ulNotify = TRUE;
  1217.  
  1218.           /*********************************
  1219.           * Get The Window Callback Handle
  1220.           *********************************/
  1221.  
  1222.           if ( ulParam1 & MCI_NOTIFY )
  1223.              {
  1224.              if ( usMessage == MCI_PLAY || usMessage == MCI_RECORD )
  1225.                {
  1226.                pFuncBlock->pInstance->hwndOldCallBack = pFuncBlock->pInstance->hwndCallBack;
  1227.                pFuncBlock->pInstance->hwndCallBack = (((PMCI_GENERIC_PARMS)ulParam2)->hwndCallback);
  1228.                }
  1229.              else
  1230.                {
  1231.                pFuncBlock->hwndCallBack = (((PMCI_GENERIC_PARMS)ulParam2)->hwndCallback);
  1232.                }
  1233.              }
  1234.           else
  1235.           /********************************************************
  1236.           * Even if the caller did not specify the MCI_NOTIFY
  1237.           * flag, and they didn't specify wait, we will treat
  1238.           * this call just like a notify, EXCEPT that when we
  1239.           * call MDMDriverNotify, we will pass a bogus
  1240.           * callback.  This prevents us from having to do a
  1241.           * tremendous amount of additional processing and the
  1242.           * caller is happy because the work is done asychronously
  1243.           *********************************************************/
  1244.  
  1245.              {
  1246.              /*---------------------------------------------------------
  1247.              * Set flag to indicate that although we are going
  1248.              * to act like it is a notify, the caller did not
  1249.              * really pass in the notify flag.  This will be
  1250.              * important when we have a situation like a play with
  1251.              * a notify, followed by a play without a wait or notify.
  1252.              * In this scenario, an aborted message should be
  1253.              * posted by the first play.
  1254.              *--------------------------------------------------------*/
  1255.  
  1256.              pFuncBlock->pInstance->fFakeNotify = TRUE;
  1257.  
  1258.              if ( usMessage == MCI_PLAY || usMessage == MCI_RECORD )
  1259.                {
  1260.                pFuncBlock->pInstance->hwndOldCallBack = pFuncBlock->pInstance->hwndCallBack;
  1261.                pFuncBlock->pInstance->hwndCallBack = 0;
  1262.                }
  1263.              else
  1264.                {
  1265.                pFuncBlock->hwndCallBack = 0;
  1266.                }
  1267.  
  1268.              } /* if !MCI_NOTIFY */
  1269.  
  1270.           } /* Message .NE. MCI Open */
  1271.  
  1272.        } /* Wait flag is not on */
  1273.  
  1274.   return;
  1275.  
  1276. } /* NotifyWaitSetup */
  1277.  
  1278.  
  1279. /********************* START OF SPECIFICATIONS *******************************
  1280. *
  1281. * SUBROUTINE NAME: AllocateInstance
  1282. *
  1283. * DESCRIPTIVE NAME: allocates memory for the instance etc.
  1284. *
  1285. * FUNCTION: Stores callbacks and sets up the instance for either notify, wait
  1286. *           or asynchronous operation.
  1287. *
  1288. *
  1289. *
  1290. * NOTES:
  1291. * ENTRY POINTS:
  1292. *
  1293. * INPUT:
  1294. *
  1295. * EXIT-NORMAL: Return Code 0.
  1296. *
  1297. * EXIT_ERROR:  Error Code.
  1298. *
  1299. * EFFECTS:
  1300. *
  1301. * INTERNAL REFERENCES: HhpAllocMem().
  1302. *
  1303. * EXTERNAL REFERENCES:
  1304. *
  1305. *********************** END OF SPECIFICATIONS *******************************/
  1306.  
  1307.  
  1308. ULONG AllocateInstance( FUNCTION_PARM_BLOCK *pFuncBlock )
  1309.  
  1310.  
  1311.  
  1312. {
  1313.  
  1314.   extern HHUGEHEAP     heap;                // Global MCD Heap
  1315.  
  1316.  
  1317.   AcquireProcSem ();
  1318.  
  1319.   /**************************************
  1320.   * Waveform audio instance structure
  1321.   ****************************************/
  1322.  
  1323.   if (!(pFuncBlock->pInstance = HhpAllocMem ( heap,
  1324.                                               sizeof (INSTANCE))))
  1325.      {
  1326.      ReleaseProcSem ();
  1327.      return ( MCIERR_OUT_OF_MEMORY );
  1328.      }
  1329.  
  1330.   ReleaseProcSem ();
  1331.  
  1332.   return ( MCIERR_SUCCESS );
  1333.  
  1334. } /* AllocateInstance */
  1335.  
  1336.