home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / mm / admct / audiosub.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  78KB  |  2,398 lines

  1. /*******************************************************************************
  2. *
  3. * SOURCE FILE NAME: AUDIOSUB.C
  4. *
  5. * DESCRIPTIVE NAME: Support functions for waveaudio MCI Driver.
  6. *
  7. *              Copyright (c) IBM Corporation  1991, 1993
  8. *                        All Rights Reserved
  9. *
  10. * NOTES: This source illustrates the following concepts.
  11. *         A. Correct processing of notifications.
  12. *         B. Handling calls the are neither MCI_WAIT or
  13. *            MCI_NOTIFY (PostMDMMessage).
  14. *         C.
  15. *         D. Using mmioGetHeader to obtain audio settings from a file (GetHeader).
  16. *         E. Creating a playlist stream (AssociatePlaylist).
  17. *         F. Installing an IO Proc (InstallIOProc).
  18. *         G. Communicating with IO Procs with different capabilites (OpenFile).
  19. *         H. Processing audio files with various file formats (OpenFile).
  20. *         H. Time format conversion (ConvertToMM + ConvertTimeFormat).
  21. *         I. Creating an SPI stream (CreateNAssociateStream)
  22. *         J. Associating an SPI stream (CreateNAssociateStream)
  23. *         K. Setting an event for use in play to/record to (DoTillEvent).
  24. *         L. Enabling the status_level event
  25. * FUNCTION: PostMDMMessage
  26. *           InstallIOProc
  27. *           OpenFile
  28. *           ConvertToMM
  29. *           ConvertTimeUnits
  30. *           CreateNAssocStream
  31. *           DoTillEvent
  32. *
  33. *********************** END OF SPECIFICATIONS ***********************/
  34.  
  35. #define INCL_BASE
  36. #define INCL_DOSMODULEMGR
  37. #define INCL_DOSSEMAPHORES
  38. #define INCL_MMIO_CODEC
  39. #define INCL_AUDIO_CODEC_ONLY
  40.  
  41. #include <os2.h>                        // OS2 defines.
  42. #include <string.h>                     // String functions.
  43. #include <os2medef.h>                   // MME includes files.
  44. #include <math.h>                       // Standard Math Lib
  45. #include <stdlib.h>                     // Standard Library
  46. #include <ssm.h>                        // SSM spi includes.
  47. #include <meerror.h>                    // MM Error Messages.
  48. #include <mmioos2.h>                    // MMIO Include.
  49. #include <mcios2.h>                     // MM System Include.
  50. #include <mmdrvos2.h>                   // MCI Driver include.
  51. #include <mcd.h>                        // AudioIFDriverInterface.
  52. #include <hhpheap.h>                    // Heap Manager Definitions
  53. #include <admcdat.h>
  54. #include <qos.h>
  55. #include <audiomcd.h>                   // Component Definitions.
  56. #include <admcfunc.h>
  57.  
  58.  
  59. #include <codec.h>
  60. //#include "wcodec.h"
  61.  
  62.  
  63.  
  64.  
  65. /********************* START OF SPECIFICATIONS *******************************
  66. *
  67. * SUBROUTINE NAME: PostMDMMessage()
  68. *
  69. * DESCRIPTIVE NAME:
  70. *
  71. * FUNCTION: This function informs the caller that a given command
  72. *           has completed (either succesfully or with an error).
  73. *           All MCI functions that this MCD handles process their
  74. *           notifications here.
  75. *
  76. *           This function uses mdmDriverNotify to inform the caller
  77. *           of completion.
  78. *
  79. *
  80. * NOTES:
  81. * ENTRY POINTS:
  82. *
  83. * INPUT:
  84. *
  85. * EXIT-NORMAL: MCIERR_SUCCESS.
  86. *
  87. * EXIT_ERROR:  Error Code.
  88. *
  89. * EFFECTS:
  90. *
  91. * INTERNAL REFERENCES:
  92. *
  93. * EXTERNAL REFERENCES: mdmDriverNotify
  94. *
  95. *********************** END OF SPECIFICATIONS *******************************/
  96.  
  97. RC PostMDMMessage ( ULONG                ulErrCode,
  98.                     USHORT               usMessage,
  99.                     FUNCTION_PARM_BLOCK  *pFuncBlock)
  100.  
  101. {
  102.  
  103.   USHORT  usNotifyType;
  104.   USHORT  usUserParm;
  105.   HWND    hWnd;
  106.  
  107.  
  108.  
  109.   /***************************************************************
  110.   * Determine the MCI Notification Code for this message
  111.   ****************************************************************/
  112.  
  113.   switch ( ULONG_LOWD(ulErrCode) )
  114.   {
  115.  
  116.   case MCI_NOTIFY_SUCCESSFUL:
  117.         usNotifyType = MCI_NOTIFY_SUCCESSFUL;
  118.        break;
  119.  
  120.   case MCI_NOTIFY_SUPERSEDED:
  121.         usNotifyType = MCI_NOTIFY_SUPERSEDED;
  122.        break;
  123.  
  124.   case MCI_NOTIFY_ABORTED:
  125.         usNotifyType = MCI_NOTIFY_ABORTED;
  126.        break;
  127.  
  128.   default:
  129.         usNotifyType = (USHORT)ulErrCode;
  130.        break;
  131.   }
  132.  
  133.  
  134.   /*******************************************************************
  135.   * MCI Messages PLAY and RECORD call this routine to notify the
  136.   * application asynchronously. The user parameter from the instance
  137.   * block is used for notifying play/record message status. All
  138.   * other messages use the function block user parameter.
  139.   *******************************************************************/
  140.  
  141.   if (usMessage != MCI_PLAY && usMessage != MCI_RECORD)
  142.      {
  143.      usUserParm = pFuncBlock->usUserParm;
  144.      hWnd = pFuncBlock->hwndCallBack;
  145.      }
  146.   else
  147.      {
  148.      usUserParm = pFuncBlock->pInstance->usUserParm;
  149.      hWnd = pFuncBlock->pInstance->hwndCallBack;
  150.      }
  151.  
  152.   /* Inform the application of the event */
  153.  
  154.   mdmDriverNotify (pFuncBlock->pInstance->usWaveDeviceID,
  155.                    hWnd,
  156.                    MM_MCINOTIFY,
  157.                    usUserParm,
  158.                    MAKEULONG (usMessage, usNotifyType));
  159.  
  160.  
  161.   return ( MCIERR_SUCCESS );
  162. }
  163.  
  164.  
  165.  
  166.  
  167. /********************* START OF SPECIFICATIONS *******************************
  168. *
  169. * SUBROUTINE NAME:              SetAudioDevice()
  170. *
  171. * DESCRIPTIVE NAME:
  172. *
  173. * FUNCTION: Set AudioDevice Attributes
  174. *
  175. *
  176. * NOTES:   This Request is Routed to the Audio Device Via
  177. *          the AudioIf Interface.
  178. *
  179. * ENTRY POINTS:
  180. *     LINKAGE:   CALL FAR
  181. *
  182. * INPUT:
  183. *
  184. * EXIT-NORMAL: Return Code 0.
  185. *
  186. * EXIT_ERROR:  Error Code.
  187. *
  188. * EFFECTS:
  189. *
  190. * INTERNAL REFERENCES: AudioIFDriverEntry().
  191. *
  192. * EXTERNAL REFERENCES:
  193. *
  194. *********************** END OF SPECIFICATIONS *******************************/
  195.  
  196. RC SetAudioDevice ( INSTANCE             *pInstance,
  197.                     PMMAUDIOHEADER       pmmaudioheader )
  198.  
  199.  
  200. {
  201.  
  202.   ULONG               ulrc;
  203.   extern     HID      hidBTarget;
  204.   extern     HID      hidBSource;
  205.   CONCB               concb;
  206.  
  207. //  MCIDRV_TEST_PARMS   mcitestparms;
  208.  
  209.   /*----------------------------------------------
  210.   * When we perform this command, it is possible
  211.   * that we could lose use (i.e. the amp mixer may
  212.   * change resource units calling MDM on this
  213.   * thread AFTER the MCIDRV_SAVE came through.
  214.   * Therefore, release
  215.   * the data access semaphore so that MCIDRV_SAVE
  216.   * will not hang.
  217.   *-----------------------------------------------*/
  218.  
  219.   MCD_ExitCrit( pInstance );
  220.   ReleaseStreamingSemaphore( pInstance );
  221.  
  222.  
  223. //  /*********************************
  224. //   * Send A Set Across the AudioIF
  225. //   * Driver Interface
  226. //   ********************************/
  227. //
  228. //  ulrc = ulpInstance->pfnVSD (&MIX,
  229. //                               MCI_SET,
  230. //                               ulParam1,
  231. //                               (LONG)pSetParms,
  232. //                               0L);
  233.  
  234. //   mconn.ulConnectionScheme = MCI_SSM_CONNECTION;
  235. //   mconn.ulConnectionInfo = ( ULONG ) &mssm;
  236.  
  237.  
  238.   /*----------------------------------------------
  239.   * We will ask the connection network if the device
  240.   * we are connected to can perform the desired
  241.   * connection.  If it can, we ask the device to go
  242.   * into that mode via the MCIDRV_TEST_AND_SET.
  243.   *-----------------------------------------------*/
  244.  
  245. //   mmaudioheader.mmXWAVHeader.WAVEHeader.usFormatTag       =   pWaveSetParms->usFormatTag;
  246. //   mmaudioheader.mmXWAVHeader.WAVEHeader.usChannels        =   pWaveSetParms->usChannels ;
  247. //   mmaudioheader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec   =   pWaveSetParms->ulSamplesPerSec;
  248. //   mmaudioheader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS =
  249. //      pInstance->mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS;
  250. //   mmaudioheader.mmXWAVHeader.WAVEHeader.usBitsPerSample   =   pWaveSetParms->usBitsPerSample;
  251.    pmmaudioheader->ulMediaType = MMIO_MEDIATYPE_AUDIO;
  252.    pmmaudioheader->ulHeaderLength = sizeof( MMAUDIOHEADER );
  253.  
  254.    concb.pMediaHeader = (PVOID) pmmaudioheader;
  255.  
  256.    /* Check to see if the device supports this connection */
  257. #ifdef CONNECTION
  258.    ulrc = mciSendCommand ( pInstance->usWaveDeviceID,
  259.                            MCIDRV_TEST_CONNECTION,
  260.                            0,
  261.                            (PVOID) &concb,
  262.                            0 );
  263.  
  264.    if ( ulrc != MCIERR_SUCCESS )
  265.       {
  266.       return ( ulrc );
  267.       }
  268.  
  269. #else
  270. //   ulrc = mciSendCommand ( pInstance->usAmpDeviceID,
  271. //                           MCIDRV_TEST_CONNECTION,
  272. //                           0,
  273. //                           (PVOID) &concb,
  274. //                           0 );
  275.  
  276. #endif
  277.   /* The MCI call could have failed OR the SSM call inside */
  278.  
  279.  
  280.  
  281.    /**********************************************
  282.    * If the device supports the connection
  283.    * modify the connection network to support it.
  284.    * We will pass in the media header (pMediaHeader)
  285.    * and the direction of the connection (ulOperation)
  286.    ***********************************************/
  287. #ifdef CONNECTION
  288.    ulrc = mciSendCommand ( pInstance->usWaveDeviceID,
  289.                            MCIDRV_MODIFY_CONNECTION,
  290.                            pInstance->ulOperation,
  291.                            (PVOID) &concb,
  292.                            0 );
  293. #else
  294.    ulrc = mciSendCommand ( pInstance->usAmpDeviceID,
  295.                            MCIDRV_MODIFY_CONNECTION,
  296.                            pInstance->ulOperation,
  297.                            (PVOID) &concb,
  298.                            0 );
  299. #endif
  300.   /* The MCI call could have failed OR the SSM call inside */
  301.  
  302.    if ( ulrc != MCIERR_SUCCESS)
  303.       {
  304.       return ( ulrc );
  305.       }
  306.  
  307.  
  308.    /*--------------------------------------------------
  309.    * It is no longer possible to lose use.  Therefore,
  310.    * reacquire the semaphore.  Note: we will always be
  311.    * able to acquire this since it is protected by the
  312.    * save access semaphore which everyone goes through
  313.    * besides save and close_exit.
  314.    *--------------------------------------------------*/
  315.    MCD_EnterCrit( pInstance );
  316.    GetStreamingSemaphore( pInstance );
  317.  
  318.    memmove( &pInstance->mmAudioHeader, pmmaudioheader, sizeof( MMAUDIOHEADER ) );
  319.  
  320.  
  321.  
  322.  
  323. // CONNECTION FEATURE---timing information is broken.
  324. #ifndef CONNECTION
  325.    /*---------------------------------------------------------
  326.    * Retrieve the block sizes from the stream protocol.  We will
  327.    * use these values for time conversions and seeks.
  328.    *-------------------------------------------------------------*/
  329.  
  330.    if ( !ulrc )
  331.       {
  332.     // 6421 -- this info will be returned by the feature rather than in
  333.     // an instance
  334.  
  335.       pInstance->StreamInfo.SpcbKey.ulDataType    = concb.pspcbkey->ulDataType;
  336.       pInstance->StreamInfo.SpcbKey.ulDataSubType = concb.pspcbkey->ulDataSubType;
  337.       pInstance->StreamInfo.SpcbKey.ulIntKey = 0;
  338.  
  339.     /*------------------------------------------------------
  340.     * Get certain streaming information from the stream handler
  341.     * we have loaded.
  342.     *--------------------------------------------------------*/
  343.     ulrc = SpiGetProtocol( concb.hid,
  344.                            &pInstance->StreamInfo.SpcbKey,
  345.                            &pInstance->StreamInfo.spcb );
  346.  
  347.       if ( ulrc )
  348.          {
  349.          return ( ulrc );
  350.          }
  351.  
  352.  
  353.       pInstance->ulBytes   = pInstance->StreamInfo.spcb.ulBytesPerUnit;
  354.       pInstance->ulMMTime  = pInstance->StreamInfo.spcb.mmtimePerUnit;
  355.  
  356.       /* Save the hid from the connected device--use for spcbkeys etc. */
  357.  
  358.       if ( pInstance->ulOperation == MCIDRV_INPUT )
  359.          {
  360.          hidBSource = concb.hid;
  361.          }
  362.       else
  363.          {
  364.          hidBTarget = concb.hid;
  365.          }
  366.  
  367.       pInstance->pdcb = concb.pdcb;
  368.  
  369.  
  370.       }
  371. #endif
  372.    return (ulrc);
  373. }
  374.  
  375. /********************* START OF SPECIFICATIONS *********************
  376. *
  377. * SUBROUTINE NAME:              AbortWait
  378. *
  379. * DESCRIPTIVE NAME: Release a Wait Thread
  380. *
  381. * FUNCTION: Release a wait Thread
  382. *
  383. * NOTES:
  384. *
  385. * ENTRY POINTS:
  386. *
  387. * INPUT: MCI_INFO message.
  388. *
  389. * EXIT-NORMAL: Return Code 0.
  390. *
  391. * EXIT_ERROR:  Error Code.
  392. *
  393. * EFFECTS:
  394. *
  395. * INTERNAL REFERENCES:
  396. *
  397. * EXTERNAL REFERENCES:
  398. *
  399. *********************** END OF SPECIFICATIONS **********************/
  400. RC AbortWaitOperation (INSTANCE * ulpInstance)
  401.  {
  402.  
  403.   ULONG           ulrc;
  404.   ULONG           lCnt;
  405.  
  406.   /*******************************************************
  407.   * Check to see if the wait pending flag is set.
  408.   * If this flag is set, then there is another thread
  409.   * processing a command with the MCI_WAIT flag.  Since
  410.   * it is done with a wait, there is no "official" means
  411.   * to abort it.  Therefore, we will perform an artificial
  412.   * SpiStop on the stream so the WAIT thread will think
  413.   * that it is finished processing.
  414.   ********************************************************/
  415.  
  416.   if (ulpInstance->usWaitPending == TRUE)
  417.      {
  418.      if ( ulpInstance->usWaitMsg != MCI_SAVE )
  419.         {
  420.         DosResetEventSem (ulpInstance->hEventSem, &lCnt);
  421.  
  422.         ulrc = ADMCStopStream ( ulpInstance,
  423.                                SPI_STOP_DISCARD);
  424.  
  425.         /*********************************************
  426.         * Wait for the Stopped event . Notice that
  427.         * more than one thread will be released and
  428.         * free to run as a result of the stop event
  429.         *********************************************/
  430.  
  431.         if (!ulrc)
  432.            DosWaitEventSem (ulpInstance->hEventSem, -1 );
  433.         }
  434.  
  435.      } /* If there is a wait operation alive */
  436.  
  437.   return (MCIERR_SUCCESS);
  438.  
  439. } /* AbortWaitOperation */
  440.  
  441. #ifdef STATUS_LEVEL
  442. /********************* START OF SPECIFICATIONS *********************
  443. *
  444. * SUBROUTINE NAME: StatusLevel
  445. *
  446. * DESCRIPTIVE NAME: Returns the level of a Digital wave file.
  447. *
  448. * FUNCTION: Processes event which indicates the average amplitute
  449. *           of a digital wave file.
  450. *
  451. * NOTES:
  452. *
  453. * ENTRY POINTS:
  454. *
  455. * INPUT: MCI_INFO message.
  456. *
  457. * EXIT-NORMAL: Return Code 0.
  458. *
  459. * EXIT_ERROR:  Error Code.
  460. *
  461. * EFFECTS:
  462. *
  463. * INTERNAL REFERENCES:
  464. *
  465. * EXTERNAL REFERENCES:
  466. *
  467. *********************** END OF SPECIFICATIONS **********************/
  468.  
  469.  
  470. ULONG StatusLevelEvent (INSTANCE * ulpInstance, MEVCB *pevcb)
  471. {
  472.    PSTATUS_EVCB      pStatus;
  473.    USHORT left;
  474.    USHORT right;
  475.    BYTE   bsample;
  476.    BYTE   bsamplemax = 0;
  477.    USHORT wsample;
  478.    USHORT wsamplemax = 0;
  479.    PBYTE pb;
  480.    PUSHORT ps;
  481.    USHORT i;
  482.  
  483.    /*******************************************************************/
  484.    /* The event contains 4 ULONGs that are evenly spaced in the       */
  485.    /* stream buffer.  These samples are interpreted as 16-bit/8-bit   */
  486.    /* stereo/mono, and the maximum absolute value from mid point      */
  487.    /* of the samples is calculated.                                   */
  488.    /*                                                                 */
  489.    /*    8-bit                     16-bit                             */
  490.    /*    0xff                      0x7fff                             */
  491.    /*     |                          |                                */
  492.    /*    0x80                        |                                */
  493.    /*     -                          0                                */
  494.    /*    0x7f                        |                                */
  495.    /*     |                          |                                */
  496.    /*    0x00                      0x8000                             */
  497.    /*                                                                 */
  498.    /*    The 8-bit values need to be shifted.                         */
  499.    /*******************************************************************/
  500.  
  501.    pStatus = (PSTATUS_EVCB)pevcb;
  502.    ulpInstance = (INSTANCE *)pStatus->pMCDInstance;
  503.    if ( ulpInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usChannels == 1) {     /* mono */
  504.       if ( ulpInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample == 8) {
  505.          for (i=0, pb=(PBYTE)&pStatus->ulSample[0]; i<16; i++, pb++) {
  506.              /* 4 ULONGS of 8-bit mono samples is 16 samples */
  507.              bsample = *pb;   /* max the absolute values of shifted samples samples */
  508.              if (bsample & 0x80) { bsample -= 128; } else { bsample = 128 - bsample; }
  509.              bsamplemax = max (bsamplemax, bsample);
  510.          }
  511.          ulpInstance->ulStatusLevel = (ULONG)bsample;
  512.       } else {   /* 16-bit */
  513.          for (i=0, ps=(PUSHORT)&pStatus->ulSample[0]; i<8; i++, ps++) {
  514.              /* 4 ULONGS of 16-bit  mono samples is 8 samples */
  515.              wsample = *ps;
  516.              if (wsample & 0x8000) { wsample = -wsample; } else { wsample = wsample; }
  517.              wsamplemax = max(wsamplemax, wsample);
  518.          }
  519.          ulpInstance->ulStatusLevel = wsample;
  520.       }
  521.    } else {      /* stereo */
  522.       if (ulpInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample == 8) {
  523.          for (i=0, pb=(PBYTE)&pStatus->ulSample[0]; i<8; i++, pb+=2) {
  524.              /* 4 ULONGS of 8-bit stereo samples is 8 samples */
  525.              bsample = *pb;   /* max the absolute values of shifted samples samples */
  526.              if (bsample & 0x80) { bsample -= 128; } else { bsample = 128 - bsample; }
  527.              bsamplemax = max (bsamplemax, bsample);
  528.          }
  529.          left = (USHORT)bsample;
  530.          for (i=0, pb=(PBYTE)&pStatus->ulSample[0] + 1; i<8; i++, pb+=2) {
  531.              /* 4 ULONGS of 8-bit stereo samples is 8 samples */
  532.              bsample = *pb;   /* max the absolute values of shifted samples samples */
  533.              if (bsample & 0x80) { bsample -= 128; } else { bsample = 128 - bsample; }
  534.              bsamplemax = max (bsamplemax, bsample);
  535.          }
  536.          right = (USHORT)bsample;
  537.          ulpInstance->ulStatusLevel = MAKEULONG (left, right);
  538.       } else {   /* 16-bit */
  539.          for (i=0, ps=(PUSHORT)&pStatus->ulSample[0]; i<4; i++, ps+=2) {
  540.              /* 4 ULONGS of 16-bit stereo samples is 4 samples */
  541.              wsample = *ps;
  542.              if (wsample & 0x8000) { wsample = -wsample; } else { wsample = wsample; }
  543.              wsamplemax = max(wsamplemax, wsample);
  544.          }
  545.          left = (USHORT)wsample;
  546.          for (i=0, ps=(PUSHORT)&pStatus->ulSample[0] + 1; i<4; i++, ps+=2) {
  547.              /* 4 ULONGS of 16-bit stereo samples is 4 samples */
  548.              wsample = *ps;
  549.              if (wsample & 0x8000) { wsample = -wsample; } else { wsample = wsample; }
  550.              wsamplemax = max(wsamplemax, wsample);
  551.          }
  552.          right = (USHORT)wsample;
  553.          ulpInstance->ulStatusLevel = MAKEULONG (left, right);
  554.       }
  555.    }
  556.  
  557.    return (0);
  558. } /* Status Level */
  559. #endif
  560.  
  561. /********************* START OF SPECIFICATIONS *********************
  562. *
  563. * SUBROUTINE NAME:      GetAudioHeader
  564. *
  565. * DESCRIPTIVE NAME: Get Audio Header From The IO Proc.
  566. *
  567. * FUNCTION: Obtain Wave Header information.
  568. *
  569. * NOTES:
  570. *
  571. * ENTRY POINTS:
  572. *     LINKAGE:   CALL FAR
  573. *
  574. * INPUT: MCI_INFO message.
  575. *
  576. * EXIT-NORMAL: Return Code 0.
  577. *
  578. * EXIT_ERROR:  Error Code.
  579. *
  580. * NOTES: This function will usually be called either when
  581. *        the file is first loaded or after a record (which
  582. *        can change the settings of the file--like the length).
  583. *
  584. * INTERNAL REFERENCES:
  585. *
  586. * EXTERNAL REFERENCES: mmioGetHeader ()   -  MMIO API
  587. *
  588. *********************** END OF SPECIFICATIONS **********************/
  589. RC   GetAudioHeader (INSTANCE * ulpInstance,
  590.                      ULONG    ulFlag )
  591. {
  592.   ULONG             ulrc;
  593.   LONG              BytesRead;
  594.   MMEXTENDINFO      mmExtInfo;
  595. //  CODECOPEN         codecopen;
  596.   CODECASSOC        codecAssoc;
  597.  
  598.  
  599.   extern HHUGEHEAP     heap;                // Global MCD Heap
  600.  
  601.  
  602.   /*******************************************************
  603.   * A streaming MCD should utilize MMIO to perform all
  604.   * file manipulations.  If we use MMIO, then the MCD
  605.   * will be free from file dependencies (i.e. if a RIFF
  606.   * io proc or a VOC io proc is loaded will be irrelevant.
  607.   ********************************************************/
  608.   if ( !ulFlag )
  609.      {
  610.  
  611.      ulrc = mmioGetHeader ( ulpInstance->hmmio,
  612.                             (PVOID) &ulpInstance->mmAudioHeader ,
  613.                             sizeof( ulpInstance->mmAudioHeader ),
  614.                             (PLONG) &BytesRead,
  615.                             (ULONG) NULL,
  616.                             (ULONG) NULL);
  617.      }
  618. #ifndef CONNECTION
  619.   else
  620.      {
  621.      PCODECINIFILEINFO pcodecini;  // temporary variable
  622.      PCODECOPEN      pcodecopen; // quick usage
  623.  
  624.      if ( !ulpInstance->pcodecini )
  625.         {
  626.  
  627.         /********************************************
  628.         * Get the size of the codecopen struct
  629.         *
  630.         * For audio, it typically is the codecopen size
  631.         * plus any codec specific information
  632.         ********************************************/
  633.  
  634.         ulrc = mmioSet( ulpInstance->hmmio,
  635.                         &mmExtInfo,
  636.                         MMIO_QUERY_EXTENDEDINFO_BASE );
  637.  
  638.         if ( ulrc )
  639.            {
  640.            return ( mmioGetLastError( ulpInstance->hmmio ) );
  641.            }
  642.  
  643.         ulpInstance->pcodecini = HhpAllocMem( heap,
  644.                                               sizeof( CODECINIFILEINFO ) +
  645.                                               mmExtInfo.ulBufSize );
  646.         if ( !ulpInstance->pcodecini)
  647.            {
  648.            return( MCIERR_OUT_OF_MEMORY);
  649.            }
  650.  
  651.         }
  652.  
  653.  
  654.      pcodecini = ulpInstance->pcodecini;
  655.  
  656.      /***********************************************
  657.      * We allocated enough memory for the codecini +
  658.      * the codecopen structures.  Advanced (and store)
  659.      * pointer to get this accomplished.
  660.      ***********************************************/
  661.  
  662.      ulpInstance->pcodecopen = ( PVOID ) ++pcodecini;
  663.      pcodecopen = ulpInstance->pcodecopen;
  664.  
  665.      mmExtInfo.ulNumCODECs = 1;
  666.      mmExtInfo.pCODECAssoc = &codecAssoc;
  667.      codecAssoc.pCodecOpen = pcodecopen;
  668.  
  669. //     codecAssoc.pCodecOpen = &codecopen;
  670.      pcodecopen->pSrcHdr = ( PVOID ) &ulpInstance->mmRealHeader;
  671.      pcodecopen->pDstHdr = ( PVOID ) &ulpInstance->mmAudioHeader;
  672.  
  673.      codecAssoc.pCODECIniFileInfo = ulpInstance->pcodecini;
  674.  
  675.      /* Query the codec (if any) that's connected to the io proc */
  676.  
  677.      ulrc = mmioSet( ulpInstance->hmmio,
  678.                      &mmExtInfo,
  679.                      MMIO_QUERY_EXTENDEDINFO_ALL );
  680.  
  681.  
  682. //     ulrc = mmioSendMessage( ulpInstance->hmmio,
  683. //                             MMIOM_RAWHEADER,
  684. //                             ( LONG ) &ulpInstance->mmAudioHeader,
  685. //                             sizeof( MMAUDIOHEADER ) );
  686.  
  687.       /*-------------------------------------------------------
  688.       * Routines below are dependent on mmAudioHeader containing
  689.       * the exact file header.
  690.       *-------------------------------------------------------*/
  691.  
  692.       memmove ( &ulpInstance->mmAudioHeader,
  693.                 &ulpInstance->mmRealHeader,
  694.                 sizeof( MMAUDIOHEADER ) );
  695.  
  696.  
  697.  
  698.  
  699.      }
  700. #endif
  701.   if ( ulrc )
  702.       {
  703.       ulrc = mmioGetLastError( ulpInstance->hmmio );
  704.       }
  705.   else
  706.      {
  707.      ulpInstance->ulDataSize = XWAVHDR.ulAudioLengthInBytes;
  708.      ulpInstance->ulAverageBytesPerSec = WAVEHDR.ulAvgBytesPerSec;
  709.  
  710.      }
  711.  
  712.   return (ulrc);
  713.  
  714. }  /* GetAudioHeader */
  715.  
  716. /********************* START OF SPECIFICATIONS *********************
  717. *
  718. * SUBROUTINE NAME: SetAudioHeader
  719. *
  720. * DESCRIPTIVE NAME: Set Audio Header in a file.
  721. *
  722. * FUNCTION: Save device settings (like bits/sample) in a file.
  723. *
  724. * NOTES:
  725. *
  726. * ENTRY POINTS:
  727. *     LINKAGE:   CALL FAR
  728. *
  729. * INPUT: MCI_INFO message.
  730. *
  731. * EXIT-NORMAL: MCIERR_SUCCESS.
  732. *
  733. * EXIT_ERROR:  Error Code.
  734. *
  735. * EFFECTS:
  736. *
  737. * INTERNAL REFERENCES:
  738. *
  739. * EXTERNAL REFERENCES: mmioGetHeader ()   -  MMIO API
  740. *
  741. *********************** END OF SPECIFICATIONS **********************/
  742. RC   SetAudioHeader (INSTANCE * pInstance)
  743. {
  744.   ULONG  ulrc;
  745.   LONG   lBogus;
  746.  
  747.   /* Fill in the necessary parameters for the setheader call */
  748.  
  749.   // 6421 --since waveheader is always accurate--no need to refill fields.
  750.  
  751.  
  752.  
  753.   /***********************************************
  754.   * Tell the io proc that is manipulating the file
  755.   * to set the file header with the values that
  756.   * we are sending.
  757.   ***********************************************/
  758.  
  759.   ulrc = mmioSetHeader( pInstance->hmmio,
  760.                         &pInstance->mmAudioHeader,
  761.                         sizeof( MMAUDIOHEADER ),
  762.                         &lBogus,
  763.                         0,
  764.                         0 );
  765.  
  766.  
  767.  
  768.   if (ulrc)
  769.      {
  770.      /*------------------------------------------
  771.      * MMIO returns failure (-1), GetLastError
  772.      * should be called for additional info
  773.      *-----------------------------------------*/
  774.  
  775.      return ( mmioGetLastError( pInstance->hmmio ) );
  776.      }
  777.  
  778.  
  779.   return (ulrc);
  780. } /* SetAudioHeader */
  781.  
  782.  
  783.  
  784. /********************* START OF SPECIFICATIONS *******************************
  785. *
  786. * SUBROUTINE NAME: SetWaveDeviceDefaults()
  787. *
  788. * DESCRIPTIVE NAME:
  789. *
  790. * FUNCTION: Allocate Memory for MCI Message parameter.
  791. *
  792. *
  793. * NOTES:
  794. * ENTRY POINTS:
  795. *
  796. * INPUT:
  797. *
  798. * EXIT-NORMAL: Return Code 0.
  799. *
  800. * EXIT_ERROR:  Error Code.
  801. *
  802. * EFFECTS:
  803. *
  804. * INTERNAL REFERENCES:
  805. *
  806. * EXTERNAL REFERENCES:
  807. *
  808. *********************** END OF SPECIFICATIONS *******************************/
  809.  
  810.  
  811. //void SyncAudioHeader( INSTANCE * ulpInstance )
  812. //
  813. //{
  814. //  WAVEHDR.usFormatTag       = AMPMIX.sMode;
  815. //  WAVEHDR.usChannels        = AMPMIX.sChannels;
  816. //  WAVEHDR.ulSamplesPerSec   = AMPMIX.lSRate;
  817. //  XWAVHDR.ulAudioLengthInMS = 0;
  818. //  WAVEHDR.usBitsPerSample   = (USHORT) AMPMIX.lBitsPerSRate;
  819. //  WAVEHDR.usBlockAlign      = (USHORT) AMPMIX.ulBlockAlignment;
  820. //  WAVEHDR.ulAvgBytesPerSec  = ulpInstance->ulAverageBytesPerSec;
  821. //
  822. //} // SyncAudioHeader
  823.  
  824. /********************* START OF SPECIFICATIONS *******************************
  825. *
  826. * SUBROUTINE NAME: SetWaveDeviceDefaults()
  827. *
  828. * DESCRIPTIVE NAME:
  829. *
  830. * FUNCTION: Allocate Memory for MCI Message parameter.
  831. *
  832. *
  833. * NOTES:
  834. * ENTRY POINTS:
  835. *
  836. * INPUT:
  837. *
  838. * EXIT-NORMAL: Return Code 0.
  839. *
  840. * EXIT_ERROR:  Error Code.
  841. *
  842. * EFFECTS:
  843. *
  844. * INTERNAL REFERENCES:
  845. *
  846. * EXTERNAL REFERENCES:
  847. *
  848. *********************** END OF SPECIFICATIONS *******************************/
  849. VOID SetWaveDeviceDefaults (INSTANCE * ulpInstance)
  850. {
  851.   WAVEHDR.usFormatTag       = ulpInstance->lDefaultFormat;   // DATATYPE_WAVEFORM
  852.   WAVEHDR.usChannels        = ulpInstance->lDefaultChannels; // Stereo
  853.   WAVEHDR.ulSamplesPerSec   = ulpInstance->lDefaultSRate;    // 22 Khz
  854.   XWAVHDR.ulAudioLengthInMS = 0;
  855.   WAVEHDR.usBitsPerSample   = ulpInstance->lDefaultBPS;      // 8 bits/sam
  856.   WAVEHDR.usBlockAlign      = ulpInstance->lDefaultChannels *
  857.                               ( ulpInstance->lDefaultBPS / 8 );
  858.   WAVEHDR.ulAvgBytesPerSec  = ulpInstance->lDefaultChannels *
  859.                               ( ulpInstance->lDefaultBPS / 8 ) *
  860.                               ulpInstance->lDefaultSRate;
  861.   XWAVHDR.ulAudioLengthInBytes = ( ulpInstance->lDefaultOperation == MCIDRV_INPUT )
  862.                                  ? 0 : 1;
  863. //  ulpInstance->ulOperation  = ulOperation;
  864. //  AMPMIX.sMode            = ulpInstance->lDefaultFormat;   // DATATYPE_WAVEFORM
  865. //  AMPMIX.lSRate           = ulpInstance->lDefaultSRate;    // 22 Khz
  866. //  AMPMIX.ulOperation      = ulOperation;                   // Play or Record
  867. //  AMPMIX.sChannels        = ulpInstance->lDefaultChannels; // Stereo
  868. //  AMPMIX.lBitsPerSRate    = ulpInstance->lDefaultBPS;      // 8 bits/sam
  869. //  AMPMIX.ulBlockAlignment = DEFAULT_BLOCK_ALIGN;           // bogus value
  870.  
  871.   ulpInstance->ulAverageBytesPerSec =  ulpInstance->lDefaultChannels *
  872.                                        ( ulpInstance->lDefaultBPS / 8 ) *
  873.                                        ulpInstance->lDefaultSRate;
  874.  
  875. //  AMPMIX.ulFlags = FIXED|VOLUME|TREBLE|BASS;
  876.  
  877.   // 6421--we will put the values in the wave header
  878.   // the wave header will be inserted in the generic SPCB to connect to AMP
  879.   // thus the amp instance will go away.
  880.  
  881. //  SyncAudioHeader( ulpInstance );
  882. }
  883.  
  884. /********************* START OF SPECIFICATIONS *******************************
  885. *
  886. * SUBROUTINE NAME: VSDInstToWaveSetParms
  887. *
  888. * DESCRIPTIVE NAME:
  889. *
  890. * FUNCTION: copy parameters from VSD Instance struct to MCI_WAVE_SET_PARMS
  891. *
  892. *
  893. * NOTES:
  894. * ENTRY POINTS:
  895. *     LINKAGE:   CALL FAR
  896. *
  897. * INPUT:
  898. *
  899. * EXIT-NORMAL: Return Code 0.
  900. *
  901. * EXIT_ERROR:  Error Code.
  902. *
  903. * EFFECTS:
  904. *
  905. * EXTERNAL REFERENCES:
  906. *
  907. *********************** END OF SPECIFICATIONS *******************************/
  908. //VOID VSDInstToWaveSetParms ( PMCI_WAVE_SET_PARMS pWaveSetParms,
  909. //                             INSTANCE            *ulpInstance)
  910. //{
  911.  
  912.   // 6421 -- since wave header is always accurrate--use it rather
  913.   // than private VSD instance.
  914.  
  915. //  pWaveSetParms->usChannels       = AMPMIX.sChannels;
  916. //  pWaveSetParms->usFormatTag      = AMPMIX.sMode;
  917. //  pWaveSetParms->ulSamplesPerSec  = AMPMIX.lSRate;
  918. //  pWaveSetParms->usBitsPerSample  = (USHORT) AMPMIX.lBitsPerSRate;
  919.  
  920. //  pWaveSetParms->usChannels       = WAVEHDR.usChannels;
  921. //  pWaveSetParms->usFormatTag      = WAVEHDR.usFormatTag;
  922. //  pWaveSetParms->ulSamplesPerSec  = WAVEHDR.ulSamplesPerSec;
  923. //  pWaveSetParms->usBitsPerSample  = WAVEHDR.usBitsPerSample;
  924. //
  925. //
  926. //}
  927.  
  928.  
  929. /********************* START OF SPECIFICATIONS *******************************
  930. *
  931. * SUBROUTINE NAME:AssocMemPlayToAudioStrm ()
  932. *
  933. * DESCRIPTIVE NAME:
  934. *
  935. * FUNCTION: Associate The Memory Play List Stream Handler with
  936. *           the currently connected audio stream handler.
  937. *
  938. *
  939. * NOTES:
  940. * ENTRY POINTS:
  941. *
  942. * INPUT:
  943. *
  944. * EXIT-NORMAL: MCIERR_SUCCESS.
  945. *
  946. * EXIT_ERROR:  Error Code.
  947. *
  948. * EFFECTS:
  949. *
  950. * INTERNAL REFERENCES:SpiAssociate()
  951. *
  952. * EXTERNAL REFERENCES:
  953. *
  954. *********************** END OF SPECIFICATIONS *******************************/
  955. RC AssociatePlayList (INSTANCE * ulpInstance)
  956.  
  957. {
  958.   ULONG ulrc;
  959.   extern HID           hidA2Source;              // hid's for memory playlist
  960.   extern HID           hidA2Target;
  961.  
  962.   /******************************************************
  963.   * Fill in the Playlist Access Control Block (ACB)
  964.   * with the correct information to set up a stream.
  965.   ******************************************************/
  966.  
  967.   ulpInstance->StreamInfo.acbPlayList.ulObjType   = ACBTYPE_MEM_PLAYL;
  968.   ulpInstance->StreamInfo.acbPlayList.ulACBLen    = sizeof(ACB_MEM_PLAYL);
  969.   ulpInstance->StreamInfo.acbPlayList.pMemoryAddr = (PVOID)ulpInstance->pPlayList;
  970.  
  971.   /*********************************************
  972.   * If this is a playback request, then the
  973.   * memory stream handler will be the source
  974.   * and the audio stream handler will be the
  975.   * target.
  976.   *********************************************/
  977.  
  978.   if ( ulpInstance->ulOperation == MCIDRV_OUTPUT )
  979.       {
  980.       ulrc = ADMCAssociate (ulpInstance->StreamInfo.hStream,
  981.                             hidA2Source,
  982.                             (PVOID) &(ulpInstance->StreamInfo.acbPlayList));
  983.       }
  984.  
  985.   /*********************************************
  986.   * If this is record request, then the
  987.   * memory stream handler will be the target
  988.   * and the audio stream handler will be the
  989.   * source (i.e. we are recording to memory)
  990.   *********************************************/
  991.  
  992.     else
  993.       {
  994.       ulrc = ADMCAssociate ( ulpInstance->StreamInfo.hStream,
  995.                              hidA2Target,
  996.                              (PVOID)&ulpInstance->StreamInfo.acbPlayList);
  997.       }
  998.  
  999.   return (ulrc);
  1000.  
  1001. } /* AssociatePlaylist */
  1002.  
  1003. /************************** START OF SPECIFICATIONS ***********************
  1004. *                                                                          *
  1005. * SUBROUTINE NAME: MCD_EnterCrit                                           *
  1006. *                                                                          *
  1007. * FUNCTION: This routine acquires access to the common areas via a         *
  1008. *           system semaphore.                                              *
  1009. *                                                                          *
  1010. * NOTES:    This routine contains OS/2 system specific functions.          *
  1011. *           DosRequestMutexSem                                             *
  1012. *                                                                          *
  1013. * INPUT:    None.                                                          *
  1014. *                                                                          *
  1015. * OUTPUT:   rc = error return code is failure to acquire semaphore.        *
  1016. *                                                                          *
  1017. * SIDE EFFECTS: Access acquired.                                           *
  1018. *                                                                          *
  1019. *************************** END OF SPECIFICATIONS **************************/
  1020.  
  1021. ULONG MCD_EnterCrit (INSTANCE * ulpInstance )
  1022. {
  1023.   /*****************************************************************
  1024.   * Request the system semaphore for the common data area.
  1025.   *****************************************************************/
  1026.  
  1027.   return( DosRequestMutexSem (ulpInstance->hmtxDataAccess, -1));  // wait for semaphore
  1028. }
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034. /************************** START OF SPECIFICATIONS ***********************
  1035. *                                                                          *
  1036. * SUBROUTINE NAME: MCD_ExitCrit                                            *
  1037. *                                                                          *
  1038. * FUNCTION: This routine releases access to the common areas via a         *
  1039. *           system semaphore.                                              *
  1040. *                                                                          *
  1041. * NOTES:    This routine contains OS/2 system specific functions.          *
  1042. *           DosReleaseMutexSem                                             *
  1043. *                                                                          *
  1044. * INPUT:    None.                                                          *
  1045. *                                                                          *
  1046. * OUTPUT:   rc = error return code is failure to release semaphore.        *
  1047. *                                                                          *
  1048. * SIDE EFFECTS: Access released.                                           *
  1049. *                                                                          *
  1050. *************************** END OF SPECIFICATIONS **************************/
  1051.  
  1052. ULONG MCD_ExitCrit (INSTANCE * ulpInstance)
  1053. {
  1054.   /************************************************************
  1055.   * Release the system semaphore for the common data area.
  1056.   *************************************************************/
  1057.  
  1058.   return( DosReleaseMutexSem (ulpInstance->hmtxDataAccess));
  1059. }
  1060.  
  1061.  
  1062. /************************** START OF SPECIFICATIONS ***********************
  1063. *                                                                          *
  1064. * SUBROUTINE NAME: MCD_EnterCrit                                           *
  1065. *                                                                          *
  1066. * FUNCTION: This routine acquires access to the common areas via a         *
  1067. *           system semaphore.                                              *
  1068. *                                                                          *
  1069. * NOTES:    This routine contains OS/2 system specific functions.          *
  1070. *           DosRequestMutexSem                                             *
  1071. *                                                                          *
  1072. * INPUT:    None.                                                          *
  1073. *                                                                          *
  1074. * OUTPUT:   rc = error return code is failure to acquire semaphore.        *
  1075. *                                                                          *
  1076. * SIDE EFFECTS: Access acquired.                                           *
  1077. *                                                                          *
  1078. *************************** END OF SPECIFICATIONS **************************/
  1079.  
  1080. ULONG GetSaveSem (INSTANCE * ulpInstance )
  1081. {
  1082.   /*****************************************************************
  1083.   * Request the system semaphore for MCIDRV_SAVE access
  1084.   *****************************************************************/
  1085.  
  1086.   return( DosRequestMutexSem (ulpInstance->hmtxSaveAccess, -1));  // wait for semaphore
  1087. }
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093. /************************** START OF SPECIFICATIONS ***********************
  1094. *                                                                          *
  1095. * SUBROUTINE NAME: MCD_ExitCrit                                            *
  1096. *                                                                          *
  1097. * FUNCTION: This routine releases access to the common areas via a         *
  1098. *           system semaphore.                                              *
  1099. *                                                                          *
  1100. * NOTES:    This routine contains OS/2 system specific functions.          *
  1101. *           DosReleaseMutexSem                                             *
  1102. *                                                                          *
  1103. * INPUT:    None.                                                          *
  1104. *                                                                          *
  1105. * OUTPUT:   rc = error return code is failure to release semaphore.        *
  1106. *                                                                          *
  1107. * SIDE EFFECTS: Access released.                                           *
  1108. *                                                                          *
  1109. *************************** END OF SPECIFICATIONS **************************/
  1110.  
  1111. ULONG GiveUpSaveSem (INSTANCE * ulpInstance)
  1112. {
  1113.   /************************************************************
  1114.   * Release the system semaphore for MCIDRV_SAVE access.
  1115.   *************************************************************/
  1116.  
  1117.   return( DosReleaseMutexSem (ulpInstance->hmtxSaveAccess));
  1118. }
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124. /************************** START OF SPECIFICATIONS ************************
  1125. *                                                                          *
  1126. * SUBROUTINE NAME: AcquireProcSem                                          *
  1127. *                                                                          *
  1128. * FUNCTION: This routine acquires access to the common areas via a         *
  1129. *           system semaphore.                                              *
  1130. *                                                                          *
  1131. * NOTES:    This routine contains OS/2 system specific functions.          *
  1132. *           DosRequestMutexSem                                             *
  1133. *                                                                          *
  1134. * INPUT:    None.                                                          *
  1135. *                                                                          *
  1136. * OUTPUT:   rc = error return code is failure to acquire semaphore.        *
  1137. *                                                                          *
  1138. * SIDE EFFECTS: Access acquired.                                           *
  1139. *                                                                          *
  1140. *************************** END OF SPECIFICATIONS **************************/
  1141.  
  1142. ULONG AcquireProcSem ( void )
  1143. {
  1144.   extern HMTX   hmtxProcSem;
  1145.  
  1146.   /**************************************************************
  1147.   * Request the system semaphore for the common data area.
  1148.   ***************************************************************/
  1149.  
  1150.   return( DosRequestMutexSem (hmtxProcSem, -1));
  1151. }
  1152.  
  1153. /************************** START OF SPECIFICATIONS ************************
  1154. *                                                                          *
  1155. * SUBROUTINE NAME: ReleaseProcSem                                          *
  1156. *                                                                          *
  1157. * FUNCTION: This routine releases access to the common areas via a         *
  1158. *           system semaphore.                                              *
  1159. *                                                                          *
  1160. * NOTES:    This routine contains OS/2 system specific functions.          *
  1161. *           DosReleaseMutexSem                                             *
  1162. *                                                                          *
  1163. * INPUT:    None.                                                          *
  1164. *                                                                          *
  1165. * OUTPUT:   rc = error return code is failure to release semaphore.        *
  1166. *                                                                          *
  1167. * SIDE EFFECTS: Access released.                                           *
  1168. *                                                                          *
  1169. *************************** END OF SPECIFICATIONS **************************/
  1170.  
  1171. ULONG ReleaseProcSem ( void )
  1172. {
  1173.    extern HMTX  hmtxProcSem;
  1174.  
  1175.   /**********************************************************
  1176.   * Release the system semaphore for the common data area.
  1177.   ***********************************************************/
  1178.  
  1179.   return( DosReleaseMutexSem (hmtxProcSem) );
  1180. }
  1181.  
  1182. /********************* START OF SPECIFICATIONS *******************************
  1183. *
  1184. * SUBROUTINE NAME: CleanUp ()
  1185. *
  1186. * DESCRIPTIVE NAME:
  1187. *
  1188. * FUNCTION: Call HhpFreeMem to dealocatte memory from global heap.
  1189. *
  1190. *
  1191. * NOTES:    Release Memory.
  1192. * ENTRY POINTS:
  1193. *
  1194. * INPUT:
  1195. *
  1196. * EXIT-NORMAL: Return Code 0.
  1197. *
  1198. * EXIT_ERROR:  Error Code.
  1199. *
  1200. * EFFECTS:
  1201. *
  1202. * INTERNAL REFERENCES: HhpFreeMem().
  1203. *
  1204. * EXTERNAL REFERENCES:
  1205. *
  1206. *********************** END OF SPECIFICATIONS *******************************/
  1207.  
  1208. RC CleanUp (PVOID MemToFree)
  1209. {
  1210.   extern HHUGEHEAP heap;
  1211.  
  1212.   /****************************
  1213.   * Enter Data Critical Section
  1214.   *****************************/
  1215.   AcquireProcSem ();
  1216.  
  1217.   /***************************
  1218.   * Free Memory off of the heap
  1219.   ****************************/
  1220.  
  1221.   HhpFreeMem (heap, MemToFree);
  1222.  
  1223.   /****************************
  1224.   * Exit Data Critical Section
  1225.   *****************************/
  1226.  
  1227.   ReleaseProcSem ();
  1228.  
  1229.   return (MCIERR_SUCCESS);
  1230.  
  1231. } /* CleanUp */
  1232.  
  1233.  
  1234.  
  1235.  
  1236. /********************* START OF SPECIFICATIONS *******************************
  1237. *
  1238. * SUBROUTINE NAME: OpenFile
  1239. *
  1240. * DESCRIPTIVE NAME: OpenFile
  1241. *
  1242. * FUNCTION: Open Element , Install IO Procs, Get Header Information
  1243. *
  1244. *
  1245. * NOTES:
  1246. * ENTRY POINTS:
  1247. *     LINKAGE:   CALL FAR
  1248. *
  1249. * INPUT:
  1250. *
  1251. * EXIT-NORMAL: Return Code 0.
  1252. *
  1253. * EXIT_ERROR:  Error Code.
  1254. *
  1255. * NOTES: Concepts this functions illustrates.
  1256. *          A. Why MMIO_TRANSLATE_HEADER is used.
  1257. *          B.
  1258. *
  1259. * INTERNAL REFERENCES: None
  1260. *
  1261. * EXTERNAL REFERENCES: None
  1262. *
  1263. *********************** END OF SPECIFICATIONS *******************************/
  1264. RC OpenFile(INSTANCE * pInstance, ULONG ulFlags )
  1265. {
  1266.  
  1267.   MMIOINFO         mmioinfo;             // mmioInfo Structure
  1268.   MMFORMATINFO     mmformatinfo;         /* io proc cap struct */
  1269.   PSZ              pFileName;            // Element Name
  1270.   LONG             lNumFormats;          /* Number of format info structs */
  1271.   BOOL             fGetRealHeader=TRUE;
  1272.  
  1273.  
  1274.   /********************************
  1275.   * Intialize data structures
  1276.   ********************************/
  1277.  
  1278.   ULONG ulrc = MCIERR_SUCCESS;
  1279.  
  1280.  
  1281.    memset( &mmioinfo, '\0', sizeof( MMIOINFO ));
  1282.    mmioinfo.fccIOProc = mmioFOURCC( 'W', 'A', 'V', 'E' ) ;
  1283.  
  1284.  
  1285.    /**************************************************
  1286.    * Set header translation flag on. It is imporatant
  1287.    * that we do this because the loaded io proc has
  1288.    * to communicate with us via the standard audio
  1289.    * header.  Until we get device capabilities, we
  1290.    * must assume that the audio device can handle
  1291.    * the raw data.
  1292.    **************************************************/
  1293.  
  1294.    mmioinfo.ulTranslate = MMIO_TRANSLATEHEADER;
  1295.  
  1296.  
  1297.    pFileName = pInstance->pszAudioFile;
  1298.    pInstance->fFileExists = FALSE;
  1299.  
  1300.  
  1301.     /********************************************
  1302.     * When we called the mmio api for temp files,
  1303.     * it returned a DOS handle to the file.  The
  1304.     * mmioOpen api allows one to pass in a Dos
  1305.     * handle rather than a filename if you place
  1306.     * the handle in adwInfo[ 0 ] and make the
  1307.     * name NULL.
  1308.     *********************************************/
  1309.  
  1310.     if ( pInstance->ulCreatedName )
  1311.        {
  1312.        mmioinfo.aulInfo[ 0 ] = pInstance->hTempFile;
  1313.        pFileName = ( PSZ ) NULL;
  1314.        }
  1315.  
  1316.     /***********************************************
  1317.     * Try to open the file.  Note: the first
  1318.     * open attempt will always specifically
  1319.     * try to open the file with the RIFF IO Proc.
  1320.     * We do this for speed reasons--if this fails
  1321.     * we let mmio do an auto identify on the file,
  1322.     * mmio will ask every io proc in the system if
  1323.     * it can load the file.
  1324.     ***********************************************/
  1325.  
  1326.     pInstance->hmmio = mmioOpen ( pFileName,
  1327.                                   &mmioinfo,
  1328.                                   ulFlags );
  1329.  
  1330.     /*********************************************************
  1331.     * If we have no file handle--the RIFF IO Proc failed to
  1332.     * open the file for one ofthe following reasons:
  1333.     *  1. Sharing violation.
  1334.     *  2. Path/File errors.
  1335.     *********************************************************/
  1336.  
  1337.     if ( pInstance->hmmio == (ULONG) NULL )
  1338.         {
  1339.  
  1340.         /*********************************************
  1341.         * We will get a sharing violation if we are
  1342.         * writing to a read-only device (CD), if the
  1343.         * file is readonly or other misc. problems.
  1344.         *********************************************/
  1345.  
  1346.         if (mmioinfo.ulErrorRet == ERROR_ACCESS_DENIED ||
  1347.             mmioinfo.ulErrorRet == ERROR_WRITE_PROTECT ||
  1348.             mmioinfo.ulErrorRet == ERROR_NETWORK_ACCESS_DENIED ||
  1349.             mmioinfo.ulErrorRet == ERROR_SHARING_VIOLATION )
  1350.             {
  1351.  
  1352.             /*********************************************************
  1353.             * If the wave fails the open, we should still try w/o the
  1354.             * exclusive flag so that another IO can possibly load it.
  1355.             * We do this because a sharing violation could occur if
  1356.             * we tried exclusively to open the file and other process
  1357.             * has it open.
  1358.             **********************************************************/
  1359.  
  1360.             ulFlags &= ~MMIO_EXCLUSIVE;
  1361.  
  1362.             pInstance->hmmio = mmioOpen ( pFileName,
  1363.                                           &mmioinfo,
  1364.                                           ulFlags );
  1365.  
  1366.             if ( mmioinfo.ulErrorRet == ERROR_ACCESS_DENIED ||
  1367.                  mmioinfo.ulErrorRet == ERROR_WRITE_PROTECT ||
  1368.                  mmioinfo.ulErrorRet == ERROR_NETWORK_ACCESS_DENIED ||
  1369.                  mmioinfo.ulErrorRet == ERROR_SHARING_VIOLATION )
  1370.                {
  1371.                return MCIERR_FILE_ATTRIBUTE;
  1372.                }
  1373.  
  1374.             pInstance->hmmio = 0;
  1375.  
  1376.             } /* if a file attribute error occurred */
  1377.  
  1378.         /*********************************************
  1379.         * We will get a file not found or an open
  1380.         * failure if the path does not exist, or the
  1381.         * file DNE or the drive is invalid.
  1382.         *********************************************/
  1383.  
  1384.  
  1385.         if (mmioinfo.ulErrorRet == ERROR_FILE_NOT_FOUND ||
  1386.             mmioinfo.ulErrorRet == ERROR_PATH_NOT_FOUND ||
  1387.             mmioinfo.ulErrorRet == ERROR_OPEN_FAILED )
  1388.            {
  1389.            return ( ERROR_FILE_NOT_FOUND );
  1390.            } /* Error File Not Found */
  1391.  
  1392.         /*********************************************
  1393.         * Map OS/2 errors to MCI or MMIO errors
  1394.         *********************************************/
  1395.  
  1396.  
  1397.         if (mmioinfo.ulErrorRet == ERROR_FILENAME_EXCED_RANGE )
  1398.            {
  1399.            return ( MMIOERR_INVALID_FILENAME );
  1400.            } /* Error File Not Found */
  1401.  
  1402.  
  1403. //        /* Ask mmio to get info about the file */
  1404. //
  1405. //        ulrc = mmioIdentifyFile( pFileName,
  1406. //                                 (ULONG) NULL,
  1407. //                                 &mmformatinfo,
  1408. //                                 &fccStorageSystem,
  1409. //                                 0,
  1410. //                                 0 );
  1411. //
  1412. //        /* if the call worked, interegate the io proc */
  1413. //
  1414. //        if ( ulrc == MMIO_SUCCESS )
  1415. //
  1416. //           {
  1417. //           /***********************************************
  1418. //           * If this is a non audio I/O proc, don't open
  1419. //           ************************************************/
  1420. //
  1421. //         if ( mmformatinfo.ulMediaType != MMIO_MEDIATYPE_AUDIO )
  1422. //               {
  1423. //               return (MCIERR_INVALID_MEDIA_TYPE);
  1424. //               }
  1425.  
  1426.            /***********************************************
  1427.            * The current release does not support opening
  1428.            * IO Procs other that RIFF format in write mode.
  1429.            * Therefore, temporary files are impossible.
  1430.            ************************************************/
  1431.            ulFlags = MMIO_READ | MMIO_DENYNONE;
  1432.            pInstance->ulOpenTemp = FALSE;
  1433.  
  1434.  
  1435.            memset( &mmioinfo, '\0', sizeof( mmioinfo ) );
  1436.  
  1437.            // need to find out why a mmioinfo struct cause identify to fail
  1438.  
  1439.            mmioinfo.ulTranslate = MMIO_TRANSLATEDATA;
  1440.            mmioinfo.aulInfo[ 3 ] = MMIO_MEDIATYPE_AUDIO;
  1441.  
  1442.  
  1443.            /* Open the file */
  1444.  
  1445.            pInstance->hmmio = mmioOpen ( pFileName,
  1446.                                          &mmioinfo,
  1447.                                          ulFlags);
  1448.  
  1449.            /* Check for errors--see comments from above */
  1450.  
  1451.            if (pInstance->hmmio == (ULONG) NULL)
  1452.              {
  1453.              if ( mmioinfo.ulErrorRet == MMIOERR_MEDIA_NOT_FOUND )
  1454.                {
  1455.                return  ( MCIERR_INVALID_MEDIA_TYPE );
  1456.                }
  1457.  
  1458.              return  ( mmioinfo.ulErrorRet );
  1459.              }
  1460.  
  1461.            memset( &mmformatinfo, '\0', sizeof( MMFORMATINFO ) );
  1462.            mmformatinfo.fccIOProc = mmioinfo.fccIOProc;
  1463.  
  1464.            ulrc = mmioGetFormats( &mmformatinfo,
  1465.                                      1,
  1466.                                      &mmformatinfo,
  1467.                                      &lNumFormats,
  1468.                                      0,
  1469.                                      0 );
  1470.  
  1471.            pInstance->ulCapabilities = 0;
  1472.  
  1473.            if ( !ulrc )
  1474.               {
  1475.               /*--------------------------------------------------
  1476.               * Determine what capabilities the current io
  1477.               * proc really has (i.e. can it record, save etc.)
  1478.               *-------------------------------------------------*/
  1479.  
  1480.               if (mmformatinfo.ulFlags & MMIO_CANSAVETRANSLATED)
  1481.                  {
  1482.                  pInstance->ulCapabilities = CAN_SAVE;
  1483.                  pInstance->ulOpenTemp = TRUE;
  1484.                  }
  1485.  
  1486.               if (mmformatinfo.ulFlags & MMIO_CANINSERTTRANSLATED )
  1487.                  {
  1488.                  pInstance->ulCapabilities |= CAN_INSERT;
  1489.                  }
  1490.  
  1491.               if ( mmformatinfo.ulFlags & MMIO_CANWRITETRANSLATED)
  1492.                  {
  1493.                  pInstance->ulCapabilities |= CAN_RECORD;
  1494.                  }
  1495.  
  1496.               /*-------------------------------------------------
  1497.               * If the io proc has the ability to record, close
  1498.               * and reopen the file with the flags necessary to
  1499.               * do this
  1500.               *-------------------------------------------------*/
  1501.  
  1502. //              if ( pInstance->ulCapabilities )
  1503. //                 {
  1504. //                 mmioClose( pInstance->hmmio, 0 );
  1505. //
  1506. //                 /***********************************************
  1507. //                 * The current release does not support opening
  1508. //                 * IO Procs other that RIFF format in write mode.
  1509. //                 * Therefore, temporary files are impossible.
  1510. //                 ************************************************/
  1511. //                 ulFlags = MMIO_READWRITE | MMIO_EXCLUSIVE;
  1512. //
  1513. //                 memset( &mmioinfo, '\0', sizeof( mmioinfo ) );
  1514. //
  1515. //                 // need to find out why a mmioinfo struct cause identify to fail
  1516. //
  1517. //                 mmioinfo.ulTranslate = MMIO_TRANSLATEDATA;
  1518. //                 mmioinfo.aulInfo[ 3 ] = MMIO_MEDIATYPE_AUDIO;
  1519. //
  1520. //                 /* Open the file */
  1521. //                 pInstance->hmmio = mmioOpen ( pFileName,
  1522. //                                               &mmioinfo,
  1523. //                                               ulFlags);
  1524. //
  1525. //                 if ( !pInstance->hmmio )
  1526. //                    {
  1527. //                    return ( mmioinfo.ulErrorRet );
  1528. //                    }
  1529. //                 } /* if we must close and reopen the file */
  1530.  
  1531.               fGetRealHeader = FALSE;
  1532.               }
  1533.            else
  1534.               {
  1535.               ulrc = MCIERR_SUCCESS;
  1536.               }
  1537. //           } /* if identify was successful */
  1538. //        else
  1539. //           {
  1540. //           return ( ulrc );
  1541. //           }
  1542.         } /* If the file was not opened with OPEN_MMIO */
  1543.  
  1544.     else
  1545.         {
  1546.         /************************************************
  1547.         * Since the wave IO Proc opened the file, we know
  1548.         * that it has the following capabilities.
  1549.         *************************************************/
  1550.         pInstance->ulCapabilities =  ( CAN_INSERT | CAN_DELETE | CAN_UNDOREDO +
  1551.                                        CAN_SAVE   | CAN_INSERT | CAN_RECORD  );
  1552.         }
  1553.  
  1554.   /******************************************
  1555.   * Get The Header Information
  1556.   * NOTE: we will always ASK for the Real header
  1557.   * in the file for hardware decompression
  1558.   * purposes.
  1559.   *******************************************/
  1560.  
  1561.   if ( !(ulFlags & MMIO_CREATE) && !pInstance->ulCreatedName)
  1562.      {
  1563. #ifndef CONNECTION
  1564.       ulrc = GetAudioHeader (pInstance, fGetRealHeader );
  1565.  
  1566.       if ( ulrc == MMIOERR_UNSUPPORTED_MESSAGE )
  1567.          {
  1568. #endif
  1569.          ulrc = GetAudioHeader (pInstance, 0);
  1570.  
  1571. #ifndef CONNECTION
  1572.          }
  1573. #endif
  1574.      } /* Not Create Flag */
  1575.   else
  1576.      {
  1577.      pInstance->ulDataSize =
  1578.      pInstance->mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes = 0;
  1579.      }
  1580.  
  1581.   pInstance->fFileExists = TRUE;
  1582.  
  1583.  
  1584.   /*******************************************************************
  1585.   * You cannot do the set header immediately after file creation
  1586.   * because future sets on samples, bitpersample, channels may follow
  1587.   ********************************************************************/
  1588.  
  1589.   return (ulrc);
  1590.  
  1591. } /* OpenFile */
  1592.  
  1593.  
  1594. /********************* START OF SPECIFICATIONS *******************************
  1595. *
  1596. * SUBROUTINE NAME: ConvertToMM ()
  1597. *
  1598. * DESCRIPTIVE NAME:
  1599. *
  1600. * FUNCTION: Convert Time values from MMTIME units to current time format.
  1601. *
  1602. *
  1603. * ENTRY POINTS:
  1604. *
  1605. * INPUT:
  1606. *
  1607. * EXIT-NORMAL: MCIERR_SUCCESS.
  1608. *
  1609. * EXIT_ERROR:  Error Code.
  1610. *
  1611. * EFFECTS:
  1612. *
  1613. * INTERNAL REFERENCES:
  1614. *
  1615. * EXTERNAL REFERENCES:
  1616. *
  1617. *********************** END OF SPECIFICATIONS *******************************/
  1618.  
  1619. RC   ConvertToMM ( INSTANCE  *ulpInstance,
  1620.                    PULONG    pulSeekPoint,
  1621.                    ULONG     ulValue)
  1622. {
  1623. /*also use floats are reverse the division/multiplications.
  1624. *  why does this function have a return value? */
  1625.  
  1626.   ULONG      ulBytesPerSample;
  1627.   ULONG      ulTemp1;
  1628.  
  1629. #ifdef CONNECTION
  1630.   if ( !ulpInstance->fConnected )
  1631.      {
  1632.      *pulSeekPoint = 0;
  1633.  
  1634.      }
  1635.   else
  1636.      {
  1637.      if ( !(ulpInstance->ulFlags & HAVE_SPCBKEY) )
  1638.         {
  1639.         GetSpcbKeyInfo( ulpInstance );
  1640.         }
  1641.      ulpInstance->ulFlags |= HAVE_SPCBKEY;
  1642. #endif
  1643.  
  1644.  
  1645.  
  1646.  
  1647.   switch (ulpInstance->ulTimeUnits)
  1648.   {
  1649.  
  1650.   case lMMTIME:
  1651.        *pulSeekPoint = ulValue;
  1652.       break;
  1653.  
  1654.   case lMILLISECONDS:
  1655.        *pulSeekPoint = MSECTOMM ( ulValue);
  1656.       break;
  1657.  
  1658.   case lSAMPLES:
  1659. // 6421 -- don't use private VSD instance
  1660.  
  1661.        ulBytesPerSample = (WAVEHDR.usBitsPerSample / 8);
  1662.  
  1663.        ulTemp1 = ulValue * ulBytesPerSample;
  1664.  
  1665.        ulTemp1 /= ulpInstance->ulBytes ;
  1666.        *pulSeekPoint = ulTemp1 * ulpInstance->ulMMTime;
  1667.  
  1668.       break;
  1669.   default:  /* the time value must be bytes */
  1670.  
  1671.        ulTemp1 = ulValue / ulpInstance->ulBytes ;
  1672.        *pulSeekPoint = ulTemp1 * ulpInstance->ulMMTime;
  1673. //       Bytes2Mmtime( ulpInstance->ulBytes,  (LONG) ulValue, ( LONG ) ulpInstance->ulMMTime, ( PLONG ) pulSeekPoint);
  1674.  
  1675.       break;
  1676.   } /* switch time units */
  1677.  
  1678. #ifdef CONNECTION
  1679.    }
  1680. #endif
  1681.  
  1682.  
  1683.   return ( MCIERR_SUCCESS );
  1684.  
  1685. } /* ConvertToMM */
  1686.  
  1687. /********************* START OF SPECIFICATIONS *******************************
  1688. *
  1689. * SUBROUTINE NAME: ConvertTimeUnits ()
  1690. *
  1691. * DESCRIPTIVE NAME:
  1692. *
  1693. * FUNCTION: Convert Time values from the current base to MMTIME units.
  1694. *           We obtained the conversion factors from SpiGetProtocol which
  1695. *           has the smallest breakdowns of mmtime per block of time and
  1696. *           bytes per block of time.
  1697. *
  1698. *
  1699. * ENTRY POINTS:
  1700. *
  1701. * INPUT:
  1702. *
  1703. * EXIT-NORMAL: MCIERR_SUCCESS.
  1704. *
  1705. * EXIT_ERROR:  Error Code.
  1706. *
  1707. * EFFECTS:
  1708. *
  1709. * INTERNAL REFERENCES:
  1710. *
  1711. * EXTERNAL REFERENCES:
  1712. *
  1713. *********************** END OF SPECIFICATIONS *******************************/
  1714.  
  1715. RC  ConvertTimeUnits ( INSTANCE    *ulpInstance,
  1716.                        PULONG      pulSeekPoint,
  1717.                        ULONG       ulValue)
  1718. {
  1719. /* add a flag and remove this file length kludge */
  1720.  
  1721.   ULONG      ulBytesPerSample;
  1722.   ULONG      ulTemp1;
  1723.  
  1724. #ifdef CONNECTION
  1725.   if ( !ulpInstance->fConnected )
  1726.      {
  1727.      *pulSeekPoint = 0;
  1728.  
  1729.      }
  1730.   else
  1731.      {
  1732.      if ( !(ulpInstance->ulFlags & HAVE_SPCBKEY) )
  1733.         {
  1734.         GetSpcbKeyInfo( ulpInstance );
  1735.         }
  1736.  
  1737.      ulpInstance->ulFlags |= HAVE_SPCBKEY;
  1738.  
  1739. #endif
  1740.  
  1741.   /*---------------------------------------------------
  1742.   * due to inaccuracies in the conversions, if the request is bytes or samples
  1743.   *  simply return the number
  1744.   *  this file length stuff is garbarge, add a new flag
  1745.   *---------------------------------------------------*/
  1746.   /**************************************
  1747.   * Computation of Media Element Length
  1748.   * This routine is called with FILE LENGTH
  1749.   * value to signify Total length is
  1750.   * requested.
  1751.   ***************************************/
  1752.   if ( ulValue == FILE_LENGTH)
  1753.       {
  1754.  
  1755.       /* due to inaccuracies in the conversions, if the request is bytes or samples
  1756.       *  simply return the number itself
  1757.       */
  1758.  
  1759.       if ( ulpInstance->ulTimeUnits == lBYTES )
  1760.          {
  1761.          *pulSeekPoint = ulpInstance->ulDataSize;
  1762.          return ( MCIERR_SUCCESS );
  1763.          }
  1764.       else if ( ulpInstance->ulTimeUnits == lSAMPLES )
  1765.          {
  1766.          ulBytesPerSample = (WAVEHDR.usBitsPerSample / 8);
  1767.          *pulSeekPoint = ulpInstance->ulDataSize / ulBytesPerSample;
  1768.          return ( MCIERR_SUCCESS );
  1769.          }
  1770.  
  1771.       /***********************************************
  1772.       * Get the number of blocks of audio information the
  1773.       * desired number of bytes consumes.
  1774.       *************************************************/
  1775.       ulTemp1 = ulpInstance->ulDataSize / ulpInstance->ulBytes;
  1776.  
  1777.  
  1778.  
  1779.       /***********************************************
  1780.       * Multiply the blocks above by the length in time
  1781.       * of a block.
  1782.       *************************************************/
  1783.  
  1784.       ulValue = ulTemp1 * ulpInstance->ulMMTime;
  1785.  
  1786.       } /* Return File Length */
  1787.  
  1788.  
  1789.   switch (ulpInstance->ulTimeUnits)
  1790.   {
  1791.   case lMMTIME:
  1792.        *pulSeekPoint = ulValue;
  1793.       break;
  1794.  
  1795.   case lMILLISECONDS:
  1796.        *pulSeekPoint = MSECFROMMM ( ulValue );
  1797.       break;
  1798.  
  1799.   case lSAMPLES:
  1800.        ulBytesPerSample = (WAVEHDR.usBitsPerSample / 8);
  1801.  
  1802.        ulTemp1 = ulValue / ulpInstance->ulMMTime ;
  1803.        ulTemp1 *= ulpInstance->ulBytes;
  1804.        *pulSeekPoint = ulTemp1 / ulBytesPerSample;
  1805.       break;
  1806.  
  1807.   default: // time value must be bytes
  1808.        ulTemp1 = ulValue / ulpInstance->ulMMTime ;
  1809.       *pulSeekPoint = ulTemp1 * ulpInstance->ulBytes;
  1810. //       Mmtime2Bytes( ulpInstance->ulBytes,  (LONG) ulValue, ( LONG ) ulpInstance->ulMMTime, ( PLONG ) pulSeekPoint);
  1811.  
  1812.       break;
  1813.  
  1814.   } /* Of Switch */
  1815.  
  1816.  
  1817. #ifdef CONNECTION
  1818.    }
  1819. #endif
  1820.  
  1821.   return ( MCIERR_SUCCESS );
  1822.  
  1823. } /* ConvertTimeUnits */
  1824.  
  1825. // CONNECTION FEATURE
  1826. /********************* START OF SPECIFICATIONS *******************************
  1827. *
  1828. * SUBROUTINE NAME: PackSSMStruct
  1829. *
  1830. * DESCRIPTIVE NAME:
  1831. *
  1832. * FUNCTION: Prepare MCI_SSM_PARMS for an MCI_CONNECTION call.
  1833. *
  1834. * NOTES: This function will create a cue time pause event.  When the
  1835. *
  1836. * ENTRY POINTS:
  1837. *
  1838. * INPUT:
  1839. *
  1840. * EXIT-NORMAL: void
  1841. *
  1842. * EXIT_ERROR:  Error Code.
  1843. *
  1844. * EFFECTS:
  1845. *
  1846. * INTERNAL REFERENCES: SpiEnableEvent()
  1847. *
  1848. * EXTERNAL REFERENCES:
  1849. *
  1850. *********************** END OF SPECIFICATIONS *******************************/
  1851.  
  1852. //void PackSSMStruct ( INSTANCE               *pInstance,
  1853. //                     PMCI_SSM_STREAM_PARMS  pmssm )
  1854. //{
  1855.  
  1856. // 6421--we no longer will be creating the stream here--rather, send
  1857. // and MCI_SSM_CONNECTION--we don't want to know the guts of the
  1858. // other sides stream handler.
  1859. //
  1860. //
  1861. //   if ( pInstance->ulOperation == OPERATION_PLAY )
  1862. //      {
  1863. //      pmssm->ulStreamFlags = MCI_SSM_SOURCE;
  1864. //      pmssm->hidSrc = pInstance->StreamInfo.hidASource;
  1865. //      pmssm->EventEntry = (PEVFN) PlayEventRoutine;
  1866. //      }
  1867. //   else
  1868. //      {
  1869. //      pmssm->ulStreamFlags = MCI_SSM_TARGET;
  1870. //      pmssm->hidTgt = pInstance->StreamInfo.hidATarget;
  1871. //      pmssm->EventEntry = (PEVFN)RecordEventRoutine;
  1872. //      }
  1873. //
  1874. //   pmssm->pspcbkey = &pInstance->StreamInfo.SpcbKey;
  1875. //   pmssm->pdcbSrc = NULL;
  1876. //   pmssm->pdcbTgt = NULL;
  1877. //   pmssm->pevcb = (PIMPL_EVCB) &pInstance->StreamInfo.Evcb;
  1878. //   pmssm->phevent = &pInstance->StreamInfo.hEvent;
  1879. //   pmssm->phstream = &pInstance->StreamInfo.hStream;
  1880. //   pmssm->hStreamBuf = 0;
  1881. //
  1882. //} // PackSSMStruct
  1883. // CONNECTION FEATURE
  1884.  
  1885.  
  1886. // Function is no longer needed.
  1887. #ifndef CONNECTION
  1888. /********************* START OF SPECIFICATIONS *******************************
  1889. *
  1890. * SUBROUTINE NAME: CreateNAssocStream
  1891. *
  1892. * DESCRIPTIVE NAME:
  1893. *
  1894. * FUNCTION: Create a stream and associate this stream with its data
  1895. *           object.
  1896. *
  1897. *
  1898. * NOTES: This function illustrates how one can create a custom event
  1899. *        structure and have SSM return events in this structure.
  1900. *        This allows one to place information like window callback handles
  1901. *        in the event structure, so that when a certain event occurs,
  1902. *        a message can be sent via this window call back handle.
  1903. *
  1904. *        The creation of this custom structure can be found in audiomcd.h
  1905. *        and the use of this structure can be found in admcplay.c and
  1906. *        admcrecd.c.  The initialization of this structure can be
  1907. *        found in admcopen.c
  1908. *
  1909. * INPUT:
  1910. *
  1911. * EXIT-NORMAL: MCIERR_SUCCESS.
  1912. *
  1913. * EXIT_ERROR:  Error Code (from SPI).
  1914. *
  1915. * EFFECTS:
  1916. *
  1917. * INTERNAL REFERENCES:
  1918. *
  1919. * EXTERNAL REFERENCES:  SpiCreateStream ()      - SSM SPI
  1920. *                       SpiAssociate ()         - SSM SPI
  1921. *
  1922. *********************** END OF SPECIFICATIONS *******************************/
  1923.  
  1924. RC CreateStream (// HID       hidSrc,         /* Source Handler HID */ // 6421--excess
  1925.                  // HID       hidTgt,         /* Target Handler HID */ // "   "     "
  1926.                  // HSTREAM   *hStream,       /* Stream Handle ()   */ // 6421--excess
  1927.                   INSTANCE  *pInstance )     /* Instance Pointer   */
  1928.                  // ULONG      ulDirection,        /* Play or Record     */ // 6421--wasted variable
  1929.                  // PEVFN     EventProc)      /* Event Entry Point  */ // 6421--excess variable
  1930.  
  1931. {
  1932.  
  1933.   ULONG     ulrc;
  1934.   HID       hidSource;
  1935.   HID       hidTarget;
  1936.   HID       hidAudio;
  1937.   PDCB      pdcbSource;
  1938.   PDCB      pdcbTarget;
  1939.  
  1940.   extern     HID                 hidASource;
  1941.   extern     HID                 hidATarget;
  1942.   extern     HID                 hidA2Source;
  1943.   extern     HID                 hidA2Target;
  1944.   extern     HID                 hidBSource;
  1945.   extern     HID                 hidBTarget;
  1946.  
  1947.  
  1948.   PEVFN     EventProc;
  1949.  
  1950.  
  1951.   /*********************************************************
  1952.   * Create the stream that play/record/cue will use.
  1953.   * The caller supplies the source and target stream
  1954.   * handlers and the audio device control block should
  1955.   * have been filled in previously ( see InitAudioDevice )
  1956.   * The caller also supplies the EventProc(edure)
  1957.   * whereg all of the stream events will be reported.
  1958.   *
  1959.   * Note: pInstance->StreamInfo.Evcb contains the
  1960.   *********************************************************/
  1961.  
  1962.    if ( pInstance->ulOperation == MCIDRV_INPUT )
  1963.       {
  1964.       hidSource = hidAudio = hidBSource;
  1965.       if ( !pInstance->usPlayLstStrm )
  1966.          {
  1967.          hidTarget = hidATarget;
  1968.          }
  1969.       else
  1970.          {
  1971.          hidTarget = hidA2Target;
  1972.          }
  1973.       /*-----------------------------------
  1974.       * Store the hid of attached MCI driver
  1975.       * Used to enable/disable events
  1976.       *------------------------------------*/
  1977.  
  1978.       pInstance->hidAttached = hidSource;
  1979.       pdcbSource = pInstance->pdcb;
  1980.       pdcbTarget = (PDCB) NULL;
  1981.       EventProc = (PEVFN) RecordEventRoutine;
  1982.  
  1983.       }
  1984.    else
  1985.       {
  1986.       if ( !pInstance->usPlayLstStrm )
  1987.          {
  1988.          hidSource = hidASource;
  1989.          }
  1990.       else
  1991.          {
  1992.          hidSource = hidA2Source;
  1993.          }
  1994.       hidTarget = hidAudio = hidBTarget;
  1995.  
  1996.       /*-----------------------------------
  1997.       * Store the hid of attached MCI driver
  1998.       * Used to enable/disable events
  1999.       *------------------------------------*/
  2000.  
  2001.       pInstance->hidAttached = hidTarget;
  2002.  
  2003.       pdcbSource = (PDCB) NULL;
  2004.       pdcbTarget = pInstance->pdcb;
  2005.       EventProc = (PEVFN) PlayEventRoutine;
  2006.  
  2007.       }
  2008.  
  2009.   ulrc = SpiCreateStream ( hidSource,
  2010.                            hidTarget,
  2011.                            &pInstance->StreamInfo.SpcbKey,
  2012.                            pdcbSource,
  2013.                            pdcbTarget,
  2014.                            (PIMPL_EVCB) &pInstance->StreamInfo.Evcb,
  2015.                            (PEVFN) EventProc,
  2016.                            (ULONG) NULL,
  2017.                            &pInstance->StreamInfo.hStream,
  2018.                            &pInstance->StreamInfo.hEvent);
  2019.  
  2020.   if (ulrc)
  2021.       return (ulrc);
  2022.  
  2023. //debug hack--remove!!!!!!
  2024. //  if ( pInstance->pcodecini )
  2025. //     {
  2026. //     CleanUp( ( PVOID ) pInstance->pcodecini );
  2027. //     }
  2028.  
  2029. /**********************************************************
  2030. * The stream must be associated with a data object
  2031. * in our case a mmio file handle.  The file system
  2032. * stream handler (FSSH) will always be the stream handler
  2033. * that we want to associate the data object with,
  2034. * therefore, if we have created a playback stream then
  2035. * FSSH is the source, so associate with the source.  On a
  2036. * record stream, FSSH is the target, so associate with
  2037. * the target.
  2038. **********************************************************/
  2039.  
  2040.  
  2041.   pInstance->StreamInfo.acbmmio.ulObjType = ACBTYPE_MMIO;
  2042.   pInstance->StreamInfo.acbmmio.ulACBLen = sizeof (ACB_MMIO);
  2043.   pInstance->StreamInfo.acbmmio.hmmio = pInstance->hmmio;
  2044.  
  2045.   if ( !pInstance->usPlayLstStrm )
  2046.      {
  2047.      if (pInstance->ulOperation == MCIDRV_OUTPUT )
  2048.          {
  2049.  
  2050.          ulrc = ADMCAssociate ( pInstance->StreamInfo.hStream,
  2051.                                 hidSource,
  2052.                                (PVOID) &pInstance->StreamInfo.acbmmio);
  2053.  
  2054.          }  /* Associating play stream */
  2055.  
  2056.      else // if ( Operation == MCIDRV_INPUT )
  2057.          {
  2058.          ulrc = ADMCAssociate ( pInstance->StreamInfo.hStream,
  2059.                                 hidTarget,
  2060.                                 (PVOID) &pInstance->StreamInfo.acbmmio);
  2061.  
  2062.          } /* Associating record stream */
  2063.  
  2064.      }
  2065.   else
  2066.      {
  2067.      ulrc = AssociatePlayList ( pInstance );
  2068.      }
  2069.  
  2070.   /******************************************************
  2071.   * Kludge until connectors are ready.
  2072.   * If the file is compressed, inform the audio stream
  2073.   * handler of the compression technique to use.
  2074.   *
  2075.   * ONLY do this if we are in playback mode.
  2076.   ******************************************************/
  2077.   if ( pInstance->ulRealTimeTranslation ==MMIO_REALTIME &&
  2078.        pInstance->ulOperation == MCIDRV_OUTPUT )
  2079.      {
  2080.      PCODECOPEN         pcodecopen = ( PCODECOPEN ) pInstance->pcodecopen;
  2081.      MMAUDIOOPEN *pbufferinfo = ( MMAUDIOOPEN *) pcodecopen->pOtherInfo;
  2082.  
  2083.      AUDIO_CODEC_INFO    audiocodecinfo;
  2084.  
  2085.      /******************************************************
  2086.      * The audio stream handler needs to know the codec that
  2087.      * we are talking to and the compression ratios that the
  2088.      * codec is using to estimate buffer sizes etc.
  2089.      ******************************************************/
  2090.  
  2091.      audiocodecinfo.ulStructLen = sizeof ( AUDIO_CODEC_INFO );
  2092.      audiocodecinfo.ulBytesPerBlock = pbufferinfo->ulBytesPerBlock ;
  2093.      audiocodecinfo.ulBlockAlignment = pbufferinfo->ulBlockAlignment;
  2094.      audiocodecinfo.hCodec = pbufferinfo->hCodec;
  2095.      audiocodecinfo.pfnCodec = pbufferinfo->pfnCodec;
  2096.  
  2097.      /* Blowing off return codes for now */
  2098.  
  2099. //     SpiSendMsg( pInstance->StreamInfo.hStream,
  2100. //                 hidAudio,
  2101. //                 AUDIO_CODEC_INF,
  2102. //                 &audiocodecinfo );
  2103.  
  2104.  
  2105.      }  /* If real-time translation */
  2106.  
  2107.  
  2108.  
  2109.   return (ulrc);
  2110.  
  2111. } /* CreateStream */
  2112. #endif
  2113.  
  2114. /********************* START OF SPECIFICATIONS *******************************
  2115. *
  2116. * SUBROUTINE NAME: DoTillEvent()
  2117. *
  2118. * DESCRIPTIVE NAME:
  2119. *
  2120. * FUNCTION: Enable a Time Event to process MCI_PLAY or MCI_RECORD with
  2121. *           the MCI_TO Flag on.
  2122. *
  2123. * NOTES: This function will create a cue time pause event.  When the
  2124. *        stream reaches the event during a play or record, the
  2125. *        audio stream handler will signal the MCD--note, the stream
  2126. *        will not be stopped, it is the MCD's responsibility.
  2127. *
  2128. * ENTRY POINTS:
  2129. *
  2130. * INPUT:
  2131. *
  2132. * EXIT-NORMAL: MCIERR_SUCCESS.
  2133. *
  2134. * EXIT_ERROR:  Error Code.
  2135. *
  2136. * EFFECTS:
  2137. *
  2138. * INTERNAL REFERENCES: SpiEnableEvent()
  2139. *
  2140. * EXTERNAL REFERENCES:
  2141. *
  2142. *********************** END OF SPECIFICATIONS *******************************/
  2143. RC CreateToEvent (INSTANCE *ulpInstance, ULONG ulTo)
  2144. {
  2145. /* rename this function CreateToEvent */
  2146.  
  2147.  
  2148.   ULONG ulrc;
  2149.   extern     HID                 hidBSource;
  2150.   extern     HID                 hidBTarget;
  2151.   HID                            hidEvents;
  2152.   hidEvents = ulpInstance->hidAttached;
  2153.  
  2154. //   if ( ulpInstance->ulOperation == MCIDRV_INPUT )
  2155. //      {
  2156. //      hidEvents = hidBSource;
  2157. //      }
  2158. //   else
  2159. //      {
  2160. //      hidEvents = hidBTarget;
  2161. //      }
  2162.  
  2163.   /*********************************************************
  2164.   * Set up a cue time pause event at the place in
  2165.   * the stream where the caller wants us to play/record
  2166.   * to.  Note: this event will pause the stream and
  2167.   * will be considerably more accurate than just
  2168.   * setting a cue point, receiving the event and stopping
  2169.   * the stream (since a normal cue point will force
  2170.   * bleed over).
  2171.   *********************************************************/
  2172.  
  2173.   ulpInstance->StreamInfo.TimeEvcb.hwndCallback      = ulpInstance->hwndCallBack;
  2174.   ulpInstance->StreamInfo.TimeEvcb.usDeviceID         = ulpInstance->usWaveDeviceID;
  2175.   ulpInstance->StreamInfo.TimeEvcb.evcb.ulType       = EVENT_CUE_TIME_PAUSE;
  2176.   ulpInstance->StreamInfo.TimeEvcb.evcb.ulFlags      = EVENT_SINGLE;
  2177.   ulpInstance->StreamInfo.TimeEvcb.evcb.hstream      = ulpInstance->StreamInfo.hStream;
  2178.   ulpInstance->StreamInfo.TimeEvcb.ulpInstance       = (ULONG) ulpInstance;
  2179.   ulpInstance->StreamInfo.TimeEvcb.evcb.mmtimeStream = ulTo;
  2180.   ulpInstance->StreamInfo.TimeEvcb.evcb.hid          = hidEvents;
  2181.  
  2182.   /* Enable the cue time pause event. */
  2183.  
  2184.   ulrc = ADMCEnableEvent((PEVCB) &ulpInstance->StreamInfo.TimeEvcb.evcb,
  2185.                         (PHEVENT) &ulpInstance->StreamInfo.hPlayToEvent);
  2186.  
  2187.   return ( ulrc );
  2188.  
  2189. } /* CreateToEvent */
  2190.  
  2191. /********************* START OF SPECIFICATIONS *********************
  2192. *
  2193. * SUBROUTINE NAME:              GetPDDName
  2194. *
  2195. * DESCRIPTIVE NAME:
  2196. *
  2197. * FUNCTION:     Retrieves the PDD name (AUDIO1$, etc.) based
  2198. *               on which AmpMixer we're connected to
  2199. *
  2200. * NOTES:        DCR 104
  2201. *
  2202. * INPUT:
  2203. *         ULONG         ulDeviceType
  2204. *         CHAR          szPDDName [MAX_PDD_NAME]        - OUTPUT
  2205. *
  2206. * EXIT-NORMAL:  NO_ERROR
  2207. *
  2208. * EXIT_ERROR:
  2209. *
  2210. *********************** END OF SPECIFICATIONS *********************************/
  2211. //RC GetPDDName (ULONG ulDeviceType, CHAR szPDDName [MAX_PDD_NAME])
  2212. //{
  2213. //
  2214. //   ULONG                   rc;
  2215. //
  2216. //   CHAR                    szIndex[2];
  2217. //   CHAR                    szAmpMix[9] = "AMPMIX0";
  2218. //
  2219. //   MCI_SYSINFO_PARMS       SysInfo;
  2220. //   MCI_SYSINFO_LOGDEVICE   SysInfoParm;
  2221. //   MCI_SYSINFO_QUERY_NAME  QueryNameParm;
  2222. //
  2223. //   memset (&SysInfo, '\0', sizeof(SysInfo));
  2224. //   memset (&SysInfoParm, '\0', sizeof(SysInfoParm));
  2225. //   memset (&QueryNameParm, '\0', sizeof(QueryNameParm));
  2226. //
  2227. //   SysInfo.ulItem       = MCI_SYSINFO_QUERY_NAMES;
  2228. //   SysInfo.usDeviceType  = LOUSHORT(ulDeviceType);
  2229. //   SysInfo.pSysInfoParm = &QueryNameParm;
  2230. //
  2231. //   itoa (HIUSHORT(ulDeviceType), szIndex, 10);
  2232. //
  2233. //   szIndex[1] = '\0';
  2234. //
  2235. //   strncat (szAmpMix, szIndex, 2);
  2236. //   strcpy (QueryNameParm.szLogicalName, szAmpMix);
  2237. //
  2238. //   if (rc = mciSendCommand (0,
  2239. //                            MCI_SYSINFO,
  2240. //                            MCI_SYSINFO_ITEM | MCI_WAIT,
  2241. //                            (PVOID) &SysInfo,
  2242. //                            0))
  2243. //           return (rc);
  2244. //
  2245. //
  2246. //
  2247. //
  2248. //   /*******************************************
  2249. //   * Get PDD associated with our AmpMixer
  2250. //   * Device name is in pSysInfoParm->szPDDName
  2251. //   ********************************************/
  2252. //
  2253. //   SysInfo.ulItem       = MCI_SYSINFO_QUERY_DRIVER;
  2254. //   SysInfo.usDeviceType  = (USHORT) ulDeviceType;
  2255. //   SysInfo.pSysInfoParm = &SysInfoParm;
  2256. //
  2257. //   strcpy (SysInfoParm.szInstallName, QueryNameParm.szInstallName);
  2258. //
  2259. //   if (rc = mciSendCommand (0,
  2260. //                            MCI_SYSINFO,
  2261. //                            MCI_SYSINFO_ITEM | MCI_WAIT,
  2262. //                            (PVOID) &SysInfo,
  2263. //                            0))
  2264. //       return (rc);
  2265. //
  2266. //   strcpy (szPDDName, SysInfoParm.szPDDName);
  2267. //
  2268. //   return ( MCIERR_SUCCESS );
  2269. //
  2270. //} /* GetPDDName */
  2271.  
  2272. /********************* START OF SPECIFICATIONS *********************
  2273. *
  2274. * SUBROUTINE NAME: Generic thread abort
  2275. *
  2276. * DESCRIPTIVE NAME:
  2277. *
  2278. * FUNCTION: This will abort any waiting command on another thread.
  2279. *
  2280. *
  2281. * EXIT-NORMAL:  NO_ERROR
  2282. *
  2283. * EXIT_ERROR:
  2284. *
  2285. *********************** END OF SPECIFICATIONS *********************************/
  2286.  
  2287.  
  2288. void GenericThreadAbort( INSTANCE             *ulpInstance,
  2289.                          FUNCTION_PARM_BLOCK  *pFuncBlock,
  2290.                          ULONG                ulCloseFlag )
  2291.  
  2292.  
  2293. {
  2294. //BOOL     fForceDiscard = FALSE;
  2295.  
  2296.   if ( ulpInstance->usNotPendingMsg == MCI_SAVE )
  2297.      {
  2298.      /****************************************
  2299.      ** Save is a non-interruptible operation
  2300.      ** wait for completion
  2301.      *****************************************/
  2302.  
  2303.      DosWaitEventSem( ulpInstance->hThreadSem, (ULONG ) -1 );
  2304.      }
  2305.    else
  2306.      {
  2307.      PostMDMMessage ( MCI_NOTIFY_ABORTED,
  2308.                       ulpInstance->usNotPendingMsg,
  2309.                       pFuncBlock);
  2310.  
  2311.  
  2312.      /* Stop the pending thread */
  2313.  
  2314.      if ( !(ulCloseFlag & MCI_CLOSE_EXIT) )
  2315.         {
  2316.         if ( pFuncBlock->usMessage == MCI_CLOSE )
  2317.            {
  2318.            /*****************************************
  2319.            * create a fake event so the thread we are
  2320.            * waiting on will have a chance to clean
  2321.            * up.  It is important that we do not do
  2322.            * an spistop since the instance may not
  2323.            * be currently active.
  2324.            *****************************************/
  2325.  
  2326.            ulpInstance->StreamEvent = EVENT_STREAM_STOPPED;
  2327.            DosPostEventSem (ulpInstance->hEventSem);
  2328.  
  2329.            DosWaitEventSem (ulpInstance->hThreadSem, (ULONG) -1);
  2330.            }
  2331.  
  2332.         else
  2333.            {
  2334.            ThreadedStop ( ulpInstance );
  2335.            }
  2336.         }
  2337.  
  2338.      } /* if !save pending */
  2339.  
  2340. } /* GenericThreadAbort */
  2341.  
  2342.  
  2343.  
  2344. /********************* START OF SPECIFICATIONS *********************
  2345. *
  2346. * SUBROUTINE NAME: ThreadedStop
  2347. *
  2348. * DESCRIPTIVE NAME:
  2349. *
  2350. * FUNCTION: Stop pending plays or records
  2351. *
  2352. * INPUT:
  2353. *
  2354. * EXIT-NORMAL:  NO_ERROR
  2355. *
  2356. * EXIT_ERROR:
  2357. *
  2358. *********************** END OF SPECIFICATIONS *********************************/
  2359.  
  2360. void ThreadedStop( INSTANCE     *ulpInstance )
  2361.  
  2362.  
  2363. {
  2364. ULONG   ulrc;
  2365. ULONG   ulSpiFlags;
  2366.  
  2367.  
  2368.  
  2369.  
  2370.    if ( ulpInstance->ulOperation == MCIDRV_OUTPUT )
  2371.       {
  2372.       ulSpiFlags = SPI_STOP_DISCARD;
  2373.       }
  2374.    else
  2375.       {
  2376.       ulSpiFlags = SPI_STOP_FLUSH;
  2377.       }
  2378.  
  2379.    /*****************************************************
  2380.    * Stop discard for play because data loss is not
  2381.    * important.
  2382.    * Stop flush a record stream so that no data will be
  2383.    * lost.
  2384.    *****************************************************/
  2385.  
  2386.    ulrc = ADMCStopStream (ulpInstance, ulSpiFlags);
  2387.  
  2388. //   if (ulrc != ERROR_STREAM_ALREADY_STOP )
  2389. //     {
  2390.      DosWaitEventSem (ulpInstance->hThreadSem, (ULONG) -1);
  2391. //     }
  2392.  
  2393.    STRMSTATE = MCI_STOP;
  2394.  
  2395.   return;
  2396.  
  2397. } /* ThreadedStop */
  2398.