home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / warptlk3.zip / TOOLKIT / SAMPLES / MM / ADMCT / ADMCCOPY.C < prev    next >
C/C++ Source or Header  |  1995-08-24  |  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 <stdlib.h>                     // begin thread prototype
  48. #include <os2medef.h>                   // MME includes files.
  49. #include <mmioos2.h>                    // MMIO Include.
  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 ) && ( ulParam1 & 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_DELETE ) ||
  164.             (ulMessage == MCI_CUT && (ulParam1 &  MCI_FROM_BUFFER )) )
  165.      {
  166.      return ( MCIERR_INVALID_FLAG );
  167.      }
  168.  
  169.  
  170.   /************************************************
  171.   * If the caller used the MCI_WAIT flag, then all
  172.   * of the processing can be done on one thread.
  173.   ************************************************/
  174.   if ( ulParam1 & MCI_WAIT )
  175.  
  176.     {
  177.     // investigate--change to fWaitPending
  178.  
  179.     pInstance->usWaitPending = TRUE;
  180.     pInstance->usWaitMsg= MCI_SAVE;
  181.  
  182.     ulrc = StartCopy( pFuncBlock );
  183.  
  184.     pInstance->usWaitPending = FALSE;
  185.  
  186.     }
  187.   else
  188.     /***************************************************
  189.     ** To determine whether or not an operation must be
  190.     ** done on a thread, use the following criteria:
  191.     **
  192.     **   A. Will the operation take a long time.
  193.     **   B. Is there any way to make it appear as if
  194.     **      a thread was active.
  195.     **
  196.     **  In the case of a save, it can potentially be a
  197.     **  LONG operation and we do not want to bully the
  198.     **  applications thread, therefore,
  199.     **
  200.     ** We must perform the paste on a thread since
  201.     ** notify was requested (note, if neither notify
  202.     ** or wait are specified, then operate like a notify
  203.     ** except without positing the message.
  204.     ****************************************************/
  205.  
  206.     {
  207.     /* Let other threads know that a save is about to start */
  208.  
  209.     pInstance->usNotifyPending = TRUE;
  210.     pInstance->usNotPendingMsg = MCI_SAVE;
  211.  
  212.     /********************************************
  213.     * Save thread will post a semaphore when it
  214.     * safe to do processing, so reset it,
  215.     * start the thread, and wait till its safe
  216.     * to go on.
  217.     ********************************************/
  218.  
  219.     DosResetEventSem (pInstance->hThreadSem, &ulCount);
  220.  
  221.     ulrc = _beginthread ( (ADMCTHREAD) StartCopy,
  222.                           0,
  223.                           NOTIFY_THREAD_STACKSIZE,
  224.                           (void *)pFuncBlock );
  225.  
  226.     /*************************************************
  227.     * Wait for the save thread to indicate that it is
  228.     * safe to continue.
  229.     **************************************************/
  230.     if ( ulrc != -1 )
  231.        {
  232.        DosWaitEventSem (pInstance->hThreadSem, -1);
  233.        ulrc = MCIERR_SUCCESS;
  234.        }
  235.     else
  236.        {
  237.        ulrc = MCIERR_OUT_OF_MEMORY;
  238.        }
  239.  
  240.     } /* this call is not a wait */
  241.  
  242.   DosResetEventSem (pInstance->hThreadSem, &ulCount);
  243.  
  244.   /* Ensure that we are in stopped state after a save */
  245.  
  246.  
  247.  
  248.  
  249.  
  250.   /* The stream is in a stopped state after cut/copy/delete */
  251.  
  252.   pInstance->StreamInfo.ulState = MCI_STOP;
  253.  
  254.   return ( MCIERR_SUCCESS );
  255.  
  256. } /* mcicopy */
  257.  
  258.  
  259.  
  260.  
  261.  
  262. /********************* START OF SPECIFICATIONS *********************
  263. *
  264. * SUBROUTINE NAME: MCIMagic
  265. *
  266. * DESCRIPTIVE: Will undo/redo the last logical action
  267. *
  268. * FUNCTION:  Undo will place the instance in the state before the
  269. *            last logical action ( record, cut, copy, paste delete).
  270. *            By contrast, redo will place the instance in the state
  271. *            it was before an undo.
  272. *
  273. * NOTES:
  274. *
  275. * ENTRY POINTS:
  276. *     LINKAGE:   CALL FAR
  277. *
  278. * INPUT: MCI_UNDO message.
  279. *
  280. * EXIT-NORMAL: MCIERR_SUCCESS
  281. *
  282. * EXIT_ERROR:  Error Code.
  283. *
  284. * EFFECTS:
  285. *
  286. * INTERNAL REFERENCES: MCIERR ().
  287. *
  288. * EXTERNAL REFERENCES:
  289. *
  290. *********************** END OF SPECIFICATIONS **********************/
  291.  
  292.  
  293.  
  294. RC MCIMagic ( FUNCTION_PARM_BLOCK *pFuncBlock,
  295.               ULONG               ulOperation )
  296.  
  297. {
  298.  
  299.   ULONG         ulrc;               // Error Code Propogated
  300. //  ULONG         ulFrom;             // Position to start deleting
  301. //  ULONG         ulLength;           // Length of info to delete
  302. //  ULONG         ulMessage;
  303.   ULONG         ulActionLoop;       // Some actions (like paste)
  304.                                     // require multiple undo/redo
  305.   ULONG         ulMaxLevels;
  306.  
  307.   LONG          lReturnCode;        // rc for mmio operations
  308.  
  309.   INSTANCE      *pInstance;       // Local Instance
  310.  
  311. //  MCI_EDIT_PARMS *pEditParms;        // Pointer to structure to edit
  312.  
  313.   PUNDOLIST     pTempList;
  314.  
  315.   /********************************************
  316.   * Dereference Pointers From Thread Block
  317.   ********************************************/
  318.  
  319.   ulrc = MCIERR_SUCCESS;
  320.   pInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  321.  
  322.  
  323.   /*******************************************
  324.   * Check for valid flags
  325.   ********************************************/
  326.  
  327.   ulrc = CheckEditFlags( pFuncBlock, TRUE );
  328.  
  329.   if ( ulrc != MCIERR_SUCCESS )
  330.      {
  331.      return ( ulrc );
  332.      }
  333.  
  334.   /*******************************************
  335.   * Ensure the io proc that we have loaded has
  336.   * the ability to undo/redo.
  337.   ********************************************/
  338.  
  339.   if ( !(pInstance->ulCapabilities & CAN_UNDOREDO )  )
  340.      {
  341.      return ( MCIERR_UNSUPPORTED_FUNCTION );
  342.      }
  343.  
  344.   /*******************************************
  345.   * We are currently using an array of undo/redo
  346.   * levels.  Check to ensure that we will have
  347.   * room to store the number of undoes
  348.   ********************************************/
  349.   if ( ulOperation == MMIOM_UNDO )
  350.      {
  351.      if  ( !pInstance->pUndoList )
  352.         {
  353.         return ( MCIERR_CANNOT_UNDO );
  354.         }
  355.      else
  356.         {
  357.         ulMaxLevels = pInstance->pUndoList->ulNumLogicalActions;
  358.         }
  359.      } /* If we are to undo */
  360.  
  361.   /*******************************************
  362.   * We are currently using an array of undo/redo
  363.   * levels.  Check to ensure that we will have
  364.   * room to store the number of redoes
  365.   ********************************************/
  366.   if ( ulOperation == MMIOM_REDO )
  367.      {
  368.      if ( !pInstance->pRedoList )
  369.         {
  370.         return ( MCIERR_CANNOT_REDO );
  371.         }
  372.      else
  373.         {
  374.         ulMaxLevels = pInstance->pRedoList->ulNumLogicalActions;
  375.         }
  376.      } /* If redo */
  377.  
  378.   /**************************************************
  379.   * Ask the io proc to undo or redo the last logical
  380.   * action (record, cut, delete, paste ).
  381.   **************************************************/
  382.  
  383.   for ( ulActionLoop = 0; ulActionLoop < ulMaxLevels; ulActionLoop++ )
  384.      {
  385.      lReturnCode = mmioSendMessage( pInstance->hmmio,
  386.                                    ulOperation,
  387.                                    0,
  388.                                    0 );
  389.  
  390.      if ( lReturnCode == MMIO_ERROR )
  391.         {
  392.         if ( ulOperation == MMIOM_UNDO )
  393.            {
  394.            return ( MCIERR_CANNOT_UNDO );
  395.            }
  396.         else
  397.            {
  398.            return ( MCIERR_CANNOT_REDO );
  399.            }
  400.  
  401.         }  /* if an error happened */
  402.      } /* Undo all logical actions (i.e. paste may take more than one */
  403.  
  404.   ulrc = SetAudioHeader (pInstance);
  405.  
  406.   if ( ulrc )
  407.      {
  408.      return ( ulrc );
  409.      }
  410.  
  411.   ulrc = GetAudioHeader ( pInstance, 0 );
  412.  
  413.   if ( ulrc )
  414.      {
  415.      return ( ulrc );
  416.      }
  417.  
  418.   /*********************************
  419.   * After an undo/redo, the stream
  420.   * position is 0.
  421.   *********************************/
  422.  
  423.   if ( pInstance->ulCreateFlag == PREROLL_STATE)
  424.      {
  425.      ulrc = ADMCSeekStream ( pInstance,
  426.                             SPI_SEEK_ABSOLUTE,
  427.                             0 );
  428.      }
  429.  
  430.   /* The stream is in a stopped state after an undo/redo */
  431.  
  432.   pInstance->StreamInfo.ulState = MCI_STOP;
  433.  
  434.   /* Update our array of undo levels */
  435.  
  436.   if ( ulOperation == MMIOM_UNDO )
  437.      {
  438.      pInstance->ulNumUndo--;
  439.      pInstance->ulNumRedo++;
  440.      pTempList = pInstance->pUndoList;
  441.      pInstance->pUndoList = pInstance->pUndoList->pNextList;
  442.      pTempList->pNextList = pInstance->pRedoList;
  443.  
  444.      pInstance->pRedoList = pTempList;
  445.      }
  446.   else
  447.      {
  448.      pInstance->ulNumRedo--;
  449.      pInstance->ulNumUndo++;
  450.      pTempList = pInstance->pRedoList;
  451.      pInstance->pRedoList = pInstance->pRedoList->pNextList;
  452.      pTempList->pNextList = pInstance->pUndoList;
  453.      pInstance->pUndoList = pTempList;
  454.  
  455.      }
  456.  
  457.   return ( ulrc );
  458.  
  459. } /* MCIMajic */
  460.  
  461.  
  462.  
  463.  
  464.  
  465. /********************* START OF SPECIFICATIONS *******************************
  466. *
  467. * SUBROUTINE NAME: StartCopy
  468. *
  469. * DESCRIPTIVE NAME: Copies data to the clipboard from a file or to a buffer.
  470. *
  471. * FUNCTION:
  472. *
  473. *
  474. * NOTES:
  475. *
  476. * ENTRY POINTS:
  477. *
  478. * INPUT:
  479. *
  480. * EXIT-NORMAL: Return Code 0.
  481. *
  482. * EXIT_ERROR:  Error Code.
  483. *
  484. * EFFECTS:
  485. *
  486. * INTERNAL REFERENCES: None
  487. *
  488. * EXTERNAL REFERENCES: mmioSendMessage
  489. *                      mmioGetLastError
  490. *                      DosDelete
  491. *
  492. *********************** END OF SPECIFICATIONS *******************************/
  493.  
  494. RC _Optlink StartCopy (VOID * pvoid)
  495.  
  496. {
  497.   FUNCTION_PARM_BLOCK * pFuncBlockCopy = (FUNCTION_PARM_BLOCK *) pvoid;
  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 = ADMCSeekStream ( pInstance,
  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, 0  );
  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.