home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / mm / admct / admcsave.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  17KB  |  563 lines

  1. /********************* START OF SPECIFICATIONS *********************
  2. *
  3. * SUBROUTINE NAME: ADMCSAVE.c
  4. *
  5. * DESCRIPTIVE NAME: Audio MCD WaveAudio Save Routines
  6. *
  7. *              Copyright (c) IBM Corporation  1991, 1993
  8. *                        All Rights Reserved
  9. *
  10. *
  11. * FUNCTION:Save an Waveform Audio Element.
  12. *
  13. *  MCI_SAVE is not a required command, however, if a streaming MCD takes
  14. *  advantage of temporary files, then it should use MCI_SAVE.
  15. *
  16. *
  17. * NOTES:
  18. *
  19. *
  20. *********************** END OF SPECIFICATIONS **********************/
  21.  
  22. #define INCL_DOSSEMAPHORES
  23. #define INCL_DOSPROCESS
  24. #define INCL_ERRORS
  25.  
  26. #include <os2.h>                        // OS2 defines.
  27. #include <string.h>                     // String functions.
  28. #include <stdlib.h>                     // begin thread prototype
  29. #include <os2medef.h>                   // MME includes files.
  30. #include <ssm.h>                        // SSM spi includes.
  31. #include <meerror.h>                    // MM Error Messages.
  32. #include <mmioos2.h>                    // MMIO Include.
  33. #include <mcios2.h>                     // MM System Include.
  34. #include <mmdrvos2.h>                     // MCI Driver Include.
  35. #include <mcd.h>                        // AudioIFDriverInterface.
  36. #include <hhpheap.h>                    // Heap Manager Definitions
  37. #include <qos.h>
  38. #include <audiomcd.h>                   // Component Definitions
  39. #include "admcfunc.h"                   // Function Prototypes
  40. #include <checkmem.h>
  41.  
  42.  
  43. /********************* START OF SPECIFICATIONS *********************
  44. *
  45. * SUBROUTINE NAME: MCISAVEFILE
  46. *
  47. * DESCRIPTIVE      Audio MCD Save File.
  48. *
  49. * FUNCTION:  Save Existing element to desired format.
  50. *            This function first ensures that the flags are vaild.
  51. *            Then it ensures that all pointers point to valid memory.
  52. *            If any operations are currently active, they are then
  53. *            aborted.
  54. *            Finally, the save operation itself is then done.
  55. *
  56. * NOTES: This function illustrates how to use the mmioSendMessage
  57. *        API to save a file.  It also explains when/why one would
  58. *        want to spawn a thread for an operation.  Finally, it shows
  59. *        how to smoothly interrupt a previous operation.
  60. *
  61. * ENTRY POINTS:
  62. *
  63. * INPUT: MCI_SAVE message.
  64. *
  65. * EXIT-NORMAL: MCIERR_SUCCESS
  66. *
  67. * EXIT_ERROR:  Error Code.
  68. *
  69. * EFFECTS:
  70. *
  71. * INTERNAL REFERENCES:  StartSave.
  72. *                       PostMDMMessage
  73. *
  74. * EXTERNAL REFERENCES:  DosWaitEventSem
  75. *                       DosResetEventSem
  76. *                       DosCreateThread
  77. *
  78. *********************** END OF SPECIFICATIONS **********************/
  79. RC  MCISaveFile (FUNCTION_PARM_BLOCK * pFuncBlock)
  80. {
  81.   ULONG             ulrc;              // Error Value
  82.   ULONG             ulParam1;
  83.   ULONG             ulCheckFlags;
  84.   ULONG             ulCnt;
  85.   ULONG             ulAbortNotify = 0; // whether or not to abort a command
  86.  
  87.   INSTANCE          *ulpInstance;      // Local Instance
  88.   PMCI_SAVE_PARMS   pSaveParms;       // Msg Data
  89.  
  90. //  PSZ               pszSaveName;
  91.  
  92.   /*****************************************
  93.   * Initialize some variables
  94.   *****************************************/
  95.  
  96.   ulParam1 =    pFuncBlock->ulParam1;
  97.   pSaveParms = (PMCI_SAVE_PARMS) pFuncBlock->ulParam2;
  98.   ulpInstance = (INSTANCE *) pFuncBlock->ulpInstance;
  99.  
  100.   /*****************************************
  101.   * Ensure that the MCI_SAVE_PARMS contain
  102.   * valid memory.
  103.   *****************************************/
  104.  
  105.   ulrc = CheckMem ( (PVOID)pSaveParms,
  106.                     sizeof (MCI_SAVE_PARMS),
  107.                     PAG_READ);
  108.  
  109.   if (ulrc != MCIERR_SUCCESS)
  110.      {
  111.      return ( MCIERR_MISSING_PARAMETER );
  112.      }
  113.  
  114.  
  115.   ulCheckFlags = ulParam1;
  116.  
  117.   ulCheckFlags &= ~( MCI_WAIT + MCI_NOTIFY + MCI_SAVE_FILE);
  118.  
  119.   /*****************************************
  120.   * The save routine only permits MCI_WAIT,
  121.   * MCI_NOTIFY + MCI_SAVE_FILE.  If any other
  122.   * flags are passed in, then return an error
  123.   ******************************************/
  124.  
  125.   if (ulCheckFlags > 0)
  126.      {
  127.      return ( MCIERR_INVALID_FLAG );
  128.      }
  129.  
  130.   /********************************************
  131.   * Check to see if the IO Proc we have loaded
  132.   * has the ability to save files.  The riff
  133.   * wave proc does, but others (like the AVC
  134.   * IO Proc) do not.
  135.   ********************************************/
  136.  
  137.   if ( !ulpInstance->ulCapabilities & CAN_SAVE )
  138.     {
  139.     return (MCIERR_UNSUPPORTED_FUNCTION);
  140.     }
  141.  
  142.   /* If no file is loaded, a save is impossible */
  143.  
  144.   if ( ulpInstance->fFileExists != TRUE )
  145.      {
  146.      return (MCIERR_FILE_NOT_FOUND);
  147.      }
  148.  
  149.   /*********************************************
  150.   * If temp files are not active, then all the
  151.   * changes have been made to the actual file
  152.   * and a save is not practical nor necessary
  153.   **********************************************/
  154.  
  155.   if ( !ulpInstance->ulUsingTemp )
  156.     {
  157.     return (MCIERR_UNSUPPORTED_FUNCTION);
  158.     }
  159.  
  160.  
  161.   /* Check to see if the user passed in a filename */
  162.  
  163.   if ( ulParam1 & MCI_SAVE_FILE )
  164.     {
  165.     /*****************************************
  166.     * Ensure that they passed a valid pointer
  167.     *****************************************/
  168.  
  169.     ulrc = CheckMem ( (PVOID) pSaveParms->pszFileName,
  170.                       1,
  171.                       PAG_READ ) ;
  172.  
  173.     if (ulrc != MCIERR_SUCCESS)
  174.         return (MCIERR_MISSING_PARAMETER);
  175.  
  176.     /* Create a local copy of the pointer */
  177.  
  178. //    pszSaveName = (PSZ) pSaveParms->pszFileName;
  179.     }
  180.   else
  181.     {
  182.  
  183.     /*****************************************
  184.     * If the caller had us generate a filename
  185.     * on the open, then save w/o a new filename
  186.     * is invalid
  187.     *****************************************/
  188.     if  ( ulpInstance->ulCreatedName )
  189.        {
  190.        return ( MCIERR_MISSING_FLAG );
  191.        }
  192.  
  193. //    pszSaveName = NULL;
  194.     }
  195.  
  196.  
  197.  
  198.  
  199.    /*****************************************
  200.    * To ensure proper syncronization, acquire
  201.    * the semaphore which is used to control
  202.    * who can check to see which processes are
  203.    * active. This function will also tell us
  204.    * if there is an operation to abort or
  205.    * supercede.
  206.    ******************************************/
  207.  
  208.    GetNotifyAbortAccess ( ulpInstance, &ulAbortNotify );
  209.  
  210.     /**********************************************************
  211.     * If there other commands alive (such as a play/save or
  212.     * record, then they should be aborted by the save command
  213.     * To abort the command it is necessary to post a message
  214.     * a stop the stream
  215.     ***********************************************************/
  216.     if ( ulAbortNotify )
  217.  
  218.       {
  219.       /* Stop any commands in progress */
  220.  
  221.       GenericThreadAbort( ulpInstance, pFuncBlock, 0 );
  222.  
  223.       /************************************************
  224.       * Ensure that no other threads think an operation
  225.       * is active by setting a flag.
  226.       *************************************************/
  227.  
  228.       ulpInstance->usNotifyPending = FALSE;
  229.  
  230.     }
  231.  
  232.   /*****************************************
  233.   * If the stream is in a state where a stop
  234.   * is required (i.e. buffers have not been
  235.   * flush to the disk) then stop the stream
  236.   ******************************************/
  237.  
  238.   if ( STRMSTATE != MCI_STOP )
  239.       {
  240.       ulrc = ADMCStopStream (ulpInstance, SPI_STOP_DISCARD );
  241.  
  242.         if (!ulrc)
  243.           {
  244.           DosWaitEventSem (ulpInstance->hEventSem, (ULONG) ONE_MINUTE );
  245.           }
  246.  
  247.       } /* If stream is not in stopped state */
  248.  
  249.  
  250.  
  251.   /************************************************
  252.   * If the caller used the MCI_WAIT flag, then all
  253.   * of the processing can be done on one thread.
  254.   ************************************************/
  255.   if ( ulParam1 & MCI_WAIT )
  256.  
  257.     {
  258.     // investigate--change to fWaitPending
  259.  
  260.     ulpInstance->usWaitPending = TRUE;
  261.     ulpInstance->usWaitMsg= MCI_SAVE;
  262.  
  263.     ulrc = StartSave (pFuncBlock);
  264.  
  265.     ulpInstance->usWaitPending = FALSE;
  266.  
  267.     }
  268.   else
  269.     /***************************************************
  270.     ** To determine whether or not an operation must be
  271.     ** done on a thread, use the following criteria:
  272.     **
  273.     **   A. Will the operation take a long time.
  274.     **   B. Is there any way to make it appear as if
  275.     **      a thread was active.
  276.     **
  277.     **  In the case of a save, it can potentially be a
  278.     **  LONG operation and we do not want to bully the
  279.     **  applications thread, therefore,
  280.     **
  281.     ** We must perform the save on a thread since
  282.     ** notify was requested (note, if neither notify
  283.     ** or wait are specified, then operate like a notify
  284.     ** except without positing the message.
  285.     ****************************************************/
  286.  
  287.     {
  288.     /* Let other threads know that a save is about to start */
  289.  
  290.     ulpInstance->usNotifyPending = TRUE;
  291.     ulpInstance->usNotPendingMsg = MCI_SAVE;
  292.  
  293.     /********************************************
  294.     * Save thread will post a semaphore when it
  295.     * safe to do processing, so reset it,
  296.     * start the thread, and wait till its safe
  297.     * to go on.
  298.     ********************************************/
  299.  
  300.     DosResetEventSem (ulpInstance->hThreadSem, &ulCnt);
  301.  
  302.     ulrc = _beginthread ( (ADMCTHREAD)StartSave,
  303.                           0,
  304.                           NOTIFY_THREAD_STACKSIZE,
  305.                          (void *)pFuncBlock );
  306.  
  307.     /*************************************************
  308.     * Wait for the save thread to indicate that it is
  309.     * safe to continue.
  310.     **************************************************/
  311.     if ( ulrc != -1 )
  312.        {
  313.        DosWaitEventSem (ulpInstance->hThreadSem, -1);
  314.        ulrc = MCIERR_SUCCESS;
  315.        }
  316.     else
  317.        {
  318.        ulrc = MCIERR_OUT_OF_MEMORY;
  319.        }
  320.  
  321.     } /* this call is not a wait */
  322.  
  323.     DosResetEventSem (ulpInstance->hThreadSem, &ulCnt);
  324.  
  325.     /* Ensure that we are in stopped state after a save */
  326.  
  327.     STRMSTATE = MCI_STOP;
  328.  
  329.     /* Remove any undo nodes if they were allocated */
  330.  
  331.     RemoveUndoNodes( ulpInstance );
  332.  
  333.     return ( ulrc );
  334.  
  335. } /* MCISaveFile */
  336.  
  337.  
  338.  
  339. /********************* START OF SPECIFICATIONS *******************************
  340. *
  341. * SUBROUTINE NAME: StartSave.
  342. *
  343. * DESCRIPTIVE NAME: Saves a file using mmio message MMIOM_SAVE
  344. *
  345. * FUNCTION:
  346. *
  347. *
  348. * NOTES: This routine is called using  a separate thread spawned by
  349. *        MCD on MCI Notify.
  350. *
  351. * ENTRY POINTS:
  352. *
  353. * INPUT:
  354. *
  355. * EXIT-NORMAL: Return Code 0.
  356. *
  357. * EXIT_ERROR:  Error Code.
  358. *
  359. * EFFECTS:
  360. *
  361. * INTERNAL REFERENCES: None
  362. *
  363. * EXTERNAL REFERENCES: mmioSendMessage
  364. *                      mmioGetLastError
  365. *                      DosDelete
  366. *
  367. *********************** END OF SPECIFICATIONS *******************************/
  368. RC  _Optlink StartSave (VOID * pvoid)
  369. {
  370.  
  371.    FUNCTION_PARM_BLOCK * pFuncBlockCopy = (FUNCTION_PARM_BLOCK *) pvoid;
  372.    ULONG               ulrc = MCIERR_SUCCESS;
  373.    ULONG               ulErr = MCI_NOTIFY_SUCCESSFUL;
  374.    ULONG               ulParam1;
  375.  
  376.    INSTANCE            *ulpInstance;
  377.  
  378.    PMCI_SAVE_PARMS    pSaveParms;
  379.  
  380.    CHAR                chSaveName[ CCHMAXPATH ];
  381.    PSZ                 pszSaveName;
  382.  
  383.   FUNCTION_PARM_BLOCK  FuncBlock;
  384.  
  385.   memmove( &FuncBlock, pFuncBlockCopy, sizeof( FUNCTION_PARM_BLOCK ) );
  386.  
  387.  
  388.    /* Initialize some variable */
  389.  
  390.    ulpInstance = (INSTANCE *) FuncBlock.ulpInstance;
  391.    pSaveParms = (PMCI_SAVE_PARMS) FuncBlock.ulParam2;
  392.    ulParam1    = FuncBlock.ulParam1;
  393.  
  394.    /***************************************************
  395.    * If a notify thread passed the filename pointer,
  396.    * we must save the string since that thread could
  397.    * return before we finish processing and the pointer
  398.    * may no longer be valid.
  399.    ***************************************************/
  400.  
  401.    if ( ulParam1 & MCI_SAVE_FILE )
  402.       {
  403.       strcpy( chSaveName, ( PSZ ) pSaveParms->pszFileName );
  404.       pszSaveName = (PSZ) chSaveName;
  405.       }
  406.    else
  407.       {
  408.       pszSaveName = NULL;
  409.       }
  410.  
  411.    /*********************************************
  412.    * We can free the save thread now that we have
  413.    * obtained any possible file names
  414.    **********************************************/
  415.  
  416.    DosPostEventSem ( ulpInstance->hThreadSem );
  417.  
  418.  
  419.    /**********************************************
  420.    * This call illustrates the use of the
  421.    * mmioSendMessage.  We are requesting that the
  422.    * IO Proc that is currently loaded save all of
  423.    * the changes that have been done to the file.
  424.    ***********************************************/
  425.  
  426.    ulrc = mmioSendMessage( ulpInstance->hmmio,
  427.                            MMIOM_SAVE,
  428.                            (LONG) pszSaveName,
  429.                            0 );
  430.  
  431.    /*********************************************
  432.    * If there were no errors, then the filename the
  433.    * caller requested is the default file name
  434.    **********************************************/
  435.  
  436.    if ( ulParam1 & MCI_SAVE_FILE && !ulrc )
  437.       {
  438.       /* If we created a temp file, it is our duty to remove it */
  439.  
  440.       if ( ulpInstance->ulCreatedName )
  441.          {
  442.          DosDelete( ( PSZ ) ulpInstance->pszAudioFile );
  443.          }
  444.  
  445.       /***************************************
  446.       * Keep the name of the new file.  This
  447.       * will be useful if the caller does an
  448.       * MCI_INFO for the filename.
  449.       ***************************************/
  450.  
  451.       strcpy( ( PSZ ) ulpInstance->pszAudioFile,
  452.                chSaveName );
  453.  
  454.       }
  455.  
  456.    /**************************************************
  457.    * Set flag which indicates that we did not create
  458.    * the current element.  This flag is used by the
  459.    * close and load routines to determine whether or
  460.    * not it is necessary to remove a file that the
  461.    * mcd created.
  462.    **************************************************/
  463.  
  464.    ulpInstance->ulCreatedName = FALSE;
  465.  
  466.  
  467.  
  468.    /**********************************************
  469.    * If an error occurred, then inform  the caller
  470.    * of the problem.
  471.    **********************************************/
  472.  
  473.    if ( ulrc )
  474.       {
  475.       /******************************************
  476.       * Right now, we just know what error
  477.       * occurred, mmioGetLastError will give
  478.       * us more details on exactly what happened
  479.       ******************************************/
  480.  
  481.       ulErr = mmioGetLastError( ulpInstance->hmmio );
  482.  
  483.       /*********************************
  484.       * If the path is not valid return
  485.       * file not found
  486.       *********************************/
  487.  
  488.       if ( ulErr == ERROR_FILE_NOT_FOUND ||
  489.            ulErr == ERROR_PATH_NOT_FOUND ||
  490.            ulErr == ERROR_INVALID_DRIVE)
  491.          {
  492.          ulErr = MCIERR_FILE_NOT_FOUND;
  493.          }
  494.  
  495.       /*******************************************
  496.       * CANNOT_WRITE comes back when there is no
  497.       * disk space
  498.       ********************************************/
  499.  
  500.       else if ( ulErr == MMIOERR_CANNOTWRITE )
  501.          {
  502.          ulErr = MCIERR_TARGET_DEVICE_FULL;
  503.          }
  504.  
  505.       /*******************************************
  506.       * File attribute errors can happen when
  507.       * one writes to a readonly device (like a CD)
  508.       * or a readonly file etc.
  509.       ********************************************/
  510.  
  511.       else if ( ulErr == ERROR_ACCESS_DENIED ||
  512.                 ulErr == ERROR_SHARING_VIOLATION  )
  513.          {
  514.          ulErr = MCIERR_FILE_ATTRIBUTE;
  515.          }
  516.  
  517.       /* If notify, send message to application */
  518.  
  519.       if (ulParam1 & MCI_NOTIFY)
  520.          {
  521.  
  522.          PostMDMMessage (ulErr, MCI_SAVE, &FuncBlock);
  523.          }
  524.  
  525.       /* else return to caller with error */
  526.  
  527.       else
  528.          {
  529.  
  530.          return ( ulErr );
  531.          }
  532.       }
  533.  
  534.    else if (ulParam1 & MCI_NOTIFY)
  535.       {
  536.       PostMDMMessage (ulErr, MCI_SAVE, &FuncBlock);
  537.       }
  538.  
  539.  
  540.    /* If this call was done with a wait, we are done */
  541.  
  542.    if ( ulParam1 & MCI_WAIT )
  543.       {
  544.       return ( MCIERR_SUCCESS );
  545.       }
  546.  
  547.  
  548.    /*********************************************
  549.    * If any operation sees that the save thread
  550.    * is still processing, they will wait on the
  551.    * thread semaphore.  Since we are done with
  552.    * save processing post the semaphore so
  553.    * waiting threads can continue.
  554.    *********************************************/
  555.  
  556.    ulpInstance->usNotifyPending = FALSE;
  557.    DosPostEventSem ( ulpInstance->hThreadSem );
  558.  
  559.    return ( ulErr );
  560.  
  561. } /* Start Save */
  562.  
  563.