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