home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv8.zip / VACPP / IBMCPP / samples / TOOLKIT / MM / ADMCT / ADMCEDIT.C < prev    next >
C/C++ Source or Header  |  1994-11-17  |  36KB  |  1,231 lines

  1. /********************* START OF SPECIFICATIONS *********************
  2. *
  3. * SUBROUTINE NAME: ADMCEDIT.C
  4. *
  5. *
  6. *              Copyright (c) IBM Corporation  1991, 1993
  7. *                        All Rights Reserved
  8. *
  9. * DESCRIPTIVE: Digital Audio clipboard manipulation and error
  10. *              detection source file
  11. *
  12. * FUNCTION:  Holds subroutines and flag checking routines for the
  13. *            mci editing operations (e.g. cut/copy/paste/delete).
  14. *
  15. *
  16. * NOTES:  Concepts illustrated in this source file:
  17. *          A. How to process MCI_FROM / MCI_TO for edit operations
  18. *             ( CheckEditFlags).
  19. *          B. Determine default from/to positions.
  20. *          C. Generic stream abort routine
  21. *          D. Retrieving information from the clipboard.
  22. *          E. Placing information into the clipboard.
  23. *          F. Using mmio memory files to manipulate clipboard data.
  24. *
  25. * ENTRY POINTS:
  26. *     LINKAGE:   CALL FAR
  27. *
  28. *
  29. * EXIT-NORMAL: MCIERR_SUCCESS
  30. *
  31. * EXIT_ERROR:  Error Code.
  32. *
  33. * EFFECTS:
  34. *
  35. * INTERNAL REFERENCES: MCIERR ().
  36. *
  37. * EXTERNAL REFERENCES:
  38. *
  39. ********************** END OF SPECIFICATIONS **********************/
  40.  
  41. #define INCL_WINCLIPBOARD
  42. #define INCL_WINWINDOWMGR
  43. #define INCL_DOSSEMAPHORES
  44. #define INCL_DOSPROCESS
  45. #define INCL_ERRORS
  46. #define INCL_WINATOM
  47. #define INCL_HEAP
  48. #define INCL_DOSMEMMGR
  49.  
  50. #include <os2.h>                        // OS2 defines.
  51. #include <string.h>                     // String functions.
  52. #include <stdio.h>
  53. #include <bsememf.h>
  54. #include <os2medef.h>                   // MME includes files.
  55. #include <mmioos2.h>                    // MMIO Include.
  56. #include <ssm.h>                        // SSM spi includes.
  57. #include <mcios2.h>
  58. #include <meerror.h>                    // MM Error Messages.
  59. #include <mmdrvos2.h>                   // MCI Driver Include.
  60. #include <mcd.h>                        // AudioIFDriverInterface.
  61. #include <hhpheap.h>                    // Heap Manager Definitions
  62. #include <qos.h>
  63. #include <audiomcd.h>                   // Component Definitions
  64. #include "admcfunc.h"                   // Function Prototypes
  65. #include "admcres.h"                    // Definition for bitmap resource
  66. #ifndef TOOLKIT
  67. #include <convert.h>                    // Data conversion routines
  68. #endif
  69. #include <checkmem.h>
  70.  
  71. #include <mmdsload.h>
  72.  
  73. /********************* START OF SPECIFICATIONS *********************
  74. *
  75. * SUBROUTINE NAME: CheckEditFlags
  76. *
  77. * DESCRIPTIVE  Ensures that editing functions have valid flags.
  78. *
  79. * FUNCTION:  Checks to see if memory is correctly allocated, from/to
  80. *            flags if the exist are valid, ensures that a file element
  81. *            is loaded (if no buffer is passed) and aborts any in
  82. *            progress commands.
  83. *
  84. * NOTES:
  85. *
  86. * ENTRY POINTS:
  87. *     LINKAGE:   CALL FAR
  88. *
  89. * INPUT: MCI_STOP message.
  90. *
  91. * EXIT-NORMAL: MCIERR_SUCCESS
  92. *
  93. * EXIT_ERROR:  Error Code.
  94. *
  95. * EFFECTS:
  96. *
  97. * INTERNAL REFERENCES:  MCIERR ().
  98. *
  99. * EXTERNAL REFERENCES:
  100. *
  101. *********************** END OF SPECIFICATIONS **********************/
  102.  
  103.  
  104.  
  105. RC CheckEditFlags( FUNCTION_PARM_BLOCK *pFuncBlock,
  106.                    ULONG               ulMCIMajic )
  107.  
  108. {
  109.  
  110.   ULONG         ulParam1;           // Flags for this Msg
  111.   ULONG         ulParam2;           // Data for this Msg
  112.   ULONG         ulrc;               // Error Code Propogated
  113.   ULONG         ulFromRequest;      // Position to operate from
  114.   ULONG         ulToRequest = 0;    // Position to operate to
  115.   ULONG         ulFileLength;       // File length--used in range checking
  116.  
  117.   ULONG         ulEditFlags;
  118.   ULONG         ulAbortNotify=FALSE;// Flag to abort preceding commands
  119.   ULONG         ulOldTimeFormat;    // Old Time Format
  120.  
  121. //  LONG          lTempVal;
  122. //  LONG          lFromPosition;
  123.  
  124.   MCI_EDIT_PARMS *pEditParms;
  125.  
  126.   INSTANCE      *ulpInstance;         // Local Instance
  127.  
  128.   /********************************************
  129.   * Dereference Pointers From Thread Block
  130.   ********************************************/
  131.  
  132.   ulParam1 = pFuncBlock->ulParam1;
  133.   ulParam2 = pFuncBlock->ulParam2;
  134.   ulrc = MCIERR_SUCCESS;
  135.   ulpInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  136.  
  137.  
  138.   /*******************************************
  139.   * Ensure that the caller passed valid
  140.   * edit parms to us.
  141.   ********************************************/
  142.  
  143.   if ( ulMCIMajic )
  144.      {
  145.      ulrc = CheckMem ( (PVOID) ulParam2,
  146.                        sizeof (MCI_GENERIC_PARMS),
  147.                        PAG_READ | PAG_WRITE );
  148.      }
  149.   else
  150.      {
  151.      ulrc = CheckMem ( (PVOID) ulParam2,
  152.                        sizeof (MCI_EDIT_PARMS),
  153.                        PAG_READ | PAG_WRITE );
  154.      }
  155.  
  156.   if (ulrc != MCIERR_SUCCESS)
  157.      {
  158.      return (MCIERR_MISSING_PARAMETER);
  159.      }
  160.  
  161.   pEditParms = (MCI_EDIT_PARMS *) ulParam2;
  162.  
  163.   /*********************************
  164.   * Mask the flags the we support
  165.   **********************************/
  166.  
  167.   ulEditFlags = pFuncBlock->ulParam1;
  168.  
  169.   if ( !ulMCIMajic )
  170.      {
  171.      ulEditFlags &= ~( MCI_FROM + MCI_TO + MCI_NOTIFY + MCI_WAIT +
  172.                        MCI_CONVERT_FORMAT + MCI_FROM_BUFFER + MCI_TO_BUFFER );
  173.      }
  174.   else
  175.      {
  176.      ulEditFlags &= ~( MCI_WAIT + MCI_NOTIFY );
  177.      }
  178.  
  179.   /* If the caller passed in an  unsupported flag--return an error */
  180.  
  181.   if ( ulEditFlags )
  182.       return ( MCIERR_INVALID_FLAG );
  183.  
  184.  
  185.   if ( ( ulParam1 & MCI_FROM_BUFFER ) && ( ulParam1 & MCI_TO_BUFFER ) )
  186.      return ( MCIERR_INVALID_FLAG );
  187.  
  188.  
  189.  
  190.   /*********************************************
  191.   * If the user passed in a buffer, ensure that
  192.   * that it contains a valid pointer.
  193.   *******************************************/
  194.  
  195.  
  196.  
  197.   if ( ( ulParam1 & MCI_FROM_BUFFER ) || ( ulParam1 & MCI_TO_BUFFER ) )
  198.      {
  199.  
  200.  
  201.      /********************************************************
  202.      * When the buffer flags are passed in the caller is also
  203.      * responsible for passing in a valid mmaudioheader in
  204.      * the case of waveaudio.
  205.      *********************************************************/
  206.  
  207.      ulrc = CheckMem ( (PVOID) pEditParms->pHeader,
  208.                        sizeof ( MMAUDIOHEADER ),
  209.                        PAG_READ | PAG_WRITE );
  210.  
  211.      if (ulrc != MCIERR_SUCCESS)
  212.         {
  213.         return ( MCIERR_INVALID_BUFFER );
  214.         }
  215.  
  216.  
  217.      ulrc = CheckMem ( (PVOID) pEditParms->pBuff,
  218.                        sizeof ( pEditParms->ulBufLen ),
  219.                        PAG_READ | PAG_WRITE );
  220.  
  221.      if (ulrc != MCIERR_SUCCESS)
  222.         {
  223.         return ( MCIERR_INVALID_BUFFER );
  224.         }
  225.  
  226.  
  227.  
  228.  
  229.      }
  230.  
  231.   /*******************************************
  232.   * If a playlist is active, the only way to
  233.   * use the MCI_EDITING functions is to
  234.   * use a buffer since mmio commands do not
  235.   * work on playlists.
  236.   *******************************************/
  237.  
  238.   if ( ulpInstance->usPlayLstStrm &&
  239.        ( !(ulParam1 & MCI_FROM_BUFFER ) || !(ulParam1 & MCI_TO_BUFFER ) ) )
  240.      {
  241.      return ( MCIERR_UNSUPPORTED_FUNCTION );
  242.      }
  243.  
  244.   /*******************************************
  245.   * Ensure that there is a file to operate on
  246.   * if this is not a playlist and the buffer
  247.   * flag has not been sent.
  248.   *******************************************/
  249.  
  250.   if ( ulpInstance->usPlayLstStrm == FALSE &&
  251.        ulpInstance->fFileExists != TRUE)
  252.     {
  253.       return ( MCIERR_FILE_NOT_FOUND );
  254.     }
  255.  
  256.   /*******************************************
  257.   * Ensure that there is a file to operate on
  258.   * if this is not a playlist and the buffer
  259.   * flag has not been sent.
  260.   *******************************************/
  261.  
  262.   if ( WAVEHDR.usFormatTag != DATATYPE_WAVEFORM )
  263.     {
  264.     return ( MCIERR_UNSUPPORTED_FUNCTION );
  265.     }
  266.  
  267.   /*****************************************
  268.   * To ensure proper syncronization, acquire
  269.   * the semaphore which is used to control
  270.   * who can check to see which processes are
  271.   * active. This function will also tell us
  272.   * if there is an operation to abort or
  273.   * supercede.
  274.   ******************************************/
  275.  
  276.   GetNotifyAbortAccess ( ulpInstance, &ulAbortNotify );
  277.  
  278.   /*******************************************
  279.   * If there is an operation active (i.e. a
  280.   * play, record or save) then post a message
  281.   * stating that the command has been
  282.   * aborted (record or play) or
  283.   * wait for completion (save).
  284.   ********************************************/
  285.  
  286.   if ( ulAbortNotify )
  287.      {
  288.      /* Stop the command on another thread */
  289.  
  290.      GenericThreadAbort( ulpInstance, pFuncBlock, 0 );
  291.  
  292.      }  /* There was a pending Notify */
  293.  
  294.  
  295.  
  296.   if ( STRMSTATE != MCI_STOP &&
  297.        ulpInstance->ulCreateFlag == PREROLL_STATE )
  298.      {
  299.      ulrc = StopStream2( ulpInstance, MCIDRV_DISCARD_STREAM_NETWORK );
  300.  
  301.      if ( ulrc )
  302.         {
  303.         return( ulrc );
  304.         }
  305.      } /* If the stream is not in a stopped state */
  306.  
  307.  
  308.  
  309.   /*********************************************
  310.   * In order to determine if the edit request
  311.   * is valid, we must retrieve the length of
  312.   * the file.
  313.   *
  314.   * Note: the length of the file is returned in
  315.   * the time units we are using currently.
  316.   *********************************************/
  317.  
  318.   ConvertTimeUnits ( ulpInstance,
  319.                      &ulFileLength,
  320.                      FILE_LENGTH);
  321.  
  322.   if ( ulParam1 & MCI_FROM )
  323.      {
  324.      /* The from request MUST be within the limits of the current file */
  325.  
  326.      if ( pEditParms->ulFrom  > ulFileLength )
  327.         {
  328.         return ( MCIERR_OUTOFRANGE );
  329.         } /* request greater than file length */
  330.  
  331.      /* Convert the MCI_FROM position to bytes. */
  332.  
  333.      if ( ulpInstance->ulTimeUnits != lBYTES )
  334.         {
  335.         // investigate combining this into one routine
  336.  
  337.         ulOldTimeFormat = ulpInstance->ulTimeUnits;
  338.  
  339.         ulrc = ConvertToMM ( ulpInstance,
  340.                              &ulFromRequest,
  341.                              pEditParms->ulFrom );
  342.  
  343.         ulpInstance->ulTimeUnits = lBYTES;
  344.  
  345.         /* Convert number to bytes */
  346.         ConvertTimeUnits ( ulpInstance,
  347.                            &ulFromRequest,
  348.                            ulFromRequest );
  349.  
  350.         ulpInstance->ulTimeUnits = ulOldTimeFormat;
  351.         }
  352.      else
  353.         {
  354.         ulFromRequest = pEditParms->ulFrom;
  355.         }
  356.  
  357. //     lFromPosition = ulFromRequest;
  358.  
  359.      } /* MCI_FROM flag passed */
  360.  
  361.  
  362.   /*******************************************************
  363.   * In order to be valid, an MCI_TO request must
  364.   *   A. Be less than the file length.
  365.   *   B. Be less than the MCI_FROM position if specified.
  366.   *   C. If no from flag is specified, be less than the
  367.   *      current file position.
  368.   ********************************************************/
  369.  
  370.   if ( ulParam1 & MCI_TO )
  371.      {
  372.      /* The TO request MUST be within the limits of the current file */
  373.  
  374.  
  375.      if ( ulParam1 & MCI_FROM )
  376.         {
  377.         if ( pEditParms->ulTo <= pEditParms->ulFrom )
  378.            {
  379.            return ( MCIERR_OUTOFRANGE );
  380.            }
  381.         } /* MCI_FROM flag passed */
  382.  
  383. //     /********************************************
  384. //     * If no from flag was passed, edit operations
  385. //     * assume the current file position as the
  386. //     * start--if so, then ensure that the to point
  387. //     * is not behind our current position.
  388. //     *********************************************/
  389. //
  390. //     if ( ulpInstance->ulCreateFlag == PREROLL_STATE )
  391. //        {
  392. //        /**********************************************
  393. //        * Get the current stream time, it will be used
  394. //        * for range checking below.
  395. //        ***********************************************/
  396. //
  397. //        ulrc = SpiGetTime( STREAM.hStream,
  398. //                           ( PMMTIME ) &( STREAM.mmStreamTime ) );
  399. //
  400. //        if ( ulrc )
  401. //           {
  402. //           return ( ulrc );
  403. //           }
  404. //
  405. //        // investigate --combine into function.
  406. //
  407. //        ulOldTimeFormat = ulpInstance->ulTimeUnits;
  408. //
  409. //        ulpInstance->ulTimeUnits = lBYTES;
  410. //
  411. //        ConvertTimeUnits ( ulpInstance,
  412. //                           &ulToPosition,
  413. //                           STREAM.mmStreamTime );
  414. //
  415. //        ulpInstance->ulTimeUnits = ulOldTimeFormat;
  416. //
  417. //        }  /* if a stream has been created */
  418. //     else
  419. //        {
  420. //        lTempVal = mmioSeek( ulpInstance->hmmio,
  421. //                                 0,
  422. //                                 SEEK_CUR );
  423. //
  424. //        if ( lTempVal == MMIO_ERROR )
  425. //           {
  426. //           return ( MMIOERR_SEEK_FAILED );
  427. //           }
  428. //
  429. //        ulToPosition = ( ULONG ) lTempVal;
  430. //        } /* else there is no stream active */
  431.  
  432.      /************************************************
  433.      * Convert the MCI_TO request to mmtime,
  434.      * then to bytes so we can compare it with
  435.      * the current file position (which is in bytes).
  436.      ************************************************/
  437.  
  438.      if ( ulpInstance->ulTimeUnits != lBYTES )
  439.         {
  440.         // investigate --combine into function.
  441.         ulOldTimeFormat = ulpInstance->ulTimeUnits;
  442.  
  443.         ulrc = ConvertToMM ( ulpInstance,
  444.                              &ulToRequest,
  445.                              pEditParms->ulTo );
  446.  
  447.         ulpInstance->ulTimeUnits = lBYTES;
  448.  
  449.         ConvertTimeUnits ( ulpInstance,
  450.                            &ulToRequest,
  451.                            ulToRequest );
  452.  
  453.         ulpInstance->ulTimeUnits = ulOldTimeFormat;
  454.         }
  455.      else
  456.         {
  457.         ulToRequest = pEditParms->ulTo;
  458.         }
  459.  
  460. // what does this do?
  461.  
  462. //     if ( ulToPosition < ulToRequest )
  463. //        {
  464. //       return ( MCIERR_OUTOFRANGE );
  465. //        }
  466.  
  467.  
  468.      if ( pEditParms->ulTo  > ulFileLength )
  469. //          pEditParms->ulTo  > ulToRequest )
  470.         {
  471.         return ( MCIERR_OUTOFRANGE );
  472.         } /* request greater than file length or current position */
  473.  
  474.  
  475.      } /* The MCI_TO flag was passed in */
  476.  
  477.  
  478.  
  479.   /* If undo or redo call, we are done */
  480.  
  481.   if ( ulMCIMajic )
  482.      {
  483.      return ( MCIERR_SUCCESS );
  484.      }
  485.  
  486.   /*********************************************
  487.   * All of the edit routines operate on a byte
  488.   * wise basis, therefore, convert the from/to
  489.   * numbers to bytes here so that code will not
  490.   * be replicated.
  491.   **********************************************/
  492.  
  493.   if ( ulParam1 & MCI_FROM )
  494.      {
  495.  
  496.      /*********************************************
  497.      * If we have a 16 bit file and the request
  498.      * starts in the midst of a sample, move to
  499.      * the beginning of the sample.
  500.      **********************************************/
  501.  
  502.      if ( WAVEHDR.usBitsPerSample == 16 &&
  503.           ulFromRequest % 2 )
  504.         {
  505.         ulFromRequest--;
  506.         }
  507.  
  508.      pEditParms->ulFrom = ulFromRequest;
  509.  
  510.      }
  511.  
  512.   if ( ulParam1 & MCI_TO )
  513.      {
  514.  
  515.      /*********************************************
  516.      * If we have a 16 bit file and the to request
  517.      * ends in the midst of a sample, move to
  518.      * the beginning of the sample.
  519.      **********************************************/
  520.  
  521.      if ( WAVEHDR.usBitsPerSample == 16 &&
  522.           ulToRequest % 2 )
  523.         {
  524.         ulToRequest--;
  525.         }
  526.  
  527.      /* We had previously converted this number to bytes */
  528.  
  529.      pEditParms->ulTo = ulToRequest;
  530.      }
  531.  
  532.  
  533.   return ( MCIERR_SUCCESS );
  534.  
  535. } /* CheckEditFlags */
  536.  
  537.  
  538.  
  539. /********************* START OF SPECIFICATIONS *********************
  540. *
  541. * SUBROUTINE NAME: GetFromToPosition
  542. *
  543. * DESCRIPTIVE  Returns the actual from/to position for edit operations.
  544. *
  545. * FUNCTION:  Will place the file the correct spot for from/to edit
  546. *            operations.  If either of the flags is not set, then it
  547. *            retrieves the defaults (current position for MCI_FROM, and
  548. *            end of file for MCI_TO ).
  549. *
  550. * NOTES:
  551. *
  552. * ENTRY POINTS:
  553. *     LINKAGE:   CALL FAR
  554. *
  555. * INPUT: MCI_STOP message.
  556. *
  557. * EXIT-NORMAL: MCIERR_SUCCESS
  558. *
  559. * EXIT_ERROR:  Error Code.
  560. *
  561. * EFFECTS:
  562. *
  563. * INTERNAL REFERENCES:  MCIERR ().
  564. *
  565. * EXTERNAL REFERENCES:
  566. *
  567. *********************** END OF SPECIFICATIONS **********************/
  568.  
  569. RC  GetFromToPosition(  LONG            lCurrFilePos,
  570.                         ULONG           ulParam1,
  571.                         MCI_EDIT_PARMS  *pEditParms,
  572.                         INSTANCE        *ulpInstance,
  573.                         PULONG          pulFromPosition,
  574.                         PULONG          pulToPosition )
  575.  
  576.  
  577. {
  578.   LONG    lTempPosition;  // temporary file position used by seek
  579.  
  580.  
  581.   if ( ulParam1 & MCI_FROM )
  582.      {
  583.      /********************************************************
  584.      * If we are not currently at the place the caller wants
  585.      * to copy from, seek there
  586.      ********************************************************/
  587.  
  588.      if ( pEditParms->ulFrom != ( ULONG ) lCurrFilePos )
  589.         {
  590.         lTempPosition = mmioSeek( ulpInstance->hmmio,
  591.                                   pEditParms->ulFrom,
  592.                                   SEEK_SET );
  593.  
  594.         if ( lTempPosition == MMIO_ERROR )
  595.            {
  596.            return ( MMIOERR_SEEK_FAILED );
  597.            }
  598.  
  599.         } /* if we are not at the from position */
  600.  
  601.      *pulFromPosition = pEditParms->ulFrom;
  602.  
  603.      } /* if the from flag was specified */
  604.   else
  605.      {
  606.      *pulFromPosition = lCurrFilePos;
  607.  
  608.      } /* else the from flag was not specified */
  609.  
  610.   if ( ulParam1 & MCI_TO )
  611.      {
  612.      *pulToPosition = pEditParms->ulTo;
  613.  
  614.      } /* MCI_TO flag specified */
  615.  
  616.   else
  617.      {
  618.      /* if no MCI_TO, we will operate to the end of file */
  619.  
  620.      *pulToPosition = XWAVHDR.ulAudioLengthInBytes;
  621.      } /* no MCI_TO flag */
  622.  
  623.   return ( MCIERR_SUCCESS );
  624.  
  625. } /* GetFromToPosition */
  626.  
  627.  
  628.  
  629. /********************* START OF SPECIFICATIONS *********************
  630. *
  631. * SUBROUTINE NAME: GetClipboardData
  632. *
  633. * DESCRIPTIVE  Gets digital audio information from the clipboard.
  634. *
  635. * FUNCTION:  Checks to see if the correct audio format is in the
  636. *            clipboard, if it is, a buffer is allocated and filled
  637. *            with wave information.
  638. *
  639. * NOTES:
  640. *
  641. * ENTRY POINTS:
  642. *     LINKAGE:   CALL FAR
  643. *
  644. * INPUT: MCI_STOP message.
  645. *
  646. * EXIT-NORMAL: Return Code 0.
  647. *
  648. * EXIT_ERROR:  Error Code.
  649. *
  650. * EFFECTS:
  651. *
  652. * INTERNAL REFERENCES:  MCIERR ().
  653. *
  654. * EXTERNAL REFERENCES: spiStopStream ()   -   SSM Spi
  655. *
  656. *********************** END OF SPECIFICATIONS **********************/
  657.  
  658. RC GetClipboardData( PVOID           *pBuffer,
  659.                      INSTANCE        *pInstance,
  660.                      ULONG           ulOperation,
  661.                      PULONG          pulBuffLen,
  662.                      ULONG           ulParam1,
  663.                      PMMAUDIOHEADER  pmmaudioheader )
  664.  
  665. {
  666. HAB            habClipboard;
  667. HMQ            hmq;
  668.  
  669. BOOL           fCreatedMQ = TRUE;  /* message queue creation? */
  670.  
  671. HMMIO          hmmioMem;           /* handle to memory file   */
  672.  
  673. MMIOINFO       mmioinfo;           /* info struct for memory file */
  674.  
  675. ULONG          ulFormatInfo = 0;
  676. ULONG          rc;
  677. PULONG         pulDataSize;
  678.  
  679. LONG           lBytesRead;
  680. LONG           lReturnCode;
  681.  
  682. MMAUDIOHEADER  mmaudioheader;
  683. MMAUDIOHEADER  mmaudioheaderTemp;
  684.  
  685.  
  686. PSZ            pTempBuffer;
  687. PVOID          pNewBuffer;
  688.  
  689.  
  690.   habClipboard = WinInitialize( 0 );
  691.   if ( !habClipboard )
  692.      {
  693.      return ( MCIERR_CLIPBOARD_ERROR );
  694.      }
  695.  
  696.   hmq = WinCreateMsgQueue( habClipboard, 0 );
  697.  
  698.   if ( !hmq )
  699.      {
  700.      fCreatedMQ = FALSE;
  701.      }
  702.  
  703. //  habClipboard = WinQueryAnchorBlock( HWND_DESKTOP );
  704.  
  705.   /*********************************************************************
  706.   * Check to see if there is a wave ( CF_WAVE is the defined type) in
  707.   * the clipboard.
  708.   *********************************************************************/
  709.  
  710.  
  711.   rc = WinQueryClipbrdFmtInfo( habClipboard,
  712.                           CF_WAVE,
  713.                           &ulFormatInfo );
  714.  
  715. //  if ( !rc )
  716. //     {
  717. //
  718. //     /*********************************************************************
  719. //     * If CF_WAVE is not in the clipboard, then it is possible that a
  720. //     * Win/OS2 OLE link is in the clipboard.  Check and see.
  721. //     *********************************************************************/
  722. //
  723. //    = WinFindAtom( WinQuerySystemAtomTable(),
  724. //                             "OwnerLink" );
  725. //     if ( !atomWave )
  726. //        {
  727. //        WinCloseClipbrd( habClipboard );
  728. //        return ( MCIERR_CLIPBOARD_EMPTY );
  729. //        }
  730. //     else
  731. //        {
  732. //        ulOleLink = TRUE;
  733. //        }
  734. //
  735. //     }
  736.  
  737.   if ( !WinOpenClipbrd( habClipboard ) )
  738.      {
  739.      WinCloseClipbrd( habClipboard );
  740.      return ( MCIERR_CLIPBOARD_ERROR );
  741.      }
  742.  
  743.   pTempBuffer = ( PSZ ) WinQueryClipbrdData( habClipboard, CF_WAVE );
  744.  
  745.   if ( !pTempBuffer )
  746.      {
  747.      WinCloseClipbrd( habClipboard );
  748.      return ( MCIERR_CLIPBOARD_ERROR );
  749.      }
  750.  
  751.  
  752.   /*********************************************************************
  753.   * We need to find out how much data is in the file, so retrieve
  754.   * the length of the riff chunk
  755.   *********************************************************************/
  756.   pulDataSize = ( PULONG ) pTempBuffer + 1;
  757.  
  758.  
  759.   memset( &mmioinfo, '\0', sizeof( MMIOINFO ) );
  760.  
  761.   /*********************************************************************
  762.   * Prepare to open a memory file--the buffer * in the clipboard contains
  763.   * actual Riff-file  which the wave io proc already knows how
  764.   * to parse--use it to retrieve the information  and keep the MCD from
  765.   * file format dependence.
  766.   *********************************************************************/
  767.  
  768.  
  769.   mmioinfo.fccIOProc = mmioFOURCC( 'W', 'A', 'V', 'E' ) ;
  770.   mmioinfo.fccChildIOProc = FOURCC_MEM;
  771.  
  772.   rc = CheckMem ( (PVOID) pulDataSize,
  773.                     sizeof ( ULONG ),
  774.                     PAG_READ | PAG_WRITE );
  775.  
  776.   if (rc != MCIERR_SUCCESS)
  777.      {
  778.      WinCloseClipbrd( habClipboard );
  779.      return (MCIERR_OUT_OF_MEMORY );
  780.      }
  781.  
  782.  
  783.   mmioinfo.cchBuffer = ( *pulDataSize) + 8;
  784.   mmioinfo.pchBuffer = pTempBuffer;
  785.  
  786.  
  787.   hmmioMem = mmioOpen( NULL,
  788.                        &mmioinfo,
  789.                        MMIO_READ );
  790.  
  791.  
  792.   if ( !hmmioMem )
  793.      {
  794.      WinCloseClipbrd( habClipboard );
  795.      return ( mmioinfo.ulErrorRet );
  796.      }
  797.  
  798.   /******************************************
  799.   * Figure out how big the file is by
  800.   * retrieving the audio header--remember that
  801.   * although this is physical memory, it is
  802.   * treated as a file by mmio.
  803.   ******************************************/
  804.  
  805.   lReturnCode  = mmioGetHeader ( hmmioMem,
  806.                                  (PVOID) &mmaudioheader,
  807.                                  sizeof( mmaudioheader ),
  808.                                  &lBytesRead,
  809.                                  (ULONG) NULL,
  810.                                  (ULONG) NULL);
  811.  
  812.   if ( lReturnCode == MMIO_SUCCESS )
  813.      {
  814.       /***********************************************
  815.       * The current routines can only process PCM.
  816.       * Sometime in the future, we will handle other
  817.       * formats like ADPCM.  Note: what about alaw + mulaw?????????
  818.       * should be easy to convert.
  819.       **********************************************/
  820.  
  821.      if ( mmaudioheader.mmXWAVHeader.WAVEHeader.usFormatTag !=
  822.           DATATYPE_WAVEFORM )
  823.         {
  824.         WinCloseClipbrd( habClipboard );
  825.         return ( MCIERR_CANNOT_CONVERT ); // is there invalid format ?
  826.         }
  827.       /***********************************************
  828.       * Have the io proc parse file format and bring in
  829.       * the entire amount in the clipboard.
  830.       **********************************************/
  831.  
  832.      *pulBuffLen = mmaudioheader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes;
  833.  
  834.      *pBuffer = HhpAllocBuffer( mmaudioheader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes + 500,
  835.                                 0 );
  836.  
  837.      lReturnCode = mmioRead( hmmioMem,
  838.                              ( PSZ ) *pBuffer,
  839.                              mmaudioheader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes );
  840.  
  841.      if ( lReturnCode != mmaudioheader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes )
  842.         {
  843.         // return better error
  844.         WinCloseClipbrd( habClipboard );
  845.         lReturnCode = mmioGetLastError( hmmioMem );
  846.         mmioClose( hmmioMem, ( WORD ) NULL );
  847.  
  848.         return( lReturnCode );
  849.         }
  850.  
  851.      } /* if we successfully retrieved the header */
  852.   else
  853.      {
  854.      // return better error
  855.      WinCloseClipbrd( habClipboard );
  856.      lReturnCode = mmioGetLastError( hmmioMem );
  857.  
  858.      mmioClose( hmmioMem, ( WORD ) NULL );
  859.      return ( lReturnCode ) ;
  860.  
  861.      } /* else we cannot retrieve the header */
  862.  
  863.  
  864.   WinCloseClipbrd( habClipboard );
  865.  
  866.  if ( ulParam1 & MCI_CONVERT_FORMAT )
  867.      {
  868.      memmove( &mmaudioheaderTemp, &pInstance->mmAudioHeader, sizeof( MMAUDIOHEADER ) );
  869.  
  870. #ifndef TOOLKIT
  871.      rc = ConvertAudio( &mmaudioheader,
  872.                         *pBuffer,
  873.                         &mmaudioheaderTemp,
  874.                         &pNewBuffer);
  875.  
  876.      if ( !rc )
  877.         {
  878.  
  879.         return ( MCIERR_CANNOT_CONVERT );
  880.         }
  881. #endif
  882.  
  883.      rc = MCIERR_SUCCESS;
  884.  
  885.      if ( pNewBuffer )
  886.         {
  887.         HhpFreeBuffer( *pBuffer );
  888.         *pBuffer = pNewBuffer;
  889.  
  890.         memmove( &mmaudioheader, &mmaudioheaderTemp, sizeof( MMAUDIOHEADER ) );
  891.         *pulBuffLen = mmaudioheader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes;
  892.         if ( pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample == 16 &&
  893.              *pulBuffLen % 2 )
  894.         *pulBuffLen = *pulBuffLen - 1;
  895.         }
  896.  
  897.      }
  898.   else
  899.      {
  900.      /*----------------------------------------------------------------------
  901.      * If the to buffer flag is passed, the caller "should" be intelligent
  902.      * enough to handle conversions.
  903.      *---------------------------------------------------------------------*/
  904.  
  905.      if ( !(ulParam1 & MCI_TO_BUFFER ) )
  906.         {
  907.         /*----------------------------------------------------
  908.         * If the clipboard contains a different format than
  909.         * what is in the current file, return an error.
  910.         *--------------------------------------------------*/
  911.  
  912.         if ( ( pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usChannels != (SHORT )
  913.                mmaudioheader.mmXWAVHeader.WAVEHeader.usChannels )                  ||
  914.              ( pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec != ( LONG )
  915.                mmaudioheader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec )             ||
  916.              ( pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample != ( LONG )
  917.                mmaudioheader.mmXWAVHeader.WAVEHeader.usBitsPerSample ) )
  918.  
  919.           {
  920.           HhpFreeBuffer( *pBuffer );
  921.           return (MCIERR_CANNOT_CONVERT );
  922.           } /* if the clipboard + file contain different formats */
  923.  
  924.         } /* if the user did not request pasting to the buffer */
  925.  
  926.      } /* else the user does not want a conversion from the clipboard done */
  927.   // is this needed?
  928.  
  929.   if ( ulParam1 & MCI_TO_BUFFER )
  930.      {
  931.      memmove( pmmaudioheader, &mmaudioheader, sizeof( MMAUDIOHEADER ) );
  932.      }
  933.  
  934.   mmioClose( hmmioMem, ( WORD ) NULL );
  935.  
  936.  
  937.   /*-----------------------------------------------------------
  938.   * Message queue creation could have failed if the process has
  939.   * already done it.
  940.   *------------------------------------------------------------*/
  941.  
  942.   if ( fCreatedMQ )
  943.      {
  944.      WinDestroyMsgQueue( hmq );
  945.      }
  946.  
  947.   WinTerminate( habClipboard );
  948.  
  949.  
  950.  
  951.   return ( rc );
  952. } /* GetClipboardData */
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959. /********************* START OF SPECIFICATIONS *********************
  960. *
  961. * SUBROUTINE NAME: PutClipboardData
  962. *
  963. * DESCRIPTIVE  Puts digital audio information into the clipboard.
  964. *
  965. * FUNCTION:  Allocates memory for digital audio information, opens
  966. *            a memory file with correct header then places a
  967. *            bitmap and wave information into the clipboard, then
  968. *            closes the clipboard.
  969. *
  970. * NOTES:
  971. *
  972. * ENTRY POINTS:
  973. *     LINKAGE:   CALL FAR
  974. *
  975. * INPUT: MCI_STOP message.
  976. *
  977. * EXIT-NORMAL: Return Code 0.
  978. *
  979. * EXIT_ERROR:  Error Code.
  980. *
  981. * EFFECTS:
  982. *
  983. * INTERNAL REFERENCES:  MCIERR ().
  984. *
  985. * EXTERNAL REFERENCES: spiStopStream ()   -   SSM Spi
  986. *
  987. *********************** END OF SPECIFICATIONS **********************/
  988.  
  989. RC PutClipboardData( PVOID            *pBuffer,
  990.                      INSTANCE         *pInstance,
  991.                      ULONG            ulOperation,
  992.                      ULONG            ulBuffLength )
  993.  
  994. {
  995. HAB            habClipboard;
  996. HMQ            hmq;
  997.  
  998. BOOL           fCreatedMQ = TRUE;  /* message queue creation? */
  999.  
  1000. HBITMAP        hbmWave;
  1001. HPS            hps;
  1002.  
  1003. HMMIO          hmmioMem;           // handle to memory file
  1004.  
  1005. MMIOINFO       mmioinfo;           // info struct for memory file
  1006.  
  1007. ULONG          rc;
  1008. extern ULONG   hModuleHandle;        // module handle for dll
  1009. ULONG          hModuleMMPM;        // module handle for dll
  1010.  
  1011. //extern HWND    hwndClipWin;               /* Clipboard win handle */
  1012.  
  1013.  
  1014. LONG           lBytesRead;
  1015. LONG           lReturnCode;
  1016.  
  1017. MMAUDIOHEADER  mmaudioheader;
  1018.  
  1019. PCHAR          pWave;
  1020.  
  1021.  
  1022.   memset( &mmioinfo, '\0', sizeof( MMIOINFO ) );
  1023.  
  1024.   /*********************************************************************
  1025.   * Prepare to open a memory file--the buffer * in the clipboard contains
  1026.   * actual Riff-file  which the wave io proc already knows how
  1027.   * to parse--use it to retrieve the information  and keep the MCD from
  1028.   * file format dependence.
  1029.   *********************************************************************/
  1030.  
  1031.  
  1032.   mmioinfo.fccIOProc = mmioFOURCC( 'W', 'A', 'V', 'E' ) ;
  1033.   mmioinfo.fccChildIOProc = FOURCC_MEM;
  1034.   mmioinfo.cchBuffer = ( ulBuffLength) + 200;
  1035.  
  1036.  
  1037.   pWave = ( PCHAR ) HhpAllocBuffer( ( ( ulBuffLength ) + 200 ), HH_SHARED );
  1038.  
  1039.   mmioinfo.pchBuffer = pWave;
  1040.  
  1041.   hmmioMem = mmioOpen( NULL,
  1042.                        &mmioinfo,
  1043.                        MMIO_READWRITE | MMIO_CREATE );
  1044.  
  1045.   if ( !hmmioMem )
  1046.      {
  1047.      return ( mmioinfo.ulErrorRet );
  1048.      }
  1049.  
  1050.   /***********************************************
  1051.   * Copy the instance header into a structure we
  1052.   * can safely modify for this particular buffer
  1053.   **********************************************/
  1054.  
  1055. // hack for codecs in io procs
  1056. // should put in local instance
  1057.  
  1058.  
  1059.  
  1060.  memmove( &mmaudioheader, &pInstance->mmAudioHeader, sizeof ( MMAUDIOHEADER ));
  1061.  
  1062.  mmaudioheader.mmXWAVHeader.WAVEHeader.usFormatTag       = pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usFormatTag;
  1063.  mmaudioheader.mmXWAVHeader.WAVEHeader.usChannels        = pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usChannels;
  1064.  mmaudioheader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec   = pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec;
  1065.  mmaudioheader.mmXWAVHeader.WAVEHeader.usBitsPerSample   = (USHORT) pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample;
  1066.  
  1067.  
  1068.  mmaudioheader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes = ulBuffLength;
  1069.  
  1070.  
  1071.   lReturnCode = mmioWrite( hmmioMem,
  1072.                            *pBuffer,
  1073.                            ulBuffLength );
  1074.  
  1075.   if ( lReturnCode != ulBuffLength )
  1076.      {
  1077.      lReturnCode = mmioGetLastError ( hmmioMem );
  1078.      mmioClose( hmmioMem, ( WORD ) NULL );
  1079.      return( lReturnCode );
  1080.      }
  1081.  
  1082.  lReturnCode  = mmioSetHeader ( hmmioMem,
  1083.                                 (PVOID) &mmaudioheader,
  1084.                                 sizeof( mmaudioheader ),
  1085.                                 &lBytesRead,
  1086.                                 (ULONG) NULL,
  1087.                                 (ULONG) NULL);
  1088.  
  1089.  
  1090.   if ( lReturnCode != MMIO_SUCCESS )
  1091.      {
  1092.      lReturnCode = mmioGetLastError ( hmmioMem );
  1093.      mmioClose( hmmioMem, ( WORD ) NULL );
  1094.      return( lReturnCode );
  1095.      }
  1096.  
  1097.   habClipboard = WinInitialize( 0 );
  1098.   if ( !habClipboard )
  1099.      {
  1100. //     WinReleasePS( hps );
  1101.      return ( MCIERR_CLIPBOARD_ERROR );
  1102.      }
  1103.  
  1104.   hmq = WinCreateMsgQueue( habClipboard, 0 );
  1105.  
  1106.   if ( !hmq )
  1107.      {
  1108.      fCreatedMQ = FALSE;
  1109.      }
  1110.  
  1111.   /********************************************************
  1112.   * The resource that is associated with this dll contains
  1113.   * a wave bitmap that we will place into the clipboard
  1114.   * along with the actual audio information, so obtain
  1115.   * a handle to the bitmap from PM.
  1116.   ********************************************************/
  1117.  
  1118. //  hps = WinGetPS( hwndClipWin );
  1119.   hps = WinGetPS( HWND_DESKTOP ) ;
  1120.  
  1121.  
  1122.   rc = MM_DosLoadModule( NULL, 0L, "MMPM", &hModuleMMPM );     //@LP01a
  1123.   if ( rc )
  1124.      {
  1125.      hModuleMMPM = hModuleHandle;
  1126.      }
  1127.  
  1128.   hbmWave = GpiLoadBitmap( hps, hModuleMMPM, WAVE_BMP, 0, 0 );
  1129.  
  1130.   if ( !hbmWave )
  1131.      {
  1132.      WinReleasePS( hps );
  1133.      mmioClose( hmmioMem, ( WORD ) NULL );
  1134.      return ( MCIERR_CLIPBOARD_ERROR );
  1135.      }
  1136.  
  1137.  
  1138.  
  1139. //  habClipboard = WinQueryAnchorBlock( HWND_DESKTOP );
  1140.  
  1141.   /***********************************************
  1142.   * Open the clipboard and prepare to copy  the
  1143.   * information into it.
  1144.   **********************************************/
  1145.  
  1146.  
  1147.   if ( !WinOpenClipbrd( habClipboard ) )
  1148.      {
  1149.      WinReleasePS( hps );
  1150.      mmioClose( hmmioMem, ( WORD ) NULL );
  1151.      return ( MCIERR_CLIPBOARD_ERROR );  // cant open clipboard
  1152.      }
  1153.  
  1154.   /***********************************************
  1155.   * Clear what was previously in the clipboard--
  1156.   * standard PM protocol.
  1157.   **********************************************/
  1158.  
  1159.  
  1160.  
  1161.   if ( !WinEmptyClipbrd( habClipboard ) )
  1162.      {
  1163.      WinCloseClipbrd( habClipboard );
  1164.      mmioClose( hmmioMem, ( WORD ) NULL );
  1165.      WinReleasePS( hps );
  1166.      return ( MCIERR_CLIPBOARD_ERROR );
  1167.      }
  1168.  
  1169.   /**************************************************
  1170.   * Place the wave and the bitmap in the  clipboard
  1171.   * if possible.
  1172.   **************************************************/
  1173.  
  1174.   if ( !WinSetClipbrdData( habClipboard,
  1175.                            ( ULONG ) hbmWave,
  1176.                            CF_BITMAP,
  1177.                            CFI_HANDLE ) )
  1178.      {
  1179.      WinCloseClipbrd( habClipboard );
  1180.      mmioClose( hmmioMem, ( WORD ) NULL );
  1181.      WinReleasePS( hps );
  1182.      return ( MCIERR_CLIPBOARD_ERROR );  // cant open clipboard
  1183.  
  1184.      }
  1185.  
  1186.   if ( !WinSetClipbrdData( habClipboard,
  1187.                            ( ULONG ) pWave,
  1188.                            CF_WAVE,
  1189.                            CFI_POINTER  ) )
  1190.      {
  1191.      WinCloseClipbrd( habClipboard );
  1192.      WinReleasePS( hps );
  1193.      mmioClose( hmmioMem, ( WORD ) NULL );
  1194.      return ( MCIERR_CLIPBOARD_ERROR );
  1195.      }
  1196.  
  1197.   /***************************
  1198.   * Perform cleanup if any.
  1199.   ***************************/
  1200.  
  1201.   mmioClose( hmmioMem, ( WORD ) NULL );
  1202.  
  1203.   /**************************************************
  1204.   * Close the clipboard as quickly as possible since
  1205.   * only one process at a time can be in it.
  1206.   **************************************************/
  1207.  
  1208.   if ( !WinCloseClipbrd( habClipboard ) )
  1209.      {
  1210.      WinReleasePS( hps );
  1211.      return ( MCIERR_CLIPBOARD_ERROR );
  1212.      }
  1213.  
  1214.   /*-----------------------------------------------------------
  1215.   * Message queue creation could have failed if the process has
  1216.   * already done it.
  1217.   *------------------------------------------------------------*/
  1218.  
  1219.   if ( fCreatedMQ )
  1220.      {
  1221.      WinDestroyMsgQueue( hmq );
  1222.      }
  1223.  
  1224.   WinReleasePS( hps );
  1225.   WinTerminate( habClipboard );
  1226.  
  1227.   return ( MCIERR_SUCCESS );
  1228. } /* PutClipboardData */
  1229.  
  1230.  
  1231.