home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mmpm21tk.zip / TK / ADMCT / ADMCCOPY.C < prev    next >
C/C++ Source or Header  |  1993-04-23  |  28KB  |  1,006 lines

  1. /********************* START OF SPECIFICATIONS *********************
  2. *
  3. * SUBROUTINE NAME: ADMCCOPY.C
  4. *
  5. * DESCRIPTIVE: Digital Audio copy to the clipboard
  6. *
  7. *              Copyright (c) IBM Corporation  1991, 1993
  8. *                        All Rights Reserved
  9. *
  10. * FUNCTION: This function accepts cut, copy, delete messages and
  11. *           acts accordingly.
  12. *           First, Check flags and paste audio information to the
  13. *           clipboard (if not delete).
  14. *           Copy either from a buffer or from a file.
  15. *
  16. * CONCEPTS ILLUSTRATED :
  17. *  1. Default positioning for cut/copy/delete messages.
  18. *  2. Using MMIOM_DELETE to remove information from a file.
  19. *  3. Positioning after a cut/copy/delete
  20. *
  21. * NOTES:
  22. *
  23. * ENTRY POINTS:
  24. *
  25. * INPUT: MCI_COPY message.
  26. *
  27. * EXIT-NORMAL: MCIERR_SUCCESS
  28. *
  29. * EXIT_ERROR:  Error Code.
  30. *
  31. * EFFECTS:
  32. *
  33. * INTERNAL REFERENCES: MCIERR ().
  34. *
  35. * EXTERNAL REFERENCES: 
  36. *
  37. *********************** END OF SPECIFICATIONS **********************/
  38.  
  39. #define INCL_DOSSEMAPHORES
  40. #define INCL_DOSPROCESS
  41. #define INCL_ERRORS
  42.  
  43.  
  44.  
  45. #include <os2.h>                        // OS2 defines.
  46. #include <string.h>                     // String functions.
  47. #include <os2medef.h>                   // MME includes files.
  48. #include <mmioos2.h>                    // MMIO Include.
  49. #include <audio.h>                      // Audio Device Defines.
  50. #include <ssm.h>                        // SSM spi includes.
  51. #include <meerror.h>                    // MM Error Messages.
  52. #include <mcios2.h>                     // MM System Include.
  53. #include <mmdrvos2.h>                   // MCI Driver Include.
  54. #include <mcd.h>                        // AudioIFDriverInterface.
  55. #include <hhpheap.h>                    // Heap Manager Definitions
  56. #include <qos.h>
  57. #include <audiomcd.h>                   // Component Definitions
  58. #include "admcfunc.h"                   // Function Prototypes
  59. #include <stdio.h>
  60.  
  61. RC MCICopy ( FUNCTION_PARM_BLOCK *pFuncBlock,
  62.              ULONG               ulMessage )
  63.  
  64. {
  65.   ULONG         ulCount;
  66.   ULONG         ulParam1;           // Flags for this Msg
  67.   ULONG         ulrc;               // Error Code Propogated
  68.   ULONG         ulFromPosition;     // position to copy from
  69.   ULONG         ulToPosition;       // position to copy to
  70.   ULONG         ulNewPosition;      // position after operation
  71.  
  72.   ULONG         ulBuffLen;          // length of the buffer to copy
  73.   ULONG         ulOldTimeFormat;    //
  74.  
  75.   LONG          lReturnCode;        // return code from mmio
  76.   LONG          lCurrFilePos;       // Get current file position
  77.   LONG          lSeekFlags;
  78.  
  79.   INSTANCE      *pInstance;       // Local Instance
  80.  
  81.   MCI_EDIT_PARMS *pEditParms;        // Pointer to structure to edit
  82.  
  83.   PVOID          pBuffer;            // pointer to wave data from clipboard.
  84.  
  85.   PMMAUDIOHEADER pmmaudioheader;
  86.  
  87.   /********************************************
  88.   * Dereference Pointers From Thread Block
  89.   ********************************************/
  90.  
  91.   ulParam1 = pFuncBlock->ulParam1;
  92.   pEditParms = ( MCI_EDIT_PARMS * ) pFuncBlock->ulParam2;
  93.   ulrc = MCIERR_SUCCESS;
  94.   pInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  95.  
  96.   /*******************************************
  97.   * Check for valid flags
  98.   ********************************************/
  99.  
  100.   ulrc = CheckEditFlags( pFuncBlock, FALSE );
  101.  
  102.   if ( ulrc != MCIERR_SUCCESS )
  103.      {
  104.      return ( ulrc );
  105.      }
  106.  
  107.   /*******************************************
  108.   * We only operate on blocks of information
  109.   * in the file.  As a result, certain time
  110.   * numbers can work out to retrieve the same
  111.   * byte--do not report an error.  See
  112.   * ConvertToMM for more information.
  113.   ********************************************/
  114.  
  115.   if ( pEditParms->ulFrom == pEditParms->ulTo &&
  116.        ( ulParam1 & ( MCI_FROM + MCI_TO ) ) )
  117.      {
  118.      return ( MCIERR_SUCCESS );
  119.      }
  120.  
  121.   /*******************************************
  122.   * Ensure the io proc that we have loaded has
  123.   * the ability to delete.
  124.   ********************************************/
  125.  
  126.   if ( !(pInstance->ulCapabilities & CAN_DELETE)  )
  127.      {
  128.      return ( MCIERR_UNSUPPORTED_FUNCTION );
  129.      }
  130.  
  131.   /*******************************************
  132.   * Ensure the io proc that we have loaded has
  133.   * the ability to cut information from the
  134.   * file (i.e. everything but copy).
  135.   ********************************************/
  136.  
  137.   if ( !pInstance->ulUsingTemp && 
  138.        ulMessage != MCI_COPY )
  139.      {
  140.      return ( MCIERR_UNSUPPORTED_FUNCTION );
  141.      }
  142.  
  143.  
  144.   /*******************************************
  145.   * From and To are pointless with the buffer
  146.   * flag.
  147.   ********************************************/
  148.  
  149.  
  150.   if ( ( ulParam1 & MCI_FROM_BUFFER )  &&
  151.        ( ( ulParam1 & MCI_FROM)  || ( ulParam1 & MCI_TO ) ) )
  152.      {
  153.      return ( MCIERR_INVALID_FLAG );
  154.      }
  155.  
  156.  
  157.   /*******************************************
  158.   * Neither cut nor paste support the from buffer
  159.   * flag since they operate on a file.
  160.   ********************************************/
  161.  
  162.   if ( ( ulParam1 & MCI_FROM_BUFFER ) || ( ulParam1 & MCI_TO_BUFFER ) ) 
  163.      if  ( ( ulMessage == MCI_CUT)  || ( ulMessage == MCI_DELETE )  )
  164.      {
  165.      return ( MCIERR_INVALID_FLAG );
  166.      }
  167.  
  168.  
  169.   /************************************************
  170.   * If the caller used the MCI_WAIT flag, then all
  171.   * of the processing can be done on one thread.
  172.   ************************************************/
  173.   if ( ulParam1 & MCI_WAIT )
  174.  
  175.     {
  176.     // investigate--change to fWaitPending
  177.  
  178.     pInstance->usWaitPending = TRUE;
  179.     pInstance->usWaitMsg= MCI_SAVE;
  180.  
  181.     ulrc = StartCopy( pFuncBlock );
  182.  
  183.     pInstance->usWaitPending = FALSE;
  184.  
  185.     }
  186.   else
  187.     /***************************************************
  188.     ** To determine whether or not an operation must be
  189.     ** done on a thread, use the following criteria:
  190.     **
  191.     **   A. Will the operation take a long time.
  192.     **   B. Is there any way to make it appear as if
  193.     **      a thread was active.
  194.     **
  195.     **  In the case of a save, it can potentially be a
  196.     **  LONG operation and we do not want to bully the
  197.     **  applications thread, therefore,
  198.     **
  199.     ** We must perform the paste on a thread since
  200.     ** notify was requested (note, if neither notify
  201.     ** or wait are specified, then operate like a notify
  202.     ** except without positing the message.
  203.     ****************************************************/
  204.  
  205.     {
  206.     /* Let other threads know that a save is about to start */
  207.  
  208.     pInstance->usNotifyPending = TRUE;
  209.     pInstance->usNotPendingMsg = MCI_SAVE;
  210.  
  211.     /********************************************
  212.     * Save thread will post a semaphore when it
  213.     * safe to do processing, so reset it,
  214.     * start the thread, and wait till its safe
  215.     * to go on.
  216.     ********************************************/
  217.  
  218.     DosResetEventSem (pInstance->hThreadSem, &ulCount);
  219.  
  220.     ulrc = _beginthread ( (PFNTHREAD)StartCopy,
  221.                           0,
  222.                           NOTIFY_THREAD_STACKSIZE,
  223.                           (ULONG) pFuncBlock );
  224.  
  225.     /*************************************************
  226.     * Wait for the save thread to indicate that it is
  227.     * safe to continue.
  228.     **************************************************/
  229.     if ( ulrc != -1 )
  230.        {
  231.        DosWaitEventSem (pInstance->hThreadSem, -1);
  232.        ulrc = MCIERR_SUCCESS;
  233.        }
  234.     else
  235.        {
  236.        ulrc = MCIERR_OUT_OF_MEMORY;
  237.        }
  238.  
  239.     } /* this call is not a wait */
  240.  
  241.   DosResetEventSem (pInstance->hThreadSem, &ulCount);
  242.  
  243.   /* Ensure that we are in stopped state after a save */
  244.  
  245.  
  246.  
  247.  
  248.  
  249.   /* The stream is in a stopped state after cut/copy/delete */
  250.  
  251.   pInstance->StreamInfo.ulState = MCI_STOP;
  252.  
  253.   return ( MCIERR_SUCCESS );
  254.  
  255. } /* mcicopy */
  256.  
  257.  
  258.  
  259.  
  260.  
  261. /********************* START OF SPECIFICATIONS *********************
  262. *
  263. * SUBROUTINE NAME: MCIMagic
  264. *
  265. * DESCRIPTIVE: Will undo/redo the last logical action
  266. *
  267. * FUNCTION:  Undo will place the instance in the state before the 
  268. *            last logical action ( record, cut, copy, paste delete).
  269. *            By contrast, redo will place the instance in the state
  270. *            it was before an undo.
  271. *
  272. * NOTES:
  273. *
  274. * ENTRY POINTS:
  275. *     LINKAGE:   CALL FAR
  276. *
  277. * INPUT: MCI_UNDO message.
  278. *
  279. * EXIT-NORMAL: MCIERR_SUCCESS
  280. *
  281. * EXIT_ERROR:  Error Code.
  282. *
  283. * EFFECTS:
  284. *
  285. * INTERNAL REFERENCES: MCIERR ().
  286. *
  287. * EXTERNAL REFERENCES:
  288. *
  289. *********************** END OF SPECIFICATIONS **********************/
  290.  
  291.  
  292.  
  293. RC MCIMagic ( FUNCTION_PARM_BLOCK *pFuncBlock,
  294.               ULONG               ulOperation )
  295.  
  296. {
  297.  
  298.   ULONG         ulrc;               // Error Code Propogated
  299.   ULONG         ulFrom;             // Position to start deleting
  300.   ULONG         ulLength;           // Length of info to delete
  301.   ULONG         ulMessage;
  302.   ULONG         ulActionLoop;       // Some actions (like paste)
  303.                                     // require multiple undo/redo
  304.   ULONG         ulMaxLevels;
  305.  
  306.   LONG          lReturnCode;        // rc for mmio operations
  307.  
  308.   INSTANCE      *pInstance;       // Local Instance
  309.  
  310.   MCI_EDIT_PARMS *pEditParms;        // Pointer to structure to edit
  311.  
  312.   PUNDOLIST     pTempList;
  313.  
  314.   /********************************************
  315.   * Dereference Pointers From Thread Block
  316.   ********************************************/
  317.  
  318.   ulrc = MCIERR_SUCCESS;
  319.   pInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  320.  
  321.  
  322.   /*******************************************
  323.   * Check for valid flags
  324.   ********************************************/
  325.  
  326.   ulrc = CheckEditFlags( pFuncBlock, TRUE );
  327.  
  328.   if ( ulrc != MCIERR_SUCCESS )
  329.      {
  330.      return ( ulrc );
  331.      }
  332.  
  333.   /*******************************************
  334.   * Ensure the io proc that we have loaded has
  335.   * the ability to undo/redo.
  336.   ********************************************/
  337.  
  338.   if ( !(pInstance->ulCapabilities & CAN_UNDOREDO )  )
  339.      {
  340.      return ( MCIERR_UNSUPPORTED_FUNCTION );
  341.      }
  342.  
  343.   /*******************************************
  344.   * We are currently using an array of undo/redo
  345.   * levels.  Check to ensure that we will have
  346.   * room to store the number of undoes
  347.   ********************************************/
  348.   if ( ulOperation == MMIOM_UNDO )
  349.      {
  350.      if  ( !pInstance->pUndoList )
  351.         {
  352.         return ( MCIERR_CANNOT_UNDO );
  353.         }
  354.      else
  355.         {
  356.         ulMaxLevels = pInstance->pUndoList->ulNumLogicalActions;
  357.         }
  358.      } /* If we are to undo */
  359.  
  360.   /*******************************************
  361.   * We are currently using an array of undo/redo
  362.   * levels.  Check to ensure that we will have
  363.   * room to store the number of redoes
  364.   ********************************************/
  365.   if ( ulOperation == MMIOM_REDO )
  366.      {
  367.      if ( !pInstance->pRedoList )
  368.         {
  369.         return ( MCIERR_CANNOT_REDO );
  370.         }
  371.      else
  372.         {
  373.         ulMaxLevels = pInstance->pRedoList->ulNumLogicalActions;
  374.         }
  375.      } /* If redo */
  376.  
  377.   /**************************************************
  378.   * Ask the io proc to undo or redo the last logical
  379.   * action (record, cut, delete, paste ).
  380.   **************************************************/
  381.  
  382.   for ( ulActionLoop = 0; ulActionLoop < ulMaxLevels; ulActionLoop++ )
  383.      {
  384.      lReturnCode = mmioSendMessage( pInstance->hmmio,
  385.                                    ulOperation,
  386.                                    ulFrom,
  387.                                    ulLength );
  388.    
  389.      if ( lReturnCode == MMIO_ERROR )
  390.         {
  391.         if ( ulOperation == MMIOM_UNDO )
  392.            {
  393.            return ( MCIERR_CANNOT_UNDO );
  394.            }
  395.         else
  396.            {
  397.            return ( MCIERR_CANNOT_REDO );
  398.            }
  399.    
  400.         }  /* if an error happened */
  401.      } /* Undo all logical actions (i.e. paste may take more than one */
  402.  
  403.   ulrc = SetAudioHeader (pInstance);
  404.  
  405.   if ( ulrc )
  406.      {
  407.      return ( ulrc );
  408.      }
  409.  
  410.   ulrc = GetAudioHeader ( pInstance );
  411.  
  412.   if ( ulrc )
  413.      {
  414.      return ( ulrc );
  415.      }
  416.  
  417.   /*********************************
  418.   * After an undo/redo, the stream
  419.   * position is 0.
  420.   *********************************/
  421.  
  422.   if ( pInstance->ulCreateFlag == PREROLL_STATE)
  423.      {
  424.      ulrc = SpiSeekStream ( pInstance->StreamInfo.hStream, 
  425.                             SPI_SEEK_ABSOLUTE, 
  426.                             0 );
  427.      }
  428.  
  429.   /* The stream is in a stopped state after an undo/redo */
  430.  
  431.   pInstance->StreamInfo.ulState = MCI_STOP;
  432.  
  433.   /* Update our array of undo levels */
  434.  
  435.   if ( ulOperation == MMIOM_UNDO )
  436.      {
  437.      pInstance->ulNumUndo--;
  438.      pInstance->ulNumRedo++;
  439.      pTempList = pInstance->pUndoList;
  440.      pInstance->pUndoList = pInstance->pUndoList->pNextList;
  441.      pTempList->pNextList = pInstance->pRedoList;
  442.  
  443.      pInstance->pRedoList = pTempList;
  444.      }
  445.   else
  446.      {
  447.      pInstance->ulNumRedo--;
  448.      pInstance->ulNumUndo++;
  449.      pTempList = pInstance->pRedoList;
  450.      pInstance->pRedoList = pInstance->pRedoList->pNextList;
  451.      pTempList->pNextList = pInstance->pUndoList;
  452.      pInstance->pUndoList = pTempList;
  453.  
  454.      }
  455.  
  456.   return ( ulrc );
  457.  
  458. } /* MCIMajic */
  459.  
  460.  
  461.  
  462.  
  463.  
  464. /********************* START OF SPECIFICATIONS *******************************
  465. *
  466. * SUBROUTINE NAME: StartCopy
  467. *
  468. * DESCRIPTIVE NAME: Copies data to the clipboard from a file or to a buffer.
  469. *
  470. * FUNCTION:
  471. *
  472. *
  473. * NOTES:
  474. *
  475. * ENTRY POINTS:
  476. *
  477. * INPUT:
  478. *
  479. * EXIT-NORMAL: Return Code 0.
  480. *
  481. * EXIT_ERROR:  Error Code.
  482. *
  483. * EFFECTS:
  484. *
  485. * INTERNAL REFERENCES: None
  486. *
  487. * EXTERNAL REFERENCES: mmioSendMessage
  488. *                      mmioGetLastError
  489. *                      DosDelete
  490. *
  491. *********************** END OF SPECIFICATIONS *******************************/
  492.  
  493. RC StartCopy( FUNCTION_PARM_BLOCK *pFuncBlockCopy )
  494.  
  495.  
  496.  
  497. {
  498.   ULONG         ulParam1;           // Flags for this Msg
  499.   ULONG         ulrc;               // Error Code Propogated
  500.   ULONG         ulFromPosition;     // position to copy from
  501.   ULONG         ulToPosition;       // position to copy to
  502.   ULONG         ulNewPosition;      // position after operation
  503.  
  504.   ULONG         ulBuffLen;          // length of the buffer to copy
  505.   ULONG         ulOldTimeFormat;    //
  506.   ULONG         ulMessage;
  507.  
  508.   LONG          lReturnCode;        // return code from mmio
  509.   LONG          lCurrFilePos;       // Get current file position
  510.   LONG          lSeekFlags;
  511.  
  512.   INSTANCE      *pInstance;       // Local Instance
  513.  
  514.   MCI_EDIT_PARMS *pEditParms;        // Pointer to structure to edit
  515.   MCI_EDIT_PARMS EditParms;
  516.  
  517.   PVOID          pBuffer;            // pointer to wave data from clipboard.
  518.  
  519.   PMMAUDIOHEADER pmmaudioheader;
  520.   FUNCTION_PARM_BLOCK  FuncBlock;
  521.  
  522.  
  523.   memmove( &FuncBlock, pFuncBlockCopy, sizeof( FUNCTION_PARM_BLOCK ) );
  524.  
  525.  
  526.   /********************************************
  527.   * Dereference Pointers From Thread Block
  528.   ********************************************/
  529.  
  530.   ulParam1 = FuncBlock.ulParam1;
  531.   ulMessage = FuncBlock.usMessage;
  532.  
  533.  
  534.   if ( ulParam1 & MCI_NOTIFY )
  535.      {
  536.      memmove( &EditParms,
  537.               ( PMCI_EDIT_PARMS ) FuncBlock.ulParam2,
  538.               sizeof( MCI_EDIT_PARMS ) );
  539.  
  540.      pEditParms = &EditParms;
  541.      }
  542.   else
  543.      {
  544.      pEditParms = ( PMCI_EDIT_PARMS ) FuncBlock.ulParam2;
  545.      }
  546.  
  547.   ulrc = MCIERR_SUCCESS;
  548.   pInstance = (INSTANCE *) FuncBlock.ulpInstance;
  549.  
  550.  
  551.   /*********************************************
  552.   * We can free the save thread now that we have
  553.   * obtained any possible file names
  554.   **********************************************/
  555.  
  556.   DosPostEventSem ( pInstance->hThreadSem );
  557.  
  558.  
  559.   /*******************************************
  560.   * Determine where we are before we start the
  561.   * copy.  This will be useful if the FROM
  562.   * flag is not specified, in which case our
  563.   * current position will be the FROM position.
  564.   ********************************************/
  565.  
  566.   /* Check to see if a stream has been created */
  567.  
  568.   if ( pInstance->ulCreateFlag == PREROLL_STATE )
  569.      {
  570.  
  571.      /**********************************************
  572.      * Get the current stream time, it may be used
  573.      * as the default starting position if MCI_FROM
  574.      * was not specified.
  575.      ***********************************************/
  576.  
  577.      ulrc = SpiGetTime( pInstance->StreamInfo.hStream,
  578.                         ( PMMTIME ) &( pInstance->StreamInfo.mmStreamTime ) );
  579.  
  580.      if ( ulrc )
  581.         {
  582.         CopyNotify( &FuncBlock, ulParam1, ulrc );
  583.         return ( ulrc );
  584.         }
  585.  
  586.      // investigate--combine the below routines into one function
  587.  
  588.      ulOldTimeFormat = pInstance->ulTimeUnits;
  589.      pInstance->ulTimeUnits = lBYTES;
  590.  
  591.      ConvertTimeUnits ( pInstance,
  592.                         ( PULONG ) &lCurrFilePos,
  593.                         pInstance->StreamInfo.mmStreamTime );
  594.  
  595.      pInstance->ulTimeUnits = ulOldTimeFormat;
  596.  
  597.      if ( lCurrFilePos > pInstance->ulDataSize )
  598.         {
  599.         lCurrFilePos = 0;
  600.         }
  601.  
  602.      lSeekFlags = SEEK_SET;
  603.  
  604.      } /* if stream has been created */
  605.   else
  606.      {
  607.      lCurrFilePos = 0;
  608.      lSeekFlags = SEEK_CUR;
  609.      } /* if no stream has been created */
  610.  
  611.   /* Ensure that the file is at the position we think it is */
  612.  
  613.   lReturnCode = mmioSeek( pInstance->hmmio,
  614.                           lCurrFilePos,
  615.                           lSeekFlags );
  616.  
  617.   if ( lReturnCode == MMIO_ERROR )
  618.      {
  619.      CopyNotify( &FuncBlock, ulParam1, MMIOERR_SEEK_FAILED );
  620.      return ( MMIOERR_SEEK_FAILED );
  621.      }
  622.  
  623.  
  624.   /* Retrieve the from and to positions to operate on */
  625.  
  626.   GetFromToPosition( lCurrFilePos,
  627.                       ulParam1,
  628.                       pEditParms,
  629.                       pInstance,
  630.                       &ulFromPosition,
  631.                       &ulToPosition );
  632.  
  633.  
  634.   /*******************************************
  635.   * Read information into a buffer and prepare
  636.   * to send it to the clipboard.
  637.   ********************************************/
  638.  
  639.   ulBuffLen = ulToPosition - ulFromPosition;
  640.  
  641.   /*****************************************
  642.   * But cut/copy place information into the
  643.   * clipboard.  However, delete simply
  644.   * removes data from the file w/o any
  645.   * clipboard operations.
  646.   ******************************************/
  647.  
  648.   if ( ulMessage != MCI_DELETE )
  649.      {
  650.      if ( ulParam1 & MCI_FROM_BUFFER )
  651.         {
  652.         /* Allocate a buffer to store the raw information */
  653.  
  654.         pBuffer = ( PVOID ) HhpAllocBuffer( pEditParms->ulBufLen + 200, 0 );
  655.  
  656.         memmove( pBuffer, pEditParms->pBuff, pEditParms->ulBufLen );
  657.  
  658.         ulBuffLen = pEditParms->ulBufLen;
  659.         }
  660.      else
  661.         {
  662.         if ( ulParam1 & MCI_TO_BUFFER )
  663.            {
  664.            /* -------------------------------------------------
  665.            * Ensure that the buffer that the caller passed in 
  666.            * is large enough
  667.            *--------------------------------------------------*/
  668.  
  669.            if ( ulBuffLen > pEditParms->ulBufLen )
  670.               {
  671.               pEditParms->ulBufLen = ulBuffLen;
  672.               CopyNotify( &FuncBlock, ulParam1, MCIERR_INVALID_BUFFER );
  673.               return ( MCIERR_INVALID_BUFFER );
  674.               }
  675.  
  676.            /* Use the callers buffer rather than our own for efficiency */
  677.  
  678.            pBuffer = pEditParms->pBuff;
  679.  
  680.            }
  681.         else
  682.            {
  683.            pBuffer = ( PVOID ) HhpAllocBuffer( (ulToPosition - ulFromPosition) + 100, 0 );
  684.            }
  685.  
  686.         /* Read the info necessary to copy into the clipboard */
  687.  
  688.         lReturnCode = mmioRead( pInstance->hmmio,
  689.                                 ( PSZ ) pBuffer,
  690.                                 ulBuffLen ); // hard coded for now
  691.  
  692.         if ( lReturnCode == MMIO_ERROR )
  693.            {
  694.            ulrc = mmioGetLastError( pInstance->hmmio );
  695.            CopyNotify( &FuncBlock, ulParam1, ulrc );
  696.            return ( ulrc );
  697.            }
  698.  
  699.      } /* else the buffer flag was not specified */
  700.  
  701.      /*******************************************
  702.      * Place information in the clipboard.
  703.      ********************************************/
  704.  
  705.      if ( ulParam1 & MCI_TO_BUFFER )
  706.         {
  707.         pEditParms->ulBufLen = ulBuffLen;
  708.         memmove( pEditParms->pHeader,
  709.                     &pInstance->mmAudioHeader, sizeof( MMAUDIOHEADER ) );
  710.  
  711.         pmmaudioheader = ( PMMAUDIOHEADER ) pEditParms->pHeader;
  712.         pmmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes = ulBuffLen;
  713.         }
  714.      else
  715.         {
  716.         ulrc = PutClipboardData( &pBuffer, pInstance, MCI_COPY, ulBuffLen );
  717.         }
  718.  
  719.      }
  720.  
  721.   /**********************************************
  722.   * If the caller wants to do a cut or delete, then
  723.   * remove the information from the file.  Else
  724.   * if the copy message was specified, no data
  725.   * will be lost, just seek back to where we
  726.   * were before the copy.
  727.   **********************************************/
  728.  
  729.   if ( ulMessage != MCI_COPY )
  730.     {
  731.     /*******************************************
  732.     * Remove the information from the file
  733.     ********************************************/
  734.  
  735.     lReturnCode = mmioSendMessage( pInstance->hmmio,
  736.                                    MMIOM_DELETE,
  737.                                    ulFromPosition,
  738.                                    ulBuffLen );
  739.  
  740.     if ( lReturnCode != MMIO_SUCCESS )
  741.       {
  742.       CopyNotify( &FuncBlock, ulParam1, lReturnCode );
  743.       return ( lReturnCode );
  744.       }
  745.  
  746.     /********************************************
  747.     * Cut/Delete are required to place the
  748.     * logical position of the file after the
  749.     * MCI_FROM position, whereas copy is supposed
  750.     * to return the file to the position where
  751.     * it was before the copy.
  752.     *********************************************/
  753.  
  754.  
  755.     if ( pInstance->ulCreateFlag == PREROLL_STATE)
  756.        {
  757.  
  758.        // investigate--combine the below routines into one function
  759.  
  760.        ulOldTimeFormat = pInstance->ulTimeUnits;
  761.        pInstance->ulTimeUnits = lBYTES;
  762.  
  763.        ConvertToMM ( pInstance,
  764.                      &ulNewPosition,
  765.                      pEditParms->ulFrom );
  766.  
  767.        ulrc = SpiSeekStream ( pInstance->StreamInfo.hStream,
  768.                               SPI_SEEK_ABSOLUTE,
  769.                               ulNewPosition );
  770.  
  771.       if ( ulrc )
  772.          {
  773.          CopyNotify( &FuncBlock, ulParam1, ulrc );
  774.          return ( ulrc );
  775.          }
  776.  
  777.  
  778.        pInstance->ulTimeUnits = ulOldTimeFormat;
  779.  
  780.  
  781.        } /* if a stream has been created */
  782.  
  783.      /* Update the undo levels */
  784.  
  785.      AddNode( pInstance, 1 );
  786.      pInstance->ulNumUndo++;
  787.  
  788.  
  789.     /* Ensure that the file header contains the correct length */
  790.  
  791.     ulrc = SetAudioHeader (pInstance);
  792.  
  793.     if ( ulrc )
  794.        {
  795.        CopyNotify( &FuncBlock, ulParam1, ulrc );
  796.        return ( ulrc );
  797.        }
  798.  
  799.     ulrc = GetAudioHeader ( pInstance );
  800.  
  801.     if ( ulrc )
  802.        {
  803.        CopyNotify( &FuncBlock, ulParam1, ulrc );
  804.        return ( ulrc );
  805.        }
  806.  
  807.  
  808.     } /* if cut message was specified */
  809.   else
  810.     {
  811.  
  812.     /*******************************************
  813.     * Return to where we were before the copy
  814.     * occurred
  815.     ********************************************/
  816.  
  817.     lReturnCode = mmioSeek( pInstance->hmmio,
  818.                             lCurrFilePos,
  819.                             SEEK_SET );
  820.  
  821.     if ( lReturnCode == MMIO_ERROR )
  822.        {
  823.        CopyNotify( &FuncBlock, ulParam1, lReturnCode );
  824.        return ( MMIOERR_SEEK_FAILED );
  825.        }
  826.  
  827.     } /* Copy message was specified */
  828.  
  829.   CopyNotify( &FuncBlock, ulParam1, MCI_NOTIFY_SUCCESSFUL );
  830.  
  831.   return ( MCIERR_SUCCESS );
  832.  
  833. } /* StartCopy */
  834.  
  835.  
  836. /********************* START OF SPECIFICATIONS *******************************
  837. *
  838. * SUBROUTINE NAME: PasteNotify
  839. *
  840. * FUNCTION: If a paste was done on via MCI_NOTIFY, alert caller to completion
  841. *           or an error.
  842. *
  843. *
  844. * NOTES:
  845. *
  846. * ENTRY POINTS:
  847. *
  848. * INPUT:
  849. *
  850. * EXIT-NORMAL: Return Code 0.
  851. *
  852. * EXIT_ERROR:  Error Code.
  853. *
  854. * EFFECTS:
  855. *
  856. * INTERNAL REFERENCES: None
  857. *
  858. * EXTERNAL REFERENCES: mmioSendMessage
  859. *                      mmioGetLastError
  860. *                      DosDelete
  861. *
  862. *********************** END OF SPECIFICATIONS *******************************/
  863.  
  864. void CopyNotify ( FUNCTION_PARM_BLOCK *pFuncBlock,
  865.                   ULONG               ulParam1,
  866.                   ULONG               ulNotifyResult )
  867.  
  868. {
  869.    if ( ulParam1 & MCI_NOTIFY )
  870.       {
  871.       PostMDMMessage (ulNotifyResult, pFuncBlock->usMessage, pFuncBlock);
  872.  
  873.       } /* if notify flag was passed */
  874.  
  875.   /*********************************************
  876.   * If any operation sees that the save thread
  877.   * is still processing, they will wait on the
  878.   * thread semaphore.  Since we are done with
  879.   * save processing post the semaphore so
  880.   * waiting threads can continue.
  881.   *********************************************/
  882.  
  883.   pFuncBlock->pInstance->usNotifyPending = FALSE;
  884.   DosPostEventSem ( pFuncBlock->pInstance->hThreadSem );
  885.  
  886.  
  887. } /* PasteNotify */
  888.  
  889.  
  890.  
  891. /********************* START OF SPECIFICATIONS *********************
  892. *
  893. * SUBROUTINE NAME: AddNode
  894. *
  895. * DESCRIPTIVE
  896. *
  897. * FUNCTION:  Adds undo/redo levels to a linked list
  898. *
  899. * NOTES: This function illustrates how to extend an
  900. *
  901. * ENTRY POINTS:
  902. *
  903. * INPUT:
  904. *
  905. * EXIT-NORMAL: MCIERR_SUCCESS
  906. *
  907. * EXIT_ERROR:  Error Code.
  908. *
  909. * EFFECTS:
  910. *
  911. * INTERNAL REFERENCES: MCIERR ().
  912. *
  913. * EXTERNAL REFERENCES:
  914. *
  915. *********************** END OF SPECIFICATIONS **********************/
  916. RC AddNode ( INSTANCE   *pInstance,
  917.              ULONG      ulNumActions )
  918.  
  919. {
  920.    PUNDOLIST   pUndoList;         // temporary pointer to item in linked list
  921.  
  922.    extern HHUGEHEAP     heap;                // Global MCD Heap
  923.  
  924.    AcquireProcSem ();
  925.  
  926.    if ( !(pUndoList = HhpAllocMem (heap, sizeof ( UNDOLIST ) ) ) )
  927.       {
  928.       return (MCIERR_OUT_OF_MEMORY);
  929.       }
  930.  
  931.    ReleaseProcSem ();
  932.  
  933.    pUndoList->ulNumLogicalActions = ulNumActions;
  934.    pUndoList->pNextList = pInstance->pUndoList;
  935.    pInstance->pUndoList = pUndoList;
  936.  
  937.    return ( MCIERR_SUCCESS );
  938.  
  939. } /* AddNode */
  940.  
  941.  
  942.  
  943.  
  944. /********************* START OF SPECIFICATIONS *********************
  945. *
  946. * SUBROUTINE NAME: RemoveNode
  947. *
  948. * DESCRIPTIVE
  949. *
  950. * FUNCTION:  Removes a undo node from a linked list
  951. *
  952. * NOTES:
  953. *
  954. * ENTRY POINTS:
  955. *
  956. * INPUT:
  957. *
  958. * EXIT-NORMAL: Return Code 0.
  959. *
  960. * EXIT_ERROR:  Error Code.
  961. *
  962. * EFFECTS:
  963. *
  964. * INTERNAL REFERENCES: MCIERR ().
  965. *
  966. * EXTERNAL REFERENCES:
  967. *
  968. *********************** END OF SPECIFICATIONS **********************/
  969. RC RemoveUndoNodes( INSTANCE     *pInstance )
  970.  
  971. {
  972.    PUNDOLIST           pTempUndo;
  973.  
  974.    extern HHUGEHEAP     heap;                // Global MCD Heap
  975.  
  976.    pTempUndo = pInstance->pUndoList;
  977.  
  978.    /* If there is a valid pointer--remove this node from the undo list */
  979.  
  980.    while ( pTempUndo )
  981.       {
  982.       pInstance->pUndoList = pInstance->pUndoList->pNextList;
  983.       CleanUp ((PVOID) pTempUndo );
  984.       pTempUndo = pInstance->pUndoList;
  985.  
  986.       }
  987.  
  988.    pTempUndo = pInstance->pRedoList;
  989.  
  990.    /* If there is a valid pointer--remove this node from the redo list */
  991.  
  992.    while ( pTempUndo )
  993.       {
  994.       pInstance->pRedoList = pInstance->pRedoList->pNextList;
  995.       CleanUp ((PVOID) pTempUndo );
  996.       pTempUndo = pInstance->pRedoList;
  997.  
  998.       }
  999.  
  1000.    return ( MCIERR_SUCCESS );
  1001.  
  1002. } /* RemoveNode */
  1003.  
  1004.  
  1005.  
  1006.