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

  1. #define INCL_DOSSEMAPHORES
  2. #define INCL_DOSPROCESS
  3. #define INCL_ERRORS
  4. #define INCL_GPI
  5.  
  6. #include <os2.h>                        // OS2 defines.
  7. #include <string.h>                     // String functions.
  8. #include <stdio.h>
  9. #include <os2medef.h>                   // MME includes files.
  10. #include <mmioos2.h>                    // MMIO Include.
  11. #include <audio.h>                      // Audio Device Defines.
  12. #include <ssm.h>                        // SSM spi includes.
  13. #include <meerror.h>                    // MM Error Messages.
  14. #include <mcios2.h>                     // MM System Include.
  15. #include <mmdrvos2.h>                   // MCI Driver Include.
  16. #include <mcd.h>                        // AudioIFDriverInterface.
  17. #include <hhpheap.h>                    // Heap Manager Definitions
  18. #include <qos.h>
  19. #include <audiomcd.h>                   // Component Definitions
  20. #include "admcfunc.h"                   // Function Prototypes
  21.  
  22.  
  23. /********************* START OF SPECIFICATIONS *********************
  24. *
  25. * SUBROUTINE NAME: ADMCPASTE.C
  26. *
  27. * DESCRIPTIVE: Digital Audio paste from the clipboard
  28. *
  29. *              Copyright (c) IBM Corporation  1991, 1993
  30. *                        All Rights Reserved
  31. *
  32. * FUNCTION:  Check flags and retrieve from the clipboard the 
  33. *            digital audio information.  Paste it either into a buffer
  34. *            or into a file.
  35. *
  36. *
  37. * NOTES: Concepts illustrated in this source file.
  38. *
  39. *  1. Processing the MCI_FROM_BUFFER flag or MCI_TO_BUFFER.
  40. *  2. Handling default positioning if no MCI_FROM/MCI_TO flags are passed
  41. *  3. Using mmio to insert information into a file.
  42. *
  43. * INPUT: MCI_PASTE message.
  44. *
  45. * EXIT-NORMAL: MCIERR_SUCCESS.
  46. *
  47. * EXIT_ERROR:  Error Code.
  48. *
  49. * EFFECTS:
  50. *
  51. * INTERNAL REFERENCES: MCIERR ().
  52. *
  53. * EXTERNAL REFERENCES: spiStopStream()     - SSM Spi
  54. *                      spiSeekStream()     - SSM Spi
  55. *
  56. *********************** END OF SPECIFICATIONS **********************/
  57.  
  58. RC MCIPaste (FUNCTION_PARM_BLOCK *pFuncBlock)
  59.  
  60. {
  61.  
  62.   ULONG         ulParam1;           // Flags for this Msg
  63.   ULONG         ulrc;               // Error Code Propogated
  64.   ULONG         ulCount;
  65.  
  66.  
  67.   INSTANCE      *pInstance;         // Local Instance
  68.  
  69.   MCI_EDIT_PARMS *pEditParms;       // Pointer to structure to edit
  70.  
  71.   /********************************************
  72.   * Dereference Pointers From Thread Block
  73.   ********************************************/
  74.  
  75.   ulParam1 = pFuncBlock->ulParam1;
  76.   pEditParms = ( MCI_EDIT_PARMS * ) pFuncBlock->ulParam2;
  77.   ulrc = MCIERR_SUCCESS;
  78.   pInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  79.  
  80.  
  81.   /*******************************************
  82.   * Check for valid flags
  83.   ********************************************/
  84.  
  85.   ulrc = CheckEditFlags( pFuncBlock, FALSE );
  86.  
  87.   if ( ulrc != MCIERR_SUCCESS )
  88.      {
  89.      return ( ulrc );
  90.      }
  91.  
  92.   /*******************************************
  93.   * From and To are pointless with the buffer
  94.   * flag.
  95.   ********************************************/
  96.  
  97.  
  98.   if ( ( ulParam1 & MCI_TO_BUFFER )  &&
  99.        ( ( ulParam1 & MCI_FROM)  || ( ulParam1 & MCI_TO ) ) )
  100.      {
  101.      return ( MCIERR_INVALID_FLAG );
  102.      }
  103.  
  104.  
  105.  
  106.   /*******************************************
  107.   * We only operate on blocks of information
  108.   * in the file.  As a result, certain time
  109.   * numbers can work out to retrieve the same
  110.   * byte--do not report an error.  See
  111.   * ConvertToMM for more information.
  112.   ********************************************/
  113.  
  114.  
  115.   if ( pEditParms->ulFrom == pEditParms->ulTo &&
  116.        ( ulParam1 & MCI_FROM )                &&
  117.        ( ulParam1 & MCI_TO   ) )
  118.      {
  119.      return ( MCIERR_SUCCESS );
  120.      }
  121.  
  122.  
  123.  
  124.   /*******************************************
  125.   * Ensure the io proc that we have loaded has
  126.   * the ability to undo/redo.
  127.   ********************************************/
  128.  
  129.   if ( !(pInstance->ulCapabilities & CAN_INSERT )  )
  130.      {
  131.      return ( MCIERR_UNSUPPORTED_FUNCTION );
  132.      }
  133.  
  134. // note--must check if destination is not adpcm--do in checkeditflags
  135.  
  136.  
  137.   /*******************************************
  138.   * Ensure the io proc that we have loaded has
  139.   * the ability to write information to the
  140.   * file.
  141.   ********************************************/
  142.  
  143.   if ( !pInstance->ulUsingTemp  )
  144.      {
  145.      return ( MCIERR_UNSUPPORTED_FUNCTION );
  146.      }
  147.  
  148.   /************************************************
  149.   * If the caller used the MCI_WAIT flag, then all
  150.   * of the processing can be done on one thread.
  151.   ************************************************/
  152.   if ( ulParam1 & MCI_WAIT )
  153.  
  154.     {
  155.     // investigate--change to fWaitPending
  156.  
  157.     pInstance->usWaitPending = TRUE;
  158.     pInstance->usWaitMsg= MCI_SAVE;
  159.  
  160.     ulrc = StartPaste( pFuncBlock );
  161.  
  162.     pInstance->usWaitPending = FALSE;
  163.  
  164.     }
  165.   else
  166.     /***************************************************
  167.     ** To determine whether or not an operation must be
  168.     ** done on a thread, use the following criteria:
  169.     **
  170.     **   A. Will the operation take a long time.
  171.     **   B. Is there any way to make it appear as if
  172.     **      a thread was active.
  173.     **
  174.     **  In the case of a save, it can potentially be a
  175.     **  LONG operation and we do not want to bully the
  176.     **  applications thread, therefore,
  177.     **
  178.     ** We must perform the paste on a thread since
  179.     ** notify was requested (note, if neither notify
  180.     ** or wait are specified, then operate like a notify
  181.     ** except without positing the message.
  182.     ****************************************************/
  183.  
  184.     {
  185.     /* Let other threads know that a save is about to start */
  186.  
  187.     pInstance->usNotifyPending = TRUE;
  188.     pInstance->usNotPendingMsg = MCI_SAVE;
  189.  
  190.     /********************************************
  191.     * Save thread will post a semaphore when it
  192.     * safe to do processing, so reset it,
  193.     * start the thread, and wait till its safe
  194.     * to go on.
  195.     ********************************************/
  196.  
  197.     DosResetEventSem (pInstance->hThreadSem, &ulCount);
  198.  
  199.     ulrc = _beginthread ( (PFNTHREAD)StartPaste,
  200.                           0,
  201.                           NOTIFY_THREAD_STACKSIZE,
  202.                           (ULONG) pFuncBlock );
  203.  
  204.     /*************************************************
  205.     * Wait for the save thread to indicate that it is
  206.     * safe to continue.
  207.     **************************************************/
  208.     if ( ulrc != -1 )
  209.        {
  210.        DosWaitEventSem (pInstance->hThreadSem, -1);
  211.        ulrc = MCIERR_SUCCESS;
  212.        }
  213.     else
  214.        {
  215.        ulrc = MCIERR_OUT_OF_MEMORY;
  216.        }
  217.  
  218.     } /* this call is not a wait */
  219.  
  220.   DosResetEventSem (pInstance->hThreadSem, &ulCount);
  221.  
  222.   /* Ensure that we are in stopped state after a save */
  223.  
  224.   pInstance->StreamInfo.ulState = MCI_STOP;
  225.  
  226.  
  227.   return ( ulrc );
  228.  
  229. } /* MCIPaste */
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237. /********************* START OF SPECIFICATIONS *******************************
  238. *
  239. * SUBROUTINE NAME: StartPaste
  240. *
  241. * DESCRIPTIVE NAME: Pastes data from the clipboard into a file.
  242. *
  243. * FUNCTION:
  244. *
  245. *
  246. * NOTES: 
  247. *
  248. * ENTRY POINTS:
  249. *
  250. * INPUT:
  251. *
  252. * EXIT-NORMAL: Return Code 0.
  253. *
  254. * EXIT_ERROR:  Error Code.
  255. *
  256. * EFFECTS:
  257. *
  258. * INTERNAL REFERENCES: None
  259. *
  260. * EXTERNAL REFERENCES: mmioSendMessage
  261. *                      mmioGetLastError
  262. *                      DosDelete
  263. *
  264. *********************** END OF SPECIFICATIONS *******************************/
  265.  
  266. RC StartPaste( FUNCTION_PARM_BLOCK *pFuncBlockCopy )
  267.  
  268.  
  269.  
  270. {
  271.   LONG                 lReturnCode;
  272.  
  273.   ULONG                ulrc;
  274.   ULONG                ulParam1;
  275.   ULONG                ulBuffLen;          // Length of the buffer
  276.   ULONG                ulFromPosition;     // Position to paste from
  277.   ULONG                ulToPosition;       // Position to paste to
  278.   ULONG                ulPasteLen;         // Length to paste into
  279.   ULONG                ulOldTimeFormat;    // old time format
  280.   ULONG                ulNewPosition;      // new position of file after paste
  281.   ULONG                ulNumUndoNeeded = 1;/* Some pastes may require multiple
  282.                                               undoes since they delete and insert */
  283.   LONG                 lCurrFilePos;
  284.  
  285.  
  286.   FUNCTION_PARM_BLOCK  FuncBlock;
  287.   PMCI_EDIT_PARMS      pEditParms;
  288.   MCI_EDIT_PARMS       EditParms;
  289.  
  290.   PVOID                pBuffer;           // pointer to wave data from clipboard.
  291.  
  292.   MMAUDIOHEADER        mmaudioheader;      // header to the memory file
  293.  
  294.   INSTANCE             *pInstance;         // Local Instance
  295.  
  296.  
  297.  
  298.   memmove( &FuncBlock, pFuncBlockCopy, sizeof( FUNCTION_PARM_BLOCK ) );
  299.  
  300.  
  301.   /********************************************
  302.   * Dereference Pointers From Thread Block
  303.   ********************************************/
  304.  
  305.   ulParam1 = FuncBlock.ulParam1;
  306.  
  307.   if ( ulParam1 & MCI_NOTIFY )
  308.      {
  309.      memmove( &EditParms, 
  310.               ( PMCI_EDIT_PARMS ) FuncBlock.ulParam2,
  311.               sizeof( MCI_EDIT_PARMS ) );
  312.    
  313.      pEditParms = &EditParms;
  314.      }
  315.   else
  316.      {
  317.      pEditParms = ( PMCI_EDIT_PARMS ) FuncBlock.ulParam2;
  318.      }
  319.  
  320.   ulrc = MCIERR_SUCCESS;
  321.   pInstance = (INSTANCE *) FuncBlock.ulpInstance;
  322.  
  323.  
  324.   /*********************************************
  325.   * We can free the save thread now that we have
  326.   * obtained any possible file names
  327.   **********************************************/
  328.  
  329.   DosPostEventSem ( pInstance->hThreadSem );
  330.  
  331.  
  332.   /*******************************************
  333.   * Determine where we are before we start the
  334.   * copy.  This will be useful if the FROM
  335.   * flag is not specified, in which case our
  336.   * current position will be the FROM position.
  337.   ********************************************/
  338.  
  339.   /* Check to see if a stream has been created */
  340.  
  341.   if ( pInstance->ulCreateFlag == PREROLL_STATE )
  342.      {
  343.  
  344.      /**********************************************
  345.      * Get the current stream time, it may be used
  346.      * as the default starting position if MCI_FROM
  347.      * was not specified.
  348.      ***********************************************/
  349.  
  350.      ulrc = SpiGetTime( pInstance->StreamInfo.hStream,
  351.                         ( PMMTIME ) &( pInstance->StreamInfo.mmStreamTime ) );
  352.  
  353.      if ( ulrc )
  354.         {
  355.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  356.         return ( ulrc );
  357.         }
  358.  
  359.      // investigate combining into one function
  360.  
  361.      ulOldTimeFormat = pInstance->ulTimeUnits;
  362.      pInstance->ulTimeUnits = lBYTES;
  363.  
  364.      ConvertTimeUnits ( pInstance,
  365.                         ( PULONG ) &lCurrFilePos,
  366.                         pInstance->StreamInfo.mmStreamTime );
  367.  
  368.      pInstance->ulTimeUnits = ulOldTimeFormat;
  369.  
  370.      } /* if stream has been created */
  371.   else
  372.      {
  373.      lCurrFilePos = 0;
  374.      }
  375.  
  376.  
  377.   lReturnCode = mmioSeek( pInstance->hmmio,
  378.                           lCurrFilePos,
  379.                           SEEK_SET );
  380.  
  381.   if ( lReturnCode == MMIO_ERROR )
  382.      {
  383.      PasteNotify( &FuncBlock, ulParam1, MMIOERR_SEEK_FAILED );
  384.      return ( MMIOERR_SEEK_FAILED );
  385.      }
  386.  
  387.  
  388.  
  389.   /* Retrieve the from and to positions to operate on */
  390.  
  391.   GetFromToPosition( lCurrFilePos,
  392.                       ulParam1,
  393.                       pEditParms,
  394.                       pInstance,
  395.                       &ulFromPosition,
  396.                       &ulToPosition );
  397.  
  398.  
  399.  
  400.   /*******************************************
  401.   * If the user passed in a buffer, use that
  402.   * rather than allocating our own.
  403.   ********************************************/
  404.  
  405.   if ( ulParam1 & MCI_FROM_BUFFER )
  406.      {
  407.  
  408.      if ( pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample == 16 &&
  409.           pEditParms->ulBufLen % 2 )
  410.         {
  411.         pEditParms->ulBufLen--;
  412.         }
  413.  
  414.  
  415.      ulBuffLen = pEditParms->ulBufLen;
  416.  
  417. //     pBuffer = HhpAllocBuffer( ulBuffLen, 0 );
  418. //
  419. //     if ( !pBuffer )
  420. //        {
  421. //        PasteNotify( &FuncBlock, ulParam1, MCIERR_OUT_OF_MEMORY );
  422. //        return ( MCIERR_OUT_OF_MEMORY );
  423. //        }
  424. //
  425. //     memmove( pBuffer, pEditParms->pBuff,  pEditParms->ulBufLen );
  426.      pBuffer = pEditParms->pBuff;
  427.      memmove( &mmaudioheader, pEditParms->pHeader,  sizeof( MMAUDIOHEADER ) );
  428.  
  429.      }
  430.   else
  431.      {
  432.      /*******************************************
  433.      * Retrieve information from the clipboard
  434.      ********************************************/
  435.  
  436.      ulrc = GetClipboardData( &pBuffer,
  437.                               pInstance,
  438.                               MCI_PASTE,
  439.                               &ulBuffLen,
  440.                               ulParam1,
  441.                               &mmaudioheader );
  442.  
  443.      if ( ulrc )
  444.         {
  445.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  446.         return ( ulrc );
  447.         }
  448.      } /* if to buffer not passed */
  449.  
  450.  
  451.  
  452.   /*******************************************
  453.   * Figure out how much information must be
  454.   * removed before pasting the information
  455.   * into the file.
  456.   ********************************************/
  457.  
  458.   ulPasteLen = ulToPosition - ulFromPosition;
  459.  
  460.  
  461.   /*******************************************
  462.   * remove the information in the file if
  463.   * from/to are specified.
  464.   ********************************************/
  465.  
  466.   if ( ulParam1 & MCI_FROM || ulParam1 & MCI_TO )
  467.      {
  468.      lReturnCode = mmioSendMessage( pInstance->hmmio,
  469.                                     MMIOM_DELETE,
  470.                                     pEditParms->ulFrom,
  471.                                     ulPasteLen );
  472.  
  473.      if ( lReturnCode != MMIO_SUCCESS )
  474.         {
  475.         ulrc = mmioGetLastError( pInstance->hmmio );
  476.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  477.         return ( ulrc );
  478.         }
  479.  
  480.      ulNumUndoNeeded++;
  481.  
  482.      } /* If delete is required */
  483.  
  484.  
  485.  
  486.   if ( !( ulParam1 & MCI_TO_BUFFER ) )
  487.      {
  488.      /*******************************************
  489.      * Let the io proc know that the information is
  490.      * about to be inserted into the file
  491.      ********************************************/
  492.  
  493.      lReturnCode = mmioSendMessage( pInstance->hmmio,
  494.                                     MMIOM_BEGININSERT,
  495.                                     0,
  496.                                     0 );
  497.  
  498.      if ( lReturnCode != MMIO_SUCCESS )
  499.         {
  500.         ulrc = mmioGetLastError( pInstance->hmmio );
  501.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  502.         return ( ulrc );
  503.         }
  504.  
  505.      /*******************************************
  506.      * Write the information that we reteived from
  507.      * the clipboard
  508.      *******************************************/
  509.  
  510.  
  511.      lReturnCode = mmioWrite( pInstance->hmmio,
  512.                               ( PSZ ) pBuffer,
  513.                               ulBuffLen );
  514.  
  515.      if ( lReturnCode == MMIO_ERROR )
  516.         {
  517.         ulrc = mmioGetLastError( pInstance->hmmio );
  518.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  519.         return ( ulrc );
  520.         }
  521.  
  522.      /*******************************************
  523.      * We have finised inserted the information
  524.      * the paste is complete
  525.      ********************************************/
  526.  
  527.  
  528.     lReturnCode = mmioSendMessage( pInstance->hmmio,
  529.                                    MMIOM_ENDINSERT,
  530.                                    0,
  531.                                    0 );
  532.  
  533.     if ( lReturnCode != MMIO_SUCCESS )
  534.        {
  535.        ulrc = mmioGetLastError( pInstance->hmmio );
  536.        PasteNotify( &FuncBlock, ulParam1, ulrc );
  537.        return ( ulrc );
  538.        }
  539.  
  540.  
  541.     /********************************************
  542.     * Update the header information in the file
  543.     * to reflect the fact that information has
  544.     * been inserted (and possibly deleted).
  545.     *********************************************/
  546.  
  547.     ulrc = SetAudioHeader (pInstance);
  548.  
  549.     if ( ulrc )
  550.        {
  551.        PasteNotify( &FuncBlock, ulParam1, ulrc );
  552.        return ( ulrc );
  553.        }
  554.  
  555.     ulrc = GetAudioHeader ( pInstance );
  556.  
  557.     if ( ulrc )
  558.        {
  559.        PasteNotify( &FuncBlock, ulParam1, ulrc );
  560.        return ( ulrc );
  561.        }
  562.  
  563.     AddNode( pInstance, ulNumUndoNeeded );
  564.     pInstance->ulNumUndo++;
  565.  
  566.     } /* if the buffer flag was not passed in */
  567.   else
  568.     {
  569.     /*--------------------------------
  570.     * ALWAYS return the audio header
  571.     * even if the call fails so that
  572.     * the caller will know that
  573.     * datatype.
  574.     *-------------------------------*/
  575.  
  576.     memmove( pEditParms->pHeader, &mmaudioheader, sizeof( MMAUDIOHEADER ) );
  577.  
  578.     if ( ( ulBuffLen ) > pEditParms->ulBufLen )
  579.        {
  580.        // let the caller know how big the buffer is
  581.        pEditParms->ulBufLen = ulBuffLen;
  582.        PasteNotify( &FuncBlock, ulParam1, MCIERR_INVALID_BUFFER );
  583.        HhpFreeBuffer( pBuffer );
  584.        return ( MCIERR_INVALID_BUFFER ); // is there a buffer too small erorr ?
  585.        }
  586.  
  587.     pEditParms->ulBufLen = ulBuffLen;
  588.  
  589.  
  590.     /* Place the buffer with the length in the edit parms */
  591.  
  592.     memmove( pEditParms->pBuff, pBuffer, ulBuffLen );
  593.  
  594.     } /* the buffer flag WAS passed in */
  595.  
  596.   /* Clean up memory allocated by clipboard operation */
  597.  
  598.   if ( !(ulParam1 & MCI_FROM_BUFFER ) )
  599.      {
  600.      HhpFreeBuffer( pBuffer );
  601.      }
  602.  
  603.   if ( pInstance->ulCreateFlag == PREROLL_STATE && !( ulParam1 & MCI_TO_BUFFER ) )
  604.      {
  605.      ulOldTimeFormat = pInstance->ulTimeUnits;
  606.      pInstance->ulTimeUnits = lBYTES;
  607.  
  608.      ulrc = ConvertToMM ( pInstance,
  609.                           &ulNewPosition,
  610.                           ulFromPosition + ulBuffLen );
  611.  
  612.      pInstance->ulTimeUnits = ulOldTimeFormat;
  613.  
  614.      ulrc = SpiSeekStream ( pInstance->StreamInfo.hStream,
  615.                             SPI_SEEK_ABSOLUTE,
  616.                             ulNewPosition );
  617.  
  618.      if ( ulrc )
  619.         {
  620.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  621.         return ( ulrc );
  622.         }
  623.  
  624.      } /* if stream was created already */
  625.  
  626.   PasteNotify( &FuncBlock, ulParam1, MCI_NOTIFY_SUCCESSFUL );
  627.  
  628.  
  629.  
  630.   return ( MCIERR_SUCCESS );
  631.  
  632. } /* StartPaste */
  633.  
  634.  
  635. /********************* START OF SPECIFICATIONS *******************************
  636. *
  637. * SUBROUTINE NAME: PasteNotify
  638. *
  639. * FUNCTION: If a paste was done on via MCI_NOTIFY, alert caller to completion
  640. *           or an error.
  641. *
  642. *
  643. * NOTES:
  644. *
  645. * ENTRY POINTS:
  646. *
  647. * INPUT:
  648. *
  649. * EXIT-NORMAL: Return Code 0.
  650. *
  651. * EXIT_ERROR:  Error Code.
  652. *
  653. * EFFECTS:
  654. *
  655. * INTERNAL REFERENCES: None
  656. *
  657. * EXTERNAL REFERENCES: mmioSendMessage
  658. *                      mmioGetLastError
  659. *                      DosDelete
  660. *
  661. *********************** END OF SPECIFICATIONS *******************************/
  662.  
  663. void PasteNotify ( FUNCTION_PARM_BLOCK *pFuncBlock,
  664.                    ULONG               ulParam1,
  665.                    ULONG               ulNotifyResult )
  666.  
  667. {
  668.    if ( ulParam1 & MCI_NOTIFY )
  669.       {
  670.       PostMDMMessage (ulNotifyResult, MCI_PASTE, pFuncBlock);
  671.  
  672.       } /* if notify flag was passed */
  673.  
  674.   /*********************************************
  675.   * If any operation sees that the save thread
  676.   * is still processing, they will wait on the
  677.   * thread semaphore.  Since we are done with
  678.   * save processing post the semaphore so
  679.   * waiting threads can continue.
  680.   *********************************************/
  681.  
  682.   pFuncBlock->pInstance->usNotifyPending = FALSE;
  683.   DosPostEventSem ( pFuncBlock->pInstance->hThreadSem );
  684.  
  685.  
  686. } /* PasteNotify */
  687.  
  688.