home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / warptlk3.zip / TOOLKIT / SAMPLES / MM / ADMCT / ADMCPST.C < prev    next >
C/C++ Source or Header  |  1995-08-24  |  19KB  |  689 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 <stdlib.h>                     // begin thread prototype
  9. #include <stdio.h>
  10. #include <os2medef.h>                   // MME includes files.
  11. #include <mmioos2.h>                    // MMIO Include.
  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 ( (ADMCTHREAD)StartPaste,
  200.                           0,
  201.                           NOTIFY_THREAD_STACKSIZE,
  202.                           (void *)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 _Optlink StartPaste (VOID * pvoid)
  267.  
  268.  
  269.  
  270. {
  271.   FUNCTION_PARM_BLOCK * pFuncBlockCopy = (FUNCTION_PARM_BLOCK *) pvoid;
  272.   LONG                 lReturnCode;
  273.  
  274.   ULONG                ulrc;
  275.   ULONG                ulParam1;
  276.   ULONG                ulBuffLen;          // Length of the buffer
  277.   ULONG                ulFromPosition;     // Position to paste from
  278.   ULONG                ulToPosition;       // Position to paste to
  279.   ULONG                ulPasteLen;         // Length to paste into
  280.   ULONG                ulOldTimeFormat;    // old time format
  281.   ULONG                ulNewPosition;      // new position of file after paste
  282.   ULONG                ulNumUndoNeeded = 1;/* Some pastes may require multiple
  283.                                               undoes since they delete and insert */
  284.   LONG                 lCurrFilePos;
  285.  
  286.  
  287.   FUNCTION_PARM_BLOCK  FuncBlock;
  288.   PMCI_EDIT_PARMS      pEditParms;
  289.   MCI_EDIT_PARMS       EditParms;
  290.  
  291.   PVOID                pBuffer;           // pointer to wave data from clipboard.
  292.  
  293.   MMAUDIOHEADER        mmaudioheader;      // header to the memory file
  294.  
  295.   INSTANCE             *pInstance;         // Local Instance
  296.  
  297.  
  298.  
  299.   memmove( &FuncBlock, pFuncBlockCopy, sizeof( FUNCTION_PARM_BLOCK ) );
  300.  
  301.  
  302.   /********************************************
  303.   * Dereference Pointers From Thread Block
  304.   ********************************************/
  305.  
  306.   ulParam1 = FuncBlock.ulParam1;
  307.  
  308.   if ( ulParam1 & MCI_NOTIFY )
  309.      {
  310.      memmove( &EditParms,
  311.               ( PMCI_EDIT_PARMS ) FuncBlock.ulParam2,
  312.               sizeof( MCI_EDIT_PARMS ) );
  313.  
  314.      pEditParms = &EditParms;
  315.      }
  316.   else
  317.      {
  318.      pEditParms = ( PMCI_EDIT_PARMS ) FuncBlock.ulParam2;
  319.      }
  320.  
  321.   ulrc = MCIERR_SUCCESS;
  322.   pInstance = (INSTANCE *) FuncBlock.ulpInstance;
  323.  
  324.  
  325.   /*********************************************
  326.   * We can free the save thread now that we have
  327.   * obtained any possible file names
  328.   **********************************************/
  329.  
  330.   DosPostEventSem ( pInstance->hThreadSem );
  331.  
  332.  
  333.   /*******************************************
  334.   * Determine where we are before we start the
  335.   * copy.  This will be useful if the FROM
  336.   * flag is not specified, in which case our
  337.   * current position will be the FROM position.
  338.   ********************************************/
  339.  
  340.   /* Check to see if a stream has been created */
  341.  
  342.   if ( pInstance->ulCreateFlag == PREROLL_STATE )
  343.      {
  344.  
  345.      /**********************************************
  346.      * Get the current stream time, it may be used
  347.      * as the default starting position if MCI_FROM
  348.      * was not specified.
  349.      ***********************************************/
  350.  
  351.      ulrc = SpiGetTime( pInstance->StreamInfo.hStream,
  352.                         ( PMMTIME ) &( pInstance->StreamInfo.mmStreamTime ) );
  353.  
  354.      if ( ulrc )
  355.         {
  356.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  357.         return ( ulrc );
  358.         }
  359.  
  360.      // investigate combining into one function
  361.  
  362.      ulOldTimeFormat = pInstance->ulTimeUnits;
  363.      pInstance->ulTimeUnits = lBYTES;
  364.  
  365.      ConvertTimeUnits ( pInstance,
  366.                         ( PULONG ) &lCurrFilePos,
  367.                         pInstance->StreamInfo.mmStreamTime );
  368.  
  369.      pInstance->ulTimeUnits = ulOldTimeFormat;
  370.  
  371.      } /* if stream has been created */
  372.   else
  373.      {
  374.      lCurrFilePos = 0;
  375.      }
  376.  
  377.  
  378.   lReturnCode = mmioSeek( pInstance->hmmio,
  379.                           lCurrFilePos,
  380.                           SEEK_SET );
  381.  
  382.   if ( lReturnCode == MMIO_ERROR )
  383.      {
  384.      PasteNotify( &FuncBlock, ulParam1, MMIOERR_SEEK_FAILED );
  385.      return ( MMIOERR_SEEK_FAILED );
  386.      }
  387.  
  388.  
  389.  
  390.   /* Retrieve the from and to positions to operate on */
  391.  
  392.   GetFromToPosition( lCurrFilePos,
  393.                       ulParam1,
  394.                       pEditParms,
  395.                       pInstance,
  396.                       &ulFromPosition,
  397.                       &ulToPosition );
  398.  
  399.  
  400.  
  401.   /*******************************************
  402.   * If the user passed in a buffer, use that
  403.   * rather than allocating our own.
  404.   ********************************************/
  405.  
  406.   if ( ulParam1 & MCI_FROM_BUFFER )
  407.      {
  408.  
  409.      if ( pInstance->mmAudioHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample == 16 &&
  410.           pEditParms->ulBufLen % 2 )
  411.         {
  412.         pEditParms->ulBufLen--;
  413.         }
  414.  
  415.  
  416.      ulBuffLen = pEditParms->ulBufLen;
  417.  
  418. //     pBuffer = HhpAllocBuffer( ulBuffLen, 0 );
  419. //
  420. //     if ( !pBuffer )
  421. //        {
  422. //        PasteNotify( &FuncBlock, ulParam1, MCIERR_OUT_OF_MEMORY );
  423. //        return ( MCIERR_OUT_OF_MEMORY );
  424. //        }
  425. //
  426. //     memmove( pBuffer, pEditParms->pBuff,  pEditParms->ulBufLen );
  427.      pBuffer = pEditParms->pBuff;
  428.      memmove( &mmaudioheader, pEditParms->pHeader,  sizeof( MMAUDIOHEADER ) );
  429.  
  430.      }
  431.   else
  432.      {
  433.      /*******************************************
  434.      * Retrieve information from the clipboard
  435.      ********************************************/
  436.  
  437.      ulrc = GetClipboardData( &pBuffer,
  438.                               pInstance,
  439.                               MCI_PASTE,
  440.                               &ulBuffLen,
  441.                               ulParam1,
  442.                               &mmaudioheader );
  443.  
  444.      if ( ulrc )
  445.         {
  446.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  447.         return ( ulrc );
  448.         }
  449.      } /* if to buffer not passed */
  450.  
  451.  
  452.  
  453.   /*******************************************
  454.   * Figure out how much information must be
  455.   * removed before pasting the information
  456.   * into the file.
  457.   ********************************************/
  458.  
  459.   ulPasteLen = ulToPosition - ulFromPosition;
  460.  
  461.  
  462.   /*******************************************
  463.   * remove the information in the file if
  464.   * from/to are specified.
  465.   ********************************************/
  466.  
  467.   if ( ulParam1 & MCI_FROM || ulParam1 & MCI_TO )
  468.      {
  469.      lReturnCode = mmioSendMessage( pInstance->hmmio,
  470.                                     MMIOM_DELETE,
  471.                                     pEditParms->ulFrom,
  472.                                     ulPasteLen );
  473.  
  474.      if ( lReturnCode != MMIO_SUCCESS )
  475.         {
  476.         ulrc = mmioGetLastError( pInstance->hmmio );
  477.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  478.         return ( ulrc );
  479.         }
  480.  
  481.      ulNumUndoNeeded++;
  482.  
  483.      } /* If delete is required */
  484.  
  485.  
  486.  
  487.   if ( !( ulParam1 & MCI_TO_BUFFER ) )
  488.      {
  489.      /*******************************************
  490.      * Let the io proc know that the information is
  491.      * about to be inserted into the file
  492.      ********************************************/
  493.  
  494.      lReturnCode = mmioSendMessage( pInstance->hmmio,
  495.                                     MMIOM_BEGININSERT,
  496.                                     0,
  497.                                     0 );
  498.  
  499.      if ( lReturnCode != MMIO_SUCCESS )
  500.         {
  501.         ulrc = mmioGetLastError( pInstance->hmmio );
  502.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  503.         return ( ulrc );
  504.         }
  505.  
  506.      /*******************************************
  507.      * Write the information that we reteived from
  508.      * the clipboard
  509.      *******************************************/
  510.  
  511.  
  512.      lReturnCode = mmioWrite( pInstance->hmmio,
  513.                               ( PSZ ) pBuffer,
  514.                               ulBuffLen );
  515.  
  516.      if ( lReturnCode == MMIO_ERROR )
  517.         {
  518.         ulrc = mmioGetLastError( pInstance->hmmio );
  519.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  520.         return ( ulrc );
  521.         }
  522.  
  523.      /*******************************************
  524.      * We have finised inserted the information
  525.      * the paste is complete
  526.      ********************************************/
  527.  
  528.  
  529.     lReturnCode = mmioSendMessage( pInstance->hmmio,
  530.                                    MMIOM_ENDINSERT,
  531.                                    0,
  532.                                    0 );
  533.  
  534.     if ( lReturnCode != MMIO_SUCCESS )
  535.        {
  536.        ulrc = mmioGetLastError( pInstance->hmmio );
  537.        PasteNotify( &FuncBlock, ulParam1, ulrc );
  538.        return ( ulrc );
  539.        }
  540.  
  541.  
  542.     /********************************************
  543.     * Update the header information in the file
  544.     * to reflect the fact that information has
  545.     * been inserted (and possibly deleted).
  546.     *********************************************/
  547.  
  548.     ulrc = SetAudioHeader (pInstance);
  549.  
  550.     if ( ulrc )
  551.        {
  552.        PasteNotify( &FuncBlock, ulParam1, ulrc );
  553.        return ( ulrc );
  554.        }
  555.  
  556.     ulrc = GetAudioHeader ( pInstance, 0  );
  557.  
  558.     if ( ulrc )
  559.        {
  560.        PasteNotify( &FuncBlock, ulParam1, ulrc );
  561.        return ( ulrc );
  562.        }
  563.  
  564.     AddNode( pInstance, ulNumUndoNeeded );
  565.     pInstance->ulNumUndo++;
  566.  
  567.     } /* if the buffer flag was not passed in */
  568.   else
  569.     {
  570.     /*--------------------------------
  571.     * ALWAYS return the audio header
  572.     * even if the call fails so that
  573.     * the caller will know that
  574.     * datatype.
  575.     *-------------------------------*/
  576.  
  577.     memmove( pEditParms->pHeader, &mmaudioheader, sizeof( MMAUDIOHEADER ) );
  578.  
  579.     if ( ( ulBuffLen ) > pEditParms->ulBufLen )
  580.        {
  581.        // let the caller know how big the buffer is
  582.        pEditParms->ulBufLen = ulBuffLen;
  583.        PasteNotify( &FuncBlock, ulParam1, MCIERR_INVALID_BUFFER );
  584.        HhpFreeBuffer( pBuffer );
  585.        return ( MCIERR_INVALID_BUFFER ); // is there a buffer too small erorr ?
  586.        }
  587.  
  588.     pEditParms->ulBufLen = ulBuffLen;
  589.  
  590.  
  591.     /* Place the buffer with the length in the edit parms */
  592.  
  593.     memmove( pEditParms->pBuff, pBuffer, ulBuffLen );
  594.  
  595.     } /* the buffer flag WAS passed in */
  596.  
  597.   /* Clean up memory allocated by clipboard operation */
  598.  
  599.   if ( !(ulParam1 & MCI_FROM_BUFFER ) )
  600.      {
  601.      HhpFreeBuffer( pBuffer );
  602.      }
  603.  
  604.   if ( pInstance->ulCreateFlag == PREROLL_STATE && !( ulParam1 & MCI_TO_BUFFER ) )
  605.      {
  606.      ulOldTimeFormat = pInstance->ulTimeUnits;
  607.      pInstance->ulTimeUnits = lBYTES;
  608.  
  609.      ulrc = ConvertToMM ( pInstance,
  610.                           &ulNewPosition,
  611.                           ulFromPosition + ulBuffLen );
  612.  
  613.      pInstance->ulTimeUnits = ulOldTimeFormat;
  614.  
  615.      ulrc = ADMCSeekStream ( pInstance,
  616.                             SPI_SEEK_ABSOLUTE,
  617.                             ulNewPosition );
  618.  
  619.      if ( ulrc )
  620.         {
  621.         PasteNotify( &FuncBlock, ulParam1, ulrc );
  622.         return ( ulrc );
  623.         }
  624.  
  625.      } /* if stream was created already */
  626.  
  627.   PasteNotify( &FuncBlock, ulParam1, MCI_NOTIFY_SUCCESSFUL );
  628.  
  629.  
  630.  
  631.   return ( MCIERR_SUCCESS );
  632.  
  633. } /* StartPaste */
  634.  
  635.  
  636. /********************* START OF SPECIFICATIONS *******************************
  637. *
  638. * SUBROUTINE NAME: PasteNotify
  639. *
  640. * FUNCTION: If a paste was done on via MCI_NOTIFY, alert caller to completion
  641. *           or an error.
  642. *
  643. *
  644. * NOTES:
  645. *
  646. * ENTRY POINTS:
  647. *
  648. * INPUT:
  649. *
  650. * EXIT-NORMAL: Return Code 0.
  651. *
  652. * EXIT_ERROR:  Error Code.
  653. *
  654. * EFFECTS:
  655. *
  656. * INTERNAL REFERENCES: None
  657. *
  658. * EXTERNAL REFERENCES: mmioSendMessage
  659. *                      mmioGetLastError
  660. *                      DosDelete
  661. *
  662. *********************** END OF SPECIFICATIONS *******************************/
  663.  
  664. void PasteNotify ( FUNCTION_PARM_BLOCK *pFuncBlock,
  665.                    ULONG               ulParam1,
  666.                    ULONG               ulNotifyResult )
  667.  
  668. {
  669.    if ( ulParam1 & MCI_NOTIFY )
  670.       {
  671.       PostMDMMessage (ulNotifyResult, MCI_PASTE, pFuncBlock);
  672.  
  673.       } /* if notify flag was passed */
  674.  
  675.   /*********************************************
  676.   * If any operation sees that the save thread
  677.   * is still processing, they will wait on the
  678.   * thread semaphore.  Since we are done with
  679.   * save processing post the semaphore so
  680.   * waiting threads can continue.
  681.   *********************************************/
  682.  
  683.   pFuncBlock->pInstance->usNotifyPending = FALSE;
  684.   DosPostEventSem ( pFuncBlock->pInstance->hThreadSem );
  685.  
  686.  
  687. } /* PasteNotify */
  688.  
  689.